libvhost-user: fix crash when rings aren't ready
[qemu/ar7.git] / target / mips / translate.c
blob3022f349cb2a06e428deb5d5dd6e90810c7c0ced
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 "target/mips/trace.h"
37 #include "trace-tcg.h"
38 #include "exec/log.h"
40 #define MIPS_DEBUG_DISAS 0
42 /* MIPS major opcodes */
43 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
45 enum {
46 /* indirect opcode tables */
47 OPC_SPECIAL = (0x00 << 26),
48 OPC_REGIMM = (0x01 << 26),
49 OPC_CP0 = (0x10 << 26),
50 OPC_CP1 = (0x11 << 26),
51 OPC_CP2 = (0x12 << 26),
52 OPC_CP3 = (0x13 << 26),
53 OPC_SPECIAL2 = (0x1C << 26),
54 OPC_SPECIAL3 = (0x1F << 26),
55 /* arithmetic with immediate */
56 OPC_ADDI = (0x08 << 26),
57 OPC_ADDIU = (0x09 << 26),
58 OPC_SLTI = (0x0A << 26),
59 OPC_SLTIU = (0x0B << 26),
60 /* logic with immediate */
61 OPC_ANDI = (0x0C << 26),
62 OPC_ORI = (0x0D << 26),
63 OPC_XORI = (0x0E << 26),
64 OPC_LUI = (0x0F << 26),
65 /* arithmetic with immediate */
66 OPC_DADDI = (0x18 << 26),
67 OPC_DADDIU = (0x19 << 26),
68 /* Jump and branches */
69 OPC_J = (0x02 << 26),
70 OPC_JAL = (0x03 << 26),
71 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
72 OPC_BEQL = (0x14 << 26),
73 OPC_BNE = (0x05 << 26),
74 OPC_BNEL = (0x15 << 26),
75 OPC_BLEZ = (0x06 << 26),
76 OPC_BLEZL = (0x16 << 26),
77 OPC_BGTZ = (0x07 << 26),
78 OPC_BGTZL = (0x17 << 26),
79 OPC_JALX = (0x1D << 26),
80 OPC_DAUI = (0x1D << 26),
81 /* Load and stores */
82 OPC_LDL = (0x1A << 26),
83 OPC_LDR = (0x1B << 26),
84 OPC_LB = (0x20 << 26),
85 OPC_LH = (0x21 << 26),
86 OPC_LWL = (0x22 << 26),
87 OPC_LW = (0x23 << 26),
88 OPC_LWPC = OPC_LW | 0x5,
89 OPC_LBU = (0x24 << 26),
90 OPC_LHU = (0x25 << 26),
91 OPC_LWR = (0x26 << 26),
92 OPC_LWU = (0x27 << 26),
93 OPC_SB = (0x28 << 26),
94 OPC_SH = (0x29 << 26),
95 OPC_SWL = (0x2A << 26),
96 OPC_SW = (0x2B << 26),
97 OPC_SDL = (0x2C << 26),
98 OPC_SDR = (0x2D << 26),
99 OPC_SWR = (0x2E << 26),
100 OPC_LL = (0x30 << 26),
101 OPC_LLD = (0x34 << 26),
102 OPC_LD = (0x37 << 26),
103 OPC_LDPC = OPC_LD | 0x5,
104 OPC_SC = (0x38 << 26),
105 OPC_SCD = (0x3C << 26),
106 OPC_SD = (0x3F << 26),
107 /* Floating point load/store */
108 OPC_LWC1 = (0x31 << 26),
109 OPC_LWC2 = (0x32 << 26),
110 OPC_LDC1 = (0x35 << 26),
111 OPC_LDC2 = (0x36 << 26),
112 OPC_SWC1 = (0x39 << 26),
113 OPC_SWC2 = (0x3A << 26),
114 OPC_SDC1 = (0x3D << 26),
115 OPC_SDC2 = (0x3E << 26),
116 /* Compact Branches */
117 OPC_BLEZALC = (0x06 << 26),
118 OPC_BGEZALC = (0x06 << 26),
119 OPC_BGEUC = (0x06 << 26),
120 OPC_BGTZALC = (0x07 << 26),
121 OPC_BLTZALC = (0x07 << 26),
122 OPC_BLTUC = (0x07 << 26),
123 OPC_BOVC = (0x08 << 26),
124 OPC_BEQZALC = (0x08 << 26),
125 OPC_BEQC = (0x08 << 26),
126 OPC_BLEZC = (0x16 << 26),
127 OPC_BGEZC = (0x16 << 26),
128 OPC_BGEC = (0x16 << 26),
129 OPC_BGTZC = (0x17 << 26),
130 OPC_BLTZC = (0x17 << 26),
131 OPC_BLTC = (0x17 << 26),
132 OPC_BNVC = (0x18 << 26),
133 OPC_BNEZALC = (0x18 << 26),
134 OPC_BNEC = (0x18 << 26),
135 OPC_BC = (0x32 << 26),
136 OPC_BEQZC = (0x36 << 26),
137 OPC_JIC = (0x36 << 26),
138 OPC_BALC = (0x3A << 26),
139 OPC_BNEZC = (0x3E << 26),
140 OPC_JIALC = (0x3E << 26),
141 /* MDMX ASE specific */
142 OPC_MDMX = (0x1E << 26),
143 /* MSA ASE, same as MDMX */
144 OPC_MSA = OPC_MDMX,
145 /* Cache and prefetch */
146 OPC_CACHE = (0x2F << 26),
147 OPC_PREF = (0x33 << 26),
148 /* PC-relative address computation / loads */
149 OPC_PCREL = (0x3B << 26),
152 /* PC-relative address computation / loads */
153 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
154 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
155 enum {
156 /* Instructions determined by bits 19 and 20 */
157 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
158 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
159 OPC_LWUPC = OPC_PCREL | (2 << 19),
161 /* Instructions determined by bits 16 ... 20 */
162 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
163 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
165 /* Other */
166 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
169 /* MIPS special opcodes */
170 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
172 enum {
173 /* Shifts */
174 OPC_SLL = 0x00 | OPC_SPECIAL,
175 /* NOP is SLL r0, r0, 0 */
176 /* SSNOP is SLL r0, r0, 1 */
177 /* EHB is SLL r0, r0, 3 */
178 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
179 OPC_ROTR = OPC_SRL | (1 << 21),
180 OPC_SRA = 0x03 | OPC_SPECIAL,
181 OPC_SLLV = 0x04 | OPC_SPECIAL,
182 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
183 OPC_ROTRV = OPC_SRLV | (1 << 6),
184 OPC_SRAV = 0x07 | OPC_SPECIAL,
185 OPC_DSLLV = 0x14 | OPC_SPECIAL,
186 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
187 OPC_DROTRV = OPC_DSRLV | (1 << 6),
188 OPC_DSRAV = 0x17 | OPC_SPECIAL,
189 OPC_DSLL = 0x38 | OPC_SPECIAL,
190 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
191 OPC_DROTR = OPC_DSRL | (1 << 21),
192 OPC_DSRA = 0x3B | OPC_SPECIAL,
193 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
194 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
195 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
196 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
197 /* Multiplication / division */
198 OPC_MULT = 0x18 | OPC_SPECIAL,
199 OPC_MULTU = 0x19 | OPC_SPECIAL,
200 OPC_DIV = 0x1A | OPC_SPECIAL,
201 OPC_DIVU = 0x1B | OPC_SPECIAL,
202 OPC_DMULT = 0x1C | OPC_SPECIAL,
203 OPC_DMULTU = 0x1D | OPC_SPECIAL,
204 OPC_DDIV = 0x1E | OPC_SPECIAL,
205 OPC_DDIVU = 0x1F | OPC_SPECIAL,
207 /* 2 registers arithmetic / logic */
208 OPC_ADD = 0x20 | OPC_SPECIAL,
209 OPC_ADDU = 0x21 | OPC_SPECIAL,
210 OPC_SUB = 0x22 | OPC_SPECIAL,
211 OPC_SUBU = 0x23 | OPC_SPECIAL,
212 OPC_AND = 0x24 | OPC_SPECIAL,
213 OPC_OR = 0x25 | OPC_SPECIAL,
214 OPC_XOR = 0x26 | OPC_SPECIAL,
215 OPC_NOR = 0x27 | OPC_SPECIAL,
216 OPC_SLT = 0x2A | OPC_SPECIAL,
217 OPC_SLTU = 0x2B | OPC_SPECIAL,
218 OPC_DADD = 0x2C | OPC_SPECIAL,
219 OPC_DADDU = 0x2D | OPC_SPECIAL,
220 OPC_DSUB = 0x2E | OPC_SPECIAL,
221 OPC_DSUBU = 0x2F | OPC_SPECIAL,
222 /* Jumps */
223 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
224 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
225 /* Traps */
226 OPC_TGE = 0x30 | OPC_SPECIAL,
227 OPC_TGEU = 0x31 | OPC_SPECIAL,
228 OPC_TLT = 0x32 | OPC_SPECIAL,
229 OPC_TLTU = 0x33 | OPC_SPECIAL,
230 OPC_TEQ = 0x34 | OPC_SPECIAL,
231 OPC_TNE = 0x36 | OPC_SPECIAL,
232 /* HI / LO registers load & stores */
233 OPC_MFHI = 0x10 | OPC_SPECIAL,
234 OPC_MTHI = 0x11 | OPC_SPECIAL,
235 OPC_MFLO = 0x12 | OPC_SPECIAL,
236 OPC_MTLO = 0x13 | OPC_SPECIAL,
237 /* Conditional moves */
238 OPC_MOVZ = 0x0A | OPC_SPECIAL,
239 OPC_MOVN = 0x0B | OPC_SPECIAL,
241 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
242 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
244 OPC_MOVCI = 0x01 | OPC_SPECIAL,
246 /* Special */
247 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
248 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
249 OPC_BREAK = 0x0D | OPC_SPECIAL,
250 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
251 OPC_SYNC = 0x0F | OPC_SPECIAL,
253 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
254 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
255 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
256 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
259 /* R6 Multiply and Divide instructions have the same Opcode
260 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
261 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
263 enum {
264 R6_OPC_MUL = OPC_MULT | (2 << 6),
265 R6_OPC_MUH = OPC_MULT | (3 << 6),
266 R6_OPC_MULU = OPC_MULTU | (2 << 6),
267 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
268 R6_OPC_DIV = OPC_DIV | (2 << 6),
269 R6_OPC_MOD = OPC_DIV | (3 << 6),
270 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
271 R6_OPC_MODU = OPC_DIVU | (3 << 6),
273 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
274 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
275 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
276 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
277 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
278 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
279 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
280 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
282 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
283 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
284 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
285 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
286 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
288 OPC_LSA = 0x05 | OPC_SPECIAL,
289 OPC_DLSA = 0x15 | OPC_SPECIAL,
292 /* Multiplication variants of the vr54xx. */
293 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
295 enum {
296 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
297 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
298 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
299 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
300 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
301 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
302 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
303 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
304 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
305 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
306 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
307 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
308 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
309 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
312 /* REGIMM (rt field) opcodes */
313 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
315 enum {
316 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
317 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
318 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
319 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
320 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
321 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
322 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
323 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
324 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
325 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
326 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
327 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
328 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
329 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
330 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
331 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
333 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
334 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
337 /* Special2 opcodes */
338 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
340 enum {
341 /* Multiply & xxx operations */
342 OPC_MADD = 0x00 | OPC_SPECIAL2,
343 OPC_MADDU = 0x01 | OPC_SPECIAL2,
344 OPC_MUL = 0x02 | OPC_SPECIAL2,
345 OPC_MSUB = 0x04 | OPC_SPECIAL2,
346 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
347 /* Loongson 2F */
348 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
349 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
350 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
351 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
352 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
353 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
354 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
355 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
356 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
357 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
358 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
359 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
360 /* Misc */
361 OPC_CLZ = 0x20 | OPC_SPECIAL2,
362 OPC_CLO = 0x21 | OPC_SPECIAL2,
363 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
364 OPC_DCLO = 0x25 | OPC_SPECIAL2,
365 /* Special */
366 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
369 /* Special3 opcodes */
370 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
372 enum {
373 OPC_EXT = 0x00 | OPC_SPECIAL3,
374 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
375 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
376 OPC_DEXT = 0x03 | OPC_SPECIAL3,
377 OPC_INS = 0x04 | OPC_SPECIAL3,
378 OPC_DINSM = 0x05 | OPC_SPECIAL3,
379 OPC_DINSU = 0x06 | OPC_SPECIAL3,
380 OPC_DINS = 0x07 | OPC_SPECIAL3,
381 OPC_FORK = 0x08 | OPC_SPECIAL3,
382 OPC_YIELD = 0x09 | OPC_SPECIAL3,
383 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
384 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
385 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
387 /* Loongson 2E */
388 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
389 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
390 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
391 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
392 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
393 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
394 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
395 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
396 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
397 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
398 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
399 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
401 /* MIPS DSP Load */
402 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
403 /* MIPS DSP Arithmetic */
404 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
405 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
406 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
407 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
408 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
409 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
410 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
411 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
412 /* MIPS DSP GPR-Based Shift Sub-class */
413 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
414 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
415 /* MIPS DSP Multiply Sub-class insns */
416 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
417 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
418 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
419 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
420 /* DSP Bit/Manipulation Sub-class */
421 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
422 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
423 /* MIPS DSP Append Sub-class */
424 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
425 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
426 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
427 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
428 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
430 /* R6 */
431 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
432 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
433 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
434 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
435 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
436 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
439 /* BSHFL opcodes */
440 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
442 enum {
443 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
444 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
445 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
446 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
447 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
448 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
451 /* DBSHFL opcodes */
452 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
454 enum {
455 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
456 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
457 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
458 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
459 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
462 /* MIPS DSP REGIMM opcodes */
463 enum {
464 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
465 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
468 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
469 /* MIPS DSP Load */
470 enum {
471 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
472 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
473 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
474 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
477 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
478 enum {
479 /* MIPS DSP Arithmetic Sub-class */
480 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
481 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
482 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
483 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
484 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
485 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
486 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
487 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
488 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
489 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
490 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
491 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
492 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
493 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
494 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
495 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
496 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
497 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
498 /* MIPS DSP Multiply Sub-class insns */
499 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
500 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
501 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
502 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
503 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
504 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
507 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
508 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
509 enum {
510 /* MIPS DSP Arithmetic Sub-class */
511 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
512 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
513 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
514 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
515 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
516 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
517 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
518 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
519 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
520 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
521 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
522 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
523 /* MIPS DSP Multiply Sub-class insns */
524 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
525 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
526 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
527 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
530 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
531 enum {
532 /* MIPS DSP Arithmetic Sub-class */
533 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
534 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
535 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
536 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
537 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
538 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
539 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
540 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
541 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
542 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
543 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
544 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
545 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
546 /* DSP Bit/Manipulation Sub-class */
547 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
548 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
549 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
550 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
551 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
554 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
555 enum {
556 /* MIPS DSP Arithmetic Sub-class */
557 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
558 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
559 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
560 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
561 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
562 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
563 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
564 /* DSP Compare-Pick Sub-class */
565 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
566 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
567 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
568 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
569 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
570 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
571 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
572 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
573 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
574 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
575 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
576 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
577 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
578 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
579 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
582 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
583 enum {
584 /* MIPS DSP GPR-Based Shift Sub-class */
585 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
586 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
587 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
588 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
589 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
590 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
591 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
592 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
593 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
594 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
595 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
596 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
597 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
598 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
599 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
600 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
601 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
602 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
603 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
604 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
605 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
606 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
609 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
610 enum {
611 /* MIPS DSP Multiply Sub-class insns */
612 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
613 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
614 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
615 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
616 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
617 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
618 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
619 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
620 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
621 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
622 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
623 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
624 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
625 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
626 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
627 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
628 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
629 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
630 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
631 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
632 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
633 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
636 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
637 enum {
638 /* DSP Bit/Manipulation Sub-class */
639 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
642 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
643 enum {
644 /* MIPS DSP Append Sub-class */
645 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
646 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
647 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
650 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
651 enum {
652 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
653 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
654 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
655 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
656 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
657 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
658 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
659 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
660 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
661 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
662 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
663 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
664 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
665 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
666 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
667 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
668 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
669 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
672 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
673 enum {
674 /* MIPS DSP Arithmetic Sub-class */
675 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
676 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
677 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
678 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
679 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
680 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
681 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
682 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
683 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
684 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
685 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
686 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
687 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
688 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
689 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
690 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
691 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
692 /* DSP Bit/Manipulation Sub-class */
693 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
694 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
695 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
697 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
698 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
701 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
702 enum {
703 /* MIPS DSP Multiply Sub-class insns */
704 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
705 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
706 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
707 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
708 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
709 /* MIPS DSP Arithmetic Sub-class */
710 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
711 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
712 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
713 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
714 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
715 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
716 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
717 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
718 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
719 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
720 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
721 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
722 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
723 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
724 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
725 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
726 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
727 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
728 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
729 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
730 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
733 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
734 enum {
735 /* DSP Compare-Pick Sub-class */
736 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
737 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
738 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
739 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
740 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
741 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
742 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
743 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
744 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
745 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
746 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
747 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
748 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
749 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
750 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
751 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
752 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
753 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
754 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
755 /* MIPS DSP Arithmetic Sub-class */
756 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
763 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
766 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
767 enum {
768 /* DSP Append Sub-class */
769 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
770 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
771 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
772 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
775 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
776 enum {
777 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
778 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
779 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
780 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
781 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
782 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
783 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
784 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
785 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
786 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
787 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
788 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
789 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
790 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
791 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
792 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
793 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
794 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
795 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
796 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
797 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
798 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
801 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
802 enum {
803 /* DSP Bit/Manipulation Sub-class */
804 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
807 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
808 enum {
809 /* MIPS DSP Multiply Sub-class insns */
810 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
811 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
812 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
813 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
814 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
815 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
816 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
817 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
818 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
819 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
820 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
821 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
822 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
823 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
824 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
825 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
826 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
827 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
828 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
829 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
830 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
835 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
838 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
839 enum {
840 /* MIPS DSP GPR-Based Shift Sub-class */
841 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
842 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
843 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
844 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
845 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
846 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
847 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
848 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
849 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
850 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
851 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
852 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
853 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
854 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
855 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
856 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
857 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
858 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
859 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
860 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
861 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
866 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
869 /* Coprocessor 0 (rs field) */
870 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
872 enum {
873 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
874 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
875 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
876 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
877 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
878 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
879 OPC_MFTR = (0x08 << 21) | OPC_CP0,
880 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
881 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
882 OPC_MTTR = (0x0C << 21) | OPC_CP0,
883 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
884 OPC_C0 = (0x10 << 21) | OPC_CP0,
885 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
886 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
889 /* MFMC0 opcodes */
890 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
892 enum {
893 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
894 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
895 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
896 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
897 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
898 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
899 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
900 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
903 /* Coprocessor 0 (with rs == C0) */
904 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
906 enum {
907 OPC_TLBR = 0x01 | OPC_C0,
908 OPC_TLBWI = 0x02 | OPC_C0,
909 OPC_TLBINV = 0x03 | OPC_C0,
910 OPC_TLBINVF = 0x04 | OPC_C0,
911 OPC_TLBWR = 0x06 | OPC_C0,
912 OPC_TLBP = 0x08 | OPC_C0,
913 OPC_RFE = 0x10 | OPC_C0,
914 OPC_ERET = 0x18 | OPC_C0,
915 OPC_DERET = 0x1F | OPC_C0,
916 OPC_WAIT = 0x20 | OPC_C0,
919 /* Coprocessor 1 (rs field) */
920 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
922 /* Values for the fmt field in FP instructions */
923 enum {
924 /* 0 - 15 are reserved */
925 FMT_S = 16, /* single fp */
926 FMT_D = 17, /* double fp */
927 FMT_E = 18, /* extended fp */
928 FMT_Q = 19, /* quad fp */
929 FMT_W = 20, /* 32-bit fixed */
930 FMT_L = 21, /* 64-bit fixed */
931 FMT_PS = 22, /* paired single fp */
932 /* 23 - 31 are reserved */
935 enum {
936 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
937 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
938 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
939 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
940 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
941 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
942 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
943 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
944 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
945 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
946 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
947 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
948 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
949 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
950 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
951 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
952 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
953 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
954 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
955 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
956 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
957 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
958 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
959 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
960 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
961 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
962 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
963 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
964 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
965 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
968 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
969 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
971 enum {
972 OPC_BC1F = (0x00 << 16) | OPC_BC1,
973 OPC_BC1T = (0x01 << 16) | OPC_BC1,
974 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
975 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
978 enum {
979 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
980 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
983 enum {
984 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
985 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
988 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
990 enum {
991 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
992 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
993 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
994 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
995 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
996 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
997 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
998 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
999 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1000 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1001 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1004 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1006 enum {
1007 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1008 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1009 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1010 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1011 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1012 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1013 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1014 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1016 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1018 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1019 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1020 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1021 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1022 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1023 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1025 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1026 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1027 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1028 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1029 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1030 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1031 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1032 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1034 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1035 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1036 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1037 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1038 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1039 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1040 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1041 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1043 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1044 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1045 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1046 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1047 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1048 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1050 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1051 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1052 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1053 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1054 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1055 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1057 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1058 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1059 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1060 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1061 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1062 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1064 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1065 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1066 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1067 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1068 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1069 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1071 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1072 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1073 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1074 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1075 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1076 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1078 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1079 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1080 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1081 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1082 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1083 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1085 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1086 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1087 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1088 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1089 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1090 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1092 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1093 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1094 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1095 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1096 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1097 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1101 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1103 enum {
1104 OPC_LWXC1 = 0x00 | OPC_CP3,
1105 OPC_LDXC1 = 0x01 | OPC_CP3,
1106 OPC_LUXC1 = 0x05 | OPC_CP3,
1107 OPC_SWXC1 = 0x08 | OPC_CP3,
1108 OPC_SDXC1 = 0x09 | OPC_CP3,
1109 OPC_SUXC1 = 0x0D | OPC_CP3,
1110 OPC_PREFX = 0x0F | OPC_CP3,
1111 OPC_ALNV_PS = 0x1E | OPC_CP3,
1112 OPC_MADD_S = 0x20 | OPC_CP3,
1113 OPC_MADD_D = 0x21 | OPC_CP3,
1114 OPC_MADD_PS = 0x26 | OPC_CP3,
1115 OPC_MSUB_S = 0x28 | OPC_CP3,
1116 OPC_MSUB_D = 0x29 | OPC_CP3,
1117 OPC_MSUB_PS = 0x2E | OPC_CP3,
1118 OPC_NMADD_S = 0x30 | OPC_CP3,
1119 OPC_NMADD_D = 0x31 | OPC_CP3,
1120 OPC_NMADD_PS= 0x36 | OPC_CP3,
1121 OPC_NMSUB_S = 0x38 | OPC_CP3,
1122 OPC_NMSUB_D = 0x39 | OPC_CP3,
1123 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1126 /* MSA Opcodes */
1127 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1128 enum {
1129 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1130 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1131 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1132 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1133 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1134 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1135 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1136 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1137 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1138 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1139 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1140 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1141 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1142 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1143 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1144 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1145 OPC_MSA_ELM = 0x19 | OPC_MSA,
1146 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1147 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1148 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1149 OPC_MSA_VEC = 0x1E | OPC_MSA,
1151 /* MI10 instruction */
1152 OPC_LD_B = (0x20) | OPC_MSA,
1153 OPC_LD_H = (0x21) | OPC_MSA,
1154 OPC_LD_W = (0x22) | OPC_MSA,
1155 OPC_LD_D = (0x23) | OPC_MSA,
1156 OPC_ST_B = (0x24) | OPC_MSA,
1157 OPC_ST_H = (0x25) | OPC_MSA,
1158 OPC_ST_W = (0x26) | OPC_MSA,
1159 OPC_ST_D = (0x27) | OPC_MSA,
1162 enum {
1163 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1164 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1165 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1166 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1167 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1168 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1169 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1170 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1171 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1172 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1173 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1174 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1175 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1177 /* I8 instruction */
1178 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1179 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1180 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1181 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1182 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1183 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1184 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1185 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1186 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1187 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1189 /* VEC/2R/2RF instruction */
1190 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1191 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1192 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1193 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1194 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1195 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1196 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1198 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1199 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1201 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1202 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1203 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1204 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1205 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1207 /* 2RF instruction df(bit 16) = _w, _d */
1208 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1209 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1210 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1211 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1212 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1213 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1214 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1215 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1216 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1217 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1218 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1219 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1220 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1221 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1222 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1223 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1225 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1226 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1227 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1228 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1229 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1230 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1231 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1232 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1233 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1234 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1235 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1236 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1237 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1238 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1239 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1240 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1241 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1242 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1243 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1244 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1245 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1246 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1247 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1248 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1249 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1250 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1251 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1252 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1253 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1254 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1255 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1256 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1257 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1258 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1259 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1260 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1261 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1262 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1263 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1264 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1265 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1266 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1267 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1268 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1269 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1270 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1271 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1272 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1273 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1274 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1275 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1276 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1277 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1278 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1279 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1280 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1281 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1282 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1283 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1284 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1285 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1286 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1287 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1288 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1290 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1291 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1292 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1293 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1294 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1295 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1296 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1297 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1298 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1299 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1301 /* 3RF instruction _df(bit 21) = _w, _d */
1302 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1303 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1304 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1305 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1306 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1307 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1308 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1309 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1310 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1311 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1312 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1313 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1314 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1315 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1316 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1317 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1318 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1319 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1320 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1321 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1322 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1323 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1324 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1325 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1326 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1327 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1328 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1329 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1330 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1331 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1332 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1333 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1334 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1335 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1336 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1337 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1338 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1339 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1340 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1341 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1342 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1344 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1345 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1346 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1347 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1348 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1349 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1350 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1351 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1352 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1353 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1354 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1355 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1356 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1359 /* global register indices */
1360 static TCGv_env cpu_env;
1361 static TCGv cpu_gpr[32], cpu_PC;
1362 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1363 static TCGv cpu_dspctrl, btarget, bcond;
1364 static TCGv_i32 hflags;
1365 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1366 static TCGv_i64 fpu_f64[32];
1367 static TCGv_i64 msa_wr_d[64];
1369 #include "exec/gen-icount.h"
1371 #define gen_helper_0e0i(name, arg) do { \
1372 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1373 gen_helper_##name(cpu_env, helper_tmp); \
1374 tcg_temp_free_i32(helper_tmp); \
1375 } while(0)
1377 #define gen_helper_0e1i(name, arg1, arg2) do { \
1378 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1379 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1380 tcg_temp_free_i32(helper_tmp); \
1381 } while(0)
1383 #define gen_helper_1e0i(name, ret, arg1) do { \
1384 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1385 gen_helper_##name(ret, cpu_env, helper_tmp); \
1386 tcg_temp_free_i32(helper_tmp); \
1387 } while(0)
1389 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1390 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1391 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1392 tcg_temp_free_i32(helper_tmp); \
1393 } while(0)
1395 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1396 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1397 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1398 tcg_temp_free_i32(helper_tmp); \
1399 } while(0)
1401 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1402 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1403 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1404 tcg_temp_free_i32(helper_tmp); \
1405 } while(0)
1407 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1408 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1409 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1410 tcg_temp_free_i32(helper_tmp); \
1411 } while(0)
1413 typedef struct DisasContext {
1414 struct TranslationBlock *tb;
1415 target_ulong pc, saved_pc;
1416 uint32_t opcode;
1417 int singlestep_enabled;
1418 int insn_flags;
1419 int32_t CP0_Config1;
1420 /* Routine used to access memory */
1421 int mem_idx;
1422 TCGMemOp default_tcg_memop_mask;
1423 uint32_t hflags, saved_hflags;
1424 int bstate;
1425 target_ulong btarget;
1426 bool ulri;
1427 int kscrexist;
1428 bool rxi;
1429 int ie;
1430 bool bi;
1431 bool bp;
1432 uint64_t PAMask;
1433 bool mvh;
1434 int CP0_LLAddr_shift;
1435 bool ps;
1436 bool vp;
1437 bool cmgcr;
1438 bool mrp;
1439 bool nan2008;
1440 bool abs2008;
1441 } DisasContext;
1443 enum {
1444 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1445 * exception condition */
1446 BS_STOP = 1, /* We want to stop translation for any reason */
1447 BS_BRANCH = 2, /* We reached a branch condition */
1448 BS_EXCP = 3, /* We reached an exception condition */
1451 static const char * const regnames[] = {
1452 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1453 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1454 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1455 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1458 static const char * const regnames_HI[] = {
1459 "HI0", "HI1", "HI2", "HI3",
1462 static const char * const regnames_LO[] = {
1463 "LO0", "LO1", "LO2", "LO3",
1466 static const char * const fregnames[] = {
1467 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1468 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1469 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1470 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1473 static const char * const msaregnames[] = {
1474 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1475 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1476 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1477 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1478 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1479 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1480 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1481 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1482 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1483 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1484 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1485 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1486 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1487 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1488 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1489 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1492 #define LOG_DISAS(...) \
1493 do { \
1494 if (MIPS_DEBUG_DISAS) { \
1495 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1497 } while (0)
1499 #define MIPS_INVAL(op) \
1500 do { \
1501 if (MIPS_DEBUG_DISAS) { \
1502 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1503 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
1504 ctx->pc, ctx->opcode, op, ctx->opcode >> 26, \
1505 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
1507 } while (0)
1509 /* General purpose registers moves. */
1510 static inline void gen_load_gpr (TCGv t, int reg)
1512 if (reg == 0)
1513 tcg_gen_movi_tl(t, 0);
1514 else
1515 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1518 static inline void gen_store_gpr (TCGv t, int reg)
1520 if (reg != 0)
1521 tcg_gen_mov_tl(cpu_gpr[reg], t);
1524 /* Moves to/from shadow registers. */
1525 static inline void gen_load_srsgpr (int from, int to)
1527 TCGv t0 = tcg_temp_new();
1529 if (from == 0)
1530 tcg_gen_movi_tl(t0, 0);
1531 else {
1532 TCGv_i32 t2 = tcg_temp_new_i32();
1533 TCGv_ptr addr = tcg_temp_new_ptr();
1535 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1536 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1537 tcg_gen_andi_i32(t2, t2, 0xf);
1538 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1539 tcg_gen_ext_i32_ptr(addr, t2);
1540 tcg_gen_add_ptr(addr, cpu_env, addr);
1542 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1543 tcg_temp_free_ptr(addr);
1544 tcg_temp_free_i32(t2);
1546 gen_store_gpr(t0, to);
1547 tcg_temp_free(t0);
1550 static inline void gen_store_srsgpr (int from, int to)
1552 if (to != 0) {
1553 TCGv t0 = tcg_temp_new();
1554 TCGv_i32 t2 = tcg_temp_new_i32();
1555 TCGv_ptr addr = tcg_temp_new_ptr();
1557 gen_load_gpr(t0, from);
1558 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1559 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1560 tcg_gen_andi_i32(t2, t2, 0xf);
1561 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1562 tcg_gen_ext_i32_ptr(addr, t2);
1563 tcg_gen_add_ptr(addr, cpu_env, addr);
1565 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1566 tcg_temp_free_ptr(addr);
1567 tcg_temp_free_i32(t2);
1568 tcg_temp_free(t0);
1572 /* Tests */
1573 static inline void gen_save_pc(target_ulong pc)
1575 tcg_gen_movi_tl(cpu_PC, pc);
1578 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1580 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1581 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1582 gen_save_pc(ctx->pc);
1583 ctx->saved_pc = ctx->pc;
1585 if (ctx->hflags != ctx->saved_hflags) {
1586 tcg_gen_movi_i32(hflags, ctx->hflags);
1587 ctx->saved_hflags = ctx->hflags;
1588 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1589 case MIPS_HFLAG_BR:
1590 break;
1591 case MIPS_HFLAG_BC:
1592 case MIPS_HFLAG_BL:
1593 case MIPS_HFLAG_B:
1594 tcg_gen_movi_tl(btarget, ctx->btarget);
1595 break;
1600 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1602 ctx->saved_hflags = ctx->hflags;
1603 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1604 case MIPS_HFLAG_BR:
1605 break;
1606 case MIPS_HFLAG_BC:
1607 case MIPS_HFLAG_BL:
1608 case MIPS_HFLAG_B:
1609 ctx->btarget = env->btarget;
1610 break;
1614 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1616 TCGv_i32 texcp = tcg_const_i32(excp);
1617 TCGv_i32 terr = tcg_const_i32(err);
1618 save_cpu_state(ctx, 1);
1619 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1620 tcg_temp_free_i32(terr);
1621 tcg_temp_free_i32(texcp);
1622 ctx->bstate = BS_EXCP;
1625 static inline void generate_exception(DisasContext *ctx, int excp)
1627 gen_helper_0e0i(raise_exception, excp);
1630 static inline void generate_exception_end(DisasContext *ctx, int excp)
1632 generate_exception_err(ctx, excp, 0);
1635 /* Floating point register moves. */
1636 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1638 if (ctx->hflags & MIPS_HFLAG_FRE) {
1639 generate_exception(ctx, EXCP_RI);
1641 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1644 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1646 TCGv_i64 t64;
1647 if (ctx->hflags & MIPS_HFLAG_FRE) {
1648 generate_exception(ctx, EXCP_RI);
1650 t64 = tcg_temp_new_i64();
1651 tcg_gen_extu_i32_i64(t64, t);
1652 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1653 tcg_temp_free_i64(t64);
1656 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1658 if (ctx->hflags & MIPS_HFLAG_F64) {
1659 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1660 } else {
1661 gen_load_fpr32(ctx, t, reg | 1);
1665 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1667 if (ctx->hflags & MIPS_HFLAG_F64) {
1668 TCGv_i64 t64 = tcg_temp_new_i64();
1669 tcg_gen_extu_i32_i64(t64, t);
1670 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1671 tcg_temp_free_i64(t64);
1672 } else {
1673 gen_store_fpr32(ctx, t, reg | 1);
1677 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1679 if (ctx->hflags & MIPS_HFLAG_F64) {
1680 tcg_gen_mov_i64(t, fpu_f64[reg]);
1681 } else {
1682 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1686 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1688 if (ctx->hflags & MIPS_HFLAG_F64) {
1689 tcg_gen_mov_i64(fpu_f64[reg], t);
1690 } else {
1691 TCGv_i64 t0;
1692 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1693 t0 = tcg_temp_new_i64();
1694 tcg_gen_shri_i64(t0, t, 32);
1695 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1696 tcg_temp_free_i64(t0);
1700 static inline int get_fp_bit (int cc)
1702 if (cc)
1703 return 24 + cc;
1704 else
1705 return 23;
1708 /* Addresses computation */
1709 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1711 tcg_gen_add_tl(ret, arg0, arg1);
1713 #if defined(TARGET_MIPS64)
1714 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1715 tcg_gen_ext32s_i64(ret, ret);
1717 #endif
1720 /* Addresses computation (translation time) */
1721 static target_long addr_add(DisasContext *ctx, target_long base,
1722 target_long offset)
1724 target_long sum = base + offset;
1726 #if defined(TARGET_MIPS64)
1727 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1728 sum = (int32_t)sum;
1730 #endif
1731 return sum;
1734 /* Sign-extract the low 32-bits to a target_long. */
1735 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
1737 #if defined(TARGET_MIPS64)
1738 tcg_gen_ext32s_i64(ret, arg);
1739 #else
1740 tcg_gen_extrl_i64_i32(ret, arg);
1741 #endif
1744 /* Sign-extract the high 32-bits to a target_long. */
1745 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
1747 #if defined(TARGET_MIPS64)
1748 tcg_gen_sari_i64(ret, arg, 32);
1749 #else
1750 tcg_gen_extrh_i64_i32(ret, arg);
1751 #endif
1754 static inline void check_cp0_enabled(DisasContext *ctx)
1756 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1757 generate_exception_err(ctx, EXCP_CpU, 0);
1760 static inline void check_cp1_enabled(DisasContext *ctx)
1762 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1763 generate_exception_err(ctx, EXCP_CpU, 1);
1766 /* Verify that the processor is running with COP1X instructions enabled.
1767 This is associated with the nabla symbol in the MIPS32 and MIPS64
1768 opcode tables. */
1770 static inline void check_cop1x(DisasContext *ctx)
1772 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1773 generate_exception_end(ctx, EXCP_RI);
1776 /* Verify that the processor is running with 64-bit floating-point
1777 operations enabled. */
1779 static inline void check_cp1_64bitmode(DisasContext *ctx)
1781 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1782 generate_exception_end(ctx, EXCP_RI);
1786 * Verify if floating point register is valid; an operation is not defined
1787 * if bit 0 of any register specification is set and the FR bit in the
1788 * Status register equals zero, since the register numbers specify an
1789 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1790 * in the Status register equals one, both even and odd register numbers
1791 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1793 * Multiple 64 bit wide registers can be checked by calling
1794 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1796 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1798 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1799 generate_exception_end(ctx, EXCP_RI);
1802 /* Verify that the processor is running with DSP instructions enabled.
1803 This is enabled by CP0 Status register MX(24) bit.
1806 static inline void check_dsp(DisasContext *ctx)
1808 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1809 if (ctx->insn_flags & ASE_DSP) {
1810 generate_exception_end(ctx, EXCP_DSPDIS);
1811 } else {
1812 generate_exception_end(ctx, EXCP_RI);
1817 static inline void check_dspr2(DisasContext *ctx)
1819 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1820 if (ctx->insn_flags & ASE_DSP) {
1821 generate_exception_end(ctx, EXCP_DSPDIS);
1822 } else {
1823 generate_exception_end(ctx, EXCP_RI);
1828 /* This code generates a "reserved instruction" exception if the
1829 CPU does not support the instruction set corresponding to flags. */
1830 static inline void check_insn(DisasContext *ctx, int flags)
1832 if (unlikely(!(ctx->insn_flags & flags))) {
1833 generate_exception_end(ctx, EXCP_RI);
1837 /* This code generates a "reserved instruction" exception if the
1838 CPU has corresponding flag set which indicates that the instruction
1839 has been removed. */
1840 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1842 if (unlikely(ctx->insn_flags & flags)) {
1843 generate_exception_end(ctx, EXCP_RI);
1847 /* This code generates a "reserved instruction" exception if the
1848 CPU does not support 64-bit paired-single (PS) floating point data type */
1849 static inline void check_ps(DisasContext *ctx)
1851 if (unlikely(!ctx->ps)) {
1852 generate_exception(ctx, EXCP_RI);
1854 check_cp1_64bitmode(ctx);
1857 #ifdef TARGET_MIPS64
1858 /* This code generates a "reserved instruction" exception if 64-bit
1859 instructions are not enabled. */
1860 static inline void check_mips_64(DisasContext *ctx)
1862 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1863 generate_exception_end(ctx, EXCP_RI);
1865 #endif
1867 #ifndef CONFIG_USER_ONLY
1868 static inline void check_mvh(DisasContext *ctx)
1870 if (unlikely(!ctx->mvh)) {
1871 generate_exception(ctx, EXCP_RI);
1874 #endif
1876 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1877 calling interface for 32 and 64-bit FPRs. No sense in changing
1878 all callers for gen_load_fpr32 when we need the CTX parameter for
1879 this one use. */
1880 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1881 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1882 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1883 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1884 int ft, int fs, int cc) \
1886 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1887 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1888 switch (ifmt) { \
1889 case FMT_PS: \
1890 check_ps(ctx); \
1891 break; \
1892 case FMT_D: \
1893 if (abs) { \
1894 check_cop1x(ctx); \
1896 check_cp1_registers(ctx, fs | ft); \
1897 break; \
1898 case FMT_S: \
1899 if (abs) { \
1900 check_cop1x(ctx); \
1902 break; \
1904 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1905 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1906 switch (n) { \
1907 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1908 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1909 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1910 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1911 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1912 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1913 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1914 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1915 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1916 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1917 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1918 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1919 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1920 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1921 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1922 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1923 default: abort(); \
1925 tcg_temp_free_i##bits (fp0); \
1926 tcg_temp_free_i##bits (fp1); \
1929 FOP_CONDS(, 0, d, FMT_D, 64)
1930 FOP_CONDS(abs, 1, d, FMT_D, 64)
1931 FOP_CONDS(, 0, s, FMT_S, 32)
1932 FOP_CONDS(abs, 1, s, FMT_S, 32)
1933 FOP_CONDS(, 0, ps, FMT_PS, 64)
1934 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1935 #undef FOP_CONDS
1937 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1938 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1939 int ft, int fs, int fd) \
1941 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1942 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1943 if (ifmt == FMT_D) { \
1944 check_cp1_registers(ctx, fs | ft | fd); \
1946 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1947 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1948 switch (n) { \
1949 case 0: \
1950 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1951 break; \
1952 case 1: \
1953 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1954 break; \
1955 case 2: \
1956 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1957 break; \
1958 case 3: \
1959 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1960 break; \
1961 case 4: \
1962 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1963 break; \
1964 case 5: \
1965 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1966 break; \
1967 case 6: \
1968 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1969 break; \
1970 case 7: \
1971 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1972 break; \
1973 case 8: \
1974 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1975 break; \
1976 case 9: \
1977 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1978 break; \
1979 case 10: \
1980 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1981 break; \
1982 case 11: \
1983 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1984 break; \
1985 case 12: \
1986 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1987 break; \
1988 case 13: \
1989 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1990 break; \
1991 case 14: \
1992 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1993 break; \
1994 case 15: \
1995 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1996 break; \
1997 case 17: \
1998 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1999 break; \
2000 case 18: \
2001 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2002 break; \
2003 case 19: \
2004 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2005 break; \
2006 case 25: \
2007 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2008 break; \
2009 case 26: \
2010 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2011 break; \
2012 case 27: \
2013 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2014 break; \
2015 default: \
2016 abort(); \
2018 STORE; \
2019 tcg_temp_free_i ## bits (fp0); \
2020 tcg_temp_free_i ## bits (fp1); \
2023 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2024 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2025 #undef FOP_CONDNS
2026 #undef gen_ldcmp_fpr32
2027 #undef gen_ldcmp_fpr64
2029 /* load/store instructions. */
2030 #ifdef CONFIG_USER_ONLY
2031 #define OP_LD_ATOMIC(insn,fname) \
2032 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2034 TCGv t0 = tcg_temp_new(); \
2035 tcg_gen_mov_tl(t0, arg1); \
2036 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2037 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2038 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2039 tcg_temp_free(t0); \
2041 #else
2042 #define OP_LD_ATOMIC(insn,fname) \
2043 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2045 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
2047 #endif
2048 OP_LD_ATOMIC(ll,ld32s);
2049 #if defined(TARGET_MIPS64)
2050 OP_LD_ATOMIC(lld,ld64);
2051 #endif
2052 #undef OP_LD_ATOMIC
2054 #ifdef CONFIG_USER_ONLY
2055 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2056 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2058 TCGv t0 = tcg_temp_new(); \
2059 TCGLabel *l1 = gen_new_label(); \
2060 TCGLabel *l2 = gen_new_label(); \
2062 tcg_gen_andi_tl(t0, arg2, almask); \
2063 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2064 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2065 generate_exception(ctx, EXCP_AdES); \
2066 gen_set_label(l1); \
2067 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2068 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2069 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2070 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2071 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2072 generate_exception_end(ctx, EXCP_SC); \
2073 gen_set_label(l2); \
2074 tcg_gen_movi_tl(t0, 0); \
2075 gen_store_gpr(t0, rt); \
2076 tcg_temp_free(t0); \
2078 #else
2079 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2080 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2082 TCGv t0 = tcg_temp_new(); \
2083 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
2084 gen_store_gpr(t0, rt); \
2085 tcg_temp_free(t0); \
2087 #endif
2088 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2089 #if defined(TARGET_MIPS64)
2090 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2091 #endif
2092 #undef OP_ST_ATOMIC
2094 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2095 int base, int16_t offset)
2097 if (base == 0) {
2098 tcg_gen_movi_tl(addr, offset);
2099 } else if (offset == 0) {
2100 gen_load_gpr(addr, base);
2101 } else {
2102 tcg_gen_movi_tl(addr, offset);
2103 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2107 static target_ulong pc_relative_pc (DisasContext *ctx)
2109 target_ulong pc = ctx->pc;
2111 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2112 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2114 pc -= branch_bytes;
2117 pc &= ~(target_ulong)3;
2118 return pc;
2121 /* Load */
2122 static void gen_ld(DisasContext *ctx, uint32_t opc,
2123 int rt, int base, int16_t offset)
2125 TCGv t0, t1, t2;
2127 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2128 /* Loongson CPU uses a load to zero register for prefetch.
2129 We emulate it as a NOP. On other CPU we must perform the
2130 actual memory access. */
2131 return;
2134 t0 = tcg_temp_new();
2135 gen_base_offset_addr(ctx, t0, base, offset);
2137 switch (opc) {
2138 #if defined(TARGET_MIPS64)
2139 case OPC_LWU:
2140 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL |
2141 ctx->default_tcg_memop_mask);
2142 gen_store_gpr(t0, rt);
2143 break;
2144 case OPC_LD:
2145 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
2146 ctx->default_tcg_memop_mask);
2147 gen_store_gpr(t0, rt);
2148 break;
2149 case OPC_LLD:
2150 case R6_OPC_LLD:
2151 op_ld_lld(t0, t0, ctx);
2152 gen_store_gpr(t0, rt);
2153 break;
2154 case OPC_LDL:
2155 t1 = tcg_temp_new();
2156 /* Do a byte access to possibly trigger a page
2157 fault with the unaligned address. */
2158 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2159 tcg_gen_andi_tl(t1, t0, 7);
2160 #ifndef TARGET_WORDS_BIGENDIAN
2161 tcg_gen_xori_tl(t1, t1, 7);
2162 #endif
2163 tcg_gen_shli_tl(t1, t1, 3);
2164 tcg_gen_andi_tl(t0, t0, ~7);
2165 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2166 tcg_gen_shl_tl(t0, t0, t1);
2167 t2 = tcg_const_tl(-1);
2168 tcg_gen_shl_tl(t2, t2, t1);
2169 gen_load_gpr(t1, rt);
2170 tcg_gen_andc_tl(t1, t1, t2);
2171 tcg_temp_free(t2);
2172 tcg_gen_or_tl(t0, t0, t1);
2173 tcg_temp_free(t1);
2174 gen_store_gpr(t0, rt);
2175 break;
2176 case OPC_LDR:
2177 t1 = tcg_temp_new();
2178 /* Do a byte access to possibly trigger a page
2179 fault with the unaligned address. */
2180 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2181 tcg_gen_andi_tl(t1, t0, 7);
2182 #ifdef TARGET_WORDS_BIGENDIAN
2183 tcg_gen_xori_tl(t1, t1, 7);
2184 #endif
2185 tcg_gen_shli_tl(t1, t1, 3);
2186 tcg_gen_andi_tl(t0, t0, ~7);
2187 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2188 tcg_gen_shr_tl(t0, t0, t1);
2189 tcg_gen_xori_tl(t1, t1, 63);
2190 t2 = tcg_const_tl(0xfffffffffffffffeull);
2191 tcg_gen_shl_tl(t2, t2, t1);
2192 gen_load_gpr(t1, rt);
2193 tcg_gen_and_tl(t1, t1, t2);
2194 tcg_temp_free(t2);
2195 tcg_gen_or_tl(t0, t0, t1);
2196 tcg_temp_free(t1);
2197 gen_store_gpr(t0, rt);
2198 break;
2199 case OPC_LDPC:
2200 t1 = tcg_const_tl(pc_relative_pc(ctx));
2201 gen_op_addr_add(ctx, t0, t0, t1);
2202 tcg_temp_free(t1);
2203 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2204 gen_store_gpr(t0, rt);
2205 break;
2206 #endif
2207 case OPC_LWPC:
2208 t1 = tcg_const_tl(pc_relative_pc(ctx));
2209 gen_op_addr_add(ctx, t0, t0, t1);
2210 tcg_temp_free(t1);
2211 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2212 gen_store_gpr(t0, rt);
2213 break;
2214 case OPC_LW:
2215 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
2216 ctx->default_tcg_memop_mask);
2217 gen_store_gpr(t0, rt);
2218 break;
2219 case OPC_LH:
2220 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
2221 ctx->default_tcg_memop_mask);
2222 gen_store_gpr(t0, rt);
2223 break;
2224 case OPC_LHU:
2225 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW |
2226 ctx->default_tcg_memop_mask);
2227 gen_store_gpr(t0, rt);
2228 break;
2229 case OPC_LB:
2230 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
2231 gen_store_gpr(t0, rt);
2232 break;
2233 case OPC_LBU:
2234 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
2235 gen_store_gpr(t0, rt);
2236 break;
2237 case OPC_LWL:
2238 t1 = tcg_temp_new();
2239 /* Do a byte access to possibly trigger a page
2240 fault with the unaligned address. */
2241 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2242 tcg_gen_andi_tl(t1, t0, 3);
2243 #ifndef TARGET_WORDS_BIGENDIAN
2244 tcg_gen_xori_tl(t1, t1, 3);
2245 #endif
2246 tcg_gen_shli_tl(t1, t1, 3);
2247 tcg_gen_andi_tl(t0, t0, ~3);
2248 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2249 tcg_gen_shl_tl(t0, t0, t1);
2250 t2 = tcg_const_tl(-1);
2251 tcg_gen_shl_tl(t2, t2, t1);
2252 gen_load_gpr(t1, rt);
2253 tcg_gen_andc_tl(t1, t1, t2);
2254 tcg_temp_free(t2);
2255 tcg_gen_or_tl(t0, t0, t1);
2256 tcg_temp_free(t1);
2257 tcg_gen_ext32s_tl(t0, t0);
2258 gen_store_gpr(t0, rt);
2259 break;
2260 case OPC_LWR:
2261 t1 = tcg_temp_new();
2262 /* Do a byte access to possibly trigger a page
2263 fault with the unaligned address. */
2264 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2265 tcg_gen_andi_tl(t1, t0, 3);
2266 #ifdef TARGET_WORDS_BIGENDIAN
2267 tcg_gen_xori_tl(t1, t1, 3);
2268 #endif
2269 tcg_gen_shli_tl(t1, t1, 3);
2270 tcg_gen_andi_tl(t0, t0, ~3);
2271 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2272 tcg_gen_shr_tl(t0, t0, t1);
2273 tcg_gen_xori_tl(t1, t1, 31);
2274 t2 = tcg_const_tl(0xfffffffeull);
2275 tcg_gen_shl_tl(t2, t2, t1);
2276 gen_load_gpr(t1, rt);
2277 tcg_gen_and_tl(t1, t1, t2);
2278 tcg_temp_free(t2);
2279 tcg_gen_or_tl(t0, t0, t1);
2280 tcg_temp_free(t1);
2281 tcg_gen_ext32s_tl(t0, t0);
2282 gen_store_gpr(t0, rt);
2283 break;
2284 case OPC_LL:
2285 case R6_OPC_LL:
2286 op_ld_ll(t0, t0, ctx);
2287 gen_store_gpr(t0, rt);
2288 break;
2290 tcg_temp_free(t0);
2293 /* Store */
2294 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2295 int base, int16_t offset)
2297 TCGv t0 = tcg_temp_new();
2298 TCGv t1 = tcg_temp_new();
2300 gen_base_offset_addr(ctx, t0, base, offset);
2301 gen_load_gpr(t1, rt);
2302 switch (opc) {
2303 #if defined(TARGET_MIPS64)
2304 case OPC_SD:
2305 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
2306 ctx->default_tcg_memop_mask);
2307 break;
2308 case OPC_SDL:
2309 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
2310 break;
2311 case OPC_SDR:
2312 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2313 break;
2314 #endif
2315 case OPC_SW:
2316 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
2317 ctx->default_tcg_memop_mask);
2318 break;
2319 case OPC_SH:
2320 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
2321 ctx->default_tcg_memop_mask);
2322 break;
2323 case OPC_SB:
2324 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2325 break;
2326 case OPC_SWL:
2327 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2328 break;
2329 case OPC_SWR:
2330 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2331 break;
2333 tcg_temp_free(t0);
2334 tcg_temp_free(t1);
2338 /* Store conditional */
2339 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2340 int base, int16_t offset)
2342 TCGv t0, t1;
2344 #ifdef CONFIG_USER_ONLY
2345 t0 = tcg_temp_local_new();
2346 t1 = tcg_temp_local_new();
2347 #else
2348 t0 = tcg_temp_new();
2349 t1 = tcg_temp_new();
2350 #endif
2351 gen_base_offset_addr(ctx, t0, base, offset);
2352 gen_load_gpr(t1, rt);
2353 switch (opc) {
2354 #if defined(TARGET_MIPS64)
2355 case OPC_SCD:
2356 case R6_OPC_SCD:
2357 op_st_scd(t1, t0, rt, ctx);
2358 break;
2359 #endif
2360 case OPC_SC:
2361 case R6_OPC_SC:
2362 op_st_sc(t1, t0, rt, ctx);
2363 break;
2365 tcg_temp_free(t1);
2366 tcg_temp_free(t0);
2369 /* Load and store */
2370 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2371 int base, int16_t offset)
2373 TCGv t0 = tcg_temp_new();
2375 gen_base_offset_addr(ctx, t0, base, offset);
2376 /* Don't do NOP if destination is zero: we must perform the actual
2377 memory access. */
2378 switch (opc) {
2379 case OPC_LWC1:
2381 TCGv_i32 fp0 = tcg_temp_new_i32();
2382 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2383 ctx->default_tcg_memop_mask);
2384 gen_store_fpr32(ctx, fp0, ft);
2385 tcg_temp_free_i32(fp0);
2387 break;
2388 case OPC_SWC1:
2390 TCGv_i32 fp0 = tcg_temp_new_i32();
2391 gen_load_fpr32(ctx, fp0, ft);
2392 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2393 ctx->default_tcg_memop_mask);
2394 tcg_temp_free_i32(fp0);
2396 break;
2397 case OPC_LDC1:
2399 TCGv_i64 fp0 = tcg_temp_new_i64();
2400 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2401 ctx->default_tcg_memop_mask);
2402 gen_store_fpr64(ctx, fp0, ft);
2403 tcg_temp_free_i64(fp0);
2405 break;
2406 case OPC_SDC1:
2408 TCGv_i64 fp0 = tcg_temp_new_i64();
2409 gen_load_fpr64(ctx, fp0, ft);
2410 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2411 ctx->default_tcg_memop_mask);
2412 tcg_temp_free_i64(fp0);
2414 break;
2415 default:
2416 MIPS_INVAL("flt_ldst");
2417 generate_exception_end(ctx, EXCP_RI);
2418 goto out;
2420 out:
2421 tcg_temp_free(t0);
2424 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2425 int rs, int16_t imm)
2427 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2428 check_cp1_enabled(ctx);
2429 switch (op) {
2430 case OPC_LDC1:
2431 case OPC_SDC1:
2432 check_insn(ctx, ISA_MIPS2);
2433 /* Fallthrough */
2434 default:
2435 gen_flt_ldst(ctx, op, rt, rs, imm);
2437 } else {
2438 generate_exception_err(ctx, EXCP_CpU, 1);
2442 /* Arithmetic with immediate operand */
2443 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2444 int rt, int rs, int16_t imm)
2446 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2448 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2449 /* If no destination, treat it as a NOP.
2450 For addi, we must generate the overflow exception when needed. */
2451 return;
2453 switch (opc) {
2454 case OPC_ADDI:
2456 TCGv t0 = tcg_temp_local_new();
2457 TCGv t1 = tcg_temp_new();
2458 TCGv t2 = tcg_temp_new();
2459 TCGLabel *l1 = gen_new_label();
2461 gen_load_gpr(t1, rs);
2462 tcg_gen_addi_tl(t0, t1, uimm);
2463 tcg_gen_ext32s_tl(t0, t0);
2465 tcg_gen_xori_tl(t1, t1, ~uimm);
2466 tcg_gen_xori_tl(t2, t0, uimm);
2467 tcg_gen_and_tl(t1, t1, t2);
2468 tcg_temp_free(t2);
2469 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2470 tcg_temp_free(t1);
2471 /* operands of same sign, result different sign */
2472 generate_exception(ctx, EXCP_OVERFLOW);
2473 gen_set_label(l1);
2474 tcg_gen_ext32s_tl(t0, t0);
2475 gen_store_gpr(t0, rt);
2476 tcg_temp_free(t0);
2478 break;
2479 case OPC_ADDIU:
2480 if (rs != 0) {
2481 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2482 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2483 } else {
2484 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2486 break;
2487 #if defined(TARGET_MIPS64)
2488 case OPC_DADDI:
2490 TCGv t0 = tcg_temp_local_new();
2491 TCGv t1 = tcg_temp_new();
2492 TCGv t2 = tcg_temp_new();
2493 TCGLabel *l1 = gen_new_label();
2495 gen_load_gpr(t1, rs);
2496 tcg_gen_addi_tl(t0, t1, uimm);
2498 tcg_gen_xori_tl(t1, t1, ~uimm);
2499 tcg_gen_xori_tl(t2, t0, uimm);
2500 tcg_gen_and_tl(t1, t1, t2);
2501 tcg_temp_free(t2);
2502 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2503 tcg_temp_free(t1);
2504 /* operands of same sign, result different sign */
2505 generate_exception(ctx, EXCP_OVERFLOW);
2506 gen_set_label(l1);
2507 gen_store_gpr(t0, rt);
2508 tcg_temp_free(t0);
2510 break;
2511 case OPC_DADDIU:
2512 if (rs != 0) {
2513 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2514 } else {
2515 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2517 break;
2518 #endif
2522 /* Logic with immediate operand */
2523 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2524 int rt, int rs, int16_t imm)
2526 target_ulong uimm;
2528 if (rt == 0) {
2529 /* If no destination, treat it as a NOP. */
2530 return;
2532 uimm = (uint16_t)imm;
2533 switch (opc) {
2534 case OPC_ANDI:
2535 if (likely(rs != 0))
2536 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2537 else
2538 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2539 break;
2540 case OPC_ORI:
2541 if (rs != 0)
2542 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2543 else
2544 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2545 break;
2546 case OPC_XORI:
2547 if (likely(rs != 0))
2548 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2549 else
2550 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2551 break;
2552 case OPC_LUI:
2553 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2554 /* OPC_AUI */
2555 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2556 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2557 } else {
2558 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2560 break;
2562 default:
2563 break;
2567 /* Set on less than with immediate operand */
2568 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2569 int rt, int rs, int16_t imm)
2571 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2572 TCGv t0;
2574 if (rt == 0) {
2575 /* If no destination, treat it as a NOP. */
2576 return;
2578 t0 = tcg_temp_new();
2579 gen_load_gpr(t0, rs);
2580 switch (opc) {
2581 case OPC_SLTI:
2582 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2583 break;
2584 case OPC_SLTIU:
2585 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2586 break;
2588 tcg_temp_free(t0);
2591 /* Shifts with immediate operand */
2592 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2593 int rt, int rs, int16_t imm)
2595 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2596 TCGv t0;
2598 if (rt == 0) {
2599 /* If no destination, treat it as a NOP. */
2600 return;
2603 t0 = tcg_temp_new();
2604 gen_load_gpr(t0, rs);
2605 switch (opc) {
2606 case OPC_SLL:
2607 tcg_gen_shli_tl(t0, t0, uimm);
2608 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2609 break;
2610 case OPC_SRA:
2611 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2612 break;
2613 case OPC_SRL:
2614 if (uimm != 0) {
2615 tcg_gen_ext32u_tl(t0, t0);
2616 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2617 } else {
2618 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2620 break;
2621 case OPC_ROTR:
2622 if (uimm != 0) {
2623 TCGv_i32 t1 = tcg_temp_new_i32();
2625 tcg_gen_trunc_tl_i32(t1, t0);
2626 tcg_gen_rotri_i32(t1, t1, uimm);
2627 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2628 tcg_temp_free_i32(t1);
2629 } else {
2630 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2632 break;
2633 #if defined(TARGET_MIPS64)
2634 case OPC_DSLL:
2635 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2636 break;
2637 case OPC_DSRA:
2638 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2639 break;
2640 case OPC_DSRL:
2641 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2642 break;
2643 case OPC_DROTR:
2644 if (uimm != 0) {
2645 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2646 } else {
2647 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2649 break;
2650 case OPC_DSLL32:
2651 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2652 break;
2653 case OPC_DSRA32:
2654 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2655 break;
2656 case OPC_DSRL32:
2657 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2658 break;
2659 case OPC_DROTR32:
2660 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2661 break;
2662 #endif
2664 tcg_temp_free(t0);
2667 /* Arithmetic */
2668 static void gen_arith(DisasContext *ctx, uint32_t opc,
2669 int rd, int rs, int rt)
2671 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2672 && opc != OPC_DADD && opc != OPC_DSUB) {
2673 /* If no destination, treat it as a NOP.
2674 For add & sub, we must generate the overflow exception when needed. */
2675 return;
2678 switch (opc) {
2679 case OPC_ADD:
2681 TCGv t0 = tcg_temp_local_new();
2682 TCGv t1 = tcg_temp_new();
2683 TCGv t2 = tcg_temp_new();
2684 TCGLabel *l1 = gen_new_label();
2686 gen_load_gpr(t1, rs);
2687 gen_load_gpr(t2, rt);
2688 tcg_gen_add_tl(t0, t1, t2);
2689 tcg_gen_ext32s_tl(t0, t0);
2690 tcg_gen_xor_tl(t1, t1, t2);
2691 tcg_gen_xor_tl(t2, t0, t2);
2692 tcg_gen_andc_tl(t1, t2, t1);
2693 tcg_temp_free(t2);
2694 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2695 tcg_temp_free(t1);
2696 /* operands of same sign, result different sign */
2697 generate_exception(ctx, EXCP_OVERFLOW);
2698 gen_set_label(l1);
2699 gen_store_gpr(t0, rd);
2700 tcg_temp_free(t0);
2702 break;
2703 case OPC_ADDU:
2704 if (rs != 0 && rt != 0) {
2705 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2706 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2707 } else if (rs == 0 && rt != 0) {
2708 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2709 } else if (rs != 0 && rt == 0) {
2710 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2711 } else {
2712 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2714 break;
2715 case OPC_SUB:
2717 TCGv t0 = tcg_temp_local_new();
2718 TCGv t1 = tcg_temp_new();
2719 TCGv t2 = tcg_temp_new();
2720 TCGLabel *l1 = gen_new_label();
2722 gen_load_gpr(t1, rs);
2723 gen_load_gpr(t2, rt);
2724 tcg_gen_sub_tl(t0, t1, t2);
2725 tcg_gen_ext32s_tl(t0, t0);
2726 tcg_gen_xor_tl(t2, t1, t2);
2727 tcg_gen_xor_tl(t1, t0, t1);
2728 tcg_gen_and_tl(t1, t1, t2);
2729 tcg_temp_free(t2);
2730 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2731 tcg_temp_free(t1);
2732 /* operands of different sign, first operand and result different sign */
2733 generate_exception(ctx, EXCP_OVERFLOW);
2734 gen_set_label(l1);
2735 gen_store_gpr(t0, rd);
2736 tcg_temp_free(t0);
2738 break;
2739 case OPC_SUBU:
2740 if (rs != 0 && rt != 0) {
2741 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2742 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2743 } else if (rs == 0 && rt != 0) {
2744 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2745 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2746 } else if (rs != 0 && rt == 0) {
2747 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2748 } else {
2749 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2751 break;
2752 #if defined(TARGET_MIPS64)
2753 case OPC_DADD:
2755 TCGv t0 = tcg_temp_local_new();
2756 TCGv t1 = tcg_temp_new();
2757 TCGv t2 = tcg_temp_new();
2758 TCGLabel *l1 = gen_new_label();
2760 gen_load_gpr(t1, rs);
2761 gen_load_gpr(t2, rt);
2762 tcg_gen_add_tl(t0, t1, t2);
2763 tcg_gen_xor_tl(t1, t1, t2);
2764 tcg_gen_xor_tl(t2, t0, t2);
2765 tcg_gen_andc_tl(t1, t2, t1);
2766 tcg_temp_free(t2);
2767 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2768 tcg_temp_free(t1);
2769 /* operands of same sign, result different sign */
2770 generate_exception(ctx, EXCP_OVERFLOW);
2771 gen_set_label(l1);
2772 gen_store_gpr(t0, rd);
2773 tcg_temp_free(t0);
2775 break;
2776 case OPC_DADDU:
2777 if (rs != 0 && rt != 0) {
2778 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2779 } else if (rs == 0 && rt != 0) {
2780 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2781 } else if (rs != 0 && rt == 0) {
2782 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2783 } else {
2784 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2786 break;
2787 case OPC_DSUB:
2789 TCGv t0 = tcg_temp_local_new();
2790 TCGv t1 = tcg_temp_new();
2791 TCGv t2 = tcg_temp_new();
2792 TCGLabel *l1 = gen_new_label();
2794 gen_load_gpr(t1, rs);
2795 gen_load_gpr(t2, rt);
2796 tcg_gen_sub_tl(t0, t1, t2);
2797 tcg_gen_xor_tl(t2, t1, t2);
2798 tcg_gen_xor_tl(t1, t0, t1);
2799 tcg_gen_and_tl(t1, t1, t2);
2800 tcg_temp_free(t2);
2801 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2802 tcg_temp_free(t1);
2803 /* operands of different sign, first operand and result different sign */
2804 generate_exception(ctx, EXCP_OVERFLOW);
2805 gen_set_label(l1);
2806 gen_store_gpr(t0, rd);
2807 tcg_temp_free(t0);
2809 break;
2810 case OPC_DSUBU:
2811 if (rs != 0 && rt != 0) {
2812 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2813 } else if (rs == 0 && rt != 0) {
2814 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2815 } else if (rs != 0 && rt == 0) {
2816 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2817 } else {
2818 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2820 break;
2821 #endif
2822 case OPC_MUL:
2823 if (likely(rs != 0 && rt != 0)) {
2824 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2825 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2826 } else {
2827 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2829 break;
2833 /* Conditional move */
2834 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2835 int rd, int rs, int rt)
2837 TCGv t0, t1, t2;
2839 if (rd == 0) {
2840 /* If no destination, treat it as a NOP. */
2841 return;
2844 t0 = tcg_temp_new();
2845 gen_load_gpr(t0, rt);
2846 t1 = tcg_const_tl(0);
2847 t2 = tcg_temp_new();
2848 gen_load_gpr(t2, rs);
2849 switch (opc) {
2850 case OPC_MOVN:
2851 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2852 break;
2853 case OPC_MOVZ:
2854 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2855 break;
2856 case OPC_SELNEZ:
2857 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2858 break;
2859 case OPC_SELEQZ:
2860 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2861 break;
2863 tcg_temp_free(t2);
2864 tcg_temp_free(t1);
2865 tcg_temp_free(t0);
2868 /* Logic */
2869 static void gen_logic(DisasContext *ctx, uint32_t opc,
2870 int rd, int rs, int rt)
2872 if (rd == 0) {
2873 /* If no destination, treat it as a NOP. */
2874 return;
2877 switch (opc) {
2878 case OPC_AND:
2879 if (likely(rs != 0 && rt != 0)) {
2880 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2881 } else {
2882 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2884 break;
2885 case OPC_NOR:
2886 if (rs != 0 && rt != 0) {
2887 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2888 } else if (rs == 0 && rt != 0) {
2889 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2890 } else if (rs != 0 && rt == 0) {
2891 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2892 } else {
2893 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2895 break;
2896 case OPC_OR:
2897 if (likely(rs != 0 && rt != 0)) {
2898 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2899 } else if (rs == 0 && rt != 0) {
2900 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2901 } else if (rs != 0 && rt == 0) {
2902 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2903 } else {
2904 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2906 break;
2907 case OPC_XOR:
2908 if (likely(rs != 0 && rt != 0)) {
2909 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2910 } else if (rs == 0 && rt != 0) {
2911 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2912 } else if (rs != 0 && rt == 0) {
2913 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2914 } else {
2915 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2917 break;
2921 /* Set on lower than */
2922 static void gen_slt(DisasContext *ctx, uint32_t opc,
2923 int rd, int rs, int rt)
2925 TCGv t0, t1;
2927 if (rd == 0) {
2928 /* If no destination, treat it as a NOP. */
2929 return;
2932 t0 = tcg_temp_new();
2933 t1 = tcg_temp_new();
2934 gen_load_gpr(t0, rs);
2935 gen_load_gpr(t1, rt);
2936 switch (opc) {
2937 case OPC_SLT:
2938 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2939 break;
2940 case OPC_SLTU:
2941 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2942 break;
2944 tcg_temp_free(t0);
2945 tcg_temp_free(t1);
2948 /* Shifts */
2949 static void gen_shift(DisasContext *ctx, uint32_t opc,
2950 int rd, int rs, int rt)
2952 TCGv t0, t1;
2954 if (rd == 0) {
2955 /* If no destination, treat it as a NOP.
2956 For add & sub, we must generate the overflow exception when needed. */
2957 return;
2960 t0 = tcg_temp_new();
2961 t1 = tcg_temp_new();
2962 gen_load_gpr(t0, rs);
2963 gen_load_gpr(t1, rt);
2964 switch (opc) {
2965 case OPC_SLLV:
2966 tcg_gen_andi_tl(t0, t0, 0x1f);
2967 tcg_gen_shl_tl(t0, t1, t0);
2968 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2969 break;
2970 case OPC_SRAV:
2971 tcg_gen_andi_tl(t0, t0, 0x1f);
2972 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2973 break;
2974 case OPC_SRLV:
2975 tcg_gen_ext32u_tl(t1, t1);
2976 tcg_gen_andi_tl(t0, t0, 0x1f);
2977 tcg_gen_shr_tl(t0, t1, t0);
2978 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2979 break;
2980 case OPC_ROTRV:
2982 TCGv_i32 t2 = tcg_temp_new_i32();
2983 TCGv_i32 t3 = tcg_temp_new_i32();
2985 tcg_gen_trunc_tl_i32(t2, t0);
2986 tcg_gen_trunc_tl_i32(t3, t1);
2987 tcg_gen_andi_i32(t2, t2, 0x1f);
2988 tcg_gen_rotr_i32(t2, t3, t2);
2989 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2990 tcg_temp_free_i32(t2);
2991 tcg_temp_free_i32(t3);
2993 break;
2994 #if defined(TARGET_MIPS64)
2995 case OPC_DSLLV:
2996 tcg_gen_andi_tl(t0, t0, 0x3f);
2997 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2998 break;
2999 case OPC_DSRAV:
3000 tcg_gen_andi_tl(t0, t0, 0x3f);
3001 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3002 break;
3003 case OPC_DSRLV:
3004 tcg_gen_andi_tl(t0, t0, 0x3f);
3005 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3006 break;
3007 case OPC_DROTRV:
3008 tcg_gen_andi_tl(t0, t0, 0x3f);
3009 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3010 break;
3011 #endif
3013 tcg_temp_free(t0);
3014 tcg_temp_free(t1);
3017 /* Arithmetic on HI/LO registers */
3018 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3020 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3021 /* Treat as NOP. */
3022 return;
3025 if (acc != 0) {
3026 check_dsp(ctx);
3029 switch (opc) {
3030 case OPC_MFHI:
3031 #if defined(TARGET_MIPS64)
3032 if (acc != 0) {
3033 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3034 } else
3035 #endif
3037 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3039 break;
3040 case OPC_MFLO:
3041 #if defined(TARGET_MIPS64)
3042 if (acc != 0) {
3043 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3044 } else
3045 #endif
3047 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3049 break;
3050 case OPC_MTHI:
3051 if (reg != 0) {
3052 #if defined(TARGET_MIPS64)
3053 if (acc != 0) {
3054 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3055 } else
3056 #endif
3058 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3060 } else {
3061 tcg_gen_movi_tl(cpu_HI[acc], 0);
3063 break;
3064 case OPC_MTLO:
3065 if (reg != 0) {
3066 #if defined(TARGET_MIPS64)
3067 if (acc != 0) {
3068 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3069 } else
3070 #endif
3072 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3074 } else {
3075 tcg_gen_movi_tl(cpu_LO[acc], 0);
3077 break;
3081 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3082 TCGMemOp memop)
3084 TCGv t0 = tcg_const_tl(addr);
3085 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3086 gen_store_gpr(t0, reg);
3087 tcg_temp_free(t0);
3090 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3091 int rs)
3093 target_long offset;
3094 target_long addr;
3096 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3097 case OPC_ADDIUPC:
3098 if (rs != 0) {
3099 offset = sextract32(ctx->opcode << 2, 0, 21);
3100 addr = addr_add(ctx, pc, offset);
3101 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3103 break;
3104 case R6_OPC_LWPC:
3105 offset = sextract32(ctx->opcode << 2, 0, 21);
3106 addr = addr_add(ctx, pc, offset);
3107 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3108 break;
3109 #if defined(TARGET_MIPS64)
3110 case OPC_LWUPC:
3111 check_mips_64(ctx);
3112 offset = sextract32(ctx->opcode << 2, 0, 21);
3113 addr = addr_add(ctx, pc, offset);
3114 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3115 break;
3116 #endif
3117 default:
3118 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3119 case OPC_AUIPC:
3120 if (rs != 0) {
3121 offset = sextract32(ctx->opcode, 0, 16) << 16;
3122 addr = addr_add(ctx, pc, offset);
3123 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3125 break;
3126 case OPC_ALUIPC:
3127 if (rs != 0) {
3128 offset = sextract32(ctx->opcode, 0, 16) << 16;
3129 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3130 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3132 break;
3133 #if defined(TARGET_MIPS64)
3134 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3135 case R6_OPC_LDPC + (1 << 16):
3136 case R6_OPC_LDPC + (2 << 16):
3137 case R6_OPC_LDPC + (3 << 16):
3138 check_mips_64(ctx);
3139 offset = sextract32(ctx->opcode << 3, 0, 21);
3140 addr = addr_add(ctx, (pc & ~0x7), offset);
3141 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3142 break;
3143 #endif
3144 default:
3145 MIPS_INVAL("OPC_PCREL");
3146 generate_exception_end(ctx, EXCP_RI);
3147 break;
3149 break;
3153 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3155 TCGv t0, t1;
3157 if (rd == 0) {
3158 /* Treat as NOP. */
3159 return;
3162 t0 = tcg_temp_new();
3163 t1 = tcg_temp_new();
3165 gen_load_gpr(t0, rs);
3166 gen_load_gpr(t1, rt);
3168 switch (opc) {
3169 case R6_OPC_DIV:
3171 TCGv t2 = tcg_temp_new();
3172 TCGv t3 = tcg_temp_new();
3173 tcg_gen_ext32s_tl(t0, t0);
3174 tcg_gen_ext32s_tl(t1, t1);
3175 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3176 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3177 tcg_gen_and_tl(t2, t2, t3);
3178 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3179 tcg_gen_or_tl(t2, t2, t3);
3180 tcg_gen_movi_tl(t3, 0);
3181 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3182 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3183 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3184 tcg_temp_free(t3);
3185 tcg_temp_free(t2);
3187 break;
3188 case R6_OPC_MOD:
3190 TCGv t2 = tcg_temp_new();
3191 TCGv t3 = tcg_temp_new();
3192 tcg_gen_ext32s_tl(t0, t0);
3193 tcg_gen_ext32s_tl(t1, t1);
3194 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3195 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3196 tcg_gen_and_tl(t2, t2, t3);
3197 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3198 tcg_gen_or_tl(t2, t2, t3);
3199 tcg_gen_movi_tl(t3, 0);
3200 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3201 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3202 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3203 tcg_temp_free(t3);
3204 tcg_temp_free(t2);
3206 break;
3207 case R6_OPC_DIVU:
3209 TCGv t2 = tcg_const_tl(0);
3210 TCGv t3 = tcg_const_tl(1);
3211 tcg_gen_ext32u_tl(t0, t0);
3212 tcg_gen_ext32u_tl(t1, t1);
3213 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3214 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3215 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3216 tcg_temp_free(t3);
3217 tcg_temp_free(t2);
3219 break;
3220 case R6_OPC_MODU:
3222 TCGv t2 = tcg_const_tl(0);
3223 TCGv t3 = tcg_const_tl(1);
3224 tcg_gen_ext32u_tl(t0, t0);
3225 tcg_gen_ext32u_tl(t1, t1);
3226 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3227 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3228 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3229 tcg_temp_free(t3);
3230 tcg_temp_free(t2);
3232 break;
3233 case R6_OPC_MUL:
3235 TCGv_i32 t2 = tcg_temp_new_i32();
3236 TCGv_i32 t3 = tcg_temp_new_i32();
3237 tcg_gen_trunc_tl_i32(t2, t0);
3238 tcg_gen_trunc_tl_i32(t3, t1);
3239 tcg_gen_mul_i32(t2, t2, t3);
3240 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3241 tcg_temp_free_i32(t2);
3242 tcg_temp_free_i32(t3);
3244 break;
3245 case R6_OPC_MUH:
3247 TCGv_i32 t2 = tcg_temp_new_i32();
3248 TCGv_i32 t3 = tcg_temp_new_i32();
3249 tcg_gen_trunc_tl_i32(t2, t0);
3250 tcg_gen_trunc_tl_i32(t3, t1);
3251 tcg_gen_muls2_i32(t2, t3, t2, t3);
3252 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3253 tcg_temp_free_i32(t2);
3254 tcg_temp_free_i32(t3);
3256 break;
3257 case R6_OPC_MULU:
3259 TCGv_i32 t2 = tcg_temp_new_i32();
3260 TCGv_i32 t3 = tcg_temp_new_i32();
3261 tcg_gen_trunc_tl_i32(t2, t0);
3262 tcg_gen_trunc_tl_i32(t3, t1);
3263 tcg_gen_mul_i32(t2, t2, t3);
3264 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3265 tcg_temp_free_i32(t2);
3266 tcg_temp_free_i32(t3);
3268 break;
3269 case R6_OPC_MUHU:
3271 TCGv_i32 t2 = tcg_temp_new_i32();
3272 TCGv_i32 t3 = tcg_temp_new_i32();
3273 tcg_gen_trunc_tl_i32(t2, t0);
3274 tcg_gen_trunc_tl_i32(t3, t1);
3275 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3276 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3277 tcg_temp_free_i32(t2);
3278 tcg_temp_free_i32(t3);
3280 break;
3281 #if defined(TARGET_MIPS64)
3282 case R6_OPC_DDIV:
3284 TCGv t2 = tcg_temp_new();
3285 TCGv t3 = tcg_temp_new();
3286 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3287 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3288 tcg_gen_and_tl(t2, t2, t3);
3289 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3290 tcg_gen_or_tl(t2, t2, t3);
3291 tcg_gen_movi_tl(t3, 0);
3292 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3293 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3294 tcg_temp_free(t3);
3295 tcg_temp_free(t2);
3297 break;
3298 case R6_OPC_DMOD:
3300 TCGv t2 = tcg_temp_new();
3301 TCGv t3 = tcg_temp_new();
3302 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3303 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3304 tcg_gen_and_tl(t2, t2, t3);
3305 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3306 tcg_gen_or_tl(t2, t2, t3);
3307 tcg_gen_movi_tl(t3, 0);
3308 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3309 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3310 tcg_temp_free(t3);
3311 tcg_temp_free(t2);
3313 break;
3314 case R6_OPC_DDIVU:
3316 TCGv t2 = tcg_const_tl(0);
3317 TCGv t3 = tcg_const_tl(1);
3318 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3319 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3320 tcg_temp_free(t3);
3321 tcg_temp_free(t2);
3323 break;
3324 case R6_OPC_DMODU:
3326 TCGv t2 = tcg_const_tl(0);
3327 TCGv t3 = tcg_const_tl(1);
3328 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3329 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3330 tcg_temp_free(t3);
3331 tcg_temp_free(t2);
3333 break;
3334 case R6_OPC_DMUL:
3335 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3336 break;
3337 case R6_OPC_DMUH:
3339 TCGv t2 = tcg_temp_new();
3340 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3341 tcg_temp_free(t2);
3343 break;
3344 case R6_OPC_DMULU:
3345 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3346 break;
3347 case R6_OPC_DMUHU:
3349 TCGv t2 = tcg_temp_new();
3350 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3351 tcg_temp_free(t2);
3353 break;
3354 #endif
3355 default:
3356 MIPS_INVAL("r6 mul/div");
3357 generate_exception_end(ctx, EXCP_RI);
3358 goto out;
3360 out:
3361 tcg_temp_free(t0);
3362 tcg_temp_free(t1);
3365 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3366 int acc, int rs, int rt)
3368 TCGv t0, t1;
3370 t0 = tcg_temp_new();
3371 t1 = tcg_temp_new();
3373 gen_load_gpr(t0, rs);
3374 gen_load_gpr(t1, rt);
3376 if (acc != 0) {
3377 check_dsp(ctx);
3380 switch (opc) {
3381 case OPC_DIV:
3383 TCGv t2 = tcg_temp_new();
3384 TCGv t3 = tcg_temp_new();
3385 tcg_gen_ext32s_tl(t0, t0);
3386 tcg_gen_ext32s_tl(t1, t1);
3387 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3388 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3389 tcg_gen_and_tl(t2, t2, t3);
3390 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3391 tcg_gen_or_tl(t2, t2, t3);
3392 tcg_gen_movi_tl(t3, 0);
3393 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3394 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3395 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3396 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3397 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3398 tcg_temp_free(t3);
3399 tcg_temp_free(t2);
3401 break;
3402 case OPC_DIVU:
3404 TCGv t2 = tcg_const_tl(0);
3405 TCGv t3 = tcg_const_tl(1);
3406 tcg_gen_ext32u_tl(t0, t0);
3407 tcg_gen_ext32u_tl(t1, t1);
3408 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3409 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3410 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3411 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3412 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3413 tcg_temp_free(t3);
3414 tcg_temp_free(t2);
3416 break;
3417 case OPC_MULT:
3419 TCGv_i32 t2 = tcg_temp_new_i32();
3420 TCGv_i32 t3 = tcg_temp_new_i32();
3421 tcg_gen_trunc_tl_i32(t2, t0);
3422 tcg_gen_trunc_tl_i32(t3, t1);
3423 tcg_gen_muls2_i32(t2, t3, t2, t3);
3424 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3425 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3426 tcg_temp_free_i32(t2);
3427 tcg_temp_free_i32(t3);
3429 break;
3430 case OPC_MULTU:
3432 TCGv_i32 t2 = tcg_temp_new_i32();
3433 TCGv_i32 t3 = tcg_temp_new_i32();
3434 tcg_gen_trunc_tl_i32(t2, t0);
3435 tcg_gen_trunc_tl_i32(t3, t1);
3436 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3437 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3438 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3439 tcg_temp_free_i32(t2);
3440 tcg_temp_free_i32(t3);
3442 break;
3443 #if defined(TARGET_MIPS64)
3444 case OPC_DDIV:
3446 TCGv t2 = tcg_temp_new();
3447 TCGv t3 = tcg_temp_new();
3448 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3449 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3450 tcg_gen_and_tl(t2, t2, t3);
3451 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3452 tcg_gen_or_tl(t2, t2, t3);
3453 tcg_gen_movi_tl(t3, 0);
3454 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3455 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3456 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3457 tcg_temp_free(t3);
3458 tcg_temp_free(t2);
3460 break;
3461 case OPC_DDIVU:
3463 TCGv t2 = tcg_const_tl(0);
3464 TCGv t3 = tcg_const_tl(1);
3465 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3466 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3467 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3468 tcg_temp_free(t3);
3469 tcg_temp_free(t2);
3471 break;
3472 case OPC_DMULT:
3473 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3474 break;
3475 case OPC_DMULTU:
3476 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3477 break;
3478 #endif
3479 case OPC_MADD:
3481 TCGv_i64 t2 = tcg_temp_new_i64();
3482 TCGv_i64 t3 = tcg_temp_new_i64();
3484 tcg_gen_ext_tl_i64(t2, t0);
3485 tcg_gen_ext_tl_i64(t3, t1);
3486 tcg_gen_mul_i64(t2, t2, t3);
3487 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3488 tcg_gen_add_i64(t2, t2, t3);
3489 tcg_temp_free_i64(t3);
3490 gen_move_low32(cpu_LO[acc], t2);
3491 gen_move_high32(cpu_HI[acc], t2);
3492 tcg_temp_free_i64(t2);
3494 break;
3495 case OPC_MADDU:
3497 TCGv_i64 t2 = tcg_temp_new_i64();
3498 TCGv_i64 t3 = tcg_temp_new_i64();
3500 tcg_gen_ext32u_tl(t0, t0);
3501 tcg_gen_ext32u_tl(t1, t1);
3502 tcg_gen_extu_tl_i64(t2, t0);
3503 tcg_gen_extu_tl_i64(t3, t1);
3504 tcg_gen_mul_i64(t2, t2, t3);
3505 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3506 tcg_gen_add_i64(t2, t2, t3);
3507 tcg_temp_free_i64(t3);
3508 gen_move_low32(cpu_LO[acc], t2);
3509 gen_move_high32(cpu_HI[acc], t2);
3510 tcg_temp_free_i64(t2);
3512 break;
3513 case OPC_MSUB:
3515 TCGv_i64 t2 = tcg_temp_new_i64();
3516 TCGv_i64 t3 = tcg_temp_new_i64();
3518 tcg_gen_ext_tl_i64(t2, t0);
3519 tcg_gen_ext_tl_i64(t3, t1);
3520 tcg_gen_mul_i64(t2, t2, t3);
3521 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3522 tcg_gen_sub_i64(t2, t3, t2);
3523 tcg_temp_free_i64(t3);
3524 gen_move_low32(cpu_LO[acc], t2);
3525 gen_move_high32(cpu_HI[acc], t2);
3526 tcg_temp_free_i64(t2);
3528 break;
3529 case OPC_MSUBU:
3531 TCGv_i64 t2 = tcg_temp_new_i64();
3532 TCGv_i64 t3 = tcg_temp_new_i64();
3534 tcg_gen_ext32u_tl(t0, t0);
3535 tcg_gen_ext32u_tl(t1, t1);
3536 tcg_gen_extu_tl_i64(t2, t0);
3537 tcg_gen_extu_tl_i64(t3, t1);
3538 tcg_gen_mul_i64(t2, t2, t3);
3539 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3540 tcg_gen_sub_i64(t2, t3, t2);
3541 tcg_temp_free_i64(t3);
3542 gen_move_low32(cpu_LO[acc], t2);
3543 gen_move_high32(cpu_HI[acc], t2);
3544 tcg_temp_free_i64(t2);
3546 break;
3547 default:
3548 MIPS_INVAL("mul/div");
3549 generate_exception_end(ctx, EXCP_RI);
3550 goto out;
3552 out:
3553 tcg_temp_free(t0);
3554 tcg_temp_free(t1);
3557 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3558 int rd, int rs, int rt)
3560 TCGv t0 = tcg_temp_new();
3561 TCGv t1 = tcg_temp_new();
3563 gen_load_gpr(t0, rs);
3564 gen_load_gpr(t1, rt);
3566 switch (opc) {
3567 case OPC_VR54XX_MULS:
3568 gen_helper_muls(t0, cpu_env, t0, t1);
3569 break;
3570 case OPC_VR54XX_MULSU:
3571 gen_helper_mulsu(t0, cpu_env, t0, t1);
3572 break;
3573 case OPC_VR54XX_MACC:
3574 gen_helper_macc(t0, cpu_env, t0, t1);
3575 break;
3576 case OPC_VR54XX_MACCU:
3577 gen_helper_maccu(t0, cpu_env, t0, t1);
3578 break;
3579 case OPC_VR54XX_MSAC:
3580 gen_helper_msac(t0, cpu_env, t0, t1);
3581 break;
3582 case OPC_VR54XX_MSACU:
3583 gen_helper_msacu(t0, cpu_env, t0, t1);
3584 break;
3585 case OPC_VR54XX_MULHI:
3586 gen_helper_mulhi(t0, cpu_env, t0, t1);
3587 break;
3588 case OPC_VR54XX_MULHIU:
3589 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3590 break;
3591 case OPC_VR54XX_MULSHI:
3592 gen_helper_mulshi(t0, cpu_env, t0, t1);
3593 break;
3594 case OPC_VR54XX_MULSHIU:
3595 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3596 break;
3597 case OPC_VR54XX_MACCHI:
3598 gen_helper_macchi(t0, cpu_env, t0, t1);
3599 break;
3600 case OPC_VR54XX_MACCHIU:
3601 gen_helper_macchiu(t0, cpu_env, t0, t1);
3602 break;
3603 case OPC_VR54XX_MSACHI:
3604 gen_helper_msachi(t0, cpu_env, t0, t1);
3605 break;
3606 case OPC_VR54XX_MSACHIU:
3607 gen_helper_msachiu(t0, cpu_env, t0, t1);
3608 break;
3609 default:
3610 MIPS_INVAL("mul vr54xx");
3611 generate_exception_end(ctx, EXCP_RI);
3612 goto out;
3614 gen_store_gpr(t0, rd);
3616 out:
3617 tcg_temp_free(t0);
3618 tcg_temp_free(t1);
3621 static void gen_cl (DisasContext *ctx, uint32_t opc,
3622 int rd, int rs)
3624 TCGv t0;
3626 if (rd == 0) {
3627 /* Treat as NOP. */
3628 return;
3630 t0 = cpu_gpr[rd];
3631 gen_load_gpr(t0, rs);
3633 switch (opc) {
3634 case OPC_CLO:
3635 case R6_OPC_CLO:
3636 #if defined(TARGET_MIPS64)
3637 case OPC_DCLO:
3638 case R6_OPC_DCLO:
3639 #endif
3640 tcg_gen_not_tl(t0, t0);
3641 break;
3644 switch (opc) {
3645 case OPC_CLO:
3646 case R6_OPC_CLO:
3647 case OPC_CLZ:
3648 case R6_OPC_CLZ:
3649 tcg_gen_ext32u_tl(t0, t0);
3650 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3651 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
3652 break;
3653 #if defined(TARGET_MIPS64)
3654 case OPC_DCLO:
3655 case R6_OPC_DCLO:
3656 case OPC_DCLZ:
3657 case R6_OPC_DCLZ:
3658 tcg_gen_clzi_i64(t0, t0, 64);
3659 break;
3660 #endif
3664 /* Godson integer instructions */
3665 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3666 int rd, int rs, int rt)
3668 TCGv t0, t1;
3670 if (rd == 0) {
3671 /* Treat as NOP. */
3672 return;
3675 switch (opc) {
3676 case OPC_MULT_G_2E:
3677 case OPC_MULT_G_2F:
3678 case OPC_MULTU_G_2E:
3679 case OPC_MULTU_G_2F:
3680 #if defined(TARGET_MIPS64)
3681 case OPC_DMULT_G_2E:
3682 case OPC_DMULT_G_2F:
3683 case OPC_DMULTU_G_2E:
3684 case OPC_DMULTU_G_2F:
3685 #endif
3686 t0 = tcg_temp_new();
3687 t1 = tcg_temp_new();
3688 break;
3689 default:
3690 t0 = tcg_temp_local_new();
3691 t1 = tcg_temp_local_new();
3692 break;
3695 gen_load_gpr(t0, rs);
3696 gen_load_gpr(t1, rt);
3698 switch (opc) {
3699 case OPC_MULT_G_2E:
3700 case OPC_MULT_G_2F:
3701 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3702 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3703 break;
3704 case OPC_MULTU_G_2E:
3705 case OPC_MULTU_G_2F:
3706 tcg_gen_ext32u_tl(t0, t0);
3707 tcg_gen_ext32u_tl(t1, t1);
3708 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3709 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3710 break;
3711 case OPC_DIV_G_2E:
3712 case OPC_DIV_G_2F:
3714 TCGLabel *l1 = gen_new_label();
3715 TCGLabel *l2 = gen_new_label();
3716 TCGLabel *l3 = gen_new_label();
3717 tcg_gen_ext32s_tl(t0, t0);
3718 tcg_gen_ext32s_tl(t1, t1);
3719 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3720 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3721 tcg_gen_br(l3);
3722 gen_set_label(l1);
3723 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3724 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3725 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3726 tcg_gen_br(l3);
3727 gen_set_label(l2);
3728 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3729 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3730 gen_set_label(l3);
3732 break;
3733 case OPC_DIVU_G_2E:
3734 case OPC_DIVU_G_2F:
3736 TCGLabel *l1 = gen_new_label();
3737 TCGLabel *l2 = gen_new_label();
3738 tcg_gen_ext32u_tl(t0, t0);
3739 tcg_gen_ext32u_tl(t1, t1);
3740 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3741 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3742 tcg_gen_br(l2);
3743 gen_set_label(l1);
3744 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3745 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3746 gen_set_label(l2);
3748 break;
3749 case OPC_MOD_G_2E:
3750 case OPC_MOD_G_2F:
3752 TCGLabel *l1 = gen_new_label();
3753 TCGLabel *l2 = gen_new_label();
3754 TCGLabel *l3 = gen_new_label();
3755 tcg_gen_ext32u_tl(t0, t0);
3756 tcg_gen_ext32u_tl(t1, t1);
3757 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3758 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3759 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3760 gen_set_label(l1);
3761 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3762 tcg_gen_br(l3);
3763 gen_set_label(l2);
3764 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3765 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3766 gen_set_label(l3);
3768 break;
3769 case OPC_MODU_G_2E:
3770 case OPC_MODU_G_2F:
3772 TCGLabel *l1 = gen_new_label();
3773 TCGLabel *l2 = gen_new_label();
3774 tcg_gen_ext32u_tl(t0, t0);
3775 tcg_gen_ext32u_tl(t1, t1);
3776 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3777 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3778 tcg_gen_br(l2);
3779 gen_set_label(l1);
3780 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3781 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3782 gen_set_label(l2);
3784 break;
3785 #if defined(TARGET_MIPS64)
3786 case OPC_DMULT_G_2E:
3787 case OPC_DMULT_G_2F:
3788 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3789 break;
3790 case OPC_DMULTU_G_2E:
3791 case OPC_DMULTU_G_2F:
3792 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3793 break;
3794 case OPC_DDIV_G_2E:
3795 case OPC_DDIV_G_2F:
3797 TCGLabel *l1 = gen_new_label();
3798 TCGLabel *l2 = gen_new_label();
3799 TCGLabel *l3 = gen_new_label();
3800 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3801 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3802 tcg_gen_br(l3);
3803 gen_set_label(l1);
3804 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3805 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3806 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3807 tcg_gen_br(l3);
3808 gen_set_label(l2);
3809 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3810 gen_set_label(l3);
3812 break;
3813 case OPC_DDIVU_G_2E:
3814 case OPC_DDIVU_G_2F:
3816 TCGLabel *l1 = gen_new_label();
3817 TCGLabel *l2 = gen_new_label();
3818 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3819 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3820 tcg_gen_br(l2);
3821 gen_set_label(l1);
3822 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3823 gen_set_label(l2);
3825 break;
3826 case OPC_DMOD_G_2E:
3827 case OPC_DMOD_G_2F:
3829 TCGLabel *l1 = gen_new_label();
3830 TCGLabel *l2 = gen_new_label();
3831 TCGLabel *l3 = gen_new_label();
3832 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3833 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3834 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3835 gen_set_label(l1);
3836 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3837 tcg_gen_br(l3);
3838 gen_set_label(l2);
3839 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3840 gen_set_label(l3);
3842 break;
3843 case OPC_DMODU_G_2E:
3844 case OPC_DMODU_G_2F:
3846 TCGLabel *l1 = gen_new_label();
3847 TCGLabel *l2 = gen_new_label();
3848 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3849 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3850 tcg_gen_br(l2);
3851 gen_set_label(l1);
3852 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3853 gen_set_label(l2);
3855 break;
3856 #endif
3859 tcg_temp_free(t0);
3860 tcg_temp_free(t1);
3863 /* Loongson multimedia instructions */
3864 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3866 uint32_t opc, shift_max;
3867 TCGv_i64 t0, t1;
3869 opc = MASK_LMI(ctx->opcode);
3870 switch (opc) {
3871 case OPC_ADD_CP2:
3872 case OPC_SUB_CP2:
3873 case OPC_DADD_CP2:
3874 case OPC_DSUB_CP2:
3875 t0 = tcg_temp_local_new_i64();
3876 t1 = tcg_temp_local_new_i64();
3877 break;
3878 default:
3879 t0 = tcg_temp_new_i64();
3880 t1 = tcg_temp_new_i64();
3881 break;
3884 check_cp1_enabled(ctx);
3885 gen_load_fpr64(ctx, t0, rs);
3886 gen_load_fpr64(ctx, t1, rt);
3888 #define LMI_HELPER(UP, LO) \
3889 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
3890 #define LMI_HELPER_1(UP, LO) \
3891 case OPC_##UP: gen_helper_##LO(t0, t0); break
3892 #define LMI_DIRECT(UP, LO, OP) \
3893 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
3895 switch (opc) {
3896 LMI_HELPER(PADDSH, paddsh);
3897 LMI_HELPER(PADDUSH, paddush);
3898 LMI_HELPER(PADDH, paddh);
3899 LMI_HELPER(PADDW, paddw);
3900 LMI_HELPER(PADDSB, paddsb);
3901 LMI_HELPER(PADDUSB, paddusb);
3902 LMI_HELPER(PADDB, paddb);
3904 LMI_HELPER(PSUBSH, psubsh);
3905 LMI_HELPER(PSUBUSH, psubush);
3906 LMI_HELPER(PSUBH, psubh);
3907 LMI_HELPER(PSUBW, psubw);
3908 LMI_HELPER(PSUBSB, psubsb);
3909 LMI_HELPER(PSUBUSB, psubusb);
3910 LMI_HELPER(PSUBB, psubb);
3912 LMI_HELPER(PSHUFH, pshufh);
3913 LMI_HELPER(PACKSSWH, packsswh);
3914 LMI_HELPER(PACKSSHB, packsshb);
3915 LMI_HELPER(PACKUSHB, packushb);
3917 LMI_HELPER(PUNPCKLHW, punpcklhw);
3918 LMI_HELPER(PUNPCKHHW, punpckhhw);
3919 LMI_HELPER(PUNPCKLBH, punpcklbh);
3920 LMI_HELPER(PUNPCKHBH, punpckhbh);
3921 LMI_HELPER(PUNPCKLWD, punpcklwd);
3922 LMI_HELPER(PUNPCKHWD, punpckhwd);
3924 LMI_HELPER(PAVGH, pavgh);
3925 LMI_HELPER(PAVGB, pavgb);
3926 LMI_HELPER(PMAXSH, pmaxsh);
3927 LMI_HELPER(PMINSH, pminsh);
3928 LMI_HELPER(PMAXUB, pmaxub);
3929 LMI_HELPER(PMINUB, pminub);
3931 LMI_HELPER(PCMPEQW, pcmpeqw);
3932 LMI_HELPER(PCMPGTW, pcmpgtw);
3933 LMI_HELPER(PCMPEQH, pcmpeqh);
3934 LMI_HELPER(PCMPGTH, pcmpgth);
3935 LMI_HELPER(PCMPEQB, pcmpeqb);
3936 LMI_HELPER(PCMPGTB, pcmpgtb);
3938 LMI_HELPER(PSLLW, psllw);
3939 LMI_HELPER(PSLLH, psllh);
3940 LMI_HELPER(PSRLW, psrlw);
3941 LMI_HELPER(PSRLH, psrlh);
3942 LMI_HELPER(PSRAW, psraw);
3943 LMI_HELPER(PSRAH, psrah);
3945 LMI_HELPER(PMULLH, pmullh);
3946 LMI_HELPER(PMULHH, pmulhh);
3947 LMI_HELPER(PMULHUH, pmulhuh);
3948 LMI_HELPER(PMADDHW, pmaddhw);
3950 LMI_HELPER(PASUBUB, pasubub);
3951 LMI_HELPER_1(BIADD, biadd);
3952 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3954 LMI_DIRECT(PADDD, paddd, add);
3955 LMI_DIRECT(PSUBD, psubd, sub);
3956 LMI_DIRECT(XOR_CP2, xor, xor);
3957 LMI_DIRECT(NOR_CP2, nor, nor);
3958 LMI_DIRECT(AND_CP2, and, and);
3959 LMI_DIRECT(OR_CP2, or, or);
3961 case OPC_PANDN:
3962 tcg_gen_andc_i64(t0, t1, t0);
3963 break;
3965 case OPC_PINSRH_0:
3966 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3967 break;
3968 case OPC_PINSRH_1:
3969 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3970 break;
3971 case OPC_PINSRH_2:
3972 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3973 break;
3974 case OPC_PINSRH_3:
3975 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3976 break;
3978 case OPC_PEXTRH:
3979 tcg_gen_andi_i64(t1, t1, 3);
3980 tcg_gen_shli_i64(t1, t1, 4);
3981 tcg_gen_shr_i64(t0, t0, t1);
3982 tcg_gen_ext16u_i64(t0, t0);
3983 break;
3985 case OPC_ADDU_CP2:
3986 tcg_gen_add_i64(t0, t0, t1);
3987 tcg_gen_ext32s_i64(t0, t0);
3988 break;
3989 case OPC_SUBU_CP2:
3990 tcg_gen_sub_i64(t0, t0, t1);
3991 tcg_gen_ext32s_i64(t0, t0);
3992 break;
3994 case OPC_SLL_CP2:
3995 shift_max = 32;
3996 goto do_shift;
3997 case OPC_SRL_CP2:
3998 shift_max = 32;
3999 goto do_shift;
4000 case OPC_SRA_CP2:
4001 shift_max = 32;
4002 goto do_shift;
4003 case OPC_DSLL_CP2:
4004 shift_max = 64;
4005 goto do_shift;
4006 case OPC_DSRL_CP2:
4007 shift_max = 64;
4008 goto do_shift;
4009 case OPC_DSRA_CP2:
4010 shift_max = 64;
4011 goto do_shift;
4012 do_shift:
4013 /* Make sure shift count isn't TCG undefined behaviour. */
4014 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4016 switch (opc) {
4017 case OPC_SLL_CP2:
4018 case OPC_DSLL_CP2:
4019 tcg_gen_shl_i64(t0, t0, t1);
4020 break;
4021 case OPC_SRA_CP2:
4022 case OPC_DSRA_CP2:
4023 /* Since SRA is UndefinedResult without sign-extended inputs,
4024 we can treat SRA and DSRA the same. */
4025 tcg_gen_sar_i64(t0, t0, t1);
4026 break;
4027 case OPC_SRL_CP2:
4028 /* We want to shift in zeros for SRL; zero-extend first. */
4029 tcg_gen_ext32u_i64(t0, t0);
4030 /* FALLTHRU */
4031 case OPC_DSRL_CP2:
4032 tcg_gen_shr_i64(t0, t0, t1);
4033 break;
4036 if (shift_max == 32) {
4037 tcg_gen_ext32s_i64(t0, t0);
4040 /* Shifts larger than MAX produce zero. */
4041 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4042 tcg_gen_neg_i64(t1, t1);
4043 tcg_gen_and_i64(t0, t0, t1);
4044 break;
4046 case OPC_ADD_CP2:
4047 case OPC_DADD_CP2:
4049 TCGv_i64 t2 = tcg_temp_new_i64();
4050 TCGLabel *lab = gen_new_label();
4052 tcg_gen_mov_i64(t2, t0);
4053 tcg_gen_add_i64(t0, t1, t2);
4054 if (opc == OPC_ADD_CP2) {
4055 tcg_gen_ext32s_i64(t0, t0);
4057 tcg_gen_xor_i64(t1, t1, t2);
4058 tcg_gen_xor_i64(t2, t2, t0);
4059 tcg_gen_andc_i64(t1, t2, t1);
4060 tcg_temp_free_i64(t2);
4061 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4062 generate_exception(ctx, EXCP_OVERFLOW);
4063 gen_set_label(lab);
4064 break;
4067 case OPC_SUB_CP2:
4068 case OPC_DSUB_CP2:
4070 TCGv_i64 t2 = tcg_temp_new_i64();
4071 TCGLabel *lab = gen_new_label();
4073 tcg_gen_mov_i64(t2, t0);
4074 tcg_gen_sub_i64(t0, t1, t2);
4075 if (opc == OPC_SUB_CP2) {
4076 tcg_gen_ext32s_i64(t0, t0);
4078 tcg_gen_xor_i64(t1, t1, t2);
4079 tcg_gen_xor_i64(t2, t2, t0);
4080 tcg_gen_and_i64(t1, t1, t2);
4081 tcg_temp_free_i64(t2);
4082 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4083 generate_exception(ctx, EXCP_OVERFLOW);
4084 gen_set_label(lab);
4085 break;
4088 case OPC_PMULUW:
4089 tcg_gen_ext32u_i64(t0, t0);
4090 tcg_gen_ext32u_i64(t1, t1);
4091 tcg_gen_mul_i64(t0, t0, t1);
4092 break;
4094 case OPC_SEQU_CP2:
4095 case OPC_SEQ_CP2:
4096 case OPC_SLTU_CP2:
4097 case OPC_SLT_CP2:
4098 case OPC_SLEU_CP2:
4099 case OPC_SLE_CP2:
4100 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4101 FD field is the CC field? */
4102 default:
4103 MIPS_INVAL("loongson_cp2");
4104 generate_exception_end(ctx, EXCP_RI);
4105 return;
4108 #undef LMI_HELPER
4109 #undef LMI_DIRECT
4111 gen_store_fpr64(ctx, t0, rd);
4113 tcg_temp_free_i64(t0);
4114 tcg_temp_free_i64(t1);
4117 /* Traps */
4118 static void gen_trap (DisasContext *ctx, uint32_t opc,
4119 int rs, int rt, int16_t imm)
4121 int cond;
4122 TCGv t0 = tcg_temp_new();
4123 TCGv t1 = tcg_temp_new();
4125 cond = 0;
4126 /* Load needed operands */
4127 switch (opc) {
4128 case OPC_TEQ:
4129 case OPC_TGE:
4130 case OPC_TGEU:
4131 case OPC_TLT:
4132 case OPC_TLTU:
4133 case OPC_TNE:
4134 /* Compare two registers */
4135 if (rs != rt) {
4136 gen_load_gpr(t0, rs);
4137 gen_load_gpr(t1, rt);
4138 cond = 1;
4140 break;
4141 case OPC_TEQI:
4142 case OPC_TGEI:
4143 case OPC_TGEIU:
4144 case OPC_TLTI:
4145 case OPC_TLTIU:
4146 case OPC_TNEI:
4147 /* Compare register to immediate */
4148 if (rs != 0 || imm != 0) {
4149 gen_load_gpr(t0, rs);
4150 tcg_gen_movi_tl(t1, (int32_t)imm);
4151 cond = 1;
4153 break;
4155 if (cond == 0) {
4156 switch (opc) {
4157 case OPC_TEQ: /* rs == rs */
4158 case OPC_TEQI: /* r0 == 0 */
4159 case OPC_TGE: /* rs >= rs */
4160 case OPC_TGEI: /* r0 >= 0 */
4161 case OPC_TGEU: /* rs >= rs unsigned */
4162 case OPC_TGEIU: /* r0 >= 0 unsigned */
4163 /* Always trap */
4164 generate_exception_end(ctx, EXCP_TRAP);
4165 break;
4166 case OPC_TLT: /* rs < rs */
4167 case OPC_TLTI: /* r0 < 0 */
4168 case OPC_TLTU: /* rs < rs unsigned */
4169 case OPC_TLTIU: /* r0 < 0 unsigned */
4170 case OPC_TNE: /* rs != rs */
4171 case OPC_TNEI: /* r0 != 0 */
4172 /* Never trap: treat as NOP. */
4173 break;
4175 } else {
4176 TCGLabel *l1 = gen_new_label();
4178 switch (opc) {
4179 case OPC_TEQ:
4180 case OPC_TEQI:
4181 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4182 break;
4183 case OPC_TGE:
4184 case OPC_TGEI:
4185 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4186 break;
4187 case OPC_TGEU:
4188 case OPC_TGEIU:
4189 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4190 break;
4191 case OPC_TLT:
4192 case OPC_TLTI:
4193 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4194 break;
4195 case OPC_TLTU:
4196 case OPC_TLTIU:
4197 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4198 break;
4199 case OPC_TNE:
4200 case OPC_TNEI:
4201 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4202 break;
4204 generate_exception(ctx, EXCP_TRAP);
4205 gen_set_label(l1);
4207 tcg_temp_free(t0);
4208 tcg_temp_free(t1);
4211 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4213 if (unlikely(ctx->singlestep_enabled)) {
4214 return false;
4217 #ifndef CONFIG_USER_ONLY
4218 return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4219 #else
4220 return true;
4221 #endif
4224 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4226 if (use_goto_tb(ctx, dest)) {
4227 tcg_gen_goto_tb(n);
4228 gen_save_pc(dest);
4229 tcg_gen_exit_tb((uintptr_t)ctx->tb + n);
4230 } else {
4231 gen_save_pc(dest);
4232 if (ctx->singlestep_enabled) {
4233 save_cpu_state(ctx, 0);
4234 gen_helper_raise_exception_debug(cpu_env);
4236 tcg_gen_exit_tb(0);
4240 /* Branches (before delay slot) */
4241 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4242 int insn_bytes,
4243 int rs, int rt, int32_t offset,
4244 int delayslot_size)
4246 target_ulong btgt = -1;
4247 int blink = 0;
4248 int bcond_compute = 0;
4249 TCGv t0 = tcg_temp_new();
4250 TCGv t1 = tcg_temp_new();
4252 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4253 #ifdef MIPS_DEBUG_DISAS
4254 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4255 TARGET_FMT_lx "\n", ctx->pc);
4256 #endif
4257 generate_exception_end(ctx, EXCP_RI);
4258 goto out;
4261 /* Load needed operands */
4262 switch (opc) {
4263 case OPC_BEQ:
4264 case OPC_BEQL:
4265 case OPC_BNE:
4266 case OPC_BNEL:
4267 /* Compare two registers */
4268 if (rs != rt) {
4269 gen_load_gpr(t0, rs);
4270 gen_load_gpr(t1, rt);
4271 bcond_compute = 1;
4273 btgt = ctx->pc + insn_bytes + offset;
4274 break;
4275 case OPC_BGEZ:
4276 case OPC_BGEZAL:
4277 case OPC_BGEZALL:
4278 case OPC_BGEZL:
4279 case OPC_BGTZ:
4280 case OPC_BGTZL:
4281 case OPC_BLEZ:
4282 case OPC_BLEZL:
4283 case OPC_BLTZ:
4284 case OPC_BLTZAL:
4285 case OPC_BLTZALL:
4286 case OPC_BLTZL:
4287 /* Compare to zero */
4288 if (rs != 0) {
4289 gen_load_gpr(t0, rs);
4290 bcond_compute = 1;
4292 btgt = ctx->pc + insn_bytes + offset;
4293 break;
4294 case OPC_BPOSGE32:
4295 #if defined(TARGET_MIPS64)
4296 case OPC_BPOSGE64:
4297 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4298 #else
4299 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4300 #endif
4301 bcond_compute = 1;
4302 btgt = ctx->pc + insn_bytes + offset;
4303 break;
4304 case OPC_J:
4305 case OPC_JAL:
4306 case OPC_JALX:
4307 /* Jump to immediate */
4308 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4309 break;
4310 case OPC_JR:
4311 case OPC_JALR:
4312 /* Jump to register */
4313 if (offset != 0 && offset != 16) {
4314 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4315 others are reserved. */
4316 MIPS_INVAL("jump hint");
4317 generate_exception_end(ctx, EXCP_RI);
4318 goto out;
4320 gen_load_gpr(btarget, rs);
4321 break;
4322 default:
4323 MIPS_INVAL("branch/jump");
4324 generate_exception_end(ctx, EXCP_RI);
4325 goto out;
4327 if (bcond_compute == 0) {
4328 /* No condition to be computed */
4329 switch (opc) {
4330 case OPC_BEQ: /* rx == rx */
4331 case OPC_BEQL: /* rx == rx likely */
4332 case OPC_BGEZ: /* 0 >= 0 */
4333 case OPC_BGEZL: /* 0 >= 0 likely */
4334 case OPC_BLEZ: /* 0 <= 0 */
4335 case OPC_BLEZL: /* 0 <= 0 likely */
4336 /* Always take */
4337 ctx->hflags |= MIPS_HFLAG_B;
4338 break;
4339 case OPC_BGEZAL: /* 0 >= 0 */
4340 case OPC_BGEZALL: /* 0 >= 0 likely */
4341 /* Always take and link */
4342 blink = 31;
4343 ctx->hflags |= MIPS_HFLAG_B;
4344 break;
4345 case OPC_BNE: /* rx != rx */
4346 case OPC_BGTZ: /* 0 > 0 */
4347 case OPC_BLTZ: /* 0 < 0 */
4348 /* Treat as NOP. */
4349 goto out;
4350 case OPC_BLTZAL: /* 0 < 0 */
4351 /* Handle as an unconditional branch to get correct delay
4352 slot checking. */
4353 blink = 31;
4354 btgt = ctx->pc + insn_bytes + delayslot_size;
4355 ctx->hflags |= MIPS_HFLAG_B;
4356 break;
4357 case OPC_BLTZALL: /* 0 < 0 likely */
4358 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4359 /* Skip the instruction in the delay slot */
4360 ctx->pc += 4;
4361 goto out;
4362 case OPC_BNEL: /* rx != rx likely */
4363 case OPC_BGTZL: /* 0 > 0 likely */
4364 case OPC_BLTZL: /* 0 < 0 likely */
4365 /* Skip the instruction in the delay slot */
4366 ctx->pc += 4;
4367 goto out;
4368 case OPC_J:
4369 ctx->hflags |= MIPS_HFLAG_B;
4370 break;
4371 case OPC_JALX:
4372 ctx->hflags |= MIPS_HFLAG_BX;
4373 /* Fallthrough */
4374 case OPC_JAL:
4375 blink = 31;
4376 ctx->hflags |= MIPS_HFLAG_B;
4377 break;
4378 case OPC_JR:
4379 ctx->hflags |= MIPS_HFLAG_BR;
4380 break;
4381 case OPC_JALR:
4382 blink = rt;
4383 ctx->hflags |= MIPS_HFLAG_BR;
4384 break;
4385 default:
4386 MIPS_INVAL("branch/jump");
4387 generate_exception_end(ctx, EXCP_RI);
4388 goto out;
4390 } else {
4391 switch (opc) {
4392 case OPC_BEQ:
4393 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4394 goto not_likely;
4395 case OPC_BEQL:
4396 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4397 goto likely;
4398 case OPC_BNE:
4399 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4400 goto not_likely;
4401 case OPC_BNEL:
4402 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4403 goto likely;
4404 case OPC_BGEZ:
4405 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4406 goto not_likely;
4407 case OPC_BGEZL:
4408 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4409 goto likely;
4410 case OPC_BGEZAL:
4411 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4412 blink = 31;
4413 goto not_likely;
4414 case OPC_BGEZALL:
4415 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4416 blink = 31;
4417 goto likely;
4418 case OPC_BGTZ:
4419 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4420 goto not_likely;
4421 case OPC_BGTZL:
4422 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4423 goto likely;
4424 case OPC_BLEZ:
4425 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4426 goto not_likely;
4427 case OPC_BLEZL:
4428 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4429 goto likely;
4430 case OPC_BLTZ:
4431 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4432 goto not_likely;
4433 case OPC_BLTZL:
4434 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4435 goto likely;
4436 case OPC_BPOSGE32:
4437 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4438 goto not_likely;
4439 #if defined(TARGET_MIPS64)
4440 case OPC_BPOSGE64:
4441 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4442 goto not_likely;
4443 #endif
4444 case OPC_BLTZAL:
4445 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4446 blink = 31;
4447 not_likely:
4448 ctx->hflags |= MIPS_HFLAG_BC;
4449 break;
4450 case OPC_BLTZALL:
4451 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4452 blink = 31;
4453 likely:
4454 ctx->hflags |= MIPS_HFLAG_BL;
4455 break;
4456 default:
4457 MIPS_INVAL("conditional branch/jump");
4458 generate_exception_end(ctx, EXCP_RI);
4459 goto out;
4463 ctx->btarget = btgt;
4465 switch (delayslot_size) {
4466 case 2:
4467 ctx->hflags |= MIPS_HFLAG_BDS16;
4468 break;
4469 case 4:
4470 ctx->hflags |= MIPS_HFLAG_BDS32;
4471 break;
4474 if (blink > 0) {
4475 int post_delay = insn_bytes + delayslot_size;
4476 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4478 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4481 out:
4482 if (insn_bytes == 2)
4483 ctx->hflags |= MIPS_HFLAG_B16;
4484 tcg_temp_free(t0);
4485 tcg_temp_free(t1);
4488 /* special3 bitfield operations */
4489 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4490 int rs, int lsb, int msb)
4492 TCGv t0 = tcg_temp_new();
4493 TCGv t1 = tcg_temp_new();
4495 gen_load_gpr(t1, rs);
4496 switch (opc) {
4497 case OPC_EXT:
4498 if (lsb + msb > 31) {
4499 goto fail;
4501 if (msb != 31) {
4502 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4503 } else {
4504 /* The two checks together imply that lsb == 0,
4505 so this is a simple sign-extension. */
4506 tcg_gen_ext32s_tl(t0, t1);
4508 break;
4509 #if defined(TARGET_MIPS64)
4510 case OPC_DEXTU:
4511 lsb += 32;
4512 goto do_dext;
4513 case OPC_DEXTM:
4514 msb += 32;
4515 goto do_dext;
4516 case OPC_DEXT:
4517 do_dext:
4518 if (lsb + msb > 63) {
4519 goto fail;
4521 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4522 break;
4523 #endif
4524 case OPC_INS:
4525 if (lsb > msb) {
4526 goto fail;
4528 gen_load_gpr(t0, rt);
4529 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4530 tcg_gen_ext32s_tl(t0, t0);
4531 break;
4532 #if defined(TARGET_MIPS64)
4533 case OPC_DINSU:
4534 lsb += 32;
4535 /* FALLTHRU */
4536 case OPC_DINSM:
4537 msb += 32;
4538 /* FALLTHRU */
4539 case OPC_DINS:
4540 if (lsb > msb) {
4541 goto fail;
4543 gen_load_gpr(t0, rt);
4544 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4545 break;
4546 #endif
4547 default:
4548 fail:
4549 MIPS_INVAL("bitops");
4550 generate_exception_end(ctx, EXCP_RI);
4551 tcg_temp_free(t0);
4552 tcg_temp_free(t1);
4553 return;
4555 gen_store_gpr(t0, rt);
4556 tcg_temp_free(t0);
4557 tcg_temp_free(t1);
4560 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4562 TCGv t0;
4564 if (rd == 0) {
4565 /* If no destination, treat it as a NOP. */
4566 return;
4569 t0 = tcg_temp_new();
4570 gen_load_gpr(t0, rt);
4571 switch (op2) {
4572 case OPC_WSBH:
4574 TCGv t1 = tcg_temp_new();
4576 tcg_gen_shri_tl(t1, t0, 8);
4577 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4578 tcg_gen_shli_tl(t0, t0, 8);
4579 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4580 tcg_gen_or_tl(t0, t0, t1);
4581 tcg_temp_free(t1);
4582 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4584 break;
4585 case OPC_SEB:
4586 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4587 break;
4588 case OPC_SEH:
4589 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4590 break;
4591 #if defined(TARGET_MIPS64)
4592 case OPC_DSBH:
4594 TCGv t1 = tcg_temp_new();
4596 tcg_gen_shri_tl(t1, t0, 8);
4597 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4598 tcg_gen_shli_tl(t0, t0, 8);
4599 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4600 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4601 tcg_temp_free(t1);
4603 break;
4604 case OPC_DSHD:
4606 TCGv t1 = tcg_temp_new();
4608 tcg_gen_shri_tl(t1, t0, 16);
4609 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4610 tcg_gen_shli_tl(t0, t0, 16);
4611 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4612 tcg_gen_or_tl(t0, t0, t1);
4613 tcg_gen_shri_tl(t1, t0, 32);
4614 tcg_gen_shli_tl(t0, t0, 32);
4615 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4616 tcg_temp_free(t1);
4618 break;
4619 #endif
4620 default:
4621 MIPS_INVAL("bsfhl");
4622 generate_exception_end(ctx, EXCP_RI);
4623 tcg_temp_free(t0);
4624 return;
4626 tcg_temp_free(t0);
4629 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4630 int imm2)
4632 TCGv t0;
4633 TCGv t1;
4634 if (rd == 0) {
4635 /* Treat as NOP. */
4636 return;
4638 t0 = tcg_temp_new();
4639 t1 = tcg_temp_new();
4640 gen_load_gpr(t0, rs);
4641 gen_load_gpr(t1, rt);
4642 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4643 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4644 if (opc == OPC_LSA) {
4645 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4648 tcg_temp_free(t1);
4649 tcg_temp_free(t0);
4651 return;
4654 static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
4655 int bp)
4657 TCGv t0;
4658 if (rd == 0) {
4659 /* Treat as NOP. */
4660 return;
4662 t0 = tcg_temp_new();
4663 gen_load_gpr(t0, rt);
4664 if (bp == 0) {
4665 switch (opc) {
4666 case OPC_ALIGN:
4667 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4668 break;
4669 #if defined(TARGET_MIPS64)
4670 case OPC_DALIGN:
4671 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4672 break;
4673 #endif
4675 } else {
4676 TCGv t1 = tcg_temp_new();
4677 gen_load_gpr(t1, rs);
4678 switch (opc) {
4679 case OPC_ALIGN:
4681 TCGv_i64 t2 = tcg_temp_new_i64();
4682 tcg_gen_concat_tl_i64(t2, t1, t0);
4683 tcg_gen_shri_i64(t2, t2, 8 * (4 - bp));
4684 gen_move_low32(cpu_gpr[rd], t2);
4685 tcg_temp_free_i64(t2);
4687 break;
4688 #if defined(TARGET_MIPS64)
4689 case OPC_DALIGN:
4690 tcg_gen_shli_tl(t0, t0, 8 * bp);
4691 tcg_gen_shri_tl(t1, t1, 8 * (8 - bp));
4692 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4693 break;
4694 #endif
4696 tcg_temp_free(t1);
4699 tcg_temp_free(t0);
4702 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4704 TCGv t0;
4705 if (rd == 0) {
4706 /* Treat as NOP. */
4707 return;
4709 t0 = tcg_temp_new();
4710 gen_load_gpr(t0, rt);
4711 switch (opc) {
4712 case OPC_BITSWAP:
4713 gen_helper_bitswap(cpu_gpr[rd], t0);
4714 break;
4715 #if defined(TARGET_MIPS64)
4716 case OPC_DBITSWAP:
4717 gen_helper_dbitswap(cpu_gpr[rd], t0);
4718 break;
4719 #endif
4721 tcg_temp_free(t0);
4724 #ifndef CONFIG_USER_ONLY
4725 /* CP0 (MMU and control) */
4726 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4728 TCGv_i64 t0 = tcg_temp_new_i64();
4729 TCGv_i64 t1 = tcg_temp_new_i64();
4731 tcg_gen_ext_tl_i64(t0, arg);
4732 tcg_gen_ld_i64(t1, cpu_env, off);
4733 #if defined(TARGET_MIPS64)
4734 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4735 #else
4736 tcg_gen_concat32_i64(t1, t1, t0);
4737 #endif
4738 tcg_gen_st_i64(t1, cpu_env, off);
4739 tcg_temp_free_i64(t1);
4740 tcg_temp_free_i64(t0);
4743 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4745 TCGv_i64 t0 = tcg_temp_new_i64();
4746 TCGv_i64 t1 = tcg_temp_new_i64();
4748 tcg_gen_ext_tl_i64(t0, arg);
4749 tcg_gen_ld_i64(t1, cpu_env, off);
4750 tcg_gen_concat32_i64(t1, t1, t0);
4751 tcg_gen_st_i64(t1, cpu_env, off);
4752 tcg_temp_free_i64(t1);
4753 tcg_temp_free_i64(t0);
4756 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
4758 TCGv_i64 t0 = tcg_temp_new_i64();
4760 tcg_gen_ld_i64(t0, cpu_env, off);
4761 #if defined(TARGET_MIPS64)
4762 tcg_gen_shri_i64(t0, t0, 30);
4763 #else
4764 tcg_gen_shri_i64(t0, t0, 32);
4765 #endif
4766 gen_move_low32(arg, t0);
4767 tcg_temp_free_i64(t0);
4770 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
4772 TCGv_i64 t0 = tcg_temp_new_i64();
4774 tcg_gen_ld_i64(t0, cpu_env, off);
4775 tcg_gen_shri_i64(t0, t0, 32 + shift);
4776 gen_move_low32(arg, t0);
4777 tcg_temp_free_i64(t0);
4780 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4782 TCGv_i32 t0 = tcg_temp_new_i32();
4784 tcg_gen_ld_i32(t0, cpu_env, off);
4785 tcg_gen_ext_i32_tl(arg, t0);
4786 tcg_temp_free_i32(t0);
4789 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4791 tcg_gen_ld_tl(arg, cpu_env, off);
4792 tcg_gen_ext32s_tl(arg, arg);
4795 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4797 TCGv_i32 t0 = tcg_temp_new_i32();
4799 tcg_gen_trunc_tl_i32(t0, arg);
4800 tcg_gen_st_i32(t0, cpu_env, off);
4801 tcg_temp_free_i32(t0);
4804 #define CP0_CHECK(c) \
4805 do { \
4806 if (!(c)) { \
4807 goto cp0_unimplemented; \
4809 } while (0)
4811 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4813 const char *rn = "invalid";
4815 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4817 switch (reg) {
4818 case 2:
4819 switch (sel) {
4820 case 0:
4821 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4822 rn = "EntryLo0";
4823 break;
4824 default:
4825 goto cp0_unimplemented;
4827 break;
4828 case 3:
4829 switch (sel) {
4830 case 0:
4831 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4832 rn = "EntryLo1";
4833 break;
4834 default:
4835 goto cp0_unimplemented;
4837 break;
4838 case 17:
4839 switch (sel) {
4840 case 0:
4841 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
4842 ctx->CP0_LLAddr_shift);
4843 rn = "LLAddr";
4844 break;
4845 case 1:
4846 CP0_CHECK(ctx->mrp);
4847 gen_helper_mfhc0_maar(arg, cpu_env);
4848 rn = "MAAR";
4849 break;
4850 default:
4851 goto cp0_unimplemented;
4853 break;
4854 case 28:
4855 switch (sel) {
4856 case 0:
4857 case 2:
4858 case 4:
4859 case 6:
4860 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
4861 rn = "TagLo";
4862 break;
4863 default:
4864 goto cp0_unimplemented;
4866 break;
4867 default:
4868 goto cp0_unimplemented;
4870 trace_mips_translate_c0("mfhc0", rn, reg, sel);
4871 return;
4873 cp0_unimplemented:
4874 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4875 tcg_gen_movi_tl(arg, 0);
4878 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4880 const char *rn = "invalid";
4881 uint64_t mask = ctx->PAMask >> 36;
4883 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4885 switch (reg) {
4886 case 2:
4887 switch (sel) {
4888 case 0:
4889 tcg_gen_andi_tl(arg, arg, mask);
4890 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4891 rn = "EntryLo0";
4892 break;
4893 default:
4894 goto cp0_unimplemented;
4896 break;
4897 case 3:
4898 switch (sel) {
4899 case 0:
4900 tcg_gen_andi_tl(arg, arg, mask);
4901 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4902 rn = "EntryLo1";
4903 break;
4904 default:
4905 goto cp0_unimplemented;
4907 break;
4908 case 17:
4909 switch (sel) {
4910 case 0:
4911 /* LLAddr is read-only (the only exception is bit 0 if LLB is
4912 supported); the CP0_LLAddr_rw_bitmask does not seem to be
4913 relevant for modern MIPS cores supporting MTHC0, therefore
4914 treating MTHC0 to LLAddr as NOP. */
4915 rn = "LLAddr";
4916 break;
4917 case 1:
4918 CP0_CHECK(ctx->mrp);
4919 gen_helper_mthc0_maar(cpu_env, arg);
4920 rn = "MAAR";
4921 break;
4922 default:
4923 goto cp0_unimplemented;
4925 break;
4926 case 28:
4927 switch (sel) {
4928 case 0:
4929 case 2:
4930 case 4:
4931 case 6:
4932 tcg_gen_andi_tl(arg, arg, mask);
4933 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
4934 rn = "TagLo";
4935 break;
4936 default:
4937 goto cp0_unimplemented;
4939 break;
4940 default:
4941 goto cp0_unimplemented;
4943 trace_mips_translate_c0("mthc0", rn, reg, sel);
4945 cp0_unimplemented:
4946 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
4949 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
4951 if (ctx->insn_flags & ISA_MIPS32R6) {
4952 tcg_gen_movi_tl(arg, 0);
4953 } else {
4954 tcg_gen_movi_tl(arg, ~0);
4958 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4960 const char *rn = "invalid";
4962 if (sel != 0)
4963 check_insn(ctx, ISA_MIPS32);
4965 switch (reg) {
4966 case 0:
4967 switch (sel) {
4968 case 0:
4969 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4970 rn = "Index";
4971 break;
4972 case 1:
4973 CP0_CHECK(ctx->insn_flags & ASE_MT);
4974 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4975 rn = "MVPControl";
4976 break;
4977 case 2:
4978 CP0_CHECK(ctx->insn_flags & ASE_MT);
4979 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4980 rn = "MVPConf0";
4981 break;
4982 case 3:
4983 CP0_CHECK(ctx->insn_flags & ASE_MT);
4984 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4985 rn = "MVPConf1";
4986 break;
4987 case 4:
4988 CP0_CHECK(ctx->vp);
4989 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
4990 rn = "VPControl";
4991 break;
4992 default:
4993 goto cp0_unimplemented;
4995 break;
4996 case 1:
4997 switch (sel) {
4998 case 0:
4999 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5000 gen_helper_mfc0_random(arg, cpu_env);
5001 rn = "Random";
5002 break;
5003 case 1:
5004 CP0_CHECK(ctx->insn_flags & ASE_MT);
5005 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5006 rn = "VPEControl";
5007 break;
5008 case 2:
5009 CP0_CHECK(ctx->insn_flags & ASE_MT);
5010 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5011 rn = "VPEConf0";
5012 break;
5013 case 3:
5014 CP0_CHECK(ctx->insn_flags & ASE_MT);
5015 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5016 rn = "VPEConf1";
5017 break;
5018 case 4:
5019 CP0_CHECK(ctx->insn_flags & ASE_MT);
5020 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5021 rn = "YQMask";
5022 break;
5023 case 5:
5024 CP0_CHECK(ctx->insn_flags & ASE_MT);
5025 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5026 rn = "VPESchedule";
5027 break;
5028 case 6:
5029 CP0_CHECK(ctx->insn_flags & ASE_MT);
5030 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5031 rn = "VPEScheFBack";
5032 break;
5033 case 7:
5034 CP0_CHECK(ctx->insn_flags & ASE_MT);
5035 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5036 rn = "VPEOpt";
5037 break;
5038 default:
5039 goto cp0_unimplemented;
5041 break;
5042 case 2:
5043 switch (sel) {
5044 case 0:
5046 TCGv_i64 tmp = tcg_temp_new_i64();
5047 tcg_gen_ld_i64(tmp, cpu_env,
5048 offsetof(CPUMIPSState, CP0_EntryLo0));
5049 #if defined(TARGET_MIPS64)
5050 if (ctx->rxi) {
5051 /* Move RI/XI fields to bits 31:30 */
5052 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5053 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5055 #endif
5056 gen_move_low32(arg, tmp);
5057 tcg_temp_free_i64(tmp);
5059 rn = "EntryLo0";
5060 break;
5061 case 1:
5062 CP0_CHECK(ctx->insn_flags & ASE_MT);
5063 gen_helper_mfc0_tcstatus(arg, cpu_env);
5064 rn = "TCStatus";
5065 break;
5066 case 2:
5067 CP0_CHECK(ctx->insn_flags & ASE_MT);
5068 gen_helper_mfc0_tcbind(arg, cpu_env);
5069 rn = "TCBind";
5070 break;
5071 case 3:
5072 CP0_CHECK(ctx->insn_flags & ASE_MT);
5073 gen_helper_mfc0_tcrestart(arg, cpu_env);
5074 rn = "TCRestart";
5075 break;
5076 case 4:
5077 CP0_CHECK(ctx->insn_flags & ASE_MT);
5078 gen_helper_mfc0_tchalt(arg, cpu_env);
5079 rn = "TCHalt";
5080 break;
5081 case 5:
5082 CP0_CHECK(ctx->insn_flags & ASE_MT);
5083 gen_helper_mfc0_tccontext(arg, cpu_env);
5084 rn = "TCContext";
5085 break;
5086 case 6:
5087 CP0_CHECK(ctx->insn_flags & ASE_MT);
5088 gen_helper_mfc0_tcschedule(arg, cpu_env);
5089 rn = "TCSchedule";
5090 break;
5091 case 7:
5092 CP0_CHECK(ctx->insn_flags & ASE_MT);
5093 gen_helper_mfc0_tcschefback(arg, cpu_env);
5094 rn = "TCScheFBack";
5095 break;
5096 default:
5097 goto cp0_unimplemented;
5099 break;
5100 case 3:
5101 switch (sel) {
5102 case 0:
5104 TCGv_i64 tmp = tcg_temp_new_i64();
5105 tcg_gen_ld_i64(tmp, cpu_env,
5106 offsetof(CPUMIPSState, CP0_EntryLo1));
5107 #if defined(TARGET_MIPS64)
5108 if (ctx->rxi) {
5109 /* Move RI/XI fields to bits 31:30 */
5110 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5111 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5113 #endif
5114 gen_move_low32(arg, tmp);
5115 tcg_temp_free_i64(tmp);
5117 rn = "EntryLo1";
5118 break;
5119 case 1:
5120 CP0_CHECK(ctx->vp);
5121 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5122 rn = "GlobalNumber";
5123 break;
5124 default:
5125 goto cp0_unimplemented;
5127 break;
5128 case 4:
5129 switch (sel) {
5130 case 0:
5131 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5132 tcg_gen_ext32s_tl(arg, arg);
5133 rn = "Context";
5134 break;
5135 case 1:
5136 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5137 rn = "ContextConfig";
5138 goto cp0_unimplemented;
5139 case 2:
5140 CP0_CHECK(ctx->ulri);
5141 tcg_gen_ld32s_tl(arg, cpu_env,
5142 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5143 rn = "UserLocal";
5144 break;
5145 default:
5146 goto cp0_unimplemented;
5148 break;
5149 case 5:
5150 switch (sel) {
5151 case 0:
5152 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5153 rn = "PageMask";
5154 break;
5155 case 1:
5156 check_insn(ctx, ISA_MIPS32R2);
5157 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5158 rn = "PageGrain";
5159 break;
5160 default:
5161 goto cp0_unimplemented;
5163 break;
5164 case 6:
5165 switch (sel) {
5166 case 0:
5167 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5168 rn = "Wired";
5169 break;
5170 case 1:
5171 check_insn(ctx, ISA_MIPS32R2);
5172 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5173 rn = "SRSConf0";
5174 break;
5175 case 2:
5176 check_insn(ctx, ISA_MIPS32R2);
5177 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5178 rn = "SRSConf1";
5179 break;
5180 case 3:
5181 check_insn(ctx, ISA_MIPS32R2);
5182 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5183 rn = "SRSConf2";
5184 break;
5185 case 4:
5186 check_insn(ctx, ISA_MIPS32R2);
5187 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5188 rn = "SRSConf3";
5189 break;
5190 case 5:
5191 check_insn(ctx, ISA_MIPS32R2);
5192 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5193 rn = "SRSConf4";
5194 break;
5195 default:
5196 goto cp0_unimplemented;
5198 break;
5199 case 7:
5200 switch (sel) {
5201 case 0:
5202 check_insn(ctx, ISA_MIPS32R2);
5203 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5204 rn = "HWREna";
5205 break;
5206 default:
5207 goto cp0_unimplemented;
5209 break;
5210 case 8:
5211 switch (sel) {
5212 case 0:
5213 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5214 tcg_gen_ext32s_tl(arg, arg);
5215 rn = "BadVAddr";
5216 break;
5217 case 1:
5218 CP0_CHECK(ctx->bi);
5219 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5220 rn = "BadInstr";
5221 break;
5222 case 2:
5223 CP0_CHECK(ctx->bp);
5224 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5225 rn = "BadInstrP";
5226 break;
5227 default:
5228 goto cp0_unimplemented;
5230 break;
5231 case 9:
5232 switch (sel) {
5233 case 0:
5234 /* Mark as an IO operation because we read the time. */
5235 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5236 gen_io_start();
5238 gen_helper_mfc0_count(arg, cpu_env);
5239 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5240 gen_io_end();
5242 /* Break the TB to be able to take timer interrupts immediately
5243 after reading count. */
5244 ctx->bstate = BS_STOP;
5245 rn = "Count";
5246 break;
5247 /* 6,7 are implementation dependent */
5248 default:
5249 goto cp0_unimplemented;
5251 break;
5252 case 10:
5253 switch (sel) {
5254 case 0:
5255 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5256 tcg_gen_ext32s_tl(arg, arg);
5257 rn = "EntryHi";
5258 break;
5259 default:
5260 goto cp0_unimplemented;
5262 break;
5263 case 11:
5264 switch (sel) {
5265 case 0:
5266 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5267 rn = "Compare";
5268 break;
5269 /* 6,7 are implementation dependent */
5270 default:
5271 goto cp0_unimplemented;
5273 break;
5274 case 12:
5275 switch (sel) {
5276 case 0:
5277 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5278 rn = "Status";
5279 break;
5280 case 1:
5281 check_insn(ctx, ISA_MIPS32R2);
5282 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5283 rn = "IntCtl";
5284 break;
5285 case 2:
5286 check_insn(ctx, ISA_MIPS32R2);
5287 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5288 rn = "SRSCtl";
5289 break;
5290 case 3:
5291 check_insn(ctx, ISA_MIPS32R2);
5292 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5293 rn = "SRSMap";
5294 break;
5295 default:
5296 goto cp0_unimplemented;
5298 break;
5299 case 13:
5300 switch (sel) {
5301 case 0:
5302 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5303 rn = "Cause";
5304 break;
5305 default:
5306 goto cp0_unimplemented;
5308 break;
5309 case 14:
5310 switch (sel) {
5311 case 0:
5312 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5313 tcg_gen_ext32s_tl(arg, arg);
5314 rn = "EPC";
5315 break;
5316 default:
5317 goto cp0_unimplemented;
5319 break;
5320 case 15:
5321 switch (sel) {
5322 case 0:
5323 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5324 rn = "PRid";
5325 break;
5326 case 1:
5327 check_insn(ctx, ISA_MIPS32R2);
5328 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5329 rn = "EBase";
5330 break;
5331 case 3:
5332 check_insn(ctx, ISA_MIPS32R2);
5333 CP0_CHECK(ctx->cmgcr);
5334 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
5335 tcg_gen_ext32s_tl(arg, arg);
5336 rn = "CMGCRBase";
5337 break;
5338 default:
5339 goto cp0_unimplemented;
5341 break;
5342 case 16:
5343 switch (sel) {
5344 case 0:
5345 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5346 rn = "Config";
5347 break;
5348 case 1:
5349 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5350 rn = "Config1";
5351 break;
5352 case 2:
5353 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5354 rn = "Config2";
5355 break;
5356 case 3:
5357 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5358 rn = "Config3";
5359 break;
5360 case 4:
5361 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5362 rn = "Config4";
5363 break;
5364 case 5:
5365 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5366 rn = "Config5";
5367 break;
5368 /* 6,7 are implementation dependent */
5369 case 6:
5370 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5371 rn = "Config6";
5372 break;
5373 case 7:
5374 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5375 rn = "Config7";
5376 break;
5377 default:
5378 goto cp0_unimplemented;
5380 break;
5381 case 17:
5382 switch (sel) {
5383 case 0:
5384 gen_helper_mfc0_lladdr(arg, cpu_env);
5385 rn = "LLAddr";
5386 break;
5387 case 1:
5388 CP0_CHECK(ctx->mrp);
5389 gen_helper_mfc0_maar(arg, cpu_env);
5390 rn = "MAAR";
5391 break;
5392 case 2:
5393 CP0_CHECK(ctx->mrp);
5394 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
5395 rn = "MAARI";
5396 break;
5397 default:
5398 goto cp0_unimplemented;
5400 break;
5401 case 18:
5402 switch (sel) {
5403 case 0 ... 7:
5404 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5405 rn = "WatchLo";
5406 break;
5407 default:
5408 goto cp0_unimplemented;
5410 break;
5411 case 19:
5412 switch (sel) {
5413 case 0 ...7:
5414 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5415 rn = "WatchHi";
5416 break;
5417 default:
5418 goto cp0_unimplemented;
5420 break;
5421 case 20:
5422 switch (sel) {
5423 case 0:
5424 #if defined(TARGET_MIPS64)
5425 check_insn(ctx, ISA_MIPS3);
5426 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5427 tcg_gen_ext32s_tl(arg, arg);
5428 rn = "XContext";
5429 break;
5430 #endif
5431 default:
5432 goto cp0_unimplemented;
5434 break;
5435 case 21:
5436 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5437 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5438 switch (sel) {
5439 case 0:
5440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5441 rn = "Framemask";
5442 break;
5443 default:
5444 goto cp0_unimplemented;
5446 break;
5447 case 22:
5448 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5449 rn = "'Diagnostic"; /* implementation dependent */
5450 break;
5451 case 23:
5452 switch (sel) {
5453 case 0:
5454 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5455 rn = "Debug";
5456 break;
5457 case 1:
5458 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5459 rn = "TraceControl";
5460 goto cp0_unimplemented;
5461 case 2:
5462 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5463 rn = "TraceControl2";
5464 goto cp0_unimplemented;
5465 case 3:
5466 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5467 rn = "UserTraceData";
5468 goto cp0_unimplemented;
5469 case 4:
5470 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5471 rn = "TraceBPC";
5472 goto cp0_unimplemented;
5473 default:
5474 goto cp0_unimplemented;
5476 break;
5477 case 24:
5478 switch (sel) {
5479 case 0:
5480 /* EJTAG support */
5481 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5482 tcg_gen_ext32s_tl(arg, arg);
5483 rn = "DEPC";
5484 break;
5485 default:
5486 goto cp0_unimplemented;
5488 break;
5489 case 25:
5490 switch (sel) {
5491 case 0:
5492 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5493 rn = "Performance0";
5494 break;
5495 case 1:
5496 // gen_helper_mfc0_performance1(arg);
5497 rn = "Performance1";
5498 goto cp0_unimplemented;
5499 case 2:
5500 // gen_helper_mfc0_performance2(arg);
5501 rn = "Performance2";
5502 goto cp0_unimplemented;
5503 case 3:
5504 // gen_helper_mfc0_performance3(arg);
5505 rn = "Performance3";
5506 goto cp0_unimplemented;
5507 case 4:
5508 // gen_helper_mfc0_performance4(arg);
5509 rn = "Performance4";
5510 goto cp0_unimplemented;
5511 case 5:
5512 // gen_helper_mfc0_performance5(arg);
5513 rn = "Performance5";
5514 goto cp0_unimplemented;
5515 case 6:
5516 // gen_helper_mfc0_performance6(arg);
5517 rn = "Performance6";
5518 goto cp0_unimplemented;
5519 case 7:
5520 // gen_helper_mfc0_performance7(arg);
5521 rn = "Performance7";
5522 goto cp0_unimplemented;
5523 default:
5524 goto cp0_unimplemented;
5526 break;
5527 case 26:
5528 switch (sel) {
5529 case 0:
5530 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
5531 rn = "ErrCtl";
5532 break;
5533 default:
5534 goto cp0_unimplemented;
5536 break;
5537 case 27:
5538 switch (sel) {
5539 case 0 ... 3:
5540 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5541 rn = "CacheErr";
5542 break;
5543 default:
5544 goto cp0_unimplemented;
5546 break;
5547 case 28:
5548 switch (sel) {
5549 case 0:
5550 case 2:
5551 case 4:
5552 case 6:
5554 TCGv_i64 tmp = tcg_temp_new_i64();
5555 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5556 gen_move_low32(arg, tmp);
5557 tcg_temp_free_i64(tmp);
5559 rn = "TagLo";
5560 break;
5561 case 1:
5562 case 3:
5563 case 5:
5564 case 7:
5565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5566 rn = "DataLo";
5567 break;
5568 default:
5569 goto cp0_unimplemented;
5571 break;
5572 case 29:
5573 switch (sel) {
5574 case 0:
5575 case 2:
5576 case 4:
5577 case 6:
5578 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5579 rn = "TagHi";
5580 break;
5581 case 1:
5582 case 3:
5583 case 5:
5584 case 7:
5585 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5586 rn = "DataHi";
5587 break;
5588 default:
5589 goto cp0_unimplemented;
5591 break;
5592 case 30:
5593 switch (sel) {
5594 case 0:
5595 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5596 tcg_gen_ext32s_tl(arg, arg);
5597 rn = "ErrorEPC";
5598 break;
5599 default:
5600 goto cp0_unimplemented;
5602 break;
5603 case 31:
5604 switch (sel) {
5605 case 0:
5606 /* EJTAG support */
5607 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5608 rn = "DESAVE";
5609 break;
5610 case 2 ... 7:
5611 CP0_CHECK(ctx->kscrexist & (1 << sel));
5612 tcg_gen_ld_tl(arg, cpu_env,
5613 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5614 tcg_gen_ext32s_tl(arg, arg);
5615 rn = "KScratch";
5616 break;
5617 default:
5618 goto cp0_unimplemented;
5620 break;
5621 default:
5622 goto cp0_unimplemented;
5624 trace_mips_translate_c0("mfc0", rn, reg, sel);
5625 return;
5627 cp0_unimplemented:
5628 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5629 gen_mfc0_unimplemented(ctx, arg);
5632 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5634 const char *rn = "invalid";
5636 if (sel != 0)
5637 check_insn(ctx, ISA_MIPS32);
5639 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5640 gen_io_start();
5643 switch (reg) {
5644 case 0:
5645 switch (sel) {
5646 case 0:
5647 gen_helper_mtc0_index(cpu_env, arg);
5648 rn = "Index";
5649 break;
5650 case 1:
5651 CP0_CHECK(ctx->insn_flags & ASE_MT);
5652 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5653 rn = "MVPControl";
5654 break;
5655 case 2:
5656 CP0_CHECK(ctx->insn_flags & ASE_MT);
5657 /* ignored */
5658 rn = "MVPConf0";
5659 break;
5660 case 3:
5661 CP0_CHECK(ctx->insn_flags & ASE_MT);
5662 /* ignored */
5663 rn = "MVPConf1";
5664 break;
5665 case 4:
5666 CP0_CHECK(ctx->vp);
5667 /* ignored */
5668 rn = "VPControl";
5669 break;
5670 default:
5671 goto cp0_unimplemented;
5673 break;
5674 case 1:
5675 switch (sel) {
5676 case 0:
5677 /* ignored */
5678 rn = "Random";
5679 break;
5680 case 1:
5681 CP0_CHECK(ctx->insn_flags & ASE_MT);
5682 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5683 rn = "VPEControl";
5684 break;
5685 case 2:
5686 CP0_CHECK(ctx->insn_flags & ASE_MT);
5687 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5688 rn = "VPEConf0";
5689 break;
5690 case 3:
5691 CP0_CHECK(ctx->insn_flags & ASE_MT);
5692 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5693 rn = "VPEConf1";
5694 break;
5695 case 4:
5696 CP0_CHECK(ctx->insn_flags & ASE_MT);
5697 gen_helper_mtc0_yqmask(cpu_env, arg);
5698 rn = "YQMask";
5699 break;
5700 case 5:
5701 CP0_CHECK(ctx->insn_flags & ASE_MT);
5702 tcg_gen_st_tl(arg, cpu_env,
5703 offsetof(CPUMIPSState, CP0_VPESchedule));
5704 rn = "VPESchedule";
5705 break;
5706 case 6:
5707 CP0_CHECK(ctx->insn_flags & ASE_MT);
5708 tcg_gen_st_tl(arg, cpu_env,
5709 offsetof(CPUMIPSState, CP0_VPEScheFBack));
5710 rn = "VPEScheFBack";
5711 break;
5712 case 7:
5713 CP0_CHECK(ctx->insn_flags & ASE_MT);
5714 gen_helper_mtc0_vpeopt(cpu_env, arg);
5715 rn = "VPEOpt";
5716 break;
5717 default:
5718 goto cp0_unimplemented;
5720 break;
5721 case 2:
5722 switch (sel) {
5723 case 0:
5724 gen_helper_mtc0_entrylo0(cpu_env, arg);
5725 rn = "EntryLo0";
5726 break;
5727 case 1:
5728 CP0_CHECK(ctx->insn_flags & ASE_MT);
5729 gen_helper_mtc0_tcstatus(cpu_env, arg);
5730 rn = "TCStatus";
5731 break;
5732 case 2:
5733 CP0_CHECK(ctx->insn_flags & ASE_MT);
5734 gen_helper_mtc0_tcbind(cpu_env, arg);
5735 rn = "TCBind";
5736 break;
5737 case 3:
5738 CP0_CHECK(ctx->insn_flags & ASE_MT);
5739 gen_helper_mtc0_tcrestart(cpu_env, arg);
5740 rn = "TCRestart";
5741 break;
5742 case 4:
5743 CP0_CHECK(ctx->insn_flags & ASE_MT);
5744 gen_helper_mtc0_tchalt(cpu_env, arg);
5745 rn = "TCHalt";
5746 break;
5747 case 5:
5748 CP0_CHECK(ctx->insn_flags & ASE_MT);
5749 gen_helper_mtc0_tccontext(cpu_env, arg);
5750 rn = "TCContext";
5751 break;
5752 case 6:
5753 CP0_CHECK(ctx->insn_flags & ASE_MT);
5754 gen_helper_mtc0_tcschedule(cpu_env, arg);
5755 rn = "TCSchedule";
5756 break;
5757 case 7:
5758 CP0_CHECK(ctx->insn_flags & ASE_MT);
5759 gen_helper_mtc0_tcschefback(cpu_env, arg);
5760 rn = "TCScheFBack";
5761 break;
5762 default:
5763 goto cp0_unimplemented;
5765 break;
5766 case 3:
5767 switch (sel) {
5768 case 0:
5769 gen_helper_mtc0_entrylo1(cpu_env, arg);
5770 rn = "EntryLo1";
5771 break;
5772 case 1:
5773 CP0_CHECK(ctx->vp);
5774 /* ignored */
5775 rn = "GlobalNumber";
5776 break;
5777 default:
5778 goto cp0_unimplemented;
5780 break;
5781 case 4:
5782 switch (sel) {
5783 case 0:
5784 gen_helper_mtc0_context(cpu_env, arg);
5785 rn = "Context";
5786 break;
5787 case 1:
5788 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5789 rn = "ContextConfig";
5790 goto cp0_unimplemented;
5791 case 2:
5792 CP0_CHECK(ctx->ulri);
5793 tcg_gen_st_tl(arg, cpu_env,
5794 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5795 rn = "UserLocal";
5796 break;
5797 default:
5798 goto cp0_unimplemented;
5800 break;
5801 case 5:
5802 switch (sel) {
5803 case 0:
5804 gen_helper_mtc0_pagemask(cpu_env, arg);
5805 rn = "PageMask";
5806 break;
5807 case 1:
5808 check_insn(ctx, ISA_MIPS32R2);
5809 gen_helper_mtc0_pagegrain(cpu_env, arg);
5810 rn = "PageGrain";
5811 ctx->bstate = BS_STOP;
5812 break;
5813 default:
5814 goto cp0_unimplemented;
5816 break;
5817 case 6:
5818 switch (sel) {
5819 case 0:
5820 gen_helper_mtc0_wired(cpu_env, arg);
5821 rn = "Wired";
5822 break;
5823 case 1:
5824 check_insn(ctx, ISA_MIPS32R2);
5825 gen_helper_mtc0_srsconf0(cpu_env, arg);
5826 rn = "SRSConf0";
5827 break;
5828 case 2:
5829 check_insn(ctx, ISA_MIPS32R2);
5830 gen_helper_mtc0_srsconf1(cpu_env, arg);
5831 rn = "SRSConf1";
5832 break;
5833 case 3:
5834 check_insn(ctx, ISA_MIPS32R2);
5835 gen_helper_mtc0_srsconf2(cpu_env, arg);
5836 rn = "SRSConf2";
5837 break;
5838 case 4:
5839 check_insn(ctx, ISA_MIPS32R2);
5840 gen_helper_mtc0_srsconf3(cpu_env, arg);
5841 rn = "SRSConf3";
5842 break;
5843 case 5:
5844 check_insn(ctx, ISA_MIPS32R2);
5845 gen_helper_mtc0_srsconf4(cpu_env, arg);
5846 rn = "SRSConf4";
5847 break;
5848 default:
5849 goto cp0_unimplemented;
5851 break;
5852 case 7:
5853 switch (sel) {
5854 case 0:
5855 check_insn(ctx, ISA_MIPS32R2);
5856 gen_helper_mtc0_hwrena(cpu_env, arg);
5857 ctx->bstate = BS_STOP;
5858 rn = "HWREna";
5859 break;
5860 default:
5861 goto cp0_unimplemented;
5863 break;
5864 case 8:
5865 switch (sel) {
5866 case 0:
5867 /* ignored */
5868 rn = "BadVAddr";
5869 break;
5870 case 1:
5871 /* ignored */
5872 rn = "BadInstr";
5873 break;
5874 case 2:
5875 /* ignored */
5876 rn = "BadInstrP";
5877 break;
5878 default:
5879 goto cp0_unimplemented;
5881 break;
5882 case 9:
5883 switch (sel) {
5884 case 0:
5885 gen_helper_mtc0_count(cpu_env, arg);
5886 rn = "Count";
5887 break;
5888 /* 6,7 are implementation dependent */
5889 default:
5890 goto cp0_unimplemented;
5892 break;
5893 case 10:
5894 switch (sel) {
5895 case 0:
5896 gen_helper_mtc0_entryhi(cpu_env, arg);
5897 rn = "EntryHi";
5898 break;
5899 default:
5900 goto cp0_unimplemented;
5902 break;
5903 case 11:
5904 switch (sel) {
5905 case 0:
5906 gen_helper_mtc0_compare(cpu_env, arg);
5907 rn = "Compare";
5908 break;
5909 /* 6,7 are implementation dependent */
5910 default:
5911 goto cp0_unimplemented;
5913 break;
5914 case 12:
5915 switch (sel) {
5916 case 0:
5917 save_cpu_state(ctx, 1);
5918 gen_helper_mtc0_status(cpu_env, arg);
5919 /* BS_STOP isn't good enough here, hflags may have changed. */
5920 gen_save_pc(ctx->pc + 4);
5921 ctx->bstate = BS_EXCP;
5922 rn = "Status";
5923 break;
5924 case 1:
5925 check_insn(ctx, ISA_MIPS32R2);
5926 gen_helper_mtc0_intctl(cpu_env, arg);
5927 /* Stop translation as we may have switched the execution mode */
5928 ctx->bstate = BS_STOP;
5929 rn = "IntCtl";
5930 break;
5931 case 2:
5932 check_insn(ctx, ISA_MIPS32R2);
5933 gen_helper_mtc0_srsctl(cpu_env, arg);
5934 /* Stop translation as we may have switched the execution mode */
5935 ctx->bstate = BS_STOP;
5936 rn = "SRSCtl";
5937 break;
5938 case 3:
5939 check_insn(ctx, ISA_MIPS32R2);
5940 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5941 /* Stop translation as we may have switched the execution mode */
5942 ctx->bstate = BS_STOP;
5943 rn = "SRSMap";
5944 break;
5945 default:
5946 goto cp0_unimplemented;
5948 break;
5949 case 13:
5950 switch (sel) {
5951 case 0:
5952 save_cpu_state(ctx, 1);
5953 gen_helper_mtc0_cause(cpu_env, arg);
5954 rn = "Cause";
5955 break;
5956 default:
5957 goto cp0_unimplemented;
5959 break;
5960 case 14:
5961 switch (sel) {
5962 case 0:
5963 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5964 rn = "EPC";
5965 break;
5966 default:
5967 goto cp0_unimplemented;
5969 break;
5970 case 15:
5971 switch (sel) {
5972 case 0:
5973 /* ignored */
5974 rn = "PRid";
5975 break;
5976 case 1:
5977 check_insn(ctx, ISA_MIPS32R2);
5978 gen_helper_mtc0_ebase(cpu_env, arg);
5979 rn = "EBase";
5980 break;
5981 default:
5982 goto cp0_unimplemented;
5984 break;
5985 case 16:
5986 switch (sel) {
5987 case 0:
5988 gen_helper_mtc0_config0(cpu_env, arg);
5989 rn = "Config";
5990 /* Stop translation as we may have switched the execution mode */
5991 ctx->bstate = BS_STOP;
5992 break;
5993 case 1:
5994 /* ignored, read only */
5995 rn = "Config1";
5996 break;
5997 case 2:
5998 gen_helper_mtc0_config2(cpu_env, arg);
5999 rn = "Config2";
6000 /* Stop translation as we may have switched the execution mode */
6001 ctx->bstate = BS_STOP;
6002 break;
6003 case 3:
6004 gen_helper_mtc0_config3(cpu_env, arg);
6005 rn = "Config3";
6006 /* Stop translation as we may have switched the execution mode */
6007 ctx->bstate = BS_STOP;
6008 break;
6009 case 4:
6010 gen_helper_mtc0_config4(cpu_env, arg);
6011 rn = "Config4";
6012 ctx->bstate = BS_STOP;
6013 break;
6014 case 5:
6015 gen_helper_mtc0_config5(cpu_env, arg);
6016 rn = "Config5";
6017 /* Stop translation as we may have switched the execution mode */
6018 ctx->bstate = BS_STOP;
6019 break;
6020 /* 6,7 are implementation dependent */
6021 case 6:
6022 /* ignored */
6023 rn = "Config6";
6024 break;
6025 case 7:
6026 /* ignored */
6027 rn = "Config7";
6028 break;
6029 default:
6030 rn = "Invalid config selector";
6031 goto cp0_unimplemented;
6033 break;
6034 case 17:
6035 switch (sel) {
6036 case 0:
6037 gen_helper_mtc0_lladdr(cpu_env, arg);
6038 rn = "LLAddr";
6039 break;
6040 case 1:
6041 CP0_CHECK(ctx->mrp);
6042 gen_helper_mtc0_maar(cpu_env, arg);
6043 rn = "MAAR";
6044 break;
6045 case 2:
6046 CP0_CHECK(ctx->mrp);
6047 gen_helper_mtc0_maari(cpu_env, arg);
6048 rn = "MAARI";
6049 break;
6050 default:
6051 goto cp0_unimplemented;
6053 break;
6054 case 18:
6055 switch (sel) {
6056 case 0 ... 7:
6057 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6058 rn = "WatchLo";
6059 break;
6060 default:
6061 goto cp0_unimplemented;
6063 break;
6064 case 19:
6065 switch (sel) {
6066 case 0 ... 7:
6067 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6068 rn = "WatchHi";
6069 break;
6070 default:
6071 goto cp0_unimplemented;
6073 break;
6074 case 20:
6075 switch (sel) {
6076 case 0:
6077 #if defined(TARGET_MIPS64)
6078 check_insn(ctx, ISA_MIPS3);
6079 gen_helper_mtc0_xcontext(cpu_env, arg);
6080 rn = "XContext";
6081 break;
6082 #endif
6083 default:
6084 goto cp0_unimplemented;
6086 break;
6087 case 21:
6088 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6089 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6090 switch (sel) {
6091 case 0:
6092 gen_helper_mtc0_framemask(cpu_env, arg);
6093 rn = "Framemask";
6094 break;
6095 default:
6096 goto cp0_unimplemented;
6098 break;
6099 case 22:
6100 /* ignored */
6101 rn = "Diagnostic"; /* implementation dependent */
6102 break;
6103 case 23:
6104 switch (sel) {
6105 case 0:
6106 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6107 /* BS_STOP isn't good enough here, hflags may have changed. */
6108 gen_save_pc(ctx->pc + 4);
6109 ctx->bstate = BS_EXCP;
6110 rn = "Debug";
6111 break;
6112 case 1:
6113 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6114 rn = "TraceControl";
6115 /* Stop translation as we may have switched the execution mode */
6116 ctx->bstate = BS_STOP;
6117 goto cp0_unimplemented;
6118 case 2:
6119 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6120 rn = "TraceControl2";
6121 /* Stop translation as we may have switched the execution mode */
6122 ctx->bstate = BS_STOP;
6123 goto cp0_unimplemented;
6124 case 3:
6125 /* Stop translation as we may have switched the execution mode */
6126 ctx->bstate = BS_STOP;
6127 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6128 rn = "UserTraceData";
6129 /* Stop translation as we may have switched the execution mode */
6130 ctx->bstate = BS_STOP;
6131 goto cp0_unimplemented;
6132 case 4:
6133 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6134 /* Stop translation as we may have switched the execution mode */
6135 ctx->bstate = BS_STOP;
6136 rn = "TraceBPC";
6137 goto cp0_unimplemented;
6138 default:
6139 goto cp0_unimplemented;
6141 break;
6142 case 24:
6143 switch (sel) {
6144 case 0:
6145 /* EJTAG support */
6146 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6147 rn = "DEPC";
6148 break;
6149 default:
6150 goto cp0_unimplemented;
6152 break;
6153 case 25:
6154 switch (sel) {
6155 case 0:
6156 gen_helper_mtc0_performance0(cpu_env, arg);
6157 rn = "Performance0";
6158 break;
6159 case 1:
6160 // gen_helper_mtc0_performance1(arg);
6161 rn = "Performance1";
6162 goto cp0_unimplemented;
6163 case 2:
6164 // gen_helper_mtc0_performance2(arg);
6165 rn = "Performance2";
6166 goto cp0_unimplemented;
6167 case 3:
6168 // gen_helper_mtc0_performance3(arg);
6169 rn = "Performance3";
6170 goto cp0_unimplemented;
6171 case 4:
6172 // gen_helper_mtc0_performance4(arg);
6173 rn = "Performance4";
6174 goto cp0_unimplemented;
6175 case 5:
6176 // gen_helper_mtc0_performance5(arg);
6177 rn = "Performance5";
6178 goto cp0_unimplemented;
6179 case 6:
6180 // gen_helper_mtc0_performance6(arg);
6181 rn = "Performance6";
6182 goto cp0_unimplemented;
6183 case 7:
6184 // gen_helper_mtc0_performance7(arg);
6185 rn = "Performance7";
6186 goto cp0_unimplemented;
6187 default:
6188 goto cp0_unimplemented;
6190 break;
6191 case 26:
6192 switch (sel) {
6193 case 0:
6194 gen_helper_mtc0_errctl(cpu_env, arg);
6195 ctx->bstate = BS_STOP;
6196 rn = "ErrCtl";
6197 break;
6198 default:
6199 goto cp0_unimplemented;
6201 break;
6202 case 27:
6203 switch (sel) {
6204 case 0 ... 3:
6205 /* ignored */
6206 rn = "CacheErr";
6207 break;
6208 default:
6209 goto cp0_unimplemented;
6211 break;
6212 case 28:
6213 switch (sel) {
6214 case 0:
6215 case 2:
6216 case 4:
6217 case 6:
6218 gen_helper_mtc0_taglo(cpu_env, arg);
6219 rn = "TagLo";
6220 break;
6221 case 1:
6222 case 3:
6223 case 5:
6224 case 7:
6225 gen_helper_mtc0_datalo(cpu_env, arg);
6226 rn = "DataLo";
6227 break;
6228 default:
6229 goto cp0_unimplemented;
6231 break;
6232 case 29:
6233 switch (sel) {
6234 case 0:
6235 case 2:
6236 case 4:
6237 case 6:
6238 gen_helper_mtc0_taghi(cpu_env, arg);
6239 rn = "TagHi";
6240 break;
6241 case 1:
6242 case 3:
6243 case 5:
6244 case 7:
6245 gen_helper_mtc0_datahi(cpu_env, arg);
6246 rn = "DataHi";
6247 break;
6248 default:
6249 rn = "invalid sel";
6250 goto cp0_unimplemented;
6252 break;
6253 case 30:
6254 switch (sel) {
6255 case 0:
6256 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6257 rn = "ErrorEPC";
6258 break;
6259 default:
6260 goto cp0_unimplemented;
6262 break;
6263 case 31:
6264 switch (sel) {
6265 case 0:
6266 /* EJTAG support */
6267 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6268 rn = "DESAVE";
6269 break;
6270 case 2 ... 7:
6271 CP0_CHECK(ctx->kscrexist & (1 << sel));
6272 tcg_gen_st_tl(arg, cpu_env,
6273 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6274 rn = "KScratch";
6275 break;
6276 default:
6277 goto cp0_unimplemented;
6279 /* Stop translation as we may have switched the execution mode */
6280 ctx->bstate = BS_STOP;
6281 break;
6282 default:
6283 goto cp0_unimplemented;
6285 trace_mips_translate_c0("mtc0", rn, reg, sel);
6287 /* For simplicity assume that all writes can cause interrupts. */
6288 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6289 gen_io_end();
6290 ctx->bstate = BS_STOP;
6292 return;
6294 cp0_unimplemented:
6295 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6298 #if defined(TARGET_MIPS64)
6299 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6301 const char *rn = "invalid";
6303 if (sel != 0)
6304 check_insn(ctx, ISA_MIPS64);
6306 switch (reg) {
6307 case 0:
6308 switch (sel) {
6309 case 0:
6310 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6311 rn = "Index";
6312 break;
6313 case 1:
6314 CP0_CHECK(ctx->insn_flags & ASE_MT);
6315 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6316 rn = "MVPControl";
6317 break;
6318 case 2:
6319 CP0_CHECK(ctx->insn_flags & ASE_MT);
6320 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6321 rn = "MVPConf0";
6322 break;
6323 case 3:
6324 CP0_CHECK(ctx->insn_flags & ASE_MT);
6325 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6326 rn = "MVPConf1";
6327 break;
6328 case 4:
6329 CP0_CHECK(ctx->vp);
6330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6331 rn = "VPControl";
6332 break;
6333 default:
6334 goto cp0_unimplemented;
6336 break;
6337 case 1:
6338 switch (sel) {
6339 case 0:
6340 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6341 gen_helper_mfc0_random(arg, cpu_env);
6342 rn = "Random";
6343 break;
6344 case 1:
6345 CP0_CHECK(ctx->insn_flags & ASE_MT);
6346 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6347 rn = "VPEControl";
6348 break;
6349 case 2:
6350 CP0_CHECK(ctx->insn_flags & ASE_MT);
6351 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6352 rn = "VPEConf0";
6353 break;
6354 case 3:
6355 CP0_CHECK(ctx->insn_flags & ASE_MT);
6356 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6357 rn = "VPEConf1";
6358 break;
6359 case 4:
6360 CP0_CHECK(ctx->insn_flags & ASE_MT);
6361 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6362 rn = "YQMask";
6363 break;
6364 case 5:
6365 CP0_CHECK(ctx->insn_flags & ASE_MT);
6366 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6367 rn = "VPESchedule";
6368 break;
6369 case 6:
6370 CP0_CHECK(ctx->insn_flags & ASE_MT);
6371 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6372 rn = "VPEScheFBack";
6373 break;
6374 case 7:
6375 CP0_CHECK(ctx->insn_flags & ASE_MT);
6376 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6377 rn = "VPEOpt";
6378 break;
6379 default:
6380 goto cp0_unimplemented;
6382 break;
6383 case 2:
6384 switch (sel) {
6385 case 0:
6386 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6387 rn = "EntryLo0";
6388 break;
6389 case 1:
6390 CP0_CHECK(ctx->insn_flags & ASE_MT);
6391 gen_helper_mfc0_tcstatus(arg, cpu_env);
6392 rn = "TCStatus";
6393 break;
6394 case 2:
6395 CP0_CHECK(ctx->insn_flags & ASE_MT);
6396 gen_helper_mfc0_tcbind(arg, cpu_env);
6397 rn = "TCBind";
6398 break;
6399 case 3:
6400 CP0_CHECK(ctx->insn_flags & ASE_MT);
6401 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6402 rn = "TCRestart";
6403 break;
6404 case 4:
6405 CP0_CHECK(ctx->insn_flags & ASE_MT);
6406 gen_helper_dmfc0_tchalt(arg, cpu_env);
6407 rn = "TCHalt";
6408 break;
6409 case 5:
6410 CP0_CHECK(ctx->insn_flags & ASE_MT);
6411 gen_helper_dmfc0_tccontext(arg, cpu_env);
6412 rn = "TCContext";
6413 break;
6414 case 6:
6415 CP0_CHECK(ctx->insn_flags & ASE_MT);
6416 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6417 rn = "TCSchedule";
6418 break;
6419 case 7:
6420 CP0_CHECK(ctx->insn_flags & ASE_MT);
6421 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6422 rn = "TCScheFBack";
6423 break;
6424 default:
6425 goto cp0_unimplemented;
6427 break;
6428 case 3:
6429 switch (sel) {
6430 case 0:
6431 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6432 rn = "EntryLo1";
6433 break;
6434 case 1:
6435 CP0_CHECK(ctx->vp);
6436 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6437 rn = "GlobalNumber";
6438 break;
6439 default:
6440 goto cp0_unimplemented;
6442 break;
6443 case 4:
6444 switch (sel) {
6445 case 0:
6446 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6447 rn = "Context";
6448 break;
6449 case 1:
6450 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6451 rn = "ContextConfig";
6452 goto cp0_unimplemented;
6453 case 2:
6454 CP0_CHECK(ctx->ulri);
6455 tcg_gen_ld_tl(arg, cpu_env,
6456 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6457 rn = "UserLocal";
6458 break;
6459 default:
6460 goto cp0_unimplemented;
6462 break;
6463 case 5:
6464 switch (sel) {
6465 case 0:
6466 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6467 rn = "PageMask";
6468 break;
6469 case 1:
6470 check_insn(ctx, ISA_MIPS32R2);
6471 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6472 rn = "PageGrain";
6473 break;
6474 default:
6475 goto cp0_unimplemented;
6477 break;
6478 case 6:
6479 switch (sel) {
6480 case 0:
6481 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6482 rn = "Wired";
6483 break;
6484 case 1:
6485 check_insn(ctx, ISA_MIPS32R2);
6486 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6487 rn = "SRSConf0";
6488 break;
6489 case 2:
6490 check_insn(ctx, ISA_MIPS32R2);
6491 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6492 rn = "SRSConf1";
6493 break;
6494 case 3:
6495 check_insn(ctx, ISA_MIPS32R2);
6496 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6497 rn = "SRSConf2";
6498 break;
6499 case 4:
6500 check_insn(ctx, ISA_MIPS32R2);
6501 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6502 rn = "SRSConf3";
6503 break;
6504 case 5:
6505 check_insn(ctx, ISA_MIPS32R2);
6506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6507 rn = "SRSConf4";
6508 break;
6509 default:
6510 goto cp0_unimplemented;
6512 break;
6513 case 7:
6514 switch (sel) {
6515 case 0:
6516 check_insn(ctx, ISA_MIPS32R2);
6517 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6518 rn = "HWREna";
6519 break;
6520 default:
6521 goto cp0_unimplemented;
6523 break;
6524 case 8:
6525 switch (sel) {
6526 case 0:
6527 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6528 rn = "BadVAddr";
6529 break;
6530 case 1:
6531 CP0_CHECK(ctx->bi);
6532 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6533 rn = "BadInstr";
6534 break;
6535 case 2:
6536 CP0_CHECK(ctx->bp);
6537 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6538 rn = "BadInstrP";
6539 break;
6540 default:
6541 goto cp0_unimplemented;
6543 break;
6544 case 9:
6545 switch (sel) {
6546 case 0:
6547 /* Mark as an IO operation because we read the time. */
6548 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6549 gen_io_start();
6551 gen_helper_mfc0_count(arg, cpu_env);
6552 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6553 gen_io_end();
6555 /* Break the TB to be able to take timer interrupts immediately
6556 after reading count. */
6557 ctx->bstate = BS_STOP;
6558 rn = "Count";
6559 break;
6560 /* 6,7 are implementation dependent */
6561 default:
6562 goto cp0_unimplemented;
6564 break;
6565 case 10:
6566 switch (sel) {
6567 case 0:
6568 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6569 rn = "EntryHi";
6570 break;
6571 default:
6572 goto cp0_unimplemented;
6574 break;
6575 case 11:
6576 switch (sel) {
6577 case 0:
6578 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6579 rn = "Compare";
6580 break;
6581 /* 6,7 are implementation dependent */
6582 default:
6583 goto cp0_unimplemented;
6585 break;
6586 case 12:
6587 switch (sel) {
6588 case 0:
6589 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6590 rn = "Status";
6591 break;
6592 case 1:
6593 check_insn(ctx, ISA_MIPS32R2);
6594 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6595 rn = "IntCtl";
6596 break;
6597 case 2:
6598 check_insn(ctx, ISA_MIPS32R2);
6599 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6600 rn = "SRSCtl";
6601 break;
6602 case 3:
6603 check_insn(ctx, ISA_MIPS32R2);
6604 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6605 rn = "SRSMap";
6606 break;
6607 default:
6608 goto cp0_unimplemented;
6610 break;
6611 case 13:
6612 switch (sel) {
6613 case 0:
6614 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6615 rn = "Cause";
6616 break;
6617 default:
6618 goto cp0_unimplemented;
6620 break;
6621 case 14:
6622 switch (sel) {
6623 case 0:
6624 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6625 rn = "EPC";
6626 break;
6627 default:
6628 goto cp0_unimplemented;
6630 break;
6631 case 15:
6632 switch (sel) {
6633 case 0:
6634 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6635 rn = "PRid";
6636 break;
6637 case 1:
6638 check_insn(ctx, ISA_MIPS32R2);
6639 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6640 rn = "EBase";
6641 break;
6642 case 3:
6643 check_insn(ctx, ISA_MIPS32R2);
6644 CP0_CHECK(ctx->cmgcr);
6645 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6646 rn = "CMGCRBase";
6647 break;
6648 default:
6649 goto cp0_unimplemented;
6651 break;
6652 case 16:
6653 switch (sel) {
6654 case 0:
6655 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6656 rn = "Config";
6657 break;
6658 case 1:
6659 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6660 rn = "Config1";
6661 break;
6662 case 2:
6663 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6664 rn = "Config2";
6665 break;
6666 case 3:
6667 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6668 rn = "Config3";
6669 break;
6670 case 4:
6671 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6672 rn = "Config4";
6673 break;
6674 case 5:
6675 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6676 rn = "Config5";
6677 break;
6678 /* 6,7 are implementation dependent */
6679 case 6:
6680 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6681 rn = "Config6";
6682 break;
6683 case 7:
6684 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6685 rn = "Config7";
6686 break;
6687 default:
6688 goto cp0_unimplemented;
6690 break;
6691 case 17:
6692 switch (sel) {
6693 case 0:
6694 gen_helper_dmfc0_lladdr(arg, cpu_env);
6695 rn = "LLAddr";
6696 break;
6697 case 1:
6698 CP0_CHECK(ctx->mrp);
6699 gen_helper_dmfc0_maar(arg, cpu_env);
6700 rn = "MAAR";
6701 break;
6702 case 2:
6703 CP0_CHECK(ctx->mrp);
6704 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6705 rn = "MAARI";
6706 break;
6707 default:
6708 goto cp0_unimplemented;
6710 break;
6711 case 18:
6712 switch (sel) {
6713 case 0 ... 7:
6714 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6715 rn = "WatchLo";
6716 break;
6717 default:
6718 goto cp0_unimplemented;
6720 break;
6721 case 19:
6722 switch (sel) {
6723 case 0 ... 7:
6724 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6725 rn = "WatchHi";
6726 break;
6727 default:
6728 goto cp0_unimplemented;
6730 break;
6731 case 20:
6732 switch (sel) {
6733 case 0:
6734 check_insn(ctx, ISA_MIPS3);
6735 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6736 rn = "XContext";
6737 break;
6738 default:
6739 goto cp0_unimplemented;
6741 break;
6742 case 21:
6743 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6744 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6745 switch (sel) {
6746 case 0:
6747 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6748 rn = "Framemask";
6749 break;
6750 default:
6751 goto cp0_unimplemented;
6753 break;
6754 case 22:
6755 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6756 rn = "'Diagnostic"; /* implementation dependent */
6757 break;
6758 case 23:
6759 switch (sel) {
6760 case 0:
6761 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6762 rn = "Debug";
6763 break;
6764 case 1:
6765 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6766 rn = "TraceControl";
6767 goto cp0_unimplemented;
6768 case 2:
6769 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6770 rn = "TraceControl2";
6771 goto cp0_unimplemented;
6772 case 3:
6773 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6774 rn = "UserTraceData";
6775 goto cp0_unimplemented;
6776 case 4:
6777 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6778 rn = "TraceBPC";
6779 goto cp0_unimplemented;
6780 default:
6781 goto cp0_unimplemented;
6783 break;
6784 case 24:
6785 switch (sel) {
6786 case 0:
6787 /* EJTAG support */
6788 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6789 rn = "DEPC";
6790 break;
6791 default:
6792 goto cp0_unimplemented;
6794 break;
6795 case 25:
6796 switch (sel) {
6797 case 0:
6798 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6799 rn = "Performance0";
6800 break;
6801 case 1:
6802 // gen_helper_dmfc0_performance1(arg);
6803 rn = "Performance1";
6804 goto cp0_unimplemented;
6805 case 2:
6806 // gen_helper_dmfc0_performance2(arg);
6807 rn = "Performance2";
6808 goto cp0_unimplemented;
6809 case 3:
6810 // gen_helper_dmfc0_performance3(arg);
6811 rn = "Performance3";
6812 goto cp0_unimplemented;
6813 case 4:
6814 // gen_helper_dmfc0_performance4(arg);
6815 rn = "Performance4";
6816 goto cp0_unimplemented;
6817 case 5:
6818 // gen_helper_dmfc0_performance5(arg);
6819 rn = "Performance5";
6820 goto cp0_unimplemented;
6821 case 6:
6822 // gen_helper_dmfc0_performance6(arg);
6823 rn = "Performance6";
6824 goto cp0_unimplemented;
6825 case 7:
6826 // gen_helper_dmfc0_performance7(arg);
6827 rn = "Performance7";
6828 goto cp0_unimplemented;
6829 default:
6830 goto cp0_unimplemented;
6832 break;
6833 case 26:
6834 switch (sel) {
6835 case 0:
6836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6837 rn = "ErrCtl";
6838 break;
6839 default:
6840 goto cp0_unimplemented;
6842 break;
6843 case 27:
6844 switch (sel) {
6845 /* ignored */
6846 case 0 ... 3:
6847 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6848 rn = "CacheErr";
6849 break;
6850 default:
6851 goto cp0_unimplemented;
6853 break;
6854 case 28:
6855 switch (sel) {
6856 case 0:
6857 case 2:
6858 case 4:
6859 case 6:
6860 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
6861 rn = "TagLo";
6862 break;
6863 case 1:
6864 case 3:
6865 case 5:
6866 case 7:
6867 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6868 rn = "DataLo";
6869 break;
6870 default:
6871 goto cp0_unimplemented;
6873 break;
6874 case 29:
6875 switch (sel) {
6876 case 0:
6877 case 2:
6878 case 4:
6879 case 6:
6880 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6881 rn = "TagHi";
6882 break;
6883 case 1:
6884 case 3:
6885 case 5:
6886 case 7:
6887 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6888 rn = "DataHi";
6889 break;
6890 default:
6891 goto cp0_unimplemented;
6893 break;
6894 case 30:
6895 switch (sel) {
6896 case 0:
6897 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6898 rn = "ErrorEPC";
6899 break;
6900 default:
6901 goto cp0_unimplemented;
6903 break;
6904 case 31:
6905 switch (sel) {
6906 case 0:
6907 /* EJTAG support */
6908 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6909 rn = "DESAVE";
6910 break;
6911 case 2 ... 7:
6912 CP0_CHECK(ctx->kscrexist & (1 << sel));
6913 tcg_gen_ld_tl(arg, cpu_env,
6914 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6915 rn = "KScratch";
6916 break;
6917 default:
6918 goto cp0_unimplemented;
6920 break;
6921 default:
6922 goto cp0_unimplemented;
6924 trace_mips_translate_c0("dmfc0", rn, reg, sel);
6925 return;
6927 cp0_unimplemented:
6928 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6929 gen_mfc0_unimplemented(ctx, arg);
6932 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6934 const char *rn = "invalid";
6936 if (sel != 0)
6937 check_insn(ctx, ISA_MIPS64);
6939 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6940 gen_io_start();
6943 switch (reg) {
6944 case 0:
6945 switch (sel) {
6946 case 0:
6947 gen_helper_mtc0_index(cpu_env, arg);
6948 rn = "Index";
6949 break;
6950 case 1:
6951 CP0_CHECK(ctx->insn_flags & ASE_MT);
6952 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6953 rn = "MVPControl";
6954 break;
6955 case 2:
6956 CP0_CHECK(ctx->insn_flags & ASE_MT);
6957 /* ignored */
6958 rn = "MVPConf0";
6959 break;
6960 case 3:
6961 CP0_CHECK(ctx->insn_flags & ASE_MT);
6962 /* ignored */
6963 rn = "MVPConf1";
6964 break;
6965 case 4:
6966 CP0_CHECK(ctx->vp);
6967 /* ignored */
6968 rn = "VPControl";
6969 break;
6970 default:
6971 goto cp0_unimplemented;
6973 break;
6974 case 1:
6975 switch (sel) {
6976 case 0:
6977 /* ignored */
6978 rn = "Random";
6979 break;
6980 case 1:
6981 CP0_CHECK(ctx->insn_flags & ASE_MT);
6982 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6983 rn = "VPEControl";
6984 break;
6985 case 2:
6986 CP0_CHECK(ctx->insn_flags & ASE_MT);
6987 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6988 rn = "VPEConf0";
6989 break;
6990 case 3:
6991 CP0_CHECK(ctx->insn_flags & ASE_MT);
6992 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6993 rn = "VPEConf1";
6994 break;
6995 case 4:
6996 CP0_CHECK(ctx->insn_flags & ASE_MT);
6997 gen_helper_mtc0_yqmask(cpu_env, arg);
6998 rn = "YQMask";
6999 break;
7000 case 5:
7001 CP0_CHECK(ctx->insn_flags & ASE_MT);
7002 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7003 rn = "VPESchedule";
7004 break;
7005 case 6:
7006 CP0_CHECK(ctx->insn_flags & ASE_MT);
7007 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7008 rn = "VPEScheFBack";
7009 break;
7010 case 7:
7011 CP0_CHECK(ctx->insn_flags & ASE_MT);
7012 gen_helper_mtc0_vpeopt(cpu_env, arg);
7013 rn = "VPEOpt";
7014 break;
7015 default:
7016 goto cp0_unimplemented;
7018 break;
7019 case 2:
7020 switch (sel) {
7021 case 0:
7022 gen_helper_dmtc0_entrylo0(cpu_env, arg);
7023 rn = "EntryLo0";
7024 break;
7025 case 1:
7026 CP0_CHECK(ctx->insn_flags & ASE_MT);
7027 gen_helper_mtc0_tcstatus(cpu_env, arg);
7028 rn = "TCStatus";
7029 break;
7030 case 2:
7031 CP0_CHECK(ctx->insn_flags & ASE_MT);
7032 gen_helper_mtc0_tcbind(cpu_env, arg);
7033 rn = "TCBind";
7034 break;
7035 case 3:
7036 CP0_CHECK(ctx->insn_flags & ASE_MT);
7037 gen_helper_mtc0_tcrestart(cpu_env, arg);
7038 rn = "TCRestart";
7039 break;
7040 case 4:
7041 CP0_CHECK(ctx->insn_flags & ASE_MT);
7042 gen_helper_mtc0_tchalt(cpu_env, arg);
7043 rn = "TCHalt";
7044 break;
7045 case 5:
7046 CP0_CHECK(ctx->insn_flags & ASE_MT);
7047 gen_helper_mtc0_tccontext(cpu_env, arg);
7048 rn = "TCContext";
7049 break;
7050 case 6:
7051 CP0_CHECK(ctx->insn_flags & ASE_MT);
7052 gen_helper_mtc0_tcschedule(cpu_env, arg);
7053 rn = "TCSchedule";
7054 break;
7055 case 7:
7056 CP0_CHECK(ctx->insn_flags & ASE_MT);
7057 gen_helper_mtc0_tcschefback(cpu_env, arg);
7058 rn = "TCScheFBack";
7059 break;
7060 default:
7061 goto cp0_unimplemented;
7063 break;
7064 case 3:
7065 switch (sel) {
7066 case 0:
7067 gen_helper_dmtc0_entrylo1(cpu_env, arg);
7068 rn = "EntryLo1";
7069 break;
7070 case 1:
7071 CP0_CHECK(ctx->vp);
7072 /* ignored */
7073 rn = "GlobalNumber";
7074 break;
7075 default:
7076 goto cp0_unimplemented;
7078 break;
7079 case 4:
7080 switch (sel) {
7081 case 0:
7082 gen_helper_mtc0_context(cpu_env, arg);
7083 rn = "Context";
7084 break;
7085 case 1:
7086 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7087 rn = "ContextConfig";
7088 goto cp0_unimplemented;
7089 case 2:
7090 CP0_CHECK(ctx->ulri);
7091 tcg_gen_st_tl(arg, cpu_env,
7092 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7093 rn = "UserLocal";
7094 break;
7095 default:
7096 goto cp0_unimplemented;
7098 break;
7099 case 5:
7100 switch (sel) {
7101 case 0:
7102 gen_helper_mtc0_pagemask(cpu_env, arg);
7103 rn = "PageMask";
7104 break;
7105 case 1:
7106 check_insn(ctx, ISA_MIPS32R2);
7107 gen_helper_mtc0_pagegrain(cpu_env, arg);
7108 rn = "PageGrain";
7109 break;
7110 default:
7111 goto cp0_unimplemented;
7113 break;
7114 case 6:
7115 switch (sel) {
7116 case 0:
7117 gen_helper_mtc0_wired(cpu_env, arg);
7118 rn = "Wired";
7119 break;
7120 case 1:
7121 check_insn(ctx, ISA_MIPS32R2);
7122 gen_helper_mtc0_srsconf0(cpu_env, arg);
7123 rn = "SRSConf0";
7124 break;
7125 case 2:
7126 check_insn(ctx, ISA_MIPS32R2);
7127 gen_helper_mtc0_srsconf1(cpu_env, arg);
7128 rn = "SRSConf1";
7129 break;
7130 case 3:
7131 check_insn(ctx, ISA_MIPS32R2);
7132 gen_helper_mtc0_srsconf2(cpu_env, arg);
7133 rn = "SRSConf2";
7134 break;
7135 case 4:
7136 check_insn(ctx, ISA_MIPS32R2);
7137 gen_helper_mtc0_srsconf3(cpu_env, arg);
7138 rn = "SRSConf3";
7139 break;
7140 case 5:
7141 check_insn(ctx, ISA_MIPS32R2);
7142 gen_helper_mtc0_srsconf4(cpu_env, arg);
7143 rn = "SRSConf4";
7144 break;
7145 default:
7146 goto cp0_unimplemented;
7148 break;
7149 case 7:
7150 switch (sel) {
7151 case 0:
7152 check_insn(ctx, ISA_MIPS32R2);
7153 gen_helper_mtc0_hwrena(cpu_env, arg);
7154 ctx->bstate = BS_STOP;
7155 rn = "HWREna";
7156 break;
7157 default:
7158 goto cp0_unimplemented;
7160 break;
7161 case 8:
7162 switch (sel) {
7163 case 0:
7164 /* ignored */
7165 rn = "BadVAddr";
7166 break;
7167 case 1:
7168 /* ignored */
7169 rn = "BadInstr";
7170 break;
7171 case 2:
7172 /* ignored */
7173 rn = "BadInstrP";
7174 break;
7175 default:
7176 goto cp0_unimplemented;
7178 break;
7179 case 9:
7180 switch (sel) {
7181 case 0:
7182 gen_helper_mtc0_count(cpu_env, arg);
7183 rn = "Count";
7184 break;
7185 /* 6,7 are implementation dependent */
7186 default:
7187 goto cp0_unimplemented;
7189 /* Stop translation as we may have switched the execution mode */
7190 ctx->bstate = BS_STOP;
7191 break;
7192 case 10:
7193 switch (sel) {
7194 case 0:
7195 gen_helper_mtc0_entryhi(cpu_env, arg);
7196 rn = "EntryHi";
7197 break;
7198 default:
7199 goto cp0_unimplemented;
7201 break;
7202 case 11:
7203 switch (sel) {
7204 case 0:
7205 gen_helper_mtc0_compare(cpu_env, arg);
7206 rn = "Compare";
7207 break;
7208 /* 6,7 are implementation dependent */
7209 default:
7210 goto cp0_unimplemented;
7212 /* Stop translation as we may have switched the execution mode */
7213 ctx->bstate = BS_STOP;
7214 break;
7215 case 12:
7216 switch (sel) {
7217 case 0:
7218 save_cpu_state(ctx, 1);
7219 gen_helper_mtc0_status(cpu_env, arg);
7220 /* BS_STOP isn't good enough here, hflags may have changed. */
7221 gen_save_pc(ctx->pc + 4);
7222 ctx->bstate = BS_EXCP;
7223 rn = "Status";
7224 break;
7225 case 1:
7226 check_insn(ctx, ISA_MIPS32R2);
7227 gen_helper_mtc0_intctl(cpu_env, arg);
7228 /* Stop translation as we may have switched the execution mode */
7229 ctx->bstate = BS_STOP;
7230 rn = "IntCtl";
7231 break;
7232 case 2:
7233 check_insn(ctx, ISA_MIPS32R2);
7234 gen_helper_mtc0_srsctl(cpu_env, arg);
7235 /* Stop translation as we may have switched the execution mode */
7236 ctx->bstate = BS_STOP;
7237 rn = "SRSCtl";
7238 break;
7239 case 3:
7240 check_insn(ctx, ISA_MIPS32R2);
7241 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7242 /* Stop translation as we may have switched the execution mode */
7243 ctx->bstate = BS_STOP;
7244 rn = "SRSMap";
7245 break;
7246 default:
7247 goto cp0_unimplemented;
7249 break;
7250 case 13:
7251 switch (sel) {
7252 case 0:
7253 save_cpu_state(ctx, 1);
7254 /* Mark as an IO operation because we may trigger a software
7255 interrupt. */
7256 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7257 gen_io_start();
7259 gen_helper_mtc0_cause(cpu_env, arg);
7260 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7261 gen_io_end();
7263 /* Stop translation as we may have triggered an intetrupt */
7264 ctx->bstate = BS_STOP;
7265 rn = "Cause";
7266 break;
7267 default:
7268 goto cp0_unimplemented;
7270 break;
7271 case 14:
7272 switch (sel) {
7273 case 0:
7274 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7275 rn = "EPC";
7276 break;
7277 default:
7278 goto cp0_unimplemented;
7280 break;
7281 case 15:
7282 switch (sel) {
7283 case 0:
7284 /* ignored */
7285 rn = "PRid";
7286 break;
7287 case 1:
7288 check_insn(ctx, ISA_MIPS32R2);
7289 gen_helper_mtc0_ebase(cpu_env, arg);
7290 rn = "EBase";
7291 break;
7292 default:
7293 goto cp0_unimplemented;
7295 break;
7296 case 16:
7297 switch (sel) {
7298 case 0:
7299 gen_helper_mtc0_config0(cpu_env, arg);
7300 rn = "Config";
7301 /* Stop translation as we may have switched the execution mode */
7302 ctx->bstate = BS_STOP;
7303 break;
7304 case 1:
7305 /* ignored, read only */
7306 rn = "Config1";
7307 break;
7308 case 2:
7309 gen_helper_mtc0_config2(cpu_env, arg);
7310 rn = "Config2";
7311 /* Stop translation as we may have switched the execution mode */
7312 ctx->bstate = BS_STOP;
7313 break;
7314 case 3:
7315 gen_helper_mtc0_config3(cpu_env, arg);
7316 rn = "Config3";
7317 /* Stop translation as we may have switched the execution mode */
7318 ctx->bstate = BS_STOP;
7319 break;
7320 case 4:
7321 /* currently ignored */
7322 rn = "Config4";
7323 break;
7324 case 5:
7325 gen_helper_mtc0_config5(cpu_env, arg);
7326 rn = "Config5";
7327 /* Stop translation as we may have switched the execution mode */
7328 ctx->bstate = BS_STOP;
7329 break;
7330 /* 6,7 are implementation dependent */
7331 default:
7332 rn = "Invalid config selector";
7333 goto cp0_unimplemented;
7335 break;
7336 case 17:
7337 switch (sel) {
7338 case 0:
7339 gen_helper_mtc0_lladdr(cpu_env, arg);
7340 rn = "LLAddr";
7341 break;
7342 case 1:
7343 CP0_CHECK(ctx->mrp);
7344 gen_helper_mtc0_maar(cpu_env, arg);
7345 rn = "MAAR";
7346 break;
7347 case 2:
7348 CP0_CHECK(ctx->mrp);
7349 gen_helper_mtc0_maari(cpu_env, arg);
7350 rn = "MAARI";
7351 break;
7352 default:
7353 goto cp0_unimplemented;
7355 break;
7356 case 18:
7357 switch (sel) {
7358 case 0 ... 7:
7359 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7360 rn = "WatchLo";
7361 break;
7362 default:
7363 goto cp0_unimplemented;
7365 break;
7366 case 19:
7367 switch (sel) {
7368 case 0 ... 7:
7369 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7370 rn = "WatchHi";
7371 break;
7372 default:
7373 goto cp0_unimplemented;
7375 break;
7376 case 20:
7377 switch (sel) {
7378 case 0:
7379 check_insn(ctx, ISA_MIPS3);
7380 gen_helper_mtc0_xcontext(cpu_env, arg);
7381 rn = "XContext";
7382 break;
7383 default:
7384 goto cp0_unimplemented;
7386 break;
7387 case 21:
7388 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7389 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7390 switch (sel) {
7391 case 0:
7392 gen_helper_mtc0_framemask(cpu_env, arg);
7393 rn = "Framemask";
7394 break;
7395 default:
7396 goto cp0_unimplemented;
7398 break;
7399 case 22:
7400 /* ignored */
7401 rn = "Diagnostic"; /* implementation dependent */
7402 break;
7403 case 23:
7404 switch (sel) {
7405 case 0:
7406 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7407 /* BS_STOP isn't good enough here, hflags may have changed. */
7408 gen_save_pc(ctx->pc + 4);
7409 ctx->bstate = BS_EXCP;
7410 rn = "Debug";
7411 break;
7412 case 1:
7413 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7414 /* Stop translation as we may have switched the execution mode */
7415 ctx->bstate = BS_STOP;
7416 rn = "TraceControl";
7417 goto cp0_unimplemented;
7418 case 2:
7419 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7420 /* Stop translation as we may have switched the execution mode */
7421 ctx->bstate = BS_STOP;
7422 rn = "TraceControl2";
7423 goto cp0_unimplemented;
7424 case 3:
7425 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7426 /* Stop translation as we may have switched the execution mode */
7427 ctx->bstate = BS_STOP;
7428 rn = "UserTraceData";
7429 goto cp0_unimplemented;
7430 case 4:
7431 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7432 /* Stop translation as we may have switched the execution mode */
7433 ctx->bstate = BS_STOP;
7434 rn = "TraceBPC";
7435 goto cp0_unimplemented;
7436 default:
7437 goto cp0_unimplemented;
7439 break;
7440 case 24:
7441 switch (sel) {
7442 case 0:
7443 /* EJTAG support */
7444 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7445 rn = "DEPC";
7446 break;
7447 default:
7448 goto cp0_unimplemented;
7450 break;
7451 case 25:
7452 switch (sel) {
7453 case 0:
7454 gen_helper_mtc0_performance0(cpu_env, arg);
7455 rn = "Performance0";
7456 break;
7457 case 1:
7458 // gen_helper_mtc0_performance1(cpu_env, arg);
7459 rn = "Performance1";
7460 goto cp0_unimplemented;
7461 case 2:
7462 // gen_helper_mtc0_performance2(cpu_env, arg);
7463 rn = "Performance2";
7464 goto cp0_unimplemented;
7465 case 3:
7466 // gen_helper_mtc0_performance3(cpu_env, arg);
7467 rn = "Performance3";
7468 goto cp0_unimplemented;
7469 case 4:
7470 // gen_helper_mtc0_performance4(cpu_env, arg);
7471 rn = "Performance4";
7472 goto cp0_unimplemented;
7473 case 5:
7474 // gen_helper_mtc0_performance5(cpu_env, arg);
7475 rn = "Performance5";
7476 goto cp0_unimplemented;
7477 case 6:
7478 // gen_helper_mtc0_performance6(cpu_env, arg);
7479 rn = "Performance6";
7480 goto cp0_unimplemented;
7481 case 7:
7482 // gen_helper_mtc0_performance7(cpu_env, arg);
7483 rn = "Performance7";
7484 goto cp0_unimplemented;
7485 default:
7486 goto cp0_unimplemented;
7488 break;
7489 case 26:
7490 switch (sel) {
7491 case 0:
7492 gen_helper_mtc0_errctl(cpu_env, arg);
7493 ctx->bstate = BS_STOP;
7494 rn = "ErrCtl";
7495 break;
7496 default:
7497 goto cp0_unimplemented;
7499 break;
7500 case 27:
7501 switch (sel) {
7502 case 0 ... 3:
7503 /* ignored */
7504 rn = "CacheErr";
7505 break;
7506 default:
7507 goto cp0_unimplemented;
7509 break;
7510 case 28:
7511 switch (sel) {
7512 case 0:
7513 case 2:
7514 case 4:
7515 case 6:
7516 gen_helper_mtc0_taglo(cpu_env, arg);
7517 rn = "TagLo";
7518 break;
7519 case 1:
7520 case 3:
7521 case 5:
7522 case 7:
7523 gen_helper_mtc0_datalo(cpu_env, arg);
7524 rn = "DataLo";
7525 break;
7526 default:
7527 goto cp0_unimplemented;
7529 break;
7530 case 29:
7531 switch (sel) {
7532 case 0:
7533 case 2:
7534 case 4:
7535 case 6:
7536 gen_helper_mtc0_taghi(cpu_env, arg);
7537 rn = "TagHi";
7538 break;
7539 case 1:
7540 case 3:
7541 case 5:
7542 case 7:
7543 gen_helper_mtc0_datahi(cpu_env, arg);
7544 rn = "DataHi";
7545 break;
7546 default:
7547 rn = "invalid sel";
7548 goto cp0_unimplemented;
7550 break;
7551 case 30:
7552 switch (sel) {
7553 case 0:
7554 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7555 rn = "ErrorEPC";
7556 break;
7557 default:
7558 goto cp0_unimplemented;
7560 break;
7561 case 31:
7562 switch (sel) {
7563 case 0:
7564 /* EJTAG support */
7565 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7566 rn = "DESAVE";
7567 break;
7568 case 2 ... 7:
7569 CP0_CHECK(ctx->kscrexist & (1 << sel));
7570 tcg_gen_st_tl(arg, cpu_env,
7571 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7572 rn = "KScratch";
7573 break;
7574 default:
7575 goto cp0_unimplemented;
7577 /* Stop translation as we may have switched the execution mode */
7578 ctx->bstate = BS_STOP;
7579 break;
7580 default:
7581 goto cp0_unimplemented;
7583 trace_mips_translate_c0("dmtc0", rn, reg, sel);
7585 /* For simplicity assume that all writes can cause interrupts. */
7586 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7587 gen_io_end();
7588 ctx->bstate = BS_STOP;
7590 return;
7592 cp0_unimplemented:
7593 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7595 #endif /* TARGET_MIPS64 */
7597 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7598 int u, int sel, int h)
7600 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7601 TCGv t0 = tcg_temp_local_new();
7603 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7604 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7605 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7606 tcg_gen_movi_tl(t0, -1);
7607 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7608 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7609 tcg_gen_movi_tl(t0, -1);
7610 else if (u == 0) {
7611 switch (rt) {
7612 case 1:
7613 switch (sel) {
7614 case 1:
7615 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7616 break;
7617 case 2:
7618 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7619 break;
7620 default:
7621 goto die;
7622 break;
7624 break;
7625 case 2:
7626 switch (sel) {
7627 case 1:
7628 gen_helper_mftc0_tcstatus(t0, cpu_env);
7629 break;
7630 case 2:
7631 gen_helper_mftc0_tcbind(t0, cpu_env);
7632 break;
7633 case 3:
7634 gen_helper_mftc0_tcrestart(t0, cpu_env);
7635 break;
7636 case 4:
7637 gen_helper_mftc0_tchalt(t0, cpu_env);
7638 break;
7639 case 5:
7640 gen_helper_mftc0_tccontext(t0, cpu_env);
7641 break;
7642 case 6:
7643 gen_helper_mftc0_tcschedule(t0, cpu_env);
7644 break;
7645 case 7:
7646 gen_helper_mftc0_tcschefback(t0, cpu_env);
7647 break;
7648 default:
7649 gen_mfc0(ctx, t0, rt, sel);
7650 break;
7652 break;
7653 case 10:
7654 switch (sel) {
7655 case 0:
7656 gen_helper_mftc0_entryhi(t0, cpu_env);
7657 break;
7658 default:
7659 gen_mfc0(ctx, t0, rt, sel);
7660 break;
7662 case 12:
7663 switch (sel) {
7664 case 0:
7665 gen_helper_mftc0_status(t0, cpu_env);
7666 break;
7667 default:
7668 gen_mfc0(ctx, t0, rt, sel);
7669 break;
7671 case 13:
7672 switch (sel) {
7673 case 0:
7674 gen_helper_mftc0_cause(t0, cpu_env);
7675 break;
7676 default:
7677 goto die;
7678 break;
7680 break;
7681 case 14:
7682 switch (sel) {
7683 case 0:
7684 gen_helper_mftc0_epc(t0, cpu_env);
7685 break;
7686 default:
7687 goto die;
7688 break;
7690 break;
7691 case 15:
7692 switch (sel) {
7693 case 1:
7694 gen_helper_mftc0_ebase(t0, cpu_env);
7695 break;
7696 default:
7697 goto die;
7698 break;
7700 break;
7701 case 16:
7702 switch (sel) {
7703 case 0 ... 7:
7704 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7705 break;
7706 default:
7707 goto die;
7708 break;
7710 break;
7711 case 23:
7712 switch (sel) {
7713 case 0:
7714 gen_helper_mftc0_debug(t0, cpu_env);
7715 break;
7716 default:
7717 gen_mfc0(ctx, t0, rt, sel);
7718 break;
7720 break;
7721 default:
7722 gen_mfc0(ctx, t0, rt, sel);
7724 } else switch (sel) {
7725 /* GPR registers. */
7726 case 0:
7727 gen_helper_1e0i(mftgpr, t0, rt);
7728 break;
7729 /* Auxiliary CPU registers */
7730 case 1:
7731 switch (rt) {
7732 case 0:
7733 gen_helper_1e0i(mftlo, t0, 0);
7734 break;
7735 case 1:
7736 gen_helper_1e0i(mfthi, t0, 0);
7737 break;
7738 case 2:
7739 gen_helper_1e0i(mftacx, t0, 0);
7740 break;
7741 case 4:
7742 gen_helper_1e0i(mftlo, t0, 1);
7743 break;
7744 case 5:
7745 gen_helper_1e0i(mfthi, t0, 1);
7746 break;
7747 case 6:
7748 gen_helper_1e0i(mftacx, t0, 1);
7749 break;
7750 case 8:
7751 gen_helper_1e0i(mftlo, t0, 2);
7752 break;
7753 case 9:
7754 gen_helper_1e0i(mfthi, t0, 2);
7755 break;
7756 case 10:
7757 gen_helper_1e0i(mftacx, t0, 2);
7758 break;
7759 case 12:
7760 gen_helper_1e0i(mftlo, t0, 3);
7761 break;
7762 case 13:
7763 gen_helper_1e0i(mfthi, t0, 3);
7764 break;
7765 case 14:
7766 gen_helper_1e0i(mftacx, t0, 3);
7767 break;
7768 case 16:
7769 gen_helper_mftdsp(t0, cpu_env);
7770 break;
7771 default:
7772 goto die;
7774 break;
7775 /* Floating point (COP1). */
7776 case 2:
7777 /* XXX: For now we support only a single FPU context. */
7778 if (h == 0) {
7779 TCGv_i32 fp0 = tcg_temp_new_i32();
7781 gen_load_fpr32(ctx, fp0, rt);
7782 tcg_gen_ext_i32_tl(t0, fp0);
7783 tcg_temp_free_i32(fp0);
7784 } else {
7785 TCGv_i32 fp0 = tcg_temp_new_i32();
7787 gen_load_fpr32h(ctx, fp0, rt);
7788 tcg_gen_ext_i32_tl(t0, fp0);
7789 tcg_temp_free_i32(fp0);
7791 break;
7792 case 3:
7793 /* XXX: For now we support only a single FPU context. */
7794 gen_helper_1e0i(cfc1, t0, rt);
7795 break;
7796 /* COP2: Not implemented. */
7797 case 4:
7798 case 5:
7799 /* fall through */
7800 default:
7801 goto die;
7803 trace_mips_translate_tr("mftr", rt, u, sel, h);
7804 gen_store_gpr(t0, rd);
7805 tcg_temp_free(t0);
7806 return;
7808 die:
7809 tcg_temp_free(t0);
7810 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7811 generate_exception_end(ctx, EXCP_RI);
7814 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7815 int u, int sel, int h)
7817 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7818 TCGv t0 = tcg_temp_local_new();
7820 gen_load_gpr(t0, rt);
7821 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7822 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7823 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7824 /* NOP */ ;
7825 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7826 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7827 /* NOP */ ;
7828 else if (u == 0) {
7829 switch (rd) {
7830 case 1:
7831 switch (sel) {
7832 case 1:
7833 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7834 break;
7835 case 2:
7836 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7837 break;
7838 default:
7839 goto die;
7840 break;
7842 break;
7843 case 2:
7844 switch (sel) {
7845 case 1:
7846 gen_helper_mttc0_tcstatus(cpu_env, t0);
7847 break;
7848 case 2:
7849 gen_helper_mttc0_tcbind(cpu_env, t0);
7850 break;
7851 case 3:
7852 gen_helper_mttc0_tcrestart(cpu_env, t0);
7853 break;
7854 case 4:
7855 gen_helper_mttc0_tchalt(cpu_env, t0);
7856 break;
7857 case 5:
7858 gen_helper_mttc0_tccontext(cpu_env, t0);
7859 break;
7860 case 6:
7861 gen_helper_mttc0_tcschedule(cpu_env, t0);
7862 break;
7863 case 7:
7864 gen_helper_mttc0_tcschefback(cpu_env, t0);
7865 break;
7866 default:
7867 gen_mtc0(ctx, t0, rd, sel);
7868 break;
7870 break;
7871 case 10:
7872 switch (sel) {
7873 case 0:
7874 gen_helper_mttc0_entryhi(cpu_env, t0);
7875 break;
7876 default:
7877 gen_mtc0(ctx, t0, rd, sel);
7878 break;
7880 case 12:
7881 switch (sel) {
7882 case 0:
7883 gen_helper_mttc0_status(cpu_env, t0);
7884 break;
7885 default:
7886 gen_mtc0(ctx, t0, rd, sel);
7887 break;
7889 case 13:
7890 switch (sel) {
7891 case 0:
7892 gen_helper_mttc0_cause(cpu_env, t0);
7893 break;
7894 default:
7895 goto die;
7896 break;
7898 break;
7899 case 15:
7900 switch (sel) {
7901 case 1:
7902 gen_helper_mttc0_ebase(cpu_env, t0);
7903 break;
7904 default:
7905 goto die;
7906 break;
7908 break;
7909 case 23:
7910 switch (sel) {
7911 case 0:
7912 gen_helper_mttc0_debug(cpu_env, t0);
7913 break;
7914 default:
7915 gen_mtc0(ctx, t0, rd, sel);
7916 break;
7918 break;
7919 default:
7920 gen_mtc0(ctx, t0, rd, sel);
7922 } else switch (sel) {
7923 /* GPR registers. */
7924 case 0:
7925 gen_helper_0e1i(mttgpr, t0, rd);
7926 break;
7927 /* Auxiliary CPU registers */
7928 case 1:
7929 switch (rd) {
7930 case 0:
7931 gen_helper_0e1i(mttlo, t0, 0);
7932 break;
7933 case 1:
7934 gen_helper_0e1i(mtthi, t0, 0);
7935 break;
7936 case 2:
7937 gen_helper_0e1i(mttacx, t0, 0);
7938 break;
7939 case 4:
7940 gen_helper_0e1i(mttlo, t0, 1);
7941 break;
7942 case 5:
7943 gen_helper_0e1i(mtthi, t0, 1);
7944 break;
7945 case 6:
7946 gen_helper_0e1i(mttacx, t0, 1);
7947 break;
7948 case 8:
7949 gen_helper_0e1i(mttlo, t0, 2);
7950 break;
7951 case 9:
7952 gen_helper_0e1i(mtthi, t0, 2);
7953 break;
7954 case 10:
7955 gen_helper_0e1i(mttacx, t0, 2);
7956 break;
7957 case 12:
7958 gen_helper_0e1i(mttlo, t0, 3);
7959 break;
7960 case 13:
7961 gen_helper_0e1i(mtthi, t0, 3);
7962 break;
7963 case 14:
7964 gen_helper_0e1i(mttacx, t0, 3);
7965 break;
7966 case 16:
7967 gen_helper_mttdsp(cpu_env, t0);
7968 break;
7969 default:
7970 goto die;
7972 break;
7973 /* Floating point (COP1). */
7974 case 2:
7975 /* XXX: For now we support only a single FPU context. */
7976 if (h == 0) {
7977 TCGv_i32 fp0 = tcg_temp_new_i32();
7979 tcg_gen_trunc_tl_i32(fp0, t0);
7980 gen_store_fpr32(ctx, fp0, rd);
7981 tcg_temp_free_i32(fp0);
7982 } else {
7983 TCGv_i32 fp0 = tcg_temp_new_i32();
7985 tcg_gen_trunc_tl_i32(fp0, t0);
7986 gen_store_fpr32h(ctx, fp0, rd);
7987 tcg_temp_free_i32(fp0);
7989 break;
7990 case 3:
7991 /* XXX: For now we support only a single FPU context. */
7993 TCGv_i32 fs_tmp = tcg_const_i32(rd);
7995 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7996 tcg_temp_free_i32(fs_tmp);
7998 /* Stop translation as we may have changed hflags */
7999 ctx->bstate = BS_STOP;
8000 break;
8001 /* COP2: Not implemented. */
8002 case 4:
8003 case 5:
8004 /* fall through */
8005 default:
8006 goto die;
8008 trace_mips_translate_tr("mttr", rd, u, sel, h);
8009 tcg_temp_free(t0);
8010 return;
8012 die:
8013 tcg_temp_free(t0);
8014 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8015 generate_exception_end(ctx, EXCP_RI);
8018 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
8020 const char *opn = "ldst";
8022 check_cp0_enabled(ctx);
8023 switch (opc) {
8024 case OPC_MFC0:
8025 if (rt == 0) {
8026 /* Treat as NOP. */
8027 return;
8029 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8030 opn = "mfc0";
8031 break;
8032 case OPC_MTC0:
8034 TCGv t0 = tcg_temp_new();
8036 gen_load_gpr(t0, rt);
8037 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8038 tcg_temp_free(t0);
8040 opn = "mtc0";
8041 break;
8042 #if defined(TARGET_MIPS64)
8043 case OPC_DMFC0:
8044 check_insn(ctx, ISA_MIPS3);
8045 if (rt == 0) {
8046 /* Treat as NOP. */
8047 return;
8049 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8050 opn = "dmfc0";
8051 break;
8052 case OPC_DMTC0:
8053 check_insn(ctx, ISA_MIPS3);
8055 TCGv t0 = tcg_temp_new();
8057 gen_load_gpr(t0, rt);
8058 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8059 tcg_temp_free(t0);
8061 opn = "dmtc0";
8062 break;
8063 #endif
8064 case OPC_MFHC0:
8065 check_mvh(ctx);
8066 if (rt == 0) {
8067 /* Treat as NOP. */
8068 return;
8070 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8071 opn = "mfhc0";
8072 break;
8073 case OPC_MTHC0:
8074 check_mvh(ctx);
8076 TCGv t0 = tcg_temp_new();
8077 gen_load_gpr(t0, rt);
8078 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8079 tcg_temp_free(t0);
8081 opn = "mthc0";
8082 break;
8083 case OPC_MFTR:
8084 check_insn(ctx, ASE_MT);
8085 if (rd == 0) {
8086 /* Treat as NOP. */
8087 return;
8089 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8090 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8091 opn = "mftr";
8092 break;
8093 case OPC_MTTR:
8094 check_insn(ctx, ASE_MT);
8095 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8096 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8097 opn = "mttr";
8098 break;
8099 case OPC_TLBWI:
8100 opn = "tlbwi";
8101 if (!env->tlb->helper_tlbwi)
8102 goto die;
8103 gen_helper_tlbwi(cpu_env);
8104 break;
8105 case OPC_TLBINV:
8106 opn = "tlbinv";
8107 if (ctx->ie >= 2) {
8108 if (!env->tlb->helper_tlbinv) {
8109 goto die;
8111 gen_helper_tlbinv(cpu_env);
8112 } /* treat as nop if TLBINV not supported */
8113 break;
8114 case OPC_TLBINVF:
8115 opn = "tlbinvf";
8116 if (ctx->ie >= 2) {
8117 if (!env->tlb->helper_tlbinvf) {
8118 goto die;
8120 gen_helper_tlbinvf(cpu_env);
8121 } /* treat as nop if TLBINV not supported */
8122 break;
8123 case OPC_TLBWR:
8124 opn = "tlbwr";
8125 if (!env->tlb->helper_tlbwr)
8126 goto die;
8127 gen_helper_tlbwr(cpu_env);
8128 break;
8129 case OPC_TLBP:
8130 opn = "tlbp";
8131 if (!env->tlb->helper_tlbp)
8132 goto die;
8133 gen_helper_tlbp(cpu_env);
8134 break;
8135 case OPC_TLBR:
8136 opn = "tlbr";
8137 if (!env->tlb->helper_tlbr)
8138 goto die;
8139 gen_helper_tlbr(cpu_env);
8140 break;
8141 case OPC_ERET: /* OPC_ERETNC */
8142 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8143 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8144 goto die;
8145 } else {
8146 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8147 if (ctx->opcode & (1 << bit_shift)) {
8148 /* OPC_ERETNC */
8149 opn = "eretnc";
8150 check_insn(ctx, ISA_MIPS32R5);
8151 gen_helper_eretnc(cpu_env);
8152 } else {
8153 /* OPC_ERET */
8154 opn = "eret";
8155 check_insn(ctx, ISA_MIPS2);
8156 gen_helper_eret(cpu_env);
8158 ctx->bstate = BS_EXCP;
8160 break;
8161 case OPC_DERET:
8162 opn = "deret";
8163 check_insn(ctx, ISA_MIPS32);
8164 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8165 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8166 goto die;
8168 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8169 MIPS_INVAL(opn);
8170 generate_exception_end(ctx, EXCP_RI);
8171 } else {
8172 gen_helper_deret(cpu_env);
8173 ctx->bstate = BS_EXCP;
8175 break;
8176 case OPC_WAIT:
8177 opn = "wait";
8178 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8179 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8180 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8181 goto die;
8183 /* If we get an exception, we want to restart at next instruction */
8184 ctx->pc += 4;
8185 save_cpu_state(ctx, 1);
8186 ctx->pc -= 4;
8187 gen_helper_wait(cpu_env);
8188 ctx->bstate = BS_EXCP;
8189 break;
8190 default:
8191 die:
8192 MIPS_INVAL(opn);
8193 generate_exception_end(ctx, EXCP_RI);
8194 return;
8196 (void)opn; /* avoid a compiler warning */
8198 #endif /* !CONFIG_USER_ONLY */
8200 /* CP1 Branches (before delay slot) */
8201 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8202 int32_t cc, int32_t offset)
8204 target_ulong btarget;
8205 TCGv_i32 t0 = tcg_temp_new_i32();
8207 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8208 generate_exception_end(ctx, EXCP_RI);
8209 goto out;
8212 if (cc != 0)
8213 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8215 btarget = ctx->pc + 4 + offset;
8217 switch (op) {
8218 case OPC_BC1F:
8219 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8220 tcg_gen_not_i32(t0, t0);
8221 tcg_gen_andi_i32(t0, t0, 1);
8222 tcg_gen_extu_i32_tl(bcond, t0);
8223 goto not_likely;
8224 case OPC_BC1FL:
8225 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8226 tcg_gen_not_i32(t0, t0);
8227 tcg_gen_andi_i32(t0, t0, 1);
8228 tcg_gen_extu_i32_tl(bcond, t0);
8229 goto likely;
8230 case OPC_BC1T:
8231 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8232 tcg_gen_andi_i32(t0, t0, 1);
8233 tcg_gen_extu_i32_tl(bcond, t0);
8234 goto not_likely;
8235 case OPC_BC1TL:
8236 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8237 tcg_gen_andi_i32(t0, t0, 1);
8238 tcg_gen_extu_i32_tl(bcond, t0);
8239 likely:
8240 ctx->hflags |= MIPS_HFLAG_BL;
8241 break;
8242 case OPC_BC1FANY2:
8244 TCGv_i32 t1 = tcg_temp_new_i32();
8245 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8246 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8247 tcg_gen_nand_i32(t0, t0, t1);
8248 tcg_temp_free_i32(t1);
8249 tcg_gen_andi_i32(t0, t0, 1);
8250 tcg_gen_extu_i32_tl(bcond, t0);
8252 goto not_likely;
8253 case OPC_BC1TANY2:
8255 TCGv_i32 t1 = tcg_temp_new_i32();
8256 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8257 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8258 tcg_gen_or_i32(t0, t0, t1);
8259 tcg_temp_free_i32(t1);
8260 tcg_gen_andi_i32(t0, t0, 1);
8261 tcg_gen_extu_i32_tl(bcond, t0);
8263 goto not_likely;
8264 case OPC_BC1FANY4:
8266 TCGv_i32 t1 = tcg_temp_new_i32();
8267 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8268 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8269 tcg_gen_and_i32(t0, t0, t1);
8270 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8271 tcg_gen_and_i32(t0, t0, t1);
8272 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8273 tcg_gen_nand_i32(t0, t0, t1);
8274 tcg_temp_free_i32(t1);
8275 tcg_gen_andi_i32(t0, t0, 1);
8276 tcg_gen_extu_i32_tl(bcond, t0);
8278 goto not_likely;
8279 case OPC_BC1TANY4:
8281 TCGv_i32 t1 = tcg_temp_new_i32();
8282 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8283 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8284 tcg_gen_or_i32(t0, t0, t1);
8285 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8286 tcg_gen_or_i32(t0, t0, t1);
8287 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8288 tcg_gen_or_i32(t0, t0, t1);
8289 tcg_temp_free_i32(t1);
8290 tcg_gen_andi_i32(t0, t0, 1);
8291 tcg_gen_extu_i32_tl(bcond, t0);
8293 not_likely:
8294 ctx->hflags |= MIPS_HFLAG_BC;
8295 break;
8296 default:
8297 MIPS_INVAL("cp1 cond branch");
8298 generate_exception_end(ctx, EXCP_RI);
8299 goto out;
8301 ctx->btarget = btarget;
8302 ctx->hflags |= MIPS_HFLAG_BDS32;
8303 out:
8304 tcg_temp_free_i32(t0);
8307 /* R6 CP1 Branches */
8308 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8309 int32_t ft, int32_t offset,
8310 int delayslot_size)
8312 target_ulong btarget;
8313 TCGv_i64 t0 = tcg_temp_new_i64();
8315 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8316 #ifdef MIPS_DEBUG_DISAS
8317 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8318 "\n", ctx->pc);
8319 #endif
8320 generate_exception_end(ctx, EXCP_RI);
8321 goto out;
8324 gen_load_fpr64(ctx, t0, ft);
8325 tcg_gen_andi_i64(t0, t0, 1);
8327 btarget = addr_add(ctx, ctx->pc + 4, offset);
8329 switch (op) {
8330 case OPC_BC1EQZ:
8331 tcg_gen_xori_i64(t0, t0, 1);
8332 ctx->hflags |= MIPS_HFLAG_BC;
8333 break;
8334 case OPC_BC1NEZ:
8335 /* t0 already set */
8336 ctx->hflags |= MIPS_HFLAG_BC;
8337 break;
8338 default:
8339 MIPS_INVAL("cp1 cond branch");
8340 generate_exception_end(ctx, EXCP_RI);
8341 goto out;
8344 tcg_gen_trunc_i64_tl(bcond, t0);
8346 ctx->btarget = btarget;
8348 switch (delayslot_size) {
8349 case 2:
8350 ctx->hflags |= MIPS_HFLAG_BDS16;
8351 break;
8352 case 4:
8353 ctx->hflags |= MIPS_HFLAG_BDS32;
8354 break;
8357 out:
8358 tcg_temp_free_i64(t0);
8361 /* Coprocessor 1 (FPU) */
8363 #define FOP(func, fmt) (((fmt) << 21) | (func))
8365 enum fopcode {
8366 OPC_ADD_S = FOP(0, FMT_S),
8367 OPC_SUB_S = FOP(1, FMT_S),
8368 OPC_MUL_S = FOP(2, FMT_S),
8369 OPC_DIV_S = FOP(3, FMT_S),
8370 OPC_SQRT_S = FOP(4, FMT_S),
8371 OPC_ABS_S = FOP(5, FMT_S),
8372 OPC_MOV_S = FOP(6, FMT_S),
8373 OPC_NEG_S = FOP(7, FMT_S),
8374 OPC_ROUND_L_S = FOP(8, FMT_S),
8375 OPC_TRUNC_L_S = FOP(9, FMT_S),
8376 OPC_CEIL_L_S = FOP(10, FMT_S),
8377 OPC_FLOOR_L_S = FOP(11, FMT_S),
8378 OPC_ROUND_W_S = FOP(12, FMT_S),
8379 OPC_TRUNC_W_S = FOP(13, FMT_S),
8380 OPC_CEIL_W_S = FOP(14, FMT_S),
8381 OPC_FLOOR_W_S = FOP(15, FMT_S),
8382 OPC_SEL_S = FOP(16, FMT_S),
8383 OPC_MOVCF_S = FOP(17, FMT_S),
8384 OPC_MOVZ_S = FOP(18, FMT_S),
8385 OPC_MOVN_S = FOP(19, FMT_S),
8386 OPC_SELEQZ_S = FOP(20, FMT_S),
8387 OPC_RECIP_S = FOP(21, FMT_S),
8388 OPC_RSQRT_S = FOP(22, FMT_S),
8389 OPC_SELNEZ_S = FOP(23, FMT_S),
8390 OPC_MADDF_S = FOP(24, FMT_S),
8391 OPC_MSUBF_S = FOP(25, FMT_S),
8392 OPC_RINT_S = FOP(26, FMT_S),
8393 OPC_CLASS_S = FOP(27, FMT_S),
8394 OPC_MIN_S = FOP(28, FMT_S),
8395 OPC_RECIP2_S = FOP(28, FMT_S),
8396 OPC_MINA_S = FOP(29, FMT_S),
8397 OPC_RECIP1_S = FOP(29, FMT_S),
8398 OPC_MAX_S = FOP(30, FMT_S),
8399 OPC_RSQRT1_S = FOP(30, FMT_S),
8400 OPC_MAXA_S = FOP(31, FMT_S),
8401 OPC_RSQRT2_S = FOP(31, FMT_S),
8402 OPC_CVT_D_S = FOP(33, FMT_S),
8403 OPC_CVT_W_S = FOP(36, FMT_S),
8404 OPC_CVT_L_S = FOP(37, FMT_S),
8405 OPC_CVT_PS_S = FOP(38, FMT_S),
8406 OPC_CMP_F_S = FOP (48, FMT_S),
8407 OPC_CMP_UN_S = FOP (49, FMT_S),
8408 OPC_CMP_EQ_S = FOP (50, FMT_S),
8409 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8410 OPC_CMP_OLT_S = FOP (52, FMT_S),
8411 OPC_CMP_ULT_S = FOP (53, FMT_S),
8412 OPC_CMP_OLE_S = FOP (54, FMT_S),
8413 OPC_CMP_ULE_S = FOP (55, FMT_S),
8414 OPC_CMP_SF_S = FOP (56, FMT_S),
8415 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8416 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8417 OPC_CMP_NGL_S = FOP (59, FMT_S),
8418 OPC_CMP_LT_S = FOP (60, FMT_S),
8419 OPC_CMP_NGE_S = FOP (61, FMT_S),
8420 OPC_CMP_LE_S = FOP (62, FMT_S),
8421 OPC_CMP_NGT_S = FOP (63, FMT_S),
8423 OPC_ADD_D = FOP(0, FMT_D),
8424 OPC_SUB_D = FOP(1, FMT_D),
8425 OPC_MUL_D = FOP(2, FMT_D),
8426 OPC_DIV_D = FOP(3, FMT_D),
8427 OPC_SQRT_D = FOP(4, FMT_D),
8428 OPC_ABS_D = FOP(5, FMT_D),
8429 OPC_MOV_D = FOP(6, FMT_D),
8430 OPC_NEG_D = FOP(7, FMT_D),
8431 OPC_ROUND_L_D = FOP(8, FMT_D),
8432 OPC_TRUNC_L_D = FOP(9, FMT_D),
8433 OPC_CEIL_L_D = FOP(10, FMT_D),
8434 OPC_FLOOR_L_D = FOP(11, FMT_D),
8435 OPC_ROUND_W_D = FOP(12, FMT_D),
8436 OPC_TRUNC_W_D = FOP(13, FMT_D),
8437 OPC_CEIL_W_D = FOP(14, FMT_D),
8438 OPC_FLOOR_W_D = FOP(15, FMT_D),
8439 OPC_SEL_D = FOP(16, FMT_D),
8440 OPC_MOVCF_D = FOP(17, FMT_D),
8441 OPC_MOVZ_D = FOP(18, FMT_D),
8442 OPC_MOVN_D = FOP(19, FMT_D),
8443 OPC_SELEQZ_D = FOP(20, FMT_D),
8444 OPC_RECIP_D = FOP(21, FMT_D),
8445 OPC_RSQRT_D = FOP(22, FMT_D),
8446 OPC_SELNEZ_D = FOP(23, FMT_D),
8447 OPC_MADDF_D = FOP(24, FMT_D),
8448 OPC_MSUBF_D = FOP(25, FMT_D),
8449 OPC_RINT_D = FOP(26, FMT_D),
8450 OPC_CLASS_D = FOP(27, FMT_D),
8451 OPC_MIN_D = FOP(28, FMT_D),
8452 OPC_RECIP2_D = FOP(28, FMT_D),
8453 OPC_MINA_D = FOP(29, FMT_D),
8454 OPC_RECIP1_D = FOP(29, FMT_D),
8455 OPC_MAX_D = FOP(30, FMT_D),
8456 OPC_RSQRT1_D = FOP(30, FMT_D),
8457 OPC_MAXA_D = FOP(31, FMT_D),
8458 OPC_RSQRT2_D = FOP(31, FMT_D),
8459 OPC_CVT_S_D = FOP(32, FMT_D),
8460 OPC_CVT_W_D = FOP(36, FMT_D),
8461 OPC_CVT_L_D = FOP(37, FMT_D),
8462 OPC_CMP_F_D = FOP (48, FMT_D),
8463 OPC_CMP_UN_D = FOP (49, FMT_D),
8464 OPC_CMP_EQ_D = FOP (50, FMT_D),
8465 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8466 OPC_CMP_OLT_D = FOP (52, FMT_D),
8467 OPC_CMP_ULT_D = FOP (53, FMT_D),
8468 OPC_CMP_OLE_D = FOP (54, FMT_D),
8469 OPC_CMP_ULE_D = FOP (55, FMT_D),
8470 OPC_CMP_SF_D = FOP (56, FMT_D),
8471 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8472 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8473 OPC_CMP_NGL_D = FOP (59, FMT_D),
8474 OPC_CMP_LT_D = FOP (60, FMT_D),
8475 OPC_CMP_NGE_D = FOP (61, FMT_D),
8476 OPC_CMP_LE_D = FOP (62, FMT_D),
8477 OPC_CMP_NGT_D = FOP (63, FMT_D),
8479 OPC_CVT_S_W = FOP(32, FMT_W),
8480 OPC_CVT_D_W = FOP(33, FMT_W),
8481 OPC_CVT_S_L = FOP(32, FMT_L),
8482 OPC_CVT_D_L = FOP(33, FMT_L),
8483 OPC_CVT_PS_PW = FOP(38, FMT_W),
8485 OPC_ADD_PS = FOP(0, FMT_PS),
8486 OPC_SUB_PS = FOP(1, FMT_PS),
8487 OPC_MUL_PS = FOP(2, FMT_PS),
8488 OPC_DIV_PS = FOP(3, FMT_PS),
8489 OPC_ABS_PS = FOP(5, FMT_PS),
8490 OPC_MOV_PS = FOP(6, FMT_PS),
8491 OPC_NEG_PS = FOP(7, FMT_PS),
8492 OPC_MOVCF_PS = FOP(17, FMT_PS),
8493 OPC_MOVZ_PS = FOP(18, FMT_PS),
8494 OPC_MOVN_PS = FOP(19, FMT_PS),
8495 OPC_ADDR_PS = FOP(24, FMT_PS),
8496 OPC_MULR_PS = FOP(26, FMT_PS),
8497 OPC_RECIP2_PS = FOP(28, FMT_PS),
8498 OPC_RECIP1_PS = FOP(29, FMT_PS),
8499 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8500 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8502 OPC_CVT_S_PU = FOP(32, FMT_PS),
8503 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8504 OPC_CVT_S_PL = FOP(40, FMT_PS),
8505 OPC_PLL_PS = FOP(44, FMT_PS),
8506 OPC_PLU_PS = FOP(45, FMT_PS),
8507 OPC_PUL_PS = FOP(46, FMT_PS),
8508 OPC_PUU_PS = FOP(47, FMT_PS),
8509 OPC_CMP_F_PS = FOP (48, FMT_PS),
8510 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8511 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8512 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8513 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8514 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8515 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8516 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8517 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8518 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8519 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8520 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8521 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8522 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8523 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8524 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8527 enum r6_f_cmp_op {
8528 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8529 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8530 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8531 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8532 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8533 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8534 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8535 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8536 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8537 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8538 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8539 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8540 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8541 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8542 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8543 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8544 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8545 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8546 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8547 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8548 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8549 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8551 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8552 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8553 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8554 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8555 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8556 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8557 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8558 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8559 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8560 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8561 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8562 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8563 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8564 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8565 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8566 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8567 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8568 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8569 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8570 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8571 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8572 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8574 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8576 TCGv t0 = tcg_temp_new();
8578 switch (opc) {
8579 case OPC_MFC1:
8581 TCGv_i32 fp0 = tcg_temp_new_i32();
8583 gen_load_fpr32(ctx, fp0, fs);
8584 tcg_gen_ext_i32_tl(t0, fp0);
8585 tcg_temp_free_i32(fp0);
8587 gen_store_gpr(t0, rt);
8588 break;
8589 case OPC_MTC1:
8590 gen_load_gpr(t0, rt);
8592 TCGv_i32 fp0 = tcg_temp_new_i32();
8594 tcg_gen_trunc_tl_i32(fp0, t0);
8595 gen_store_fpr32(ctx, fp0, fs);
8596 tcg_temp_free_i32(fp0);
8598 break;
8599 case OPC_CFC1:
8600 gen_helper_1e0i(cfc1, t0, fs);
8601 gen_store_gpr(t0, rt);
8602 break;
8603 case OPC_CTC1:
8604 gen_load_gpr(t0, rt);
8605 save_cpu_state(ctx, 0);
8607 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8609 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8610 tcg_temp_free_i32(fs_tmp);
8612 /* Stop translation as we may have changed hflags */
8613 ctx->bstate = BS_STOP;
8614 break;
8615 #if defined(TARGET_MIPS64)
8616 case OPC_DMFC1:
8617 gen_load_fpr64(ctx, t0, fs);
8618 gen_store_gpr(t0, rt);
8619 break;
8620 case OPC_DMTC1:
8621 gen_load_gpr(t0, rt);
8622 gen_store_fpr64(ctx, t0, fs);
8623 break;
8624 #endif
8625 case OPC_MFHC1:
8627 TCGv_i32 fp0 = tcg_temp_new_i32();
8629 gen_load_fpr32h(ctx, fp0, fs);
8630 tcg_gen_ext_i32_tl(t0, fp0);
8631 tcg_temp_free_i32(fp0);
8633 gen_store_gpr(t0, rt);
8634 break;
8635 case OPC_MTHC1:
8636 gen_load_gpr(t0, rt);
8638 TCGv_i32 fp0 = tcg_temp_new_i32();
8640 tcg_gen_trunc_tl_i32(fp0, t0);
8641 gen_store_fpr32h(ctx, fp0, fs);
8642 tcg_temp_free_i32(fp0);
8644 break;
8645 default:
8646 MIPS_INVAL("cp1 move");
8647 generate_exception_end(ctx, EXCP_RI);
8648 goto out;
8651 out:
8652 tcg_temp_free(t0);
8655 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8657 TCGLabel *l1;
8658 TCGCond cond;
8659 TCGv_i32 t0;
8661 if (rd == 0) {
8662 /* Treat as NOP. */
8663 return;
8666 if (tf)
8667 cond = TCG_COND_EQ;
8668 else
8669 cond = TCG_COND_NE;
8671 l1 = gen_new_label();
8672 t0 = tcg_temp_new_i32();
8673 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8674 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8675 tcg_temp_free_i32(t0);
8676 if (rs == 0) {
8677 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8678 } else {
8679 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8681 gen_set_label(l1);
8684 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
8685 int tf)
8687 int cond;
8688 TCGv_i32 t0 = tcg_temp_new_i32();
8689 TCGLabel *l1 = gen_new_label();
8691 if (tf)
8692 cond = TCG_COND_EQ;
8693 else
8694 cond = TCG_COND_NE;
8696 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8697 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8698 gen_load_fpr32(ctx, t0, fs);
8699 gen_store_fpr32(ctx, t0, fd);
8700 gen_set_label(l1);
8701 tcg_temp_free_i32(t0);
8704 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8706 int cond;
8707 TCGv_i32 t0 = tcg_temp_new_i32();
8708 TCGv_i64 fp0;
8709 TCGLabel *l1 = gen_new_label();
8711 if (tf)
8712 cond = TCG_COND_EQ;
8713 else
8714 cond = TCG_COND_NE;
8716 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8717 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8718 tcg_temp_free_i32(t0);
8719 fp0 = tcg_temp_new_i64();
8720 gen_load_fpr64(ctx, fp0, fs);
8721 gen_store_fpr64(ctx, fp0, fd);
8722 tcg_temp_free_i64(fp0);
8723 gen_set_label(l1);
8726 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8727 int cc, int tf)
8729 int cond;
8730 TCGv_i32 t0 = tcg_temp_new_i32();
8731 TCGLabel *l1 = gen_new_label();
8732 TCGLabel *l2 = gen_new_label();
8734 if (tf)
8735 cond = TCG_COND_EQ;
8736 else
8737 cond = TCG_COND_NE;
8739 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8740 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8741 gen_load_fpr32(ctx, t0, fs);
8742 gen_store_fpr32(ctx, t0, fd);
8743 gen_set_label(l1);
8745 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8746 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8747 gen_load_fpr32h(ctx, t0, fs);
8748 gen_store_fpr32h(ctx, t0, fd);
8749 tcg_temp_free_i32(t0);
8750 gen_set_label(l2);
8753 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8754 int fs)
8756 TCGv_i32 t1 = tcg_const_i32(0);
8757 TCGv_i32 fp0 = tcg_temp_new_i32();
8758 TCGv_i32 fp1 = tcg_temp_new_i32();
8759 TCGv_i32 fp2 = tcg_temp_new_i32();
8760 gen_load_fpr32(ctx, fp0, fd);
8761 gen_load_fpr32(ctx, fp1, ft);
8762 gen_load_fpr32(ctx, fp2, fs);
8764 switch (op1) {
8765 case OPC_SEL_S:
8766 tcg_gen_andi_i32(fp0, fp0, 1);
8767 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8768 break;
8769 case OPC_SELEQZ_S:
8770 tcg_gen_andi_i32(fp1, fp1, 1);
8771 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8772 break;
8773 case OPC_SELNEZ_S:
8774 tcg_gen_andi_i32(fp1, fp1, 1);
8775 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8776 break;
8777 default:
8778 MIPS_INVAL("gen_sel_s");
8779 generate_exception_end(ctx, EXCP_RI);
8780 break;
8783 gen_store_fpr32(ctx, fp0, fd);
8784 tcg_temp_free_i32(fp2);
8785 tcg_temp_free_i32(fp1);
8786 tcg_temp_free_i32(fp0);
8787 tcg_temp_free_i32(t1);
8790 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8791 int fs)
8793 TCGv_i64 t1 = tcg_const_i64(0);
8794 TCGv_i64 fp0 = tcg_temp_new_i64();
8795 TCGv_i64 fp1 = tcg_temp_new_i64();
8796 TCGv_i64 fp2 = tcg_temp_new_i64();
8797 gen_load_fpr64(ctx, fp0, fd);
8798 gen_load_fpr64(ctx, fp1, ft);
8799 gen_load_fpr64(ctx, fp2, fs);
8801 switch (op1) {
8802 case OPC_SEL_D:
8803 tcg_gen_andi_i64(fp0, fp0, 1);
8804 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8805 break;
8806 case OPC_SELEQZ_D:
8807 tcg_gen_andi_i64(fp1, fp1, 1);
8808 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8809 break;
8810 case OPC_SELNEZ_D:
8811 tcg_gen_andi_i64(fp1, fp1, 1);
8812 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8813 break;
8814 default:
8815 MIPS_INVAL("gen_sel_d");
8816 generate_exception_end(ctx, EXCP_RI);
8817 break;
8820 gen_store_fpr64(ctx, fp0, fd);
8821 tcg_temp_free_i64(fp2);
8822 tcg_temp_free_i64(fp1);
8823 tcg_temp_free_i64(fp0);
8824 tcg_temp_free_i64(t1);
8827 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8828 int ft, int fs, int fd, int cc)
8830 uint32_t func = ctx->opcode & 0x3f;
8831 switch (op1) {
8832 case OPC_ADD_S:
8834 TCGv_i32 fp0 = tcg_temp_new_i32();
8835 TCGv_i32 fp1 = tcg_temp_new_i32();
8837 gen_load_fpr32(ctx, fp0, fs);
8838 gen_load_fpr32(ctx, fp1, ft);
8839 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
8840 tcg_temp_free_i32(fp1);
8841 gen_store_fpr32(ctx, fp0, fd);
8842 tcg_temp_free_i32(fp0);
8844 break;
8845 case OPC_SUB_S:
8847 TCGv_i32 fp0 = tcg_temp_new_i32();
8848 TCGv_i32 fp1 = tcg_temp_new_i32();
8850 gen_load_fpr32(ctx, fp0, fs);
8851 gen_load_fpr32(ctx, fp1, ft);
8852 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
8853 tcg_temp_free_i32(fp1);
8854 gen_store_fpr32(ctx, fp0, fd);
8855 tcg_temp_free_i32(fp0);
8857 break;
8858 case OPC_MUL_S:
8860 TCGv_i32 fp0 = tcg_temp_new_i32();
8861 TCGv_i32 fp1 = tcg_temp_new_i32();
8863 gen_load_fpr32(ctx, fp0, fs);
8864 gen_load_fpr32(ctx, fp1, ft);
8865 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
8866 tcg_temp_free_i32(fp1);
8867 gen_store_fpr32(ctx, fp0, fd);
8868 tcg_temp_free_i32(fp0);
8870 break;
8871 case OPC_DIV_S:
8873 TCGv_i32 fp0 = tcg_temp_new_i32();
8874 TCGv_i32 fp1 = tcg_temp_new_i32();
8876 gen_load_fpr32(ctx, fp0, fs);
8877 gen_load_fpr32(ctx, fp1, ft);
8878 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
8879 tcg_temp_free_i32(fp1);
8880 gen_store_fpr32(ctx, fp0, fd);
8881 tcg_temp_free_i32(fp0);
8883 break;
8884 case OPC_SQRT_S:
8886 TCGv_i32 fp0 = tcg_temp_new_i32();
8888 gen_load_fpr32(ctx, fp0, fs);
8889 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
8890 gen_store_fpr32(ctx, fp0, fd);
8891 tcg_temp_free_i32(fp0);
8893 break;
8894 case OPC_ABS_S:
8896 TCGv_i32 fp0 = tcg_temp_new_i32();
8898 gen_load_fpr32(ctx, fp0, fs);
8899 if (ctx->abs2008) {
8900 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
8901 } else {
8902 gen_helper_float_abs_s(fp0, fp0);
8904 gen_store_fpr32(ctx, fp0, fd);
8905 tcg_temp_free_i32(fp0);
8907 break;
8908 case OPC_MOV_S:
8910 TCGv_i32 fp0 = tcg_temp_new_i32();
8912 gen_load_fpr32(ctx, fp0, fs);
8913 gen_store_fpr32(ctx, fp0, fd);
8914 tcg_temp_free_i32(fp0);
8916 break;
8917 case OPC_NEG_S:
8919 TCGv_i32 fp0 = tcg_temp_new_i32();
8921 gen_load_fpr32(ctx, fp0, fs);
8922 if (ctx->abs2008) {
8923 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
8924 } else {
8925 gen_helper_float_chs_s(fp0, fp0);
8927 gen_store_fpr32(ctx, fp0, fd);
8928 tcg_temp_free_i32(fp0);
8930 break;
8931 case OPC_ROUND_L_S:
8932 check_cp1_64bitmode(ctx);
8934 TCGv_i32 fp32 = tcg_temp_new_i32();
8935 TCGv_i64 fp64 = tcg_temp_new_i64();
8937 gen_load_fpr32(ctx, fp32, fs);
8938 if (ctx->nan2008) {
8939 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
8940 } else {
8941 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
8943 tcg_temp_free_i32(fp32);
8944 gen_store_fpr64(ctx, fp64, fd);
8945 tcg_temp_free_i64(fp64);
8947 break;
8948 case OPC_TRUNC_L_S:
8949 check_cp1_64bitmode(ctx);
8951 TCGv_i32 fp32 = tcg_temp_new_i32();
8952 TCGv_i64 fp64 = tcg_temp_new_i64();
8954 gen_load_fpr32(ctx, fp32, fs);
8955 if (ctx->nan2008) {
8956 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
8957 } else {
8958 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
8960 tcg_temp_free_i32(fp32);
8961 gen_store_fpr64(ctx, fp64, fd);
8962 tcg_temp_free_i64(fp64);
8964 break;
8965 case OPC_CEIL_L_S:
8966 check_cp1_64bitmode(ctx);
8968 TCGv_i32 fp32 = tcg_temp_new_i32();
8969 TCGv_i64 fp64 = tcg_temp_new_i64();
8971 gen_load_fpr32(ctx, fp32, fs);
8972 if (ctx->nan2008) {
8973 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
8974 } else {
8975 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
8977 tcg_temp_free_i32(fp32);
8978 gen_store_fpr64(ctx, fp64, fd);
8979 tcg_temp_free_i64(fp64);
8981 break;
8982 case OPC_FLOOR_L_S:
8983 check_cp1_64bitmode(ctx);
8985 TCGv_i32 fp32 = tcg_temp_new_i32();
8986 TCGv_i64 fp64 = tcg_temp_new_i64();
8988 gen_load_fpr32(ctx, fp32, fs);
8989 if (ctx->nan2008) {
8990 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
8991 } else {
8992 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
8994 tcg_temp_free_i32(fp32);
8995 gen_store_fpr64(ctx, fp64, fd);
8996 tcg_temp_free_i64(fp64);
8998 break;
8999 case OPC_ROUND_W_S:
9001 TCGv_i32 fp0 = tcg_temp_new_i32();
9003 gen_load_fpr32(ctx, fp0, fs);
9004 if (ctx->nan2008) {
9005 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
9006 } else {
9007 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
9009 gen_store_fpr32(ctx, fp0, fd);
9010 tcg_temp_free_i32(fp0);
9012 break;
9013 case OPC_TRUNC_W_S:
9015 TCGv_i32 fp0 = tcg_temp_new_i32();
9017 gen_load_fpr32(ctx, fp0, fs);
9018 if (ctx->nan2008) {
9019 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
9020 } else {
9021 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
9023 gen_store_fpr32(ctx, fp0, fd);
9024 tcg_temp_free_i32(fp0);
9026 break;
9027 case OPC_CEIL_W_S:
9029 TCGv_i32 fp0 = tcg_temp_new_i32();
9031 gen_load_fpr32(ctx, fp0, fs);
9032 if (ctx->nan2008) {
9033 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
9034 } else {
9035 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
9037 gen_store_fpr32(ctx, fp0, fd);
9038 tcg_temp_free_i32(fp0);
9040 break;
9041 case OPC_FLOOR_W_S:
9043 TCGv_i32 fp0 = tcg_temp_new_i32();
9045 gen_load_fpr32(ctx, fp0, fs);
9046 if (ctx->nan2008) {
9047 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
9048 } else {
9049 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
9051 gen_store_fpr32(ctx, fp0, fd);
9052 tcg_temp_free_i32(fp0);
9054 break;
9055 case OPC_SEL_S:
9056 check_insn(ctx, ISA_MIPS32R6);
9057 gen_sel_s(ctx, op1, fd, ft, fs);
9058 break;
9059 case OPC_SELEQZ_S:
9060 check_insn(ctx, ISA_MIPS32R6);
9061 gen_sel_s(ctx, op1, fd, ft, fs);
9062 break;
9063 case OPC_SELNEZ_S:
9064 check_insn(ctx, ISA_MIPS32R6);
9065 gen_sel_s(ctx, op1, fd, ft, fs);
9066 break;
9067 case OPC_MOVCF_S:
9068 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9069 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9070 break;
9071 case OPC_MOVZ_S:
9072 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9074 TCGLabel *l1 = gen_new_label();
9075 TCGv_i32 fp0;
9077 if (ft != 0) {
9078 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9080 fp0 = tcg_temp_new_i32();
9081 gen_load_fpr32(ctx, fp0, fs);
9082 gen_store_fpr32(ctx, fp0, fd);
9083 tcg_temp_free_i32(fp0);
9084 gen_set_label(l1);
9086 break;
9087 case OPC_MOVN_S:
9088 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9090 TCGLabel *l1 = gen_new_label();
9091 TCGv_i32 fp0;
9093 if (ft != 0) {
9094 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9095 fp0 = tcg_temp_new_i32();
9096 gen_load_fpr32(ctx, fp0, fs);
9097 gen_store_fpr32(ctx, fp0, fd);
9098 tcg_temp_free_i32(fp0);
9099 gen_set_label(l1);
9102 break;
9103 case OPC_RECIP_S:
9105 TCGv_i32 fp0 = tcg_temp_new_i32();
9107 gen_load_fpr32(ctx, fp0, fs);
9108 gen_helper_float_recip_s(fp0, cpu_env, fp0);
9109 gen_store_fpr32(ctx, fp0, fd);
9110 tcg_temp_free_i32(fp0);
9112 break;
9113 case OPC_RSQRT_S:
9115 TCGv_i32 fp0 = tcg_temp_new_i32();
9117 gen_load_fpr32(ctx, fp0, fs);
9118 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
9119 gen_store_fpr32(ctx, fp0, fd);
9120 tcg_temp_free_i32(fp0);
9122 break;
9123 case OPC_MADDF_S:
9124 check_insn(ctx, ISA_MIPS32R6);
9126 TCGv_i32 fp0 = tcg_temp_new_i32();
9127 TCGv_i32 fp1 = tcg_temp_new_i32();
9128 TCGv_i32 fp2 = tcg_temp_new_i32();
9129 gen_load_fpr32(ctx, fp0, fs);
9130 gen_load_fpr32(ctx, fp1, ft);
9131 gen_load_fpr32(ctx, fp2, fd);
9132 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
9133 gen_store_fpr32(ctx, fp2, fd);
9134 tcg_temp_free_i32(fp2);
9135 tcg_temp_free_i32(fp1);
9136 tcg_temp_free_i32(fp0);
9138 break;
9139 case OPC_MSUBF_S:
9140 check_insn(ctx, ISA_MIPS32R6);
9142 TCGv_i32 fp0 = tcg_temp_new_i32();
9143 TCGv_i32 fp1 = tcg_temp_new_i32();
9144 TCGv_i32 fp2 = tcg_temp_new_i32();
9145 gen_load_fpr32(ctx, fp0, fs);
9146 gen_load_fpr32(ctx, fp1, ft);
9147 gen_load_fpr32(ctx, fp2, fd);
9148 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9149 gen_store_fpr32(ctx, fp2, fd);
9150 tcg_temp_free_i32(fp2);
9151 tcg_temp_free_i32(fp1);
9152 tcg_temp_free_i32(fp0);
9154 break;
9155 case OPC_RINT_S:
9156 check_insn(ctx, ISA_MIPS32R6);
9158 TCGv_i32 fp0 = tcg_temp_new_i32();
9159 gen_load_fpr32(ctx, fp0, fs);
9160 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9161 gen_store_fpr32(ctx, fp0, fd);
9162 tcg_temp_free_i32(fp0);
9164 break;
9165 case OPC_CLASS_S:
9166 check_insn(ctx, ISA_MIPS32R6);
9168 TCGv_i32 fp0 = tcg_temp_new_i32();
9169 gen_load_fpr32(ctx, fp0, fs);
9170 gen_helper_float_class_s(fp0, cpu_env, fp0);
9171 gen_store_fpr32(ctx, fp0, fd);
9172 tcg_temp_free_i32(fp0);
9174 break;
9175 case OPC_MIN_S: /* OPC_RECIP2_S */
9176 if (ctx->insn_flags & ISA_MIPS32R6) {
9177 /* OPC_MIN_S */
9178 TCGv_i32 fp0 = tcg_temp_new_i32();
9179 TCGv_i32 fp1 = tcg_temp_new_i32();
9180 TCGv_i32 fp2 = tcg_temp_new_i32();
9181 gen_load_fpr32(ctx, fp0, fs);
9182 gen_load_fpr32(ctx, fp1, ft);
9183 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9184 gen_store_fpr32(ctx, fp2, fd);
9185 tcg_temp_free_i32(fp2);
9186 tcg_temp_free_i32(fp1);
9187 tcg_temp_free_i32(fp0);
9188 } else {
9189 /* OPC_RECIP2_S */
9190 check_cp1_64bitmode(ctx);
9192 TCGv_i32 fp0 = tcg_temp_new_i32();
9193 TCGv_i32 fp1 = tcg_temp_new_i32();
9195 gen_load_fpr32(ctx, fp0, fs);
9196 gen_load_fpr32(ctx, fp1, ft);
9197 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9198 tcg_temp_free_i32(fp1);
9199 gen_store_fpr32(ctx, fp0, fd);
9200 tcg_temp_free_i32(fp0);
9203 break;
9204 case OPC_MINA_S: /* OPC_RECIP1_S */
9205 if (ctx->insn_flags & ISA_MIPS32R6) {
9206 /* OPC_MINA_S */
9207 TCGv_i32 fp0 = tcg_temp_new_i32();
9208 TCGv_i32 fp1 = tcg_temp_new_i32();
9209 TCGv_i32 fp2 = tcg_temp_new_i32();
9210 gen_load_fpr32(ctx, fp0, fs);
9211 gen_load_fpr32(ctx, fp1, ft);
9212 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9213 gen_store_fpr32(ctx, fp2, fd);
9214 tcg_temp_free_i32(fp2);
9215 tcg_temp_free_i32(fp1);
9216 tcg_temp_free_i32(fp0);
9217 } else {
9218 /* OPC_RECIP1_S */
9219 check_cp1_64bitmode(ctx);
9221 TCGv_i32 fp0 = tcg_temp_new_i32();
9223 gen_load_fpr32(ctx, fp0, fs);
9224 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9225 gen_store_fpr32(ctx, fp0, fd);
9226 tcg_temp_free_i32(fp0);
9229 break;
9230 case OPC_MAX_S: /* OPC_RSQRT1_S */
9231 if (ctx->insn_flags & ISA_MIPS32R6) {
9232 /* OPC_MAX_S */
9233 TCGv_i32 fp0 = tcg_temp_new_i32();
9234 TCGv_i32 fp1 = tcg_temp_new_i32();
9235 gen_load_fpr32(ctx, fp0, fs);
9236 gen_load_fpr32(ctx, fp1, ft);
9237 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9238 gen_store_fpr32(ctx, fp1, fd);
9239 tcg_temp_free_i32(fp1);
9240 tcg_temp_free_i32(fp0);
9241 } else {
9242 /* OPC_RSQRT1_S */
9243 check_cp1_64bitmode(ctx);
9245 TCGv_i32 fp0 = tcg_temp_new_i32();
9247 gen_load_fpr32(ctx, fp0, fs);
9248 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9249 gen_store_fpr32(ctx, fp0, fd);
9250 tcg_temp_free_i32(fp0);
9253 break;
9254 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9255 if (ctx->insn_flags & ISA_MIPS32R6) {
9256 /* OPC_MAXA_S */
9257 TCGv_i32 fp0 = tcg_temp_new_i32();
9258 TCGv_i32 fp1 = tcg_temp_new_i32();
9259 gen_load_fpr32(ctx, fp0, fs);
9260 gen_load_fpr32(ctx, fp1, ft);
9261 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9262 gen_store_fpr32(ctx, fp1, fd);
9263 tcg_temp_free_i32(fp1);
9264 tcg_temp_free_i32(fp0);
9265 } else {
9266 /* OPC_RSQRT2_S */
9267 check_cp1_64bitmode(ctx);
9269 TCGv_i32 fp0 = tcg_temp_new_i32();
9270 TCGv_i32 fp1 = tcg_temp_new_i32();
9272 gen_load_fpr32(ctx, fp0, fs);
9273 gen_load_fpr32(ctx, fp1, ft);
9274 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9275 tcg_temp_free_i32(fp1);
9276 gen_store_fpr32(ctx, fp0, fd);
9277 tcg_temp_free_i32(fp0);
9280 break;
9281 case OPC_CVT_D_S:
9282 check_cp1_registers(ctx, fd);
9284 TCGv_i32 fp32 = tcg_temp_new_i32();
9285 TCGv_i64 fp64 = tcg_temp_new_i64();
9287 gen_load_fpr32(ctx, fp32, fs);
9288 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9289 tcg_temp_free_i32(fp32);
9290 gen_store_fpr64(ctx, fp64, fd);
9291 tcg_temp_free_i64(fp64);
9293 break;
9294 case OPC_CVT_W_S:
9296 TCGv_i32 fp0 = tcg_temp_new_i32();
9298 gen_load_fpr32(ctx, fp0, fs);
9299 if (ctx->nan2008) {
9300 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
9301 } else {
9302 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
9304 gen_store_fpr32(ctx, fp0, fd);
9305 tcg_temp_free_i32(fp0);
9307 break;
9308 case OPC_CVT_L_S:
9309 check_cp1_64bitmode(ctx);
9311 TCGv_i32 fp32 = tcg_temp_new_i32();
9312 TCGv_i64 fp64 = tcg_temp_new_i64();
9314 gen_load_fpr32(ctx, fp32, fs);
9315 if (ctx->nan2008) {
9316 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
9317 } else {
9318 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
9320 tcg_temp_free_i32(fp32);
9321 gen_store_fpr64(ctx, fp64, fd);
9322 tcg_temp_free_i64(fp64);
9324 break;
9325 case OPC_CVT_PS_S:
9326 check_ps(ctx);
9328 TCGv_i64 fp64 = tcg_temp_new_i64();
9329 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9330 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9332 gen_load_fpr32(ctx, fp32_0, fs);
9333 gen_load_fpr32(ctx, fp32_1, ft);
9334 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9335 tcg_temp_free_i32(fp32_1);
9336 tcg_temp_free_i32(fp32_0);
9337 gen_store_fpr64(ctx, fp64, fd);
9338 tcg_temp_free_i64(fp64);
9340 break;
9341 case OPC_CMP_F_S:
9342 case OPC_CMP_UN_S:
9343 case OPC_CMP_EQ_S:
9344 case OPC_CMP_UEQ_S:
9345 case OPC_CMP_OLT_S:
9346 case OPC_CMP_ULT_S:
9347 case OPC_CMP_OLE_S:
9348 case OPC_CMP_ULE_S:
9349 case OPC_CMP_SF_S:
9350 case OPC_CMP_NGLE_S:
9351 case OPC_CMP_SEQ_S:
9352 case OPC_CMP_NGL_S:
9353 case OPC_CMP_LT_S:
9354 case OPC_CMP_NGE_S:
9355 case OPC_CMP_LE_S:
9356 case OPC_CMP_NGT_S:
9357 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9358 if (ctx->opcode & (1 << 6)) {
9359 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9360 } else {
9361 gen_cmp_s(ctx, func-48, ft, fs, cc);
9363 break;
9364 case OPC_ADD_D:
9365 check_cp1_registers(ctx, fs | ft | fd);
9367 TCGv_i64 fp0 = tcg_temp_new_i64();
9368 TCGv_i64 fp1 = tcg_temp_new_i64();
9370 gen_load_fpr64(ctx, fp0, fs);
9371 gen_load_fpr64(ctx, fp1, ft);
9372 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9373 tcg_temp_free_i64(fp1);
9374 gen_store_fpr64(ctx, fp0, fd);
9375 tcg_temp_free_i64(fp0);
9377 break;
9378 case OPC_SUB_D:
9379 check_cp1_registers(ctx, fs | ft | fd);
9381 TCGv_i64 fp0 = tcg_temp_new_i64();
9382 TCGv_i64 fp1 = tcg_temp_new_i64();
9384 gen_load_fpr64(ctx, fp0, fs);
9385 gen_load_fpr64(ctx, fp1, ft);
9386 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9387 tcg_temp_free_i64(fp1);
9388 gen_store_fpr64(ctx, fp0, fd);
9389 tcg_temp_free_i64(fp0);
9391 break;
9392 case OPC_MUL_D:
9393 check_cp1_registers(ctx, fs | ft | fd);
9395 TCGv_i64 fp0 = tcg_temp_new_i64();
9396 TCGv_i64 fp1 = tcg_temp_new_i64();
9398 gen_load_fpr64(ctx, fp0, fs);
9399 gen_load_fpr64(ctx, fp1, ft);
9400 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9401 tcg_temp_free_i64(fp1);
9402 gen_store_fpr64(ctx, fp0, fd);
9403 tcg_temp_free_i64(fp0);
9405 break;
9406 case OPC_DIV_D:
9407 check_cp1_registers(ctx, fs | ft | fd);
9409 TCGv_i64 fp0 = tcg_temp_new_i64();
9410 TCGv_i64 fp1 = tcg_temp_new_i64();
9412 gen_load_fpr64(ctx, fp0, fs);
9413 gen_load_fpr64(ctx, fp1, ft);
9414 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9415 tcg_temp_free_i64(fp1);
9416 gen_store_fpr64(ctx, fp0, fd);
9417 tcg_temp_free_i64(fp0);
9419 break;
9420 case OPC_SQRT_D:
9421 check_cp1_registers(ctx, fs | fd);
9423 TCGv_i64 fp0 = tcg_temp_new_i64();
9425 gen_load_fpr64(ctx, fp0, fs);
9426 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9427 gen_store_fpr64(ctx, fp0, fd);
9428 tcg_temp_free_i64(fp0);
9430 break;
9431 case OPC_ABS_D:
9432 check_cp1_registers(ctx, fs | fd);
9434 TCGv_i64 fp0 = tcg_temp_new_i64();
9436 gen_load_fpr64(ctx, fp0, fs);
9437 if (ctx->abs2008) {
9438 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
9439 } else {
9440 gen_helper_float_abs_d(fp0, fp0);
9442 gen_store_fpr64(ctx, fp0, fd);
9443 tcg_temp_free_i64(fp0);
9445 break;
9446 case OPC_MOV_D:
9447 check_cp1_registers(ctx, fs | fd);
9449 TCGv_i64 fp0 = tcg_temp_new_i64();
9451 gen_load_fpr64(ctx, fp0, fs);
9452 gen_store_fpr64(ctx, fp0, fd);
9453 tcg_temp_free_i64(fp0);
9455 break;
9456 case OPC_NEG_D:
9457 check_cp1_registers(ctx, fs | fd);
9459 TCGv_i64 fp0 = tcg_temp_new_i64();
9461 gen_load_fpr64(ctx, fp0, fs);
9462 if (ctx->abs2008) {
9463 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
9464 } else {
9465 gen_helper_float_chs_d(fp0, fp0);
9467 gen_store_fpr64(ctx, fp0, fd);
9468 tcg_temp_free_i64(fp0);
9470 break;
9471 case OPC_ROUND_L_D:
9472 check_cp1_64bitmode(ctx);
9474 TCGv_i64 fp0 = tcg_temp_new_i64();
9476 gen_load_fpr64(ctx, fp0, fs);
9477 if (ctx->nan2008) {
9478 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
9479 } else {
9480 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
9482 gen_store_fpr64(ctx, fp0, fd);
9483 tcg_temp_free_i64(fp0);
9485 break;
9486 case OPC_TRUNC_L_D:
9487 check_cp1_64bitmode(ctx);
9489 TCGv_i64 fp0 = tcg_temp_new_i64();
9491 gen_load_fpr64(ctx, fp0, fs);
9492 if (ctx->nan2008) {
9493 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
9494 } else {
9495 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
9497 gen_store_fpr64(ctx, fp0, fd);
9498 tcg_temp_free_i64(fp0);
9500 break;
9501 case OPC_CEIL_L_D:
9502 check_cp1_64bitmode(ctx);
9504 TCGv_i64 fp0 = tcg_temp_new_i64();
9506 gen_load_fpr64(ctx, fp0, fs);
9507 if (ctx->nan2008) {
9508 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
9509 } else {
9510 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
9512 gen_store_fpr64(ctx, fp0, fd);
9513 tcg_temp_free_i64(fp0);
9515 break;
9516 case OPC_FLOOR_L_D:
9517 check_cp1_64bitmode(ctx);
9519 TCGv_i64 fp0 = tcg_temp_new_i64();
9521 gen_load_fpr64(ctx, fp0, fs);
9522 if (ctx->nan2008) {
9523 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
9524 } else {
9525 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
9527 gen_store_fpr64(ctx, fp0, fd);
9528 tcg_temp_free_i64(fp0);
9530 break;
9531 case OPC_ROUND_W_D:
9532 check_cp1_registers(ctx, fs);
9534 TCGv_i32 fp32 = tcg_temp_new_i32();
9535 TCGv_i64 fp64 = tcg_temp_new_i64();
9537 gen_load_fpr64(ctx, fp64, fs);
9538 if (ctx->nan2008) {
9539 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
9540 } else {
9541 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
9543 tcg_temp_free_i64(fp64);
9544 gen_store_fpr32(ctx, fp32, fd);
9545 tcg_temp_free_i32(fp32);
9547 break;
9548 case OPC_TRUNC_W_D:
9549 check_cp1_registers(ctx, fs);
9551 TCGv_i32 fp32 = tcg_temp_new_i32();
9552 TCGv_i64 fp64 = tcg_temp_new_i64();
9554 gen_load_fpr64(ctx, fp64, fs);
9555 if (ctx->nan2008) {
9556 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
9557 } else {
9558 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
9560 tcg_temp_free_i64(fp64);
9561 gen_store_fpr32(ctx, fp32, fd);
9562 tcg_temp_free_i32(fp32);
9564 break;
9565 case OPC_CEIL_W_D:
9566 check_cp1_registers(ctx, fs);
9568 TCGv_i32 fp32 = tcg_temp_new_i32();
9569 TCGv_i64 fp64 = tcg_temp_new_i64();
9571 gen_load_fpr64(ctx, fp64, fs);
9572 if (ctx->nan2008) {
9573 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
9574 } else {
9575 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
9577 tcg_temp_free_i64(fp64);
9578 gen_store_fpr32(ctx, fp32, fd);
9579 tcg_temp_free_i32(fp32);
9581 break;
9582 case OPC_FLOOR_W_D:
9583 check_cp1_registers(ctx, fs);
9585 TCGv_i32 fp32 = tcg_temp_new_i32();
9586 TCGv_i64 fp64 = tcg_temp_new_i64();
9588 gen_load_fpr64(ctx, fp64, fs);
9589 if (ctx->nan2008) {
9590 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
9591 } else {
9592 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
9594 tcg_temp_free_i64(fp64);
9595 gen_store_fpr32(ctx, fp32, fd);
9596 tcg_temp_free_i32(fp32);
9598 break;
9599 case OPC_SEL_D:
9600 check_insn(ctx, ISA_MIPS32R6);
9601 gen_sel_d(ctx, op1, fd, ft, fs);
9602 break;
9603 case OPC_SELEQZ_D:
9604 check_insn(ctx, ISA_MIPS32R6);
9605 gen_sel_d(ctx, op1, fd, ft, fs);
9606 break;
9607 case OPC_SELNEZ_D:
9608 check_insn(ctx, ISA_MIPS32R6);
9609 gen_sel_d(ctx, op1, fd, ft, fs);
9610 break;
9611 case OPC_MOVCF_D:
9612 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9613 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9614 break;
9615 case OPC_MOVZ_D:
9616 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9618 TCGLabel *l1 = gen_new_label();
9619 TCGv_i64 fp0;
9621 if (ft != 0) {
9622 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9624 fp0 = tcg_temp_new_i64();
9625 gen_load_fpr64(ctx, fp0, fs);
9626 gen_store_fpr64(ctx, fp0, fd);
9627 tcg_temp_free_i64(fp0);
9628 gen_set_label(l1);
9630 break;
9631 case OPC_MOVN_D:
9632 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9634 TCGLabel *l1 = gen_new_label();
9635 TCGv_i64 fp0;
9637 if (ft != 0) {
9638 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9639 fp0 = tcg_temp_new_i64();
9640 gen_load_fpr64(ctx, fp0, fs);
9641 gen_store_fpr64(ctx, fp0, fd);
9642 tcg_temp_free_i64(fp0);
9643 gen_set_label(l1);
9646 break;
9647 case OPC_RECIP_D:
9648 check_cp1_registers(ctx, fs | fd);
9650 TCGv_i64 fp0 = tcg_temp_new_i64();
9652 gen_load_fpr64(ctx, fp0, fs);
9653 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9654 gen_store_fpr64(ctx, fp0, fd);
9655 tcg_temp_free_i64(fp0);
9657 break;
9658 case OPC_RSQRT_D:
9659 check_cp1_registers(ctx, fs | fd);
9661 TCGv_i64 fp0 = tcg_temp_new_i64();
9663 gen_load_fpr64(ctx, fp0, fs);
9664 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9665 gen_store_fpr64(ctx, fp0, fd);
9666 tcg_temp_free_i64(fp0);
9668 break;
9669 case OPC_MADDF_D:
9670 check_insn(ctx, ISA_MIPS32R6);
9672 TCGv_i64 fp0 = tcg_temp_new_i64();
9673 TCGv_i64 fp1 = tcg_temp_new_i64();
9674 TCGv_i64 fp2 = tcg_temp_new_i64();
9675 gen_load_fpr64(ctx, fp0, fs);
9676 gen_load_fpr64(ctx, fp1, ft);
9677 gen_load_fpr64(ctx, fp2, fd);
9678 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9679 gen_store_fpr64(ctx, fp2, fd);
9680 tcg_temp_free_i64(fp2);
9681 tcg_temp_free_i64(fp1);
9682 tcg_temp_free_i64(fp0);
9684 break;
9685 case OPC_MSUBF_D:
9686 check_insn(ctx, ISA_MIPS32R6);
9688 TCGv_i64 fp0 = tcg_temp_new_i64();
9689 TCGv_i64 fp1 = tcg_temp_new_i64();
9690 TCGv_i64 fp2 = tcg_temp_new_i64();
9691 gen_load_fpr64(ctx, fp0, fs);
9692 gen_load_fpr64(ctx, fp1, ft);
9693 gen_load_fpr64(ctx, fp2, fd);
9694 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9695 gen_store_fpr64(ctx, fp2, fd);
9696 tcg_temp_free_i64(fp2);
9697 tcg_temp_free_i64(fp1);
9698 tcg_temp_free_i64(fp0);
9700 break;
9701 case OPC_RINT_D:
9702 check_insn(ctx, ISA_MIPS32R6);
9704 TCGv_i64 fp0 = tcg_temp_new_i64();
9705 gen_load_fpr64(ctx, fp0, fs);
9706 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9707 gen_store_fpr64(ctx, fp0, fd);
9708 tcg_temp_free_i64(fp0);
9710 break;
9711 case OPC_CLASS_D:
9712 check_insn(ctx, ISA_MIPS32R6);
9714 TCGv_i64 fp0 = tcg_temp_new_i64();
9715 gen_load_fpr64(ctx, fp0, fs);
9716 gen_helper_float_class_d(fp0, cpu_env, fp0);
9717 gen_store_fpr64(ctx, fp0, fd);
9718 tcg_temp_free_i64(fp0);
9720 break;
9721 case OPC_MIN_D: /* OPC_RECIP2_D */
9722 if (ctx->insn_flags & ISA_MIPS32R6) {
9723 /* OPC_MIN_D */
9724 TCGv_i64 fp0 = tcg_temp_new_i64();
9725 TCGv_i64 fp1 = tcg_temp_new_i64();
9726 gen_load_fpr64(ctx, fp0, fs);
9727 gen_load_fpr64(ctx, fp1, ft);
9728 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9729 gen_store_fpr64(ctx, fp1, fd);
9730 tcg_temp_free_i64(fp1);
9731 tcg_temp_free_i64(fp0);
9732 } else {
9733 /* OPC_RECIP2_D */
9734 check_cp1_64bitmode(ctx);
9736 TCGv_i64 fp0 = tcg_temp_new_i64();
9737 TCGv_i64 fp1 = tcg_temp_new_i64();
9739 gen_load_fpr64(ctx, fp0, fs);
9740 gen_load_fpr64(ctx, fp1, ft);
9741 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9742 tcg_temp_free_i64(fp1);
9743 gen_store_fpr64(ctx, fp0, fd);
9744 tcg_temp_free_i64(fp0);
9747 break;
9748 case OPC_MINA_D: /* OPC_RECIP1_D */
9749 if (ctx->insn_flags & ISA_MIPS32R6) {
9750 /* OPC_MINA_D */
9751 TCGv_i64 fp0 = tcg_temp_new_i64();
9752 TCGv_i64 fp1 = tcg_temp_new_i64();
9753 gen_load_fpr64(ctx, fp0, fs);
9754 gen_load_fpr64(ctx, fp1, ft);
9755 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9756 gen_store_fpr64(ctx, fp1, fd);
9757 tcg_temp_free_i64(fp1);
9758 tcg_temp_free_i64(fp0);
9759 } else {
9760 /* OPC_RECIP1_D */
9761 check_cp1_64bitmode(ctx);
9763 TCGv_i64 fp0 = tcg_temp_new_i64();
9765 gen_load_fpr64(ctx, fp0, fs);
9766 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9767 gen_store_fpr64(ctx, fp0, fd);
9768 tcg_temp_free_i64(fp0);
9771 break;
9772 case OPC_MAX_D: /* OPC_RSQRT1_D */
9773 if (ctx->insn_flags & ISA_MIPS32R6) {
9774 /* OPC_MAX_D */
9775 TCGv_i64 fp0 = tcg_temp_new_i64();
9776 TCGv_i64 fp1 = tcg_temp_new_i64();
9777 gen_load_fpr64(ctx, fp0, fs);
9778 gen_load_fpr64(ctx, fp1, ft);
9779 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9780 gen_store_fpr64(ctx, fp1, fd);
9781 tcg_temp_free_i64(fp1);
9782 tcg_temp_free_i64(fp0);
9783 } else {
9784 /* OPC_RSQRT1_D */
9785 check_cp1_64bitmode(ctx);
9787 TCGv_i64 fp0 = tcg_temp_new_i64();
9789 gen_load_fpr64(ctx, fp0, fs);
9790 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9791 gen_store_fpr64(ctx, fp0, fd);
9792 tcg_temp_free_i64(fp0);
9795 break;
9796 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9797 if (ctx->insn_flags & ISA_MIPS32R6) {
9798 /* OPC_MAXA_D */
9799 TCGv_i64 fp0 = tcg_temp_new_i64();
9800 TCGv_i64 fp1 = tcg_temp_new_i64();
9801 gen_load_fpr64(ctx, fp0, fs);
9802 gen_load_fpr64(ctx, fp1, ft);
9803 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9804 gen_store_fpr64(ctx, fp1, fd);
9805 tcg_temp_free_i64(fp1);
9806 tcg_temp_free_i64(fp0);
9807 } else {
9808 /* OPC_RSQRT2_D */
9809 check_cp1_64bitmode(ctx);
9811 TCGv_i64 fp0 = tcg_temp_new_i64();
9812 TCGv_i64 fp1 = tcg_temp_new_i64();
9814 gen_load_fpr64(ctx, fp0, fs);
9815 gen_load_fpr64(ctx, fp1, ft);
9816 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9817 tcg_temp_free_i64(fp1);
9818 gen_store_fpr64(ctx, fp0, fd);
9819 tcg_temp_free_i64(fp0);
9822 break;
9823 case OPC_CMP_F_D:
9824 case OPC_CMP_UN_D:
9825 case OPC_CMP_EQ_D:
9826 case OPC_CMP_UEQ_D:
9827 case OPC_CMP_OLT_D:
9828 case OPC_CMP_ULT_D:
9829 case OPC_CMP_OLE_D:
9830 case OPC_CMP_ULE_D:
9831 case OPC_CMP_SF_D:
9832 case OPC_CMP_NGLE_D:
9833 case OPC_CMP_SEQ_D:
9834 case OPC_CMP_NGL_D:
9835 case OPC_CMP_LT_D:
9836 case OPC_CMP_NGE_D:
9837 case OPC_CMP_LE_D:
9838 case OPC_CMP_NGT_D:
9839 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9840 if (ctx->opcode & (1 << 6)) {
9841 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9842 } else {
9843 gen_cmp_d(ctx, func-48, ft, fs, cc);
9845 break;
9846 case OPC_CVT_S_D:
9847 check_cp1_registers(ctx, fs);
9849 TCGv_i32 fp32 = tcg_temp_new_i32();
9850 TCGv_i64 fp64 = tcg_temp_new_i64();
9852 gen_load_fpr64(ctx, fp64, fs);
9853 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
9854 tcg_temp_free_i64(fp64);
9855 gen_store_fpr32(ctx, fp32, fd);
9856 tcg_temp_free_i32(fp32);
9858 break;
9859 case OPC_CVT_W_D:
9860 check_cp1_registers(ctx, fs);
9862 TCGv_i32 fp32 = tcg_temp_new_i32();
9863 TCGv_i64 fp64 = tcg_temp_new_i64();
9865 gen_load_fpr64(ctx, fp64, fs);
9866 if (ctx->nan2008) {
9867 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
9868 } else {
9869 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
9871 tcg_temp_free_i64(fp64);
9872 gen_store_fpr32(ctx, fp32, fd);
9873 tcg_temp_free_i32(fp32);
9875 break;
9876 case OPC_CVT_L_D:
9877 check_cp1_64bitmode(ctx);
9879 TCGv_i64 fp0 = tcg_temp_new_i64();
9881 gen_load_fpr64(ctx, fp0, fs);
9882 if (ctx->nan2008) {
9883 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
9884 } else {
9885 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
9887 gen_store_fpr64(ctx, fp0, fd);
9888 tcg_temp_free_i64(fp0);
9890 break;
9891 case OPC_CVT_S_W:
9893 TCGv_i32 fp0 = tcg_temp_new_i32();
9895 gen_load_fpr32(ctx, fp0, fs);
9896 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
9897 gen_store_fpr32(ctx, fp0, fd);
9898 tcg_temp_free_i32(fp0);
9900 break;
9901 case OPC_CVT_D_W:
9902 check_cp1_registers(ctx, fd);
9904 TCGv_i32 fp32 = tcg_temp_new_i32();
9905 TCGv_i64 fp64 = tcg_temp_new_i64();
9907 gen_load_fpr32(ctx, fp32, fs);
9908 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
9909 tcg_temp_free_i32(fp32);
9910 gen_store_fpr64(ctx, fp64, fd);
9911 tcg_temp_free_i64(fp64);
9913 break;
9914 case OPC_CVT_S_L:
9915 check_cp1_64bitmode(ctx);
9917 TCGv_i32 fp32 = tcg_temp_new_i32();
9918 TCGv_i64 fp64 = tcg_temp_new_i64();
9920 gen_load_fpr64(ctx, fp64, fs);
9921 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
9922 tcg_temp_free_i64(fp64);
9923 gen_store_fpr32(ctx, fp32, fd);
9924 tcg_temp_free_i32(fp32);
9926 break;
9927 case OPC_CVT_D_L:
9928 check_cp1_64bitmode(ctx);
9930 TCGv_i64 fp0 = tcg_temp_new_i64();
9932 gen_load_fpr64(ctx, fp0, fs);
9933 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
9934 gen_store_fpr64(ctx, fp0, fd);
9935 tcg_temp_free_i64(fp0);
9937 break;
9938 case OPC_CVT_PS_PW:
9939 check_ps(ctx);
9941 TCGv_i64 fp0 = tcg_temp_new_i64();
9943 gen_load_fpr64(ctx, fp0, fs);
9944 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
9945 gen_store_fpr64(ctx, fp0, fd);
9946 tcg_temp_free_i64(fp0);
9948 break;
9949 case OPC_ADD_PS:
9950 check_ps(ctx);
9952 TCGv_i64 fp0 = tcg_temp_new_i64();
9953 TCGv_i64 fp1 = tcg_temp_new_i64();
9955 gen_load_fpr64(ctx, fp0, fs);
9956 gen_load_fpr64(ctx, fp1, ft);
9957 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
9958 tcg_temp_free_i64(fp1);
9959 gen_store_fpr64(ctx, fp0, fd);
9960 tcg_temp_free_i64(fp0);
9962 break;
9963 case OPC_SUB_PS:
9964 check_ps(ctx);
9966 TCGv_i64 fp0 = tcg_temp_new_i64();
9967 TCGv_i64 fp1 = tcg_temp_new_i64();
9969 gen_load_fpr64(ctx, fp0, fs);
9970 gen_load_fpr64(ctx, fp1, ft);
9971 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
9972 tcg_temp_free_i64(fp1);
9973 gen_store_fpr64(ctx, fp0, fd);
9974 tcg_temp_free_i64(fp0);
9976 break;
9977 case OPC_MUL_PS:
9978 check_ps(ctx);
9980 TCGv_i64 fp0 = tcg_temp_new_i64();
9981 TCGv_i64 fp1 = tcg_temp_new_i64();
9983 gen_load_fpr64(ctx, fp0, fs);
9984 gen_load_fpr64(ctx, fp1, ft);
9985 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
9986 tcg_temp_free_i64(fp1);
9987 gen_store_fpr64(ctx, fp0, fd);
9988 tcg_temp_free_i64(fp0);
9990 break;
9991 case OPC_ABS_PS:
9992 check_ps(ctx);
9994 TCGv_i64 fp0 = tcg_temp_new_i64();
9996 gen_load_fpr64(ctx, fp0, fs);
9997 gen_helper_float_abs_ps(fp0, fp0);
9998 gen_store_fpr64(ctx, fp0, fd);
9999 tcg_temp_free_i64(fp0);
10001 break;
10002 case OPC_MOV_PS:
10003 check_ps(ctx);
10005 TCGv_i64 fp0 = tcg_temp_new_i64();
10007 gen_load_fpr64(ctx, fp0, fs);
10008 gen_store_fpr64(ctx, fp0, fd);
10009 tcg_temp_free_i64(fp0);
10011 break;
10012 case OPC_NEG_PS:
10013 check_ps(ctx);
10015 TCGv_i64 fp0 = tcg_temp_new_i64();
10017 gen_load_fpr64(ctx, fp0, fs);
10018 gen_helper_float_chs_ps(fp0, fp0);
10019 gen_store_fpr64(ctx, fp0, fd);
10020 tcg_temp_free_i64(fp0);
10022 break;
10023 case OPC_MOVCF_PS:
10024 check_ps(ctx);
10025 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10026 break;
10027 case OPC_MOVZ_PS:
10028 check_ps(ctx);
10030 TCGLabel *l1 = gen_new_label();
10031 TCGv_i64 fp0;
10033 if (ft != 0)
10034 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10035 fp0 = tcg_temp_new_i64();
10036 gen_load_fpr64(ctx, fp0, fs);
10037 gen_store_fpr64(ctx, fp0, fd);
10038 tcg_temp_free_i64(fp0);
10039 gen_set_label(l1);
10041 break;
10042 case OPC_MOVN_PS:
10043 check_ps(ctx);
10045 TCGLabel *l1 = gen_new_label();
10046 TCGv_i64 fp0;
10048 if (ft != 0) {
10049 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10050 fp0 = tcg_temp_new_i64();
10051 gen_load_fpr64(ctx, fp0, fs);
10052 gen_store_fpr64(ctx, fp0, fd);
10053 tcg_temp_free_i64(fp0);
10054 gen_set_label(l1);
10057 break;
10058 case OPC_ADDR_PS:
10059 check_ps(ctx);
10061 TCGv_i64 fp0 = tcg_temp_new_i64();
10062 TCGv_i64 fp1 = tcg_temp_new_i64();
10064 gen_load_fpr64(ctx, fp0, ft);
10065 gen_load_fpr64(ctx, fp1, fs);
10066 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
10067 tcg_temp_free_i64(fp1);
10068 gen_store_fpr64(ctx, fp0, fd);
10069 tcg_temp_free_i64(fp0);
10071 break;
10072 case OPC_MULR_PS:
10073 check_ps(ctx);
10075 TCGv_i64 fp0 = tcg_temp_new_i64();
10076 TCGv_i64 fp1 = tcg_temp_new_i64();
10078 gen_load_fpr64(ctx, fp0, ft);
10079 gen_load_fpr64(ctx, fp1, fs);
10080 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
10081 tcg_temp_free_i64(fp1);
10082 gen_store_fpr64(ctx, fp0, fd);
10083 tcg_temp_free_i64(fp0);
10085 break;
10086 case OPC_RECIP2_PS:
10087 check_ps(ctx);
10089 TCGv_i64 fp0 = tcg_temp_new_i64();
10090 TCGv_i64 fp1 = tcg_temp_new_i64();
10092 gen_load_fpr64(ctx, fp0, fs);
10093 gen_load_fpr64(ctx, fp1, ft);
10094 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
10095 tcg_temp_free_i64(fp1);
10096 gen_store_fpr64(ctx, fp0, fd);
10097 tcg_temp_free_i64(fp0);
10099 break;
10100 case OPC_RECIP1_PS:
10101 check_ps(ctx);
10103 TCGv_i64 fp0 = tcg_temp_new_i64();
10105 gen_load_fpr64(ctx, fp0, fs);
10106 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
10107 gen_store_fpr64(ctx, fp0, fd);
10108 tcg_temp_free_i64(fp0);
10110 break;
10111 case OPC_RSQRT1_PS:
10112 check_ps(ctx);
10114 TCGv_i64 fp0 = tcg_temp_new_i64();
10116 gen_load_fpr64(ctx, fp0, fs);
10117 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
10118 gen_store_fpr64(ctx, fp0, fd);
10119 tcg_temp_free_i64(fp0);
10121 break;
10122 case OPC_RSQRT2_PS:
10123 check_ps(ctx);
10125 TCGv_i64 fp0 = tcg_temp_new_i64();
10126 TCGv_i64 fp1 = tcg_temp_new_i64();
10128 gen_load_fpr64(ctx, fp0, fs);
10129 gen_load_fpr64(ctx, fp1, ft);
10130 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
10131 tcg_temp_free_i64(fp1);
10132 gen_store_fpr64(ctx, fp0, fd);
10133 tcg_temp_free_i64(fp0);
10135 break;
10136 case OPC_CVT_S_PU:
10137 check_cp1_64bitmode(ctx);
10139 TCGv_i32 fp0 = tcg_temp_new_i32();
10141 gen_load_fpr32h(ctx, fp0, fs);
10142 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
10143 gen_store_fpr32(ctx, fp0, fd);
10144 tcg_temp_free_i32(fp0);
10146 break;
10147 case OPC_CVT_PW_PS:
10148 check_ps(ctx);
10150 TCGv_i64 fp0 = tcg_temp_new_i64();
10152 gen_load_fpr64(ctx, fp0, fs);
10153 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
10154 gen_store_fpr64(ctx, fp0, fd);
10155 tcg_temp_free_i64(fp0);
10157 break;
10158 case OPC_CVT_S_PL:
10159 check_cp1_64bitmode(ctx);
10161 TCGv_i32 fp0 = tcg_temp_new_i32();
10163 gen_load_fpr32(ctx, fp0, fs);
10164 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10165 gen_store_fpr32(ctx, fp0, fd);
10166 tcg_temp_free_i32(fp0);
10168 break;
10169 case OPC_PLL_PS:
10170 check_ps(ctx);
10172 TCGv_i32 fp0 = tcg_temp_new_i32();
10173 TCGv_i32 fp1 = tcg_temp_new_i32();
10175 gen_load_fpr32(ctx, fp0, fs);
10176 gen_load_fpr32(ctx, fp1, ft);
10177 gen_store_fpr32h(ctx, fp0, fd);
10178 gen_store_fpr32(ctx, fp1, fd);
10179 tcg_temp_free_i32(fp0);
10180 tcg_temp_free_i32(fp1);
10182 break;
10183 case OPC_PLU_PS:
10184 check_ps(ctx);
10186 TCGv_i32 fp0 = tcg_temp_new_i32();
10187 TCGv_i32 fp1 = tcg_temp_new_i32();
10189 gen_load_fpr32(ctx, fp0, fs);
10190 gen_load_fpr32h(ctx, fp1, ft);
10191 gen_store_fpr32(ctx, fp1, fd);
10192 gen_store_fpr32h(ctx, fp0, fd);
10193 tcg_temp_free_i32(fp0);
10194 tcg_temp_free_i32(fp1);
10196 break;
10197 case OPC_PUL_PS:
10198 check_ps(ctx);
10200 TCGv_i32 fp0 = tcg_temp_new_i32();
10201 TCGv_i32 fp1 = tcg_temp_new_i32();
10203 gen_load_fpr32h(ctx, fp0, fs);
10204 gen_load_fpr32(ctx, fp1, ft);
10205 gen_store_fpr32(ctx, fp1, fd);
10206 gen_store_fpr32h(ctx, fp0, fd);
10207 tcg_temp_free_i32(fp0);
10208 tcg_temp_free_i32(fp1);
10210 break;
10211 case OPC_PUU_PS:
10212 check_ps(ctx);
10214 TCGv_i32 fp0 = tcg_temp_new_i32();
10215 TCGv_i32 fp1 = tcg_temp_new_i32();
10217 gen_load_fpr32h(ctx, fp0, fs);
10218 gen_load_fpr32h(ctx, fp1, ft);
10219 gen_store_fpr32(ctx, fp1, fd);
10220 gen_store_fpr32h(ctx, fp0, fd);
10221 tcg_temp_free_i32(fp0);
10222 tcg_temp_free_i32(fp1);
10224 break;
10225 case OPC_CMP_F_PS:
10226 case OPC_CMP_UN_PS:
10227 case OPC_CMP_EQ_PS:
10228 case OPC_CMP_UEQ_PS:
10229 case OPC_CMP_OLT_PS:
10230 case OPC_CMP_ULT_PS:
10231 case OPC_CMP_OLE_PS:
10232 case OPC_CMP_ULE_PS:
10233 case OPC_CMP_SF_PS:
10234 case OPC_CMP_NGLE_PS:
10235 case OPC_CMP_SEQ_PS:
10236 case OPC_CMP_NGL_PS:
10237 case OPC_CMP_LT_PS:
10238 case OPC_CMP_NGE_PS:
10239 case OPC_CMP_LE_PS:
10240 case OPC_CMP_NGT_PS:
10241 if (ctx->opcode & (1 << 6)) {
10242 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10243 } else {
10244 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10246 break;
10247 default:
10248 MIPS_INVAL("farith");
10249 generate_exception_end(ctx, EXCP_RI);
10250 return;
10254 /* Coprocessor 3 (FPU) */
10255 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10256 int fd, int fs, int base, int index)
10258 TCGv t0 = tcg_temp_new();
10260 if (base == 0) {
10261 gen_load_gpr(t0, index);
10262 } else if (index == 0) {
10263 gen_load_gpr(t0, base);
10264 } else {
10265 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10267 /* Don't do NOP if destination is zero: we must perform the actual
10268 memory access. */
10269 switch (opc) {
10270 case OPC_LWXC1:
10271 check_cop1x(ctx);
10273 TCGv_i32 fp0 = tcg_temp_new_i32();
10275 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10276 tcg_gen_trunc_tl_i32(fp0, t0);
10277 gen_store_fpr32(ctx, fp0, fd);
10278 tcg_temp_free_i32(fp0);
10280 break;
10281 case OPC_LDXC1:
10282 check_cop1x(ctx);
10283 check_cp1_registers(ctx, fd);
10285 TCGv_i64 fp0 = tcg_temp_new_i64();
10286 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10287 gen_store_fpr64(ctx, fp0, fd);
10288 tcg_temp_free_i64(fp0);
10290 break;
10291 case OPC_LUXC1:
10292 check_cp1_64bitmode(ctx);
10293 tcg_gen_andi_tl(t0, t0, ~0x7);
10295 TCGv_i64 fp0 = tcg_temp_new_i64();
10297 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10298 gen_store_fpr64(ctx, fp0, fd);
10299 tcg_temp_free_i64(fp0);
10301 break;
10302 case OPC_SWXC1:
10303 check_cop1x(ctx);
10305 TCGv_i32 fp0 = tcg_temp_new_i32();
10306 gen_load_fpr32(ctx, fp0, fs);
10307 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10308 tcg_temp_free_i32(fp0);
10310 break;
10311 case OPC_SDXC1:
10312 check_cop1x(ctx);
10313 check_cp1_registers(ctx, fs);
10315 TCGv_i64 fp0 = tcg_temp_new_i64();
10316 gen_load_fpr64(ctx, fp0, fs);
10317 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10318 tcg_temp_free_i64(fp0);
10320 break;
10321 case OPC_SUXC1:
10322 check_cp1_64bitmode(ctx);
10323 tcg_gen_andi_tl(t0, t0, ~0x7);
10325 TCGv_i64 fp0 = tcg_temp_new_i64();
10326 gen_load_fpr64(ctx, fp0, fs);
10327 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10328 tcg_temp_free_i64(fp0);
10330 break;
10332 tcg_temp_free(t0);
10335 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10336 int fd, int fr, int fs, int ft)
10338 switch (opc) {
10339 case OPC_ALNV_PS:
10340 check_ps(ctx);
10342 TCGv t0 = tcg_temp_local_new();
10343 TCGv_i32 fp = tcg_temp_new_i32();
10344 TCGv_i32 fph = tcg_temp_new_i32();
10345 TCGLabel *l1 = gen_new_label();
10346 TCGLabel *l2 = gen_new_label();
10348 gen_load_gpr(t0, fr);
10349 tcg_gen_andi_tl(t0, t0, 0x7);
10351 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10352 gen_load_fpr32(ctx, fp, fs);
10353 gen_load_fpr32h(ctx, fph, fs);
10354 gen_store_fpr32(ctx, fp, fd);
10355 gen_store_fpr32h(ctx, fph, fd);
10356 tcg_gen_br(l2);
10357 gen_set_label(l1);
10358 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10359 tcg_temp_free(t0);
10360 #ifdef TARGET_WORDS_BIGENDIAN
10361 gen_load_fpr32(ctx, fp, fs);
10362 gen_load_fpr32h(ctx, fph, ft);
10363 gen_store_fpr32h(ctx, fp, fd);
10364 gen_store_fpr32(ctx, fph, fd);
10365 #else
10366 gen_load_fpr32h(ctx, fph, fs);
10367 gen_load_fpr32(ctx, fp, ft);
10368 gen_store_fpr32(ctx, fph, fd);
10369 gen_store_fpr32h(ctx, fp, fd);
10370 #endif
10371 gen_set_label(l2);
10372 tcg_temp_free_i32(fp);
10373 tcg_temp_free_i32(fph);
10375 break;
10376 case OPC_MADD_S:
10377 check_cop1x(ctx);
10379 TCGv_i32 fp0 = tcg_temp_new_i32();
10380 TCGv_i32 fp1 = tcg_temp_new_i32();
10381 TCGv_i32 fp2 = tcg_temp_new_i32();
10383 gen_load_fpr32(ctx, fp0, fs);
10384 gen_load_fpr32(ctx, fp1, ft);
10385 gen_load_fpr32(ctx, fp2, fr);
10386 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10387 tcg_temp_free_i32(fp0);
10388 tcg_temp_free_i32(fp1);
10389 gen_store_fpr32(ctx, fp2, fd);
10390 tcg_temp_free_i32(fp2);
10392 break;
10393 case OPC_MADD_D:
10394 check_cop1x(ctx);
10395 check_cp1_registers(ctx, fd | fs | ft | fr);
10397 TCGv_i64 fp0 = tcg_temp_new_i64();
10398 TCGv_i64 fp1 = tcg_temp_new_i64();
10399 TCGv_i64 fp2 = tcg_temp_new_i64();
10401 gen_load_fpr64(ctx, fp0, fs);
10402 gen_load_fpr64(ctx, fp1, ft);
10403 gen_load_fpr64(ctx, fp2, fr);
10404 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10405 tcg_temp_free_i64(fp0);
10406 tcg_temp_free_i64(fp1);
10407 gen_store_fpr64(ctx, fp2, fd);
10408 tcg_temp_free_i64(fp2);
10410 break;
10411 case OPC_MADD_PS:
10412 check_ps(ctx);
10414 TCGv_i64 fp0 = tcg_temp_new_i64();
10415 TCGv_i64 fp1 = tcg_temp_new_i64();
10416 TCGv_i64 fp2 = tcg_temp_new_i64();
10418 gen_load_fpr64(ctx, fp0, fs);
10419 gen_load_fpr64(ctx, fp1, ft);
10420 gen_load_fpr64(ctx, fp2, fr);
10421 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10422 tcg_temp_free_i64(fp0);
10423 tcg_temp_free_i64(fp1);
10424 gen_store_fpr64(ctx, fp2, fd);
10425 tcg_temp_free_i64(fp2);
10427 break;
10428 case OPC_MSUB_S:
10429 check_cop1x(ctx);
10431 TCGv_i32 fp0 = tcg_temp_new_i32();
10432 TCGv_i32 fp1 = tcg_temp_new_i32();
10433 TCGv_i32 fp2 = tcg_temp_new_i32();
10435 gen_load_fpr32(ctx, fp0, fs);
10436 gen_load_fpr32(ctx, fp1, ft);
10437 gen_load_fpr32(ctx, fp2, fr);
10438 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10439 tcg_temp_free_i32(fp0);
10440 tcg_temp_free_i32(fp1);
10441 gen_store_fpr32(ctx, fp2, fd);
10442 tcg_temp_free_i32(fp2);
10444 break;
10445 case OPC_MSUB_D:
10446 check_cop1x(ctx);
10447 check_cp1_registers(ctx, fd | fs | ft | fr);
10449 TCGv_i64 fp0 = tcg_temp_new_i64();
10450 TCGv_i64 fp1 = tcg_temp_new_i64();
10451 TCGv_i64 fp2 = tcg_temp_new_i64();
10453 gen_load_fpr64(ctx, fp0, fs);
10454 gen_load_fpr64(ctx, fp1, ft);
10455 gen_load_fpr64(ctx, fp2, fr);
10456 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10457 tcg_temp_free_i64(fp0);
10458 tcg_temp_free_i64(fp1);
10459 gen_store_fpr64(ctx, fp2, fd);
10460 tcg_temp_free_i64(fp2);
10462 break;
10463 case OPC_MSUB_PS:
10464 check_ps(ctx);
10466 TCGv_i64 fp0 = tcg_temp_new_i64();
10467 TCGv_i64 fp1 = tcg_temp_new_i64();
10468 TCGv_i64 fp2 = tcg_temp_new_i64();
10470 gen_load_fpr64(ctx, fp0, fs);
10471 gen_load_fpr64(ctx, fp1, ft);
10472 gen_load_fpr64(ctx, fp2, fr);
10473 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10474 tcg_temp_free_i64(fp0);
10475 tcg_temp_free_i64(fp1);
10476 gen_store_fpr64(ctx, fp2, fd);
10477 tcg_temp_free_i64(fp2);
10479 break;
10480 case OPC_NMADD_S:
10481 check_cop1x(ctx);
10483 TCGv_i32 fp0 = tcg_temp_new_i32();
10484 TCGv_i32 fp1 = tcg_temp_new_i32();
10485 TCGv_i32 fp2 = tcg_temp_new_i32();
10487 gen_load_fpr32(ctx, fp0, fs);
10488 gen_load_fpr32(ctx, fp1, ft);
10489 gen_load_fpr32(ctx, fp2, fr);
10490 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10491 tcg_temp_free_i32(fp0);
10492 tcg_temp_free_i32(fp1);
10493 gen_store_fpr32(ctx, fp2, fd);
10494 tcg_temp_free_i32(fp2);
10496 break;
10497 case OPC_NMADD_D:
10498 check_cop1x(ctx);
10499 check_cp1_registers(ctx, fd | fs | ft | fr);
10501 TCGv_i64 fp0 = tcg_temp_new_i64();
10502 TCGv_i64 fp1 = tcg_temp_new_i64();
10503 TCGv_i64 fp2 = tcg_temp_new_i64();
10505 gen_load_fpr64(ctx, fp0, fs);
10506 gen_load_fpr64(ctx, fp1, ft);
10507 gen_load_fpr64(ctx, fp2, fr);
10508 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10509 tcg_temp_free_i64(fp0);
10510 tcg_temp_free_i64(fp1);
10511 gen_store_fpr64(ctx, fp2, fd);
10512 tcg_temp_free_i64(fp2);
10514 break;
10515 case OPC_NMADD_PS:
10516 check_ps(ctx);
10518 TCGv_i64 fp0 = tcg_temp_new_i64();
10519 TCGv_i64 fp1 = tcg_temp_new_i64();
10520 TCGv_i64 fp2 = tcg_temp_new_i64();
10522 gen_load_fpr64(ctx, fp0, fs);
10523 gen_load_fpr64(ctx, fp1, ft);
10524 gen_load_fpr64(ctx, fp2, fr);
10525 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10526 tcg_temp_free_i64(fp0);
10527 tcg_temp_free_i64(fp1);
10528 gen_store_fpr64(ctx, fp2, fd);
10529 tcg_temp_free_i64(fp2);
10531 break;
10532 case OPC_NMSUB_S:
10533 check_cop1x(ctx);
10535 TCGv_i32 fp0 = tcg_temp_new_i32();
10536 TCGv_i32 fp1 = tcg_temp_new_i32();
10537 TCGv_i32 fp2 = tcg_temp_new_i32();
10539 gen_load_fpr32(ctx, fp0, fs);
10540 gen_load_fpr32(ctx, fp1, ft);
10541 gen_load_fpr32(ctx, fp2, fr);
10542 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10543 tcg_temp_free_i32(fp0);
10544 tcg_temp_free_i32(fp1);
10545 gen_store_fpr32(ctx, fp2, fd);
10546 tcg_temp_free_i32(fp2);
10548 break;
10549 case OPC_NMSUB_D:
10550 check_cop1x(ctx);
10551 check_cp1_registers(ctx, fd | fs | ft | fr);
10553 TCGv_i64 fp0 = tcg_temp_new_i64();
10554 TCGv_i64 fp1 = tcg_temp_new_i64();
10555 TCGv_i64 fp2 = tcg_temp_new_i64();
10557 gen_load_fpr64(ctx, fp0, fs);
10558 gen_load_fpr64(ctx, fp1, ft);
10559 gen_load_fpr64(ctx, fp2, fr);
10560 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10561 tcg_temp_free_i64(fp0);
10562 tcg_temp_free_i64(fp1);
10563 gen_store_fpr64(ctx, fp2, fd);
10564 tcg_temp_free_i64(fp2);
10566 break;
10567 case OPC_NMSUB_PS:
10568 check_ps(ctx);
10570 TCGv_i64 fp0 = tcg_temp_new_i64();
10571 TCGv_i64 fp1 = tcg_temp_new_i64();
10572 TCGv_i64 fp2 = tcg_temp_new_i64();
10574 gen_load_fpr64(ctx, fp0, fs);
10575 gen_load_fpr64(ctx, fp1, ft);
10576 gen_load_fpr64(ctx, fp2, fr);
10577 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10578 tcg_temp_free_i64(fp0);
10579 tcg_temp_free_i64(fp1);
10580 gen_store_fpr64(ctx, fp2, fd);
10581 tcg_temp_free_i64(fp2);
10583 break;
10584 default:
10585 MIPS_INVAL("flt3_arith");
10586 generate_exception_end(ctx, EXCP_RI);
10587 return;
10591 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
10593 TCGv t0;
10595 #if !defined(CONFIG_USER_ONLY)
10596 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10597 Therefore only check the ISA in system mode. */
10598 check_insn(ctx, ISA_MIPS32R2);
10599 #endif
10600 t0 = tcg_temp_new();
10602 switch (rd) {
10603 case 0:
10604 gen_helper_rdhwr_cpunum(t0, cpu_env);
10605 gen_store_gpr(t0, rt);
10606 break;
10607 case 1:
10608 gen_helper_rdhwr_synci_step(t0, cpu_env);
10609 gen_store_gpr(t0, rt);
10610 break;
10611 case 2:
10612 gen_helper_rdhwr_cc(t0, cpu_env);
10613 gen_store_gpr(t0, rt);
10614 break;
10615 case 3:
10616 gen_helper_rdhwr_ccres(t0, cpu_env);
10617 gen_store_gpr(t0, rt);
10618 break;
10619 case 4:
10620 check_insn(ctx, ISA_MIPS32R6);
10621 if (sel != 0) {
10622 /* Performance counter registers are not implemented other than
10623 * control register 0.
10625 generate_exception(ctx, EXCP_RI);
10627 gen_helper_rdhwr_performance(t0, cpu_env);
10628 gen_store_gpr(t0, rt);
10629 break;
10630 case 5:
10631 check_insn(ctx, ISA_MIPS32R6);
10632 gen_helper_rdhwr_xnp(t0, cpu_env);
10633 gen_store_gpr(t0, rt);
10634 break;
10635 case 29:
10636 #if defined(CONFIG_USER_ONLY)
10637 tcg_gen_ld_tl(t0, cpu_env,
10638 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10639 gen_store_gpr(t0, rt);
10640 break;
10641 #else
10642 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10643 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10644 tcg_gen_ld_tl(t0, cpu_env,
10645 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10646 gen_store_gpr(t0, rt);
10647 } else {
10648 generate_exception_end(ctx, EXCP_RI);
10650 break;
10651 #endif
10652 default: /* Invalid */
10653 MIPS_INVAL("rdhwr");
10654 generate_exception_end(ctx, EXCP_RI);
10655 break;
10657 tcg_temp_free(t0);
10660 static inline void clear_branch_hflags(DisasContext *ctx)
10662 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10663 if (ctx->bstate == BS_NONE) {
10664 save_cpu_state(ctx, 0);
10665 } else {
10666 /* it is not safe to save ctx->hflags as hflags may be changed
10667 in execution time by the instruction in delay / forbidden slot. */
10668 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10672 static void gen_branch(DisasContext *ctx, int insn_bytes)
10674 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10675 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10676 /* Branches completion */
10677 clear_branch_hflags(ctx);
10678 ctx->bstate = BS_BRANCH;
10679 /* FIXME: Need to clear can_do_io. */
10680 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10681 case MIPS_HFLAG_FBNSLOT:
10682 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10683 break;
10684 case MIPS_HFLAG_B:
10685 /* unconditional branch */
10686 if (proc_hflags & MIPS_HFLAG_BX) {
10687 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10689 gen_goto_tb(ctx, 0, ctx->btarget);
10690 break;
10691 case MIPS_HFLAG_BL:
10692 /* blikely taken case */
10693 gen_goto_tb(ctx, 0, ctx->btarget);
10694 break;
10695 case MIPS_HFLAG_BC:
10696 /* Conditional branch */
10698 TCGLabel *l1 = gen_new_label();
10700 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10701 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10702 gen_set_label(l1);
10703 gen_goto_tb(ctx, 0, ctx->btarget);
10705 break;
10706 case MIPS_HFLAG_BR:
10707 /* unconditional branch to register */
10708 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10709 TCGv t0 = tcg_temp_new();
10710 TCGv_i32 t1 = tcg_temp_new_i32();
10712 tcg_gen_andi_tl(t0, btarget, 0x1);
10713 tcg_gen_trunc_tl_i32(t1, t0);
10714 tcg_temp_free(t0);
10715 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10716 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10717 tcg_gen_or_i32(hflags, hflags, t1);
10718 tcg_temp_free_i32(t1);
10720 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10721 } else {
10722 tcg_gen_mov_tl(cpu_PC, btarget);
10724 if (ctx->singlestep_enabled) {
10725 save_cpu_state(ctx, 0);
10726 gen_helper_raise_exception_debug(cpu_env);
10728 tcg_gen_exit_tb(0);
10729 break;
10730 default:
10731 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
10732 abort();
10737 /* Compact Branches */
10738 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
10739 int rs, int rt, int32_t offset)
10741 int bcond_compute = 0;
10742 TCGv t0 = tcg_temp_new();
10743 TCGv t1 = tcg_temp_new();
10744 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
10746 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10747 #ifdef MIPS_DEBUG_DISAS
10748 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10749 "\n", ctx->pc);
10750 #endif
10751 generate_exception_end(ctx, EXCP_RI);
10752 goto out;
10755 /* Load needed operands and calculate btarget */
10756 switch (opc) {
10757 /* compact branch */
10758 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10759 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10760 gen_load_gpr(t0, rs);
10761 gen_load_gpr(t1, rt);
10762 bcond_compute = 1;
10763 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10764 if (rs <= rt && rs == 0) {
10765 /* OPC_BEQZALC, OPC_BNEZALC */
10766 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10768 break;
10769 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10770 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10771 gen_load_gpr(t0, rs);
10772 gen_load_gpr(t1, rt);
10773 bcond_compute = 1;
10774 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10775 break;
10776 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10777 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10778 if (rs == 0 || rs == rt) {
10779 /* OPC_BLEZALC, OPC_BGEZALC */
10780 /* OPC_BGTZALC, OPC_BLTZALC */
10781 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10783 gen_load_gpr(t0, rs);
10784 gen_load_gpr(t1, rt);
10785 bcond_compute = 1;
10786 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10787 break;
10788 case OPC_BC:
10789 case OPC_BALC:
10790 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10791 break;
10792 case OPC_BEQZC:
10793 case OPC_BNEZC:
10794 if (rs != 0) {
10795 /* OPC_BEQZC, OPC_BNEZC */
10796 gen_load_gpr(t0, rs);
10797 bcond_compute = 1;
10798 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10799 } else {
10800 /* OPC_JIC, OPC_JIALC */
10801 TCGv tbase = tcg_temp_new();
10802 TCGv toffset = tcg_temp_new();
10804 gen_load_gpr(tbase, rt);
10805 tcg_gen_movi_tl(toffset, offset);
10806 gen_op_addr_add(ctx, btarget, tbase, toffset);
10807 tcg_temp_free(tbase);
10808 tcg_temp_free(toffset);
10810 break;
10811 default:
10812 MIPS_INVAL("Compact branch/jump");
10813 generate_exception_end(ctx, EXCP_RI);
10814 goto out;
10817 if (bcond_compute == 0) {
10818 /* Uncoditional compact branch */
10819 switch (opc) {
10820 case OPC_JIALC:
10821 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10822 /* Fallthrough */
10823 case OPC_JIC:
10824 ctx->hflags |= MIPS_HFLAG_BR;
10825 break;
10826 case OPC_BALC:
10827 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10828 /* Fallthrough */
10829 case OPC_BC:
10830 ctx->hflags |= MIPS_HFLAG_B;
10831 break;
10832 default:
10833 MIPS_INVAL("Compact branch/jump");
10834 generate_exception_end(ctx, EXCP_RI);
10835 goto out;
10838 /* Generating branch here as compact branches don't have delay slot */
10839 gen_branch(ctx, 4);
10840 } else {
10841 /* Conditional compact branch */
10842 TCGLabel *fs = gen_new_label();
10843 save_cpu_state(ctx, 0);
10845 switch (opc) {
10846 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10847 if (rs == 0 && rt != 0) {
10848 /* OPC_BLEZALC */
10849 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10850 } else if (rs != 0 && rt != 0 && rs == rt) {
10851 /* OPC_BGEZALC */
10852 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10853 } else {
10854 /* OPC_BGEUC */
10855 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
10857 break;
10858 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10859 if (rs == 0 && rt != 0) {
10860 /* OPC_BGTZALC */
10861 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10862 } else if (rs != 0 && rt != 0 && rs == rt) {
10863 /* OPC_BLTZALC */
10864 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10865 } else {
10866 /* OPC_BLTUC */
10867 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
10869 break;
10870 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10871 if (rs == 0 && rt != 0) {
10872 /* OPC_BLEZC */
10873 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10874 } else if (rs != 0 && rt != 0 && rs == rt) {
10875 /* OPC_BGEZC */
10876 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10877 } else {
10878 /* OPC_BGEC */
10879 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
10881 break;
10882 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10883 if (rs == 0 && rt != 0) {
10884 /* OPC_BGTZC */
10885 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10886 } else if (rs != 0 && rt != 0 && rs == rt) {
10887 /* OPC_BLTZC */
10888 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10889 } else {
10890 /* OPC_BLTC */
10891 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
10893 break;
10894 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10895 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10896 if (rs >= rt) {
10897 /* OPC_BOVC, OPC_BNVC */
10898 TCGv t2 = tcg_temp_new();
10899 TCGv t3 = tcg_temp_new();
10900 TCGv t4 = tcg_temp_new();
10901 TCGv input_overflow = tcg_temp_new();
10903 gen_load_gpr(t0, rs);
10904 gen_load_gpr(t1, rt);
10905 tcg_gen_ext32s_tl(t2, t0);
10906 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
10907 tcg_gen_ext32s_tl(t3, t1);
10908 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
10909 tcg_gen_or_tl(input_overflow, input_overflow, t4);
10911 tcg_gen_add_tl(t4, t2, t3);
10912 tcg_gen_ext32s_tl(t4, t4);
10913 tcg_gen_xor_tl(t2, t2, t3);
10914 tcg_gen_xor_tl(t3, t4, t3);
10915 tcg_gen_andc_tl(t2, t3, t2);
10916 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
10917 tcg_gen_or_tl(t4, t4, input_overflow);
10918 if (opc == OPC_BOVC) {
10919 /* OPC_BOVC */
10920 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
10921 } else {
10922 /* OPC_BNVC */
10923 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
10925 tcg_temp_free(input_overflow);
10926 tcg_temp_free(t4);
10927 tcg_temp_free(t3);
10928 tcg_temp_free(t2);
10929 } else if (rs < rt && rs == 0) {
10930 /* OPC_BEQZALC, OPC_BNEZALC */
10931 if (opc == OPC_BEQZALC) {
10932 /* OPC_BEQZALC */
10933 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
10934 } else {
10935 /* OPC_BNEZALC */
10936 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
10938 } else {
10939 /* OPC_BEQC, OPC_BNEC */
10940 if (opc == OPC_BEQC) {
10941 /* OPC_BEQC */
10942 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
10943 } else {
10944 /* OPC_BNEC */
10945 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
10948 break;
10949 case OPC_BEQZC:
10950 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
10951 break;
10952 case OPC_BNEZC:
10953 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
10954 break;
10955 default:
10956 MIPS_INVAL("Compact conditional branch/jump");
10957 generate_exception_end(ctx, EXCP_RI);
10958 goto out;
10961 /* Generating branch here as compact branches don't have delay slot */
10962 gen_goto_tb(ctx, 1, ctx->btarget);
10963 gen_set_label(fs);
10965 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
10968 out:
10969 tcg_temp_free(t0);
10970 tcg_temp_free(t1);
10973 /* ISA extensions (ASEs) */
10974 /* MIPS16 extension to MIPS32 */
10976 /* MIPS16 major opcodes */
10977 enum {
10978 M16_OPC_ADDIUSP = 0x00,
10979 M16_OPC_ADDIUPC = 0x01,
10980 M16_OPC_B = 0x02,
10981 M16_OPC_JAL = 0x03,
10982 M16_OPC_BEQZ = 0x04,
10983 M16_OPC_BNEQZ = 0x05,
10984 M16_OPC_SHIFT = 0x06,
10985 M16_OPC_LD = 0x07,
10986 M16_OPC_RRIA = 0x08,
10987 M16_OPC_ADDIU8 = 0x09,
10988 M16_OPC_SLTI = 0x0a,
10989 M16_OPC_SLTIU = 0x0b,
10990 M16_OPC_I8 = 0x0c,
10991 M16_OPC_LI = 0x0d,
10992 M16_OPC_CMPI = 0x0e,
10993 M16_OPC_SD = 0x0f,
10994 M16_OPC_LB = 0x10,
10995 M16_OPC_LH = 0x11,
10996 M16_OPC_LWSP = 0x12,
10997 M16_OPC_LW = 0x13,
10998 M16_OPC_LBU = 0x14,
10999 M16_OPC_LHU = 0x15,
11000 M16_OPC_LWPC = 0x16,
11001 M16_OPC_LWU = 0x17,
11002 M16_OPC_SB = 0x18,
11003 M16_OPC_SH = 0x19,
11004 M16_OPC_SWSP = 0x1a,
11005 M16_OPC_SW = 0x1b,
11006 M16_OPC_RRR = 0x1c,
11007 M16_OPC_RR = 0x1d,
11008 M16_OPC_EXTEND = 0x1e,
11009 M16_OPC_I64 = 0x1f
11012 /* I8 funct field */
11013 enum {
11014 I8_BTEQZ = 0x0,
11015 I8_BTNEZ = 0x1,
11016 I8_SWRASP = 0x2,
11017 I8_ADJSP = 0x3,
11018 I8_SVRS = 0x4,
11019 I8_MOV32R = 0x5,
11020 I8_MOVR32 = 0x7
11023 /* RRR f field */
11024 enum {
11025 RRR_DADDU = 0x0,
11026 RRR_ADDU = 0x1,
11027 RRR_DSUBU = 0x2,
11028 RRR_SUBU = 0x3
11031 /* RR funct field */
11032 enum {
11033 RR_JR = 0x00,
11034 RR_SDBBP = 0x01,
11035 RR_SLT = 0x02,
11036 RR_SLTU = 0x03,
11037 RR_SLLV = 0x04,
11038 RR_BREAK = 0x05,
11039 RR_SRLV = 0x06,
11040 RR_SRAV = 0x07,
11041 RR_DSRL = 0x08,
11042 RR_CMP = 0x0a,
11043 RR_NEG = 0x0b,
11044 RR_AND = 0x0c,
11045 RR_OR = 0x0d,
11046 RR_XOR = 0x0e,
11047 RR_NOT = 0x0f,
11048 RR_MFHI = 0x10,
11049 RR_CNVT = 0x11,
11050 RR_MFLO = 0x12,
11051 RR_DSRA = 0x13,
11052 RR_DSLLV = 0x14,
11053 RR_DSRLV = 0x16,
11054 RR_DSRAV = 0x17,
11055 RR_MULT = 0x18,
11056 RR_MULTU = 0x19,
11057 RR_DIV = 0x1a,
11058 RR_DIVU = 0x1b,
11059 RR_DMULT = 0x1c,
11060 RR_DMULTU = 0x1d,
11061 RR_DDIV = 0x1e,
11062 RR_DDIVU = 0x1f
11065 /* I64 funct field */
11066 enum {
11067 I64_LDSP = 0x0,
11068 I64_SDSP = 0x1,
11069 I64_SDRASP = 0x2,
11070 I64_DADJSP = 0x3,
11071 I64_LDPC = 0x4,
11072 I64_DADDIU5 = 0x5,
11073 I64_DADDIUPC = 0x6,
11074 I64_DADDIUSP = 0x7
11077 /* RR ry field for CNVT */
11078 enum {
11079 RR_RY_CNVT_ZEB = 0x0,
11080 RR_RY_CNVT_ZEH = 0x1,
11081 RR_RY_CNVT_ZEW = 0x2,
11082 RR_RY_CNVT_SEB = 0x4,
11083 RR_RY_CNVT_SEH = 0x5,
11084 RR_RY_CNVT_SEW = 0x6,
11087 static int xlat (int r)
11089 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11091 return map[r];
11094 static void gen_mips16_save (DisasContext *ctx,
11095 int xsregs, int aregs,
11096 int do_ra, int do_s0, int do_s1,
11097 int framesize)
11099 TCGv t0 = tcg_temp_new();
11100 TCGv t1 = tcg_temp_new();
11101 TCGv t2 = tcg_temp_new();
11102 int args, astatic;
11104 switch (aregs) {
11105 case 0:
11106 case 1:
11107 case 2:
11108 case 3:
11109 case 11:
11110 args = 0;
11111 break;
11112 case 4:
11113 case 5:
11114 case 6:
11115 case 7:
11116 args = 1;
11117 break;
11118 case 8:
11119 case 9:
11120 case 10:
11121 args = 2;
11122 break;
11123 case 12:
11124 case 13:
11125 args = 3;
11126 break;
11127 case 14:
11128 args = 4;
11129 break;
11130 default:
11131 generate_exception_end(ctx, EXCP_RI);
11132 return;
11135 switch (args) {
11136 case 4:
11137 gen_base_offset_addr(ctx, t0, 29, 12);
11138 gen_load_gpr(t1, 7);
11139 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11140 /* Fall through */
11141 case 3:
11142 gen_base_offset_addr(ctx, t0, 29, 8);
11143 gen_load_gpr(t1, 6);
11144 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11145 /* Fall through */
11146 case 2:
11147 gen_base_offset_addr(ctx, t0, 29, 4);
11148 gen_load_gpr(t1, 5);
11149 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11150 /* Fall through */
11151 case 1:
11152 gen_base_offset_addr(ctx, t0, 29, 0);
11153 gen_load_gpr(t1, 4);
11154 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11157 gen_load_gpr(t0, 29);
11159 #define DECR_AND_STORE(reg) do { \
11160 tcg_gen_movi_tl(t2, -4); \
11161 gen_op_addr_add(ctx, t0, t0, t2); \
11162 gen_load_gpr(t1, reg); \
11163 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
11164 } while (0)
11166 if (do_ra) {
11167 DECR_AND_STORE(31);
11170 switch (xsregs) {
11171 case 7:
11172 DECR_AND_STORE(30);
11173 /* Fall through */
11174 case 6:
11175 DECR_AND_STORE(23);
11176 /* Fall through */
11177 case 5:
11178 DECR_AND_STORE(22);
11179 /* Fall through */
11180 case 4:
11181 DECR_AND_STORE(21);
11182 /* Fall through */
11183 case 3:
11184 DECR_AND_STORE(20);
11185 /* Fall through */
11186 case 2:
11187 DECR_AND_STORE(19);
11188 /* Fall through */
11189 case 1:
11190 DECR_AND_STORE(18);
11193 if (do_s1) {
11194 DECR_AND_STORE(17);
11196 if (do_s0) {
11197 DECR_AND_STORE(16);
11200 switch (aregs) {
11201 case 0:
11202 case 4:
11203 case 8:
11204 case 12:
11205 case 14:
11206 astatic = 0;
11207 break;
11208 case 1:
11209 case 5:
11210 case 9:
11211 case 13:
11212 astatic = 1;
11213 break;
11214 case 2:
11215 case 6:
11216 case 10:
11217 astatic = 2;
11218 break;
11219 case 3:
11220 case 7:
11221 astatic = 3;
11222 break;
11223 case 11:
11224 astatic = 4;
11225 break;
11226 default:
11227 generate_exception_end(ctx, EXCP_RI);
11228 return;
11231 if (astatic > 0) {
11232 DECR_AND_STORE(7);
11233 if (astatic > 1) {
11234 DECR_AND_STORE(6);
11235 if (astatic > 2) {
11236 DECR_AND_STORE(5);
11237 if (astatic > 3) {
11238 DECR_AND_STORE(4);
11243 #undef DECR_AND_STORE
11245 tcg_gen_movi_tl(t2, -framesize);
11246 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11247 tcg_temp_free(t0);
11248 tcg_temp_free(t1);
11249 tcg_temp_free(t2);
11252 static void gen_mips16_restore (DisasContext *ctx,
11253 int xsregs, int aregs,
11254 int do_ra, int do_s0, int do_s1,
11255 int framesize)
11257 int astatic;
11258 TCGv t0 = tcg_temp_new();
11259 TCGv t1 = tcg_temp_new();
11260 TCGv t2 = tcg_temp_new();
11262 tcg_gen_movi_tl(t2, framesize);
11263 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11265 #define DECR_AND_LOAD(reg) do { \
11266 tcg_gen_movi_tl(t2, -4); \
11267 gen_op_addr_add(ctx, t0, t0, t2); \
11268 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11269 gen_store_gpr(t1, reg); \
11270 } while (0)
11272 if (do_ra) {
11273 DECR_AND_LOAD(31);
11276 switch (xsregs) {
11277 case 7:
11278 DECR_AND_LOAD(30);
11279 /* Fall through */
11280 case 6:
11281 DECR_AND_LOAD(23);
11282 /* Fall through */
11283 case 5:
11284 DECR_AND_LOAD(22);
11285 /* Fall through */
11286 case 4:
11287 DECR_AND_LOAD(21);
11288 /* Fall through */
11289 case 3:
11290 DECR_AND_LOAD(20);
11291 /* Fall through */
11292 case 2:
11293 DECR_AND_LOAD(19);
11294 /* Fall through */
11295 case 1:
11296 DECR_AND_LOAD(18);
11299 if (do_s1) {
11300 DECR_AND_LOAD(17);
11302 if (do_s0) {
11303 DECR_AND_LOAD(16);
11306 switch (aregs) {
11307 case 0:
11308 case 4:
11309 case 8:
11310 case 12:
11311 case 14:
11312 astatic = 0;
11313 break;
11314 case 1:
11315 case 5:
11316 case 9:
11317 case 13:
11318 astatic = 1;
11319 break;
11320 case 2:
11321 case 6:
11322 case 10:
11323 astatic = 2;
11324 break;
11325 case 3:
11326 case 7:
11327 astatic = 3;
11328 break;
11329 case 11:
11330 astatic = 4;
11331 break;
11332 default:
11333 generate_exception_end(ctx, EXCP_RI);
11334 return;
11337 if (astatic > 0) {
11338 DECR_AND_LOAD(7);
11339 if (astatic > 1) {
11340 DECR_AND_LOAD(6);
11341 if (astatic > 2) {
11342 DECR_AND_LOAD(5);
11343 if (astatic > 3) {
11344 DECR_AND_LOAD(4);
11349 #undef DECR_AND_LOAD
11351 tcg_gen_movi_tl(t2, framesize);
11352 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11353 tcg_temp_free(t0);
11354 tcg_temp_free(t1);
11355 tcg_temp_free(t2);
11358 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11359 int is_64_bit, int extended)
11361 TCGv t0;
11363 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11364 generate_exception_end(ctx, EXCP_RI);
11365 return;
11368 t0 = tcg_temp_new();
11370 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11371 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11372 if (!is_64_bit) {
11373 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11376 tcg_temp_free(t0);
11379 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
11380 int16_t offset)
11382 TCGv_i32 t0 = tcg_const_i32(op);
11383 TCGv t1 = tcg_temp_new();
11384 gen_base_offset_addr(ctx, t1, base, offset);
11385 gen_helper_cache(cpu_env, t1, t0);
11388 #if defined(TARGET_MIPS64)
11389 static void decode_i64_mips16 (DisasContext *ctx,
11390 int ry, int funct, int16_t offset,
11391 int extended)
11393 switch (funct) {
11394 case I64_LDSP:
11395 check_insn(ctx, ISA_MIPS3);
11396 check_mips_64(ctx);
11397 offset = extended ? offset : offset << 3;
11398 gen_ld(ctx, OPC_LD, ry, 29, offset);
11399 break;
11400 case I64_SDSP:
11401 check_insn(ctx, ISA_MIPS3);
11402 check_mips_64(ctx);
11403 offset = extended ? offset : offset << 3;
11404 gen_st(ctx, OPC_SD, ry, 29, offset);
11405 break;
11406 case I64_SDRASP:
11407 check_insn(ctx, ISA_MIPS3);
11408 check_mips_64(ctx);
11409 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11410 gen_st(ctx, OPC_SD, 31, 29, offset);
11411 break;
11412 case I64_DADJSP:
11413 check_insn(ctx, ISA_MIPS3);
11414 check_mips_64(ctx);
11415 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11416 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11417 break;
11418 case I64_LDPC:
11419 check_insn(ctx, ISA_MIPS3);
11420 check_mips_64(ctx);
11421 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11422 generate_exception_end(ctx, EXCP_RI);
11423 } else {
11424 offset = extended ? offset : offset << 3;
11425 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11427 break;
11428 case I64_DADDIU5:
11429 check_insn(ctx, ISA_MIPS3);
11430 check_mips_64(ctx);
11431 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11432 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11433 break;
11434 case I64_DADDIUPC:
11435 check_insn(ctx, ISA_MIPS3);
11436 check_mips_64(ctx);
11437 offset = extended ? offset : offset << 2;
11438 gen_addiupc(ctx, ry, offset, 1, extended);
11439 break;
11440 case I64_DADDIUSP:
11441 check_insn(ctx, ISA_MIPS3);
11442 check_mips_64(ctx);
11443 offset = extended ? offset : offset << 2;
11444 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11445 break;
11448 #endif
11450 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11452 int extend = cpu_lduw_code(env, ctx->pc + 2);
11453 int op, rx, ry, funct, sa;
11454 int16_t imm, offset;
11456 ctx->opcode = (ctx->opcode << 16) | extend;
11457 op = (ctx->opcode >> 11) & 0x1f;
11458 sa = (ctx->opcode >> 22) & 0x1f;
11459 funct = (ctx->opcode >> 8) & 0x7;
11460 rx = xlat((ctx->opcode >> 8) & 0x7);
11461 ry = xlat((ctx->opcode >> 5) & 0x7);
11462 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11463 | ((ctx->opcode >> 21) & 0x3f) << 5
11464 | (ctx->opcode & 0x1f));
11466 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11467 counterparts. */
11468 switch (op) {
11469 case M16_OPC_ADDIUSP:
11470 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11471 break;
11472 case M16_OPC_ADDIUPC:
11473 gen_addiupc(ctx, rx, imm, 0, 1);
11474 break;
11475 case M16_OPC_B:
11476 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11477 /* No delay slot, so just process as a normal instruction */
11478 break;
11479 case M16_OPC_BEQZ:
11480 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11481 /* No delay slot, so just process as a normal instruction */
11482 break;
11483 case M16_OPC_BNEQZ:
11484 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11485 /* No delay slot, so just process as a normal instruction */
11486 break;
11487 case M16_OPC_SHIFT:
11488 switch (ctx->opcode & 0x3) {
11489 case 0x0:
11490 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11491 break;
11492 case 0x1:
11493 #if defined(TARGET_MIPS64)
11494 check_mips_64(ctx);
11495 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11496 #else
11497 generate_exception_end(ctx, EXCP_RI);
11498 #endif
11499 break;
11500 case 0x2:
11501 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11502 break;
11503 case 0x3:
11504 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11505 break;
11507 break;
11508 #if defined(TARGET_MIPS64)
11509 case M16_OPC_LD:
11510 check_insn(ctx, ISA_MIPS3);
11511 check_mips_64(ctx);
11512 gen_ld(ctx, OPC_LD, ry, rx, offset);
11513 break;
11514 #endif
11515 case M16_OPC_RRIA:
11516 imm = ctx->opcode & 0xf;
11517 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11518 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11519 imm = (int16_t) (imm << 1) >> 1;
11520 if ((ctx->opcode >> 4) & 0x1) {
11521 #if defined(TARGET_MIPS64)
11522 check_mips_64(ctx);
11523 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11524 #else
11525 generate_exception_end(ctx, EXCP_RI);
11526 #endif
11527 } else {
11528 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11530 break;
11531 case M16_OPC_ADDIU8:
11532 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11533 break;
11534 case M16_OPC_SLTI:
11535 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11536 break;
11537 case M16_OPC_SLTIU:
11538 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11539 break;
11540 case M16_OPC_I8:
11541 switch (funct) {
11542 case I8_BTEQZ:
11543 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11544 break;
11545 case I8_BTNEZ:
11546 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11547 break;
11548 case I8_SWRASP:
11549 gen_st(ctx, OPC_SW, 31, 29, imm);
11550 break;
11551 case I8_ADJSP:
11552 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11553 break;
11554 case I8_SVRS:
11555 check_insn(ctx, ISA_MIPS32);
11557 int xsregs = (ctx->opcode >> 24) & 0x7;
11558 int aregs = (ctx->opcode >> 16) & 0xf;
11559 int do_ra = (ctx->opcode >> 6) & 0x1;
11560 int do_s0 = (ctx->opcode >> 5) & 0x1;
11561 int do_s1 = (ctx->opcode >> 4) & 0x1;
11562 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11563 | (ctx->opcode & 0xf)) << 3;
11565 if (ctx->opcode & (1 << 7)) {
11566 gen_mips16_save(ctx, xsregs, aregs,
11567 do_ra, do_s0, do_s1,
11568 framesize);
11569 } else {
11570 gen_mips16_restore(ctx, xsregs, aregs,
11571 do_ra, do_s0, do_s1,
11572 framesize);
11575 break;
11576 default:
11577 generate_exception_end(ctx, EXCP_RI);
11578 break;
11580 break;
11581 case M16_OPC_LI:
11582 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11583 break;
11584 case M16_OPC_CMPI:
11585 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11586 break;
11587 #if defined(TARGET_MIPS64)
11588 case M16_OPC_SD:
11589 check_insn(ctx, ISA_MIPS3);
11590 check_mips_64(ctx);
11591 gen_st(ctx, OPC_SD, ry, rx, offset);
11592 break;
11593 #endif
11594 case M16_OPC_LB:
11595 gen_ld(ctx, OPC_LB, ry, rx, offset);
11596 break;
11597 case M16_OPC_LH:
11598 gen_ld(ctx, OPC_LH, ry, rx, offset);
11599 break;
11600 case M16_OPC_LWSP:
11601 gen_ld(ctx, OPC_LW, rx, 29, offset);
11602 break;
11603 case M16_OPC_LW:
11604 gen_ld(ctx, OPC_LW, ry, rx, offset);
11605 break;
11606 case M16_OPC_LBU:
11607 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11608 break;
11609 case M16_OPC_LHU:
11610 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11611 break;
11612 case M16_OPC_LWPC:
11613 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11614 break;
11615 #if defined(TARGET_MIPS64)
11616 case M16_OPC_LWU:
11617 check_insn(ctx, ISA_MIPS3);
11618 check_mips_64(ctx);
11619 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11620 break;
11621 #endif
11622 case M16_OPC_SB:
11623 gen_st(ctx, OPC_SB, ry, rx, offset);
11624 break;
11625 case M16_OPC_SH:
11626 gen_st(ctx, OPC_SH, ry, rx, offset);
11627 break;
11628 case M16_OPC_SWSP:
11629 gen_st(ctx, OPC_SW, rx, 29, offset);
11630 break;
11631 case M16_OPC_SW:
11632 gen_st(ctx, OPC_SW, ry, rx, offset);
11633 break;
11634 #if defined(TARGET_MIPS64)
11635 case M16_OPC_I64:
11636 decode_i64_mips16(ctx, ry, funct, offset, 1);
11637 break;
11638 #endif
11639 default:
11640 generate_exception_end(ctx, EXCP_RI);
11641 break;
11644 return 4;
11647 static inline bool is_uhi(int sdbbp_code)
11649 #ifdef CONFIG_USER_ONLY
11650 return false;
11651 #else
11652 return semihosting_enabled() && sdbbp_code == 1;
11653 #endif
11656 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11658 int rx, ry;
11659 int sa;
11660 int op, cnvt_op, op1, offset;
11661 int funct;
11662 int n_bytes;
11664 op = (ctx->opcode >> 11) & 0x1f;
11665 sa = (ctx->opcode >> 2) & 0x7;
11666 sa = sa == 0 ? 8 : sa;
11667 rx = xlat((ctx->opcode >> 8) & 0x7);
11668 cnvt_op = (ctx->opcode >> 5) & 0x7;
11669 ry = xlat((ctx->opcode >> 5) & 0x7);
11670 op1 = offset = ctx->opcode & 0x1f;
11672 n_bytes = 2;
11674 switch (op) {
11675 case M16_OPC_ADDIUSP:
11677 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11679 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11681 break;
11682 case M16_OPC_ADDIUPC:
11683 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11684 break;
11685 case M16_OPC_B:
11686 offset = (ctx->opcode & 0x7ff) << 1;
11687 offset = (int16_t)(offset << 4) >> 4;
11688 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11689 /* No delay slot, so just process as a normal instruction */
11690 break;
11691 case M16_OPC_JAL:
11692 offset = cpu_lduw_code(env, ctx->pc + 2);
11693 offset = (((ctx->opcode & 0x1f) << 21)
11694 | ((ctx->opcode >> 5) & 0x1f) << 16
11695 | offset) << 2;
11696 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11697 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11698 n_bytes = 4;
11699 break;
11700 case M16_OPC_BEQZ:
11701 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11702 ((int8_t)ctx->opcode) << 1, 0);
11703 /* No delay slot, so just process as a normal instruction */
11704 break;
11705 case M16_OPC_BNEQZ:
11706 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11707 ((int8_t)ctx->opcode) << 1, 0);
11708 /* No delay slot, so just process as a normal instruction */
11709 break;
11710 case M16_OPC_SHIFT:
11711 switch (ctx->opcode & 0x3) {
11712 case 0x0:
11713 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11714 break;
11715 case 0x1:
11716 #if defined(TARGET_MIPS64)
11717 check_insn(ctx, ISA_MIPS3);
11718 check_mips_64(ctx);
11719 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11720 #else
11721 generate_exception_end(ctx, EXCP_RI);
11722 #endif
11723 break;
11724 case 0x2:
11725 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11726 break;
11727 case 0x3:
11728 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11729 break;
11731 break;
11732 #if defined(TARGET_MIPS64)
11733 case M16_OPC_LD:
11734 check_insn(ctx, ISA_MIPS3);
11735 check_mips_64(ctx);
11736 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
11737 break;
11738 #endif
11739 case M16_OPC_RRIA:
11741 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
11743 if ((ctx->opcode >> 4) & 1) {
11744 #if defined(TARGET_MIPS64)
11745 check_insn(ctx, ISA_MIPS3);
11746 check_mips_64(ctx);
11747 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11748 #else
11749 generate_exception_end(ctx, EXCP_RI);
11750 #endif
11751 } else {
11752 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11755 break;
11756 case M16_OPC_ADDIU8:
11758 int16_t imm = (int8_t) ctx->opcode;
11760 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11762 break;
11763 case M16_OPC_SLTI:
11765 int16_t imm = (uint8_t) ctx->opcode;
11766 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11768 break;
11769 case M16_OPC_SLTIU:
11771 int16_t imm = (uint8_t) ctx->opcode;
11772 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11774 break;
11775 case M16_OPC_I8:
11777 int reg32;
11779 funct = (ctx->opcode >> 8) & 0x7;
11780 switch (funct) {
11781 case I8_BTEQZ:
11782 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
11783 ((int8_t)ctx->opcode) << 1, 0);
11784 break;
11785 case I8_BTNEZ:
11786 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
11787 ((int8_t)ctx->opcode) << 1, 0);
11788 break;
11789 case I8_SWRASP:
11790 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
11791 break;
11792 case I8_ADJSP:
11793 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
11794 ((int8_t)ctx->opcode) << 3);
11795 break;
11796 case I8_SVRS:
11797 check_insn(ctx, ISA_MIPS32);
11799 int do_ra = ctx->opcode & (1 << 6);
11800 int do_s0 = ctx->opcode & (1 << 5);
11801 int do_s1 = ctx->opcode & (1 << 4);
11802 int framesize = ctx->opcode & 0xf;
11804 if (framesize == 0) {
11805 framesize = 128;
11806 } else {
11807 framesize = framesize << 3;
11810 if (ctx->opcode & (1 << 7)) {
11811 gen_mips16_save(ctx, 0, 0,
11812 do_ra, do_s0, do_s1, framesize);
11813 } else {
11814 gen_mips16_restore(ctx, 0, 0,
11815 do_ra, do_s0, do_s1, framesize);
11818 break;
11819 case I8_MOV32R:
11821 int rz = xlat(ctx->opcode & 0x7);
11823 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
11824 ((ctx->opcode >> 5) & 0x7);
11825 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
11827 break;
11828 case I8_MOVR32:
11829 reg32 = ctx->opcode & 0x1f;
11830 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
11831 break;
11832 default:
11833 generate_exception_end(ctx, EXCP_RI);
11834 break;
11837 break;
11838 case M16_OPC_LI:
11840 int16_t imm = (uint8_t) ctx->opcode;
11842 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
11844 break;
11845 case M16_OPC_CMPI:
11847 int16_t imm = (uint8_t) ctx->opcode;
11848 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
11850 break;
11851 #if defined(TARGET_MIPS64)
11852 case M16_OPC_SD:
11853 check_insn(ctx, ISA_MIPS3);
11854 check_mips_64(ctx);
11855 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
11856 break;
11857 #endif
11858 case M16_OPC_LB:
11859 gen_ld(ctx, OPC_LB, ry, rx, offset);
11860 break;
11861 case M16_OPC_LH:
11862 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
11863 break;
11864 case M16_OPC_LWSP:
11865 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11866 break;
11867 case M16_OPC_LW:
11868 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
11869 break;
11870 case M16_OPC_LBU:
11871 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11872 break;
11873 case M16_OPC_LHU:
11874 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
11875 break;
11876 case M16_OPC_LWPC:
11877 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
11878 break;
11879 #if defined (TARGET_MIPS64)
11880 case M16_OPC_LWU:
11881 check_insn(ctx, ISA_MIPS3);
11882 check_mips_64(ctx);
11883 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
11884 break;
11885 #endif
11886 case M16_OPC_SB:
11887 gen_st(ctx, OPC_SB, ry, rx, offset);
11888 break;
11889 case M16_OPC_SH:
11890 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
11891 break;
11892 case M16_OPC_SWSP:
11893 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11894 break;
11895 case M16_OPC_SW:
11896 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
11897 break;
11898 case M16_OPC_RRR:
11900 int rz = xlat((ctx->opcode >> 2) & 0x7);
11901 int mips32_op;
11903 switch (ctx->opcode & 0x3) {
11904 case RRR_ADDU:
11905 mips32_op = OPC_ADDU;
11906 break;
11907 case RRR_SUBU:
11908 mips32_op = OPC_SUBU;
11909 break;
11910 #if defined(TARGET_MIPS64)
11911 case RRR_DADDU:
11912 mips32_op = OPC_DADDU;
11913 check_insn(ctx, ISA_MIPS3);
11914 check_mips_64(ctx);
11915 break;
11916 case RRR_DSUBU:
11917 mips32_op = OPC_DSUBU;
11918 check_insn(ctx, ISA_MIPS3);
11919 check_mips_64(ctx);
11920 break;
11921 #endif
11922 default:
11923 generate_exception_end(ctx, EXCP_RI);
11924 goto done;
11927 gen_arith(ctx, mips32_op, rz, rx, ry);
11928 done:
11931 break;
11932 case M16_OPC_RR:
11933 switch (op1) {
11934 case RR_JR:
11936 int nd = (ctx->opcode >> 7) & 0x1;
11937 int link = (ctx->opcode >> 6) & 0x1;
11938 int ra = (ctx->opcode >> 5) & 0x1;
11940 if (nd) {
11941 check_insn(ctx, ISA_MIPS32);
11944 if (link) {
11945 op = OPC_JALR;
11946 } else {
11947 op = OPC_JR;
11950 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
11951 (nd ? 0 : 2));
11953 break;
11954 case RR_SDBBP:
11955 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
11956 gen_helper_do_semihosting(cpu_env);
11957 } else {
11958 /* XXX: not clear which exception should be raised
11959 * when in debug mode...
11961 check_insn(ctx, ISA_MIPS32);
11962 generate_exception_end(ctx, EXCP_DBp);
11964 break;
11965 case RR_SLT:
11966 gen_slt(ctx, OPC_SLT, 24, rx, ry);
11967 break;
11968 case RR_SLTU:
11969 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
11970 break;
11971 case RR_BREAK:
11972 generate_exception_end(ctx, EXCP_BREAK);
11973 break;
11974 case RR_SLLV:
11975 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
11976 break;
11977 case RR_SRLV:
11978 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
11979 break;
11980 case RR_SRAV:
11981 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
11982 break;
11983 #if defined (TARGET_MIPS64)
11984 case RR_DSRL:
11985 check_insn(ctx, ISA_MIPS3);
11986 check_mips_64(ctx);
11987 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
11988 break;
11989 #endif
11990 case RR_CMP:
11991 gen_logic(ctx, OPC_XOR, 24, rx, ry);
11992 break;
11993 case RR_NEG:
11994 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
11995 break;
11996 case RR_AND:
11997 gen_logic(ctx, OPC_AND, rx, rx, ry);
11998 break;
11999 case RR_OR:
12000 gen_logic(ctx, OPC_OR, rx, rx, ry);
12001 break;
12002 case RR_XOR:
12003 gen_logic(ctx, OPC_XOR, rx, rx, ry);
12004 break;
12005 case RR_NOT:
12006 gen_logic(ctx, OPC_NOR, rx, ry, 0);
12007 break;
12008 case RR_MFHI:
12009 gen_HILO(ctx, OPC_MFHI, 0, rx);
12010 break;
12011 case RR_CNVT:
12012 check_insn(ctx, ISA_MIPS32);
12013 switch (cnvt_op) {
12014 case RR_RY_CNVT_ZEB:
12015 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12016 break;
12017 case RR_RY_CNVT_ZEH:
12018 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12019 break;
12020 case RR_RY_CNVT_SEB:
12021 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12022 break;
12023 case RR_RY_CNVT_SEH:
12024 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12025 break;
12026 #if defined (TARGET_MIPS64)
12027 case RR_RY_CNVT_ZEW:
12028 check_insn(ctx, ISA_MIPS64);
12029 check_mips_64(ctx);
12030 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12031 break;
12032 case RR_RY_CNVT_SEW:
12033 check_insn(ctx, ISA_MIPS64);
12034 check_mips_64(ctx);
12035 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12036 break;
12037 #endif
12038 default:
12039 generate_exception_end(ctx, EXCP_RI);
12040 break;
12042 break;
12043 case RR_MFLO:
12044 gen_HILO(ctx, OPC_MFLO, 0, rx);
12045 break;
12046 #if defined (TARGET_MIPS64)
12047 case RR_DSRA:
12048 check_insn(ctx, ISA_MIPS3);
12049 check_mips_64(ctx);
12050 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
12051 break;
12052 case RR_DSLLV:
12053 check_insn(ctx, ISA_MIPS3);
12054 check_mips_64(ctx);
12055 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
12056 break;
12057 case RR_DSRLV:
12058 check_insn(ctx, ISA_MIPS3);
12059 check_mips_64(ctx);
12060 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
12061 break;
12062 case RR_DSRAV:
12063 check_insn(ctx, ISA_MIPS3);
12064 check_mips_64(ctx);
12065 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
12066 break;
12067 #endif
12068 case RR_MULT:
12069 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
12070 break;
12071 case RR_MULTU:
12072 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
12073 break;
12074 case RR_DIV:
12075 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
12076 break;
12077 case RR_DIVU:
12078 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
12079 break;
12080 #if defined (TARGET_MIPS64)
12081 case RR_DMULT:
12082 check_insn(ctx, ISA_MIPS3);
12083 check_mips_64(ctx);
12084 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
12085 break;
12086 case RR_DMULTU:
12087 check_insn(ctx, ISA_MIPS3);
12088 check_mips_64(ctx);
12089 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
12090 break;
12091 case RR_DDIV:
12092 check_insn(ctx, ISA_MIPS3);
12093 check_mips_64(ctx);
12094 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
12095 break;
12096 case RR_DDIVU:
12097 check_insn(ctx, ISA_MIPS3);
12098 check_mips_64(ctx);
12099 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
12100 break;
12101 #endif
12102 default:
12103 generate_exception_end(ctx, EXCP_RI);
12104 break;
12106 break;
12107 case M16_OPC_EXTEND:
12108 decode_extended_mips16_opc(env, ctx);
12109 n_bytes = 4;
12110 break;
12111 #if defined(TARGET_MIPS64)
12112 case M16_OPC_I64:
12113 funct = (ctx->opcode >> 8) & 0x7;
12114 decode_i64_mips16(ctx, ry, funct, offset, 0);
12115 break;
12116 #endif
12117 default:
12118 generate_exception_end(ctx, EXCP_RI);
12119 break;
12122 return n_bytes;
12125 /* microMIPS extension to MIPS32/MIPS64 */
12128 * microMIPS32/microMIPS64 major opcodes
12130 * 1. MIPS Architecture for Programmers Volume II-B:
12131 * The microMIPS32 Instruction Set (Revision 3.05)
12133 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12135 * 2. MIPS Architecture For Programmers Volume II-A:
12136 * The MIPS64 Instruction Set (Revision 3.51)
12139 enum {
12140 POOL32A = 0x00,
12141 POOL16A = 0x01,
12142 LBU16 = 0x02,
12143 MOVE16 = 0x03,
12144 ADDI32 = 0x04,
12145 R6_LUI = 0x04,
12146 AUI = 0x04,
12147 LBU32 = 0x05,
12148 SB32 = 0x06,
12149 LB32 = 0x07,
12151 POOL32B = 0x08,
12152 POOL16B = 0x09,
12153 LHU16 = 0x0a,
12154 ANDI16 = 0x0b,
12155 ADDIU32 = 0x0c,
12156 LHU32 = 0x0d,
12157 SH32 = 0x0e,
12158 LH32 = 0x0f,
12160 POOL32I = 0x10,
12161 POOL16C = 0x11,
12162 LWSP16 = 0x12,
12163 POOL16D = 0x13,
12164 ORI32 = 0x14,
12165 POOL32F = 0x15,
12166 POOL32S = 0x16, /* MIPS64 */
12167 DADDIU32 = 0x17, /* MIPS64 */
12169 POOL32C = 0x18,
12170 LWGP16 = 0x19,
12171 LW16 = 0x1a,
12172 POOL16E = 0x1b,
12173 XORI32 = 0x1c,
12174 JALS32 = 0x1d,
12175 BOVC = 0x1d,
12176 BEQC = 0x1d,
12177 BEQZALC = 0x1d,
12178 ADDIUPC = 0x1e,
12179 PCREL = 0x1e,
12180 BNVC = 0x1f,
12181 BNEC = 0x1f,
12182 BNEZALC = 0x1f,
12184 R6_BEQZC = 0x20,
12185 JIC = 0x20,
12186 POOL16F = 0x21,
12187 SB16 = 0x22,
12188 BEQZ16 = 0x23,
12189 BEQZC16 = 0x23,
12190 SLTI32 = 0x24,
12191 BEQ32 = 0x25,
12192 BC = 0x25,
12193 SWC132 = 0x26,
12194 LWC132 = 0x27,
12196 /* 0x29 is reserved */
12197 RES_29 = 0x29,
12198 R6_BNEZC = 0x28,
12199 JIALC = 0x28,
12200 SH16 = 0x2a,
12201 BNEZ16 = 0x2b,
12202 BNEZC16 = 0x2b,
12203 SLTIU32 = 0x2c,
12204 BNE32 = 0x2d,
12205 BALC = 0x2d,
12206 SDC132 = 0x2e,
12207 LDC132 = 0x2f,
12209 /* 0x31 is reserved */
12210 RES_31 = 0x31,
12211 BLEZALC = 0x30,
12212 BGEZALC = 0x30,
12213 BGEUC = 0x30,
12214 SWSP16 = 0x32,
12215 B16 = 0x33,
12216 BC16 = 0x33,
12217 ANDI32 = 0x34,
12218 J32 = 0x35,
12219 BGTZC = 0x35,
12220 BLTZC = 0x35,
12221 BLTC = 0x35,
12222 SD32 = 0x36, /* MIPS64 */
12223 LD32 = 0x37, /* MIPS64 */
12225 /* 0x39 is reserved */
12226 RES_39 = 0x39,
12227 BGTZALC = 0x38,
12228 BLTZALC = 0x38,
12229 BLTUC = 0x38,
12230 SW16 = 0x3a,
12231 LI16 = 0x3b,
12232 JALX32 = 0x3c,
12233 JAL32 = 0x3d,
12234 BLEZC = 0x3d,
12235 BGEZC = 0x3d,
12236 BGEC = 0x3d,
12237 SW32 = 0x3e,
12238 LW32 = 0x3f
12241 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12242 enum {
12243 ADDIUPC_00 = 0x00,
12244 ADDIUPC_07 = 0x07,
12245 AUIPC = 0x1e,
12246 ALUIPC = 0x1f,
12247 LWPC_08 = 0x08,
12248 LWPC_0F = 0x0F,
12251 /* POOL32A encoding of minor opcode field */
12253 enum {
12254 /* These opcodes are distinguished only by bits 9..6; those bits are
12255 * what are recorded below. */
12256 SLL32 = 0x0,
12257 SRL32 = 0x1,
12258 SRA = 0x2,
12259 ROTR = 0x3,
12260 SELEQZ = 0x5,
12261 SELNEZ = 0x6,
12262 R6_RDHWR = 0x7,
12264 SLLV = 0x0,
12265 SRLV = 0x1,
12266 SRAV = 0x2,
12267 ROTRV = 0x3,
12268 ADD = 0x4,
12269 ADDU32 = 0x5,
12270 SUB = 0x6,
12271 SUBU32 = 0x7,
12272 MUL = 0x8,
12273 AND = 0x9,
12274 OR32 = 0xa,
12275 NOR = 0xb,
12276 XOR32 = 0xc,
12277 SLT = 0xd,
12278 SLTU = 0xe,
12280 MOVN = 0x0,
12281 R6_MUL = 0x0,
12282 MOVZ = 0x1,
12283 MUH = 0x1,
12284 MULU = 0x2,
12285 MUHU = 0x3,
12286 LWXS = 0x4,
12287 R6_DIV = 0x4,
12288 MOD = 0x5,
12289 R6_DIVU = 0x6,
12290 MODU = 0x7,
12292 /* The following can be distinguished by their lower 6 bits. */
12293 BREAK32 = 0x07,
12294 INS = 0x0c,
12295 LSA = 0x0f,
12296 ALIGN = 0x1f,
12297 EXT = 0x2c,
12298 POOL32AXF = 0x3c,
12299 SIGRIE = 0x3f
12302 /* POOL32AXF encoding of minor opcode field extension */
12305 * 1. MIPS Architecture for Programmers Volume II-B:
12306 * The microMIPS32 Instruction Set (Revision 3.05)
12308 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12310 * 2. MIPS Architecture for Programmers VolumeIV-e:
12311 * The MIPS DSP Application-Specific Extension
12312 * to the microMIPS32 Architecture (Revision 2.34)
12314 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12317 enum {
12318 /* bits 11..6 */
12319 TEQ = 0x00,
12320 TGE = 0x08,
12321 TGEU = 0x10,
12322 TLT = 0x20,
12323 TLTU = 0x28,
12324 TNE = 0x30,
12326 MFC0 = 0x03,
12327 MTC0 = 0x0b,
12329 /* begin of microMIPS32 DSP */
12331 /* bits 13..12 for 0x01 */
12332 MFHI_ACC = 0x0,
12333 MFLO_ACC = 0x1,
12334 MTHI_ACC = 0x2,
12335 MTLO_ACC = 0x3,
12337 /* bits 13..12 for 0x2a */
12338 MADD_ACC = 0x0,
12339 MADDU_ACC = 0x1,
12340 MSUB_ACC = 0x2,
12341 MSUBU_ACC = 0x3,
12343 /* bits 13..12 for 0x32 */
12344 MULT_ACC = 0x0,
12345 MULTU_ACC = 0x1,
12347 /* end of microMIPS32 DSP */
12349 /* bits 15..12 for 0x2c */
12350 BITSWAP = 0x0,
12351 SEB = 0x2,
12352 SEH = 0x3,
12353 CLO = 0x4,
12354 CLZ = 0x5,
12355 RDHWR = 0x6,
12356 WSBH = 0x7,
12357 MULT = 0x8,
12358 MULTU = 0x9,
12359 DIV = 0xa,
12360 DIVU = 0xb,
12361 MADD = 0xc,
12362 MADDU = 0xd,
12363 MSUB = 0xe,
12364 MSUBU = 0xf,
12366 /* bits 15..12 for 0x34 */
12367 MFC2 = 0x4,
12368 MTC2 = 0x5,
12369 MFHC2 = 0x8,
12370 MTHC2 = 0x9,
12371 CFC2 = 0xc,
12372 CTC2 = 0xd,
12374 /* bits 15..12 for 0x3c */
12375 JALR = 0x0,
12376 JR = 0x0, /* alias */
12377 JALRC = 0x0,
12378 JRC = 0x0,
12379 JALR_HB = 0x1,
12380 JALRC_HB = 0x1,
12381 JALRS = 0x4,
12382 JALRS_HB = 0x5,
12384 /* bits 15..12 for 0x05 */
12385 RDPGPR = 0xe,
12386 WRPGPR = 0xf,
12388 /* bits 15..12 for 0x0d */
12389 TLBP = 0x0,
12390 TLBR = 0x1,
12391 TLBWI = 0x2,
12392 TLBWR = 0x3,
12393 TLBINV = 0x4,
12394 TLBINVF = 0x5,
12395 WAIT = 0x9,
12396 IRET = 0xd,
12397 DERET = 0xe,
12398 ERET = 0xf,
12400 /* bits 15..12 for 0x15 */
12401 DMT = 0x0,
12402 DVPE = 0x1,
12403 EMT = 0x2,
12404 EVPE = 0x3,
12406 /* bits 15..12 for 0x1d */
12407 DI = 0x4,
12408 EI = 0x5,
12410 /* bits 15..12 for 0x2d */
12411 SYNC = 0x6,
12412 SYSCALL = 0x8,
12413 SDBBP = 0xd,
12415 /* bits 15..12 for 0x35 */
12416 MFHI32 = 0x0,
12417 MFLO32 = 0x1,
12418 MTHI32 = 0x2,
12419 MTLO32 = 0x3,
12422 /* POOL32B encoding of minor opcode field (bits 15..12) */
12424 enum {
12425 LWC2 = 0x0,
12426 LWP = 0x1,
12427 LDP = 0x4,
12428 LWM32 = 0x5,
12429 CACHE = 0x6,
12430 LDM = 0x7,
12431 SWC2 = 0x8,
12432 SWP = 0x9,
12433 SDP = 0xc,
12434 SWM32 = 0xd,
12435 SDM = 0xf
12438 /* POOL32C encoding of minor opcode field (bits 15..12) */
12440 enum {
12441 LWL = 0x0,
12442 SWL = 0x8,
12443 LWR = 0x1,
12444 SWR = 0x9,
12445 PREF = 0x2,
12446 /* 0xa is reserved */
12447 LL = 0x3,
12448 SC = 0xb,
12449 LDL = 0x4,
12450 SDL = 0xc,
12451 LDR = 0x5,
12452 SDR = 0xd,
12453 /* 0x6 is reserved */
12454 LWU = 0xe,
12455 LLD = 0x7,
12456 SCD = 0xf
12459 /* POOL32F encoding of minor opcode field (bits 5..0) */
12461 enum {
12462 /* These are the bit 7..6 values */
12463 ADD_FMT = 0x0,
12465 SUB_FMT = 0x1,
12467 MUL_FMT = 0x2,
12469 DIV_FMT = 0x3,
12471 /* These are the bit 8..6 values */
12472 MOVN_FMT = 0x0,
12473 RSQRT2_FMT = 0x0,
12474 MOVF_FMT = 0x0,
12475 RINT_FMT = 0x0,
12476 SELNEZ_FMT = 0x0,
12478 MOVZ_FMT = 0x1,
12479 LWXC1 = 0x1,
12480 MOVT_FMT = 0x1,
12481 CLASS_FMT = 0x1,
12482 SELEQZ_FMT = 0x1,
12484 PLL_PS = 0x2,
12485 SWXC1 = 0x2,
12486 SEL_FMT = 0x2,
12488 PLU_PS = 0x3,
12489 LDXC1 = 0x3,
12491 MOVN_FMT_04 = 0x4,
12492 PUL_PS = 0x4,
12493 SDXC1 = 0x4,
12494 RECIP2_FMT = 0x4,
12496 MOVZ_FMT_05 = 0x05,
12497 PUU_PS = 0x5,
12498 LUXC1 = 0x5,
12500 CVT_PS_S = 0x6,
12501 SUXC1 = 0x6,
12502 ADDR_PS = 0x6,
12503 PREFX = 0x6,
12504 MADDF_FMT = 0x6,
12506 MULR_PS = 0x7,
12507 MSUBF_FMT = 0x7,
12509 MADD_S = 0x01,
12510 MADD_D = 0x09,
12511 MADD_PS = 0x11,
12512 ALNV_PS = 0x19,
12513 MSUB_S = 0x21,
12514 MSUB_D = 0x29,
12515 MSUB_PS = 0x31,
12517 NMADD_S = 0x02,
12518 NMADD_D = 0x0a,
12519 NMADD_PS = 0x12,
12520 NMSUB_S = 0x22,
12521 NMSUB_D = 0x2a,
12522 NMSUB_PS = 0x32,
12524 MIN_FMT = 0x3,
12525 MAX_FMT = 0xb,
12526 MINA_FMT = 0x23,
12527 MAXA_FMT = 0x2b,
12528 POOL32FXF = 0x3b,
12530 CABS_COND_FMT = 0x1c, /* MIPS3D */
12531 C_COND_FMT = 0x3c,
12533 CMP_CONDN_S = 0x5,
12534 CMP_CONDN_D = 0x15
12537 /* POOL32Fxf encoding of minor opcode extension field */
12539 enum {
12540 CVT_L = 0x04,
12541 RSQRT_FMT = 0x08,
12542 FLOOR_L = 0x0c,
12543 CVT_PW_PS = 0x1c,
12544 CVT_W = 0x24,
12545 SQRT_FMT = 0x28,
12546 FLOOR_W = 0x2c,
12547 CVT_PS_PW = 0x3c,
12548 CFC1 = 0x40,
12549 RECIP_FMT = 0x48,
12550 CEIL_L = 0x4c,
12551 CTC1 = 0x60,
12552 CEIL_W = 0x6c,
12553 MFC1 = 0x80,
12554 CVT_S_PL = 0x84,
12555 TRUNC_L = 0x8c,
12556 MTC1 = 0xa0,
12557 CVT_S_PU = 0xa4,
12558 TRUNC_W = 0xac,
12559 MFHC1 = 0xc0,
12560 ROUND_L = 0xcc,
12561 MTHC1 = 0xe0,
12562 ROUND_W = 0xec,
12564 MOV_FMT = 0x01,
12565 MOVF = 0x05,
12566 ABS_FMT = 0x0d,
12567 RSQRT1_FMT = 0x1d,
12568 MOVT = 0x25,
12569 NEG_FMT = 0x2d,
12570 CVT_D = 0x4d,
12571 RECIP1_FMT = 0x5d,
12572 CVT_S = 0x6d
12575 /* POOL32I encoding of minor opcode field (bits 25..21) */
12577 enum {
12578 BLTZ = 0x00,
12579 BLTZAL = 0x01,
12580 BGEZ = 0x02,
12581 BGEZAL = 0x03,
12582 BLEZ = 0x04,
12583 BNEZC = 0x05,
12584 BGTZ = 0x06,
12585 BEQZC = 0x07,
12586 TLTI = 0x08,
12587 BC1EQZC = 0x08,
12588 TGEI = 0x09,
12589 BC1NEZC = 0x09,
12590 TLTIU = 0x0a,
12591 BC2EQZC = 0x0a,
12592 TGEIU = 0x0b,
12593 BC2NEZC = 0x0a,
12594 TNEI = 0x0c,
12595 R6_SYNCI = 0x0c,
12596 LUI = 0x0d,
12597 TEQI = 0x0e,
12598 SYNCI = 0x10,
12599 BLTZALS = 0x11,
12600 BGEZALS = 0x13,
12601 BC2F = 0x14,
12602 BC2T = 0x15,
12603 BPOSGE64 = 0x1a,
12604 BPOSGE32 = 0x1b,
12605 /* These overlap and are distinguished by bit16 of the instruction */
12606 BC1F = 0x1c,
12607 BC1T = 0x1d,
12608 BC1ANY2F = 0x1c,
12609 BC1ANY2T = 0x1d,
12610 BC1ANY4F = 0x1e,
12611 BC1ANY4T = 0x1f
12614 /* POOL16A encoding of minor opcode field */
12616 enum {
12617 ADDU16 = 0x0,
12618 SUBU16 = 0x1
12621 /* POOL16B encoding of minor opcode field */
12623 enum {
12624 SLL16 = 0x0,
12625 SRL16 = 0x1
12628 /* POOL16C encoding of minor opcode field */
12630 enum {
12631 NOT16 = 0x00,
12632 XOR16 = 0x04,
12633 AND16 = 0x08,
12634 OR16 = 0x0c,
12635 LWM16 = 0x10,
12636 SWM16 = 0x14,
12637 JR16 = 0x18,
12638 JRC16 = 0x1a,
12639 JALR16 = 0x1c,
12640 JALR16S = 0x1e,
12641 MFHI16 = 0x20,
12642 MFLO16 = 0x24,
12643 BREAK16 = 0x28,
12644 SDBBP16 = 0x2c,
12645 JRADDIUSP = 0x30
12648 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
12650 enum {
12651 R6_NOT16 = 0x00,
12652 R6_AND16 = 0x01,
12653 R6_LWM16 = 0x02,
12654 R6_JRC16 = 0x03,
12655 MOVEP = 0x04,
12656 MOVEP_07 = 0x07,
12657 R6_XOR16 = 0x08,
12658 R6_OR16 = 0x09,
12659 R6_SWM16 = 0x0a,
12660 JALRC16 = 0x0b,
12661 MOVEP_0C = 0x0c,
12662 MOVEP_0F = 0x0f,
12663 JRCADDIUSP = 0x13,
12664 R6_BREAK16 = 0x1b,
12665 R6_SDBBP16 = 0x3b
12668 /* POOL16D encoding of minor opcode field */
12670 enum {
12671 ADDIUS5 = 0x0,
12672 ADDIUSP = 0x1
12675 /* POOL16E encoding of minor opcode field */
12677 enum {
12678 ADDIUR2 = 0x0,
12679 ADDIUR1SP = 0x1
12682 static int mmreg (int r)
12684 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12686 return map[r];
12689 /* Used for 16-bit store instructions. */
12690 static int mmreg2 (int r)
12692 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12694 return map[r];
12697 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12698 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12699 #define uMIPS_RS2(op) uMIPS_RS(op)
12700 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12701 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12702 #define uMIPS_RS5(op) (op & 0x1f)
12704 /* Signed immediate */
12705 #define SIMM(op, start, width) \
12706 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12707 << (32-width)) \
12708 >> (32-width))
12709 /* Zero-extended immediate */
12710 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12712 static void gen_addiur1sp(DisasContext *ctx)
12714 int rd = mmreg(uMIPS_RD(ctx->opcode));
12716 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12719 static void gen_addiur2(DisasContext *ctx)
12721 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12722 int rd = mmreg(uMIPS_RD(ctx->opcode));
12723 int rs = mmreg(uMIPS_RS(ctx->opcode));
12725 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12728 static void gen_addiusp(DisasContext *ctx)
12730 int encoded = ZIMM(ctx->opcode, 1, 9);
12731 int decoded;
12733 if (encoded <= 1) {
12734 decoded = 256 + encoded;
12735 } else if (encoded <= 255) {
12736 decoded = encoded;
12737 } else if (encoded <= 509) {
12738 decoded = encoded - 512;
12739 } else {
12740 decoded = encoded - 768;
12743 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
12746 static void gen_addius5(DisasContext *ctx)
12748 int imm = SIMM(ctx->opcode, 1, 4);
12749 int rd = (ctx->opcode >> 5) & 0x1f;
12751 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
12754 static void gen_andi16(DisasContext *ctx)
12756 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
12757 31, 32, 63, 64, 255, 32768, 65535 };
12758 int rd = mmreg(uMIPS_RD(ctx->opcode));
12759 int rs = mmreg(uMIPS_RS(ctx->opcode));
12760 int encoded = ZIMM(ctx->opcode, 0, 4);
12762 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
12765 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
12766 int base, int16_t offset)
12768 TCGv t0, t1;
12769 TCGv_i32 t2;
12771 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12772 generate_exception_end(ctx, EXCP_RI);
12773 return;
12776 t0 = tcg_temp_new();
12778 gen_base_offset_addr(ctx, t0, base, offset);
12780 t1 = tcg_const_tl(reglist);
12781 t2 = tcg_const_i32(ctx->mem_idx);
12783 save_cpu_state(ctx, 1);
12784 switch (opc) {
12785 case LWM32:
12786 gen_helper_lwm(cpu_env, t0, t1, t2);
12787 break;
12788 case SWM32:
12789 gen_helper_swm(cpu_env, t0, t1, t2);
12790 break;
12791 #ifdef TARGET_MIPS64
12792 case LDM:
12793 gen_helper_ldm(cpu_env, t0, t1, t2);
12794 break;
12795 case SDM:
12796 gen_helper_sdm(cpu_env, t0, t1, t2);
12797 break;
12798 #endif
12800 tcg_temp_free(t0);
12801 tcg_temp_free(t1);
12802 tcg_temp_free_i32(t2);
12806 static void gen_pool16c_insn(DisasContext *ctx)
12808 int rd = mmreg((ctx->opcode >> 3) & 0x7);
12809 int rs = mmreg(ctx->opcode & 0x7);
12811 switch (((ctx->opcode) >> 4) & 0x3f) {
12812 case NOT16 + 0:
12813 case NOT16 + 1:
12814 case NOT16 + 2:
12815 case NOT16 + 3:
12816 gen_logic(ctx, OPC_NOR, rd, rs, 0);
12817 break;
12818 case XOR16 + 0:
12819 case XOR16 + 1:
12820 case XOR16 + 2:
12821 case XOR16 + 3:
12822 gen_logic(ctx, OPC_XOR, rd, rd, rs);
12823 break;
12824 case AND16 + 0:
12825 case AND16 + 1:
12826 case AND16 + 2:
12827 case AND16 + 3:
12828 gen_logic(ctx, OPC_AND, rd, rd, rs);
12829 break;
12830 case OR16 + 0:
12831 case OR16 + 1:
12832 case OR16 + 2:
12833 case OR16 + 3:
12834 gen_logic(ctx, OPC_OR, rd, rd, rs);
12835 break;
12836 case LWM16 + 0:
12837 case LWM16 + 1:
12838 case LWM16 + 2:
12839 case LWM16 + 3:
12841 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12842 int offset = ZIMM(ctx->opcode, 0, 4);
12844 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
12845 29, offset << 2);
12847 break;
12848 case SWM16 + 0:
12849 case SWM16 + 1:
12850 case SWM16 + 2:
12851 case SWM16 + 3:
12853 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12854 int offset = ZIMM(ctx->opcode, 0, 4);
12856 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
12857 29, offset << 2);
12859 break;
12860 case JR16 + 0:
12861 case JR16 + 1:
12863 int reg = ctx->opcode & 0x1f;
12865 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
12867 break;
12868 case JRC16 + 0:
12869 case JRC16 + 1:
12871 int reg = ctx->opcode & 0x1f;
12872 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
12873 /* Let normal delay slot handling in our caller take us
12874 to the branch target. */
12876 break;
12877 case JALR16 + 0:
12878 case JALR16 + 1:
12879 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
12880 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12881 break;
12882 case JALR16S + 0:
12883 case JALR16S + 1:
12884 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
12885 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12886 break;
12887 case MFHI16 + 0:
12888 case MFHI16 + 1:
12889 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
12890 break;
12891 case MFLO16 + 0:
12892 case MFLO16 + 1:
12893 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
12894 break;
12895 case BREAK16:
12896 generate_exception_end(ctx, EXCP_BREAK);
12897 break;
12898 case SDBBP16:
12899 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
12900 gen_helper_do_semihosting(cpu_env);
12901 } else {
12902 /* XXX: not clear which exception should be raised
12903 * when in debug mode...
12905 check_insn(ctx, ISA_MIPS32);
12906 generate_exception_end(ctx, EXCP_DBp);
12908 break;
12909 case JRADDIUSP + 0:
12910 case JRADDIUSP + 1:
12912 int imm = ZIMM(ctx->opcode, 0, 5);
12913 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12914 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12915 /* Let normal delay slot handling in our caller take us
12916 to the branch target. */
12918 break;
12919 default:
12920 generate_exception_end(ctx, EXCP_RI);
12921 break;
12925 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
12926 int enc_rs)
12928 int rd, rs, re, rt;
12929 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
12930 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
12931 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
12932 rd = rd_enc[enc_dest];
12933 re = re_enc[enc_dest];
12934 rs = rs_rt_enc[enc_rs];
12935 rt = rs_rt_enc[enc_rt];
12936 if (rs) {
12937 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
12938 } else {
12939 tcg_gen_movi_tl(cpu_gpr[rd], 0);
12941 if (rt) {
12942 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
12943 } else {
12944 tcg_gen_movi_tl(cpu_gpr[re], 0);
12948 static void gen_pool16c_r6_insn(DisasContext *ctx)
12950 int rt = mmreg((ctx->opcode >> 7) & 0x7);
12951 int rs = mmreg((ctx->opcode >> 4) & 0x7);
12953 switch (ctx->opcode & 0xf) {
12954 case R6_NOT16:
12955 gen_logic(ctx, OPC_NOR, rt, rs, 0);
12956 break;
12957 case R6_AND16:
12958 gen_logic(ctx, OPC_AND, rt, rt, rs);
12959 break;
12960 case R6_LWM16:
12962 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
12963 int offset = extract32(ctx->opcode, 4, 4);
12964 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
12966 break;
12967 case R6_JRC16: /* JRCADDIUSP */
12968 if ((ctx->opcode >> 4) & 1) {
12969 /* JRCADDIUSP */
12970 int imm = extract32(ctx->opcode, 5, 5);
12971 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12972 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12973 } else {
12974 /* JRC16 */
12975 int rs = extract32(ctx->opcode, 5, 5);
12976 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
12978 break;
12979 case MOVEP ... MOVEP_07:
12980 case MOVEP_0C ... MOVEP_0F:
12982 int enc_dest = uMIPS_RD(ctx->opcode);
12983 int enc_rt = uMIPS_RS2(ctx->opcode);
12984 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
12985 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
12987 break;
12988 case R6_XOR16:
12989 gen_logic(ctx, OPC_XOR, rt, rt, rs);
12990 break;
12991 case R6_OR16:
12992 gen_logic(ctx, OPC_OR, rt, rt, rs);
12993 break;
12994 case R6_SWM16:
12996 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
12997 int offset = extract32(ctx->opcode, 4, 4);
12998 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
13000 break;
13001 case JALRC16: /* BREAK16, SDBBP16 */
13002 switch (ctx->opcode & 0x3f) {
13003 case JALRC16:
13004 case JALRC16 + 0x20:
13005 /* JALRC16 */
13006 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
13007 31, 0, 0);
13008 break;
13009 case R6_BREAK16:
13010 /* BREAK16 */
13011 generate_exception(ctx, EXCP_BREAK);
13012 break;
13013 case R6_SDBBP16:
13014 /* SDBBP16 */
13015 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
13016 gen_helper_do_semihosting(cpu_env);
13017 } else {
13018 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13019 generate_exception(ctx, EXCP_RI);
13020 } else {
13021 generate_exception(ctx, EXCP_DBp);
13024 break;
13026 break;
13027 default:
13028 generate_exception(ctx, EXCP_RI);
13029 break;
13033 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
13035 TCGv t0 = tcg_temp_new();
13036 TCGv t1 = tcg_temp_new();
13038 gen_load_gpr(t0, base);
13040 if (index != 0) {
13041 gen_load_gpr(t1, index);
13042 tcg_gen_shli_tl(t1, t1, 2);
13043 gen_op_addr_add(ctx, t0, t1, t0);
13046 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13047 gen_store_gpr(t1, rd);
13049 tcg_temp_free(t0);
13050 tcg_temp_free(t1);
13053 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
13054 int base, int16_t offset)
13056 TCGv t0, t1;
13058 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
13059 generate_exception_end(ctx, EXCP_RI);
13060 return;
13063 t0 = tcg_temp_new();
13064 t1 = tcg_temp_new();
13066 gen_base_offset_addr(ctx, t0, base, offset);
13068 switch (opc) {
13069 case LWP:
13070 if (rd == base) {
13071 generate_exception_end(ctx, EXCP_RI);
13072 return;
13074 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13075 gen_store_gpr(t1, rd);
13076 tcg_gen_movi_tl(t1, 4);
13077 gen_op_addr_add(ctx, t0, t0, t1);
13078 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13079 gen_store_gpr(t1, rd+1);
13080 break;
13081 case SWP:
13082 gen_load_gpr(t1, rd);
13083 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13084 tcg_gen_movi_tl(t1, 4);
13085 gen_op_addr_add(ctx, t0, t0, t1);
13086 gen_load_gpr(t1, rd+1);
13087 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13088 break;
13089 #ifdef TARGET_MIPS64
13090 case LDP:
13091 if (rd == base) {
13092 generate_exception_end(ctx, EXCP_RI);
13093 return;
13095 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13096 gen_store_gpr(t1, rd);
13097 tcg_gen_movi_tl(t1, 8);
13098 gen_op_addr_add(ctx, t0, t0, t1);
13099 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13100 gen_store_gpr(t1, rd+1);
13101 break;
13102 case SDP:
13103 gen_load_gpr(t1, rd);
13104 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13105 tcg_gen_movi_tl(t1, 8);
13106 gen_op_addr_add(ctx, t0, t0, t1);
13107 gen_load_gpr(t1, rd+1);
13108 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13109 break;
13110 #endif
13112 tcg_temp_free(t0);
13113 tcg_temp_free(t1);
13116 static void gen_sync(int stype)
13118 TCGBar tcg_mo = TCG_BAR_SC;
13120 switch (stype) {
13121 case 0x4: /* SYNC_WMB */
13122 tcg_mo |= TCG_MO_ST_ST;
13123 break;
13124 case 0x10: /* SYNC_MB */
13125 tcg_mo |= TCG_MO_ALL;
13126 break;
13127 case 0x11: /* SYNC_ACQUIRE */
13128 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
13129 break;
13130 case 0x12: /* SYNC_RELEASE */
13131 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
13132 break;
13133 case 0x13: /* SYNC_RMB */
13134 tcg_mo |= TCG_MO_LD_LD;
13135 break;
13136 default:
13137 tcg_mo |= TCG_MO_ALL;
13138 break;
13141 tcg_gen_mb(tcg_mo);
13144 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
13146 int extension = (ctx->opcode >> 6) & 0x3f;
13147 int minor = (ctx->opcode >> 12) & 0xf;
13148 uint32_t mips32_op;
13150 switch (extension) {
13151 case TEQ:
13152 mips32_op = OPC_TEQ;
13153 goto do_trap;
13154 case TGE:
13155 mips32_op = OPC_TGE;
13156 goto do_trap;
13157 case TGEU:
13158 mips32_op = OPC_TGEU;
13159 goto do_trap;
13160 case TLT:
13161 mips32_op = OPC_TLT;
13162 goto do_trap;
13163 case TLTU:
13164 mips32_op = OPC_TLTU;
13165 goto do_trap;
13166 case TNE:
13167 mips32_op = OPC_TNE;
13168 do_trap:
13169 gen_trap(ctx, mips32_op, rs, rt, -1);
13170 break;
13171 #ifndef CONFIG_USER_ONLY
13172 case MFC0:
13173 case MFC0 + 32:
13174 check_cp0_enabled(ctx);
13175 if (rt == 0) {
13176 /* Treat as NOP. */
13177 break;
13179 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
13180 break;
13181 case MTC0:
13182 case MTC0 + 32:
13183 check_cp0_enabled(ctx);
13185 TCGv t0 = tcg_temp_new();
13187 gen_load_gpr(t0, rt);
13188 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
13189 tcg_temp_free(t0);
13191 break;
13192 #endif
13193 case 0x2a:
13194 switch (minor & 3) {
13195 case MADD_ACC:
13196 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
13197 break;
13198 case MADDU_ACC:
13199 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
13200 break;
13201 case MSUB_ACC:
13202 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
13203 break;
13204 case MSUBU_ACC:
13205 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
13206 break;
13207 default:
13208 goto pool32axf_invalid;
13210 break;
13211 case 0x32:
13212 switch (minor & 3) {
13213 case MULT_ACC:
13214 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
13215 break;
13216 case MULTU_ACC:
13217 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
13218 break;
13219 default:
13220 goto pool32axf_invalid;
13222 break;
13223 case 0x2c:
13224 switch (minor) {
13225 case BITSWAP:
13226 check_insn(ctx, ISA_MIPS32R6);
13227 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
13228 break;
13229 case SEB:
13230 gen_bshfl(ctx, OPC_SEB, rs, rt);
13231 break;
13232 case SEH:
13233 gen_bshfl(ctx, OPC_SEH, rs, rt);
13234 break;
13235 case CLO:
13236 mips32_op = OPC_CLO;
13237 goto do_cl;
13238 case CLZ:
13239 mips32_op = OPC_CLZ;
13240 do_cl:
13241 check_insn(ctx, ISA_MIPS32);
13242 gen_cl(ctx, mips32_op, rt, rs);
13243 break;
13244 case RDHWR:
13245 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13246 gen_rdhwr(ctx, rt, rs, 0);
13247 break;
13248 case WSBH:
13249 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13250 break;
13251 case MULT:
13252 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13253 mips32_op = OPC_MULT;
13254 goto do_mul;
13255 case MULTU:
13256 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13257 mips32_op = OPC_MULTU;
13258 goto do_mul;
13259 case DIV:
13260 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13261 mips32_op = OPC_DIV;
13262 goto do_div;
13263 case DIVU:
13264 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13265 mips32_op = OPC_DIVU;
13266 goto do_div;
13267 do_div:
13268 check_insn(ctx, ISA_MIPS32);
13269 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13270 break;
13271 case MADD:
13272 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13273 mips32_op = OPC_MADD;
13274 goto do_mul;
13275 case MADDU:
13276 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13277 mips32_op = OPC_MADDU;
13278 goto do_mul;
13279 case MSUB:
13280 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13281 mips32_op = OPC_MSUB;
13282 goto do_mul;
13283 case MSUBU:
13284 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13285 mips32_op = OPC_MSUBU;
13286 do_mul:
13287 check_insn(ctx, ISA_MIPS32);
13288 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13289 break;
13290 default:
13291 goto pool32axf_invalid;
13293 break;
13294 case 0x34:
13295 switch (minor) {
13296 case MFC2:
13297 case MTC2:
13298 case MFHC2:
13299 case MTHC2:
13300 case CFC2:
13301 case CTC2:
13302 generate_exception_err(ctx, EXCP_CpU, 2);
13303 break;
13304 default:
13305 goto pool32axf_invalid;
13307 break;
13308 case 0x3c:
13309 switch (minor) {
13310 case JALR: /* JALRC */
13311 case JALR_HB: /* JALRC_HB */
13312 if (ctx->insn_flags & ISA_MIPS32R6) {
13313 /* JALRC, JALRC_HB */
13314 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13315 } else {
13316 /* JALR, JALR_HB */
13317 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13318 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13320 break;
13321 case JALRS:
13322 case JALRS_HB:
13323 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13324 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13325 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13326 break;
13327 default:
13328 goto pool32axf_invalid;
13330 break;
13331 case 0x05:
13332 switch (minor) {
13333 case RDPGPR:
13334 check_cp0_enabled(ctx);
13335 check_insn(ctx, ISA_MIPS32R2);
13336 gen_load_srsgpr(rs, rt);
13337 break;
13338 case WRPGPR:
13339 check_cp0_enabled(ctx);
13340 check_insn(ctx, ISA_MIPS32R2);
13341 gen_store_srsgpr(rs, rt);
13342 break;
13343 default:
13344 goto pool32axf_invalid;
13346 break;
13347 #ifndef CONFIG_USER_ONLY
13348 case 0x0d:
13349 switch (minor) {
13350 case TLBP:
13351 mips32_op = OPC_TLBP;
13352 goto do_cp0;
13353 case TLBR:
13354 mips32_op = OPC_TLBR;
13355 goto do_cp0;
13356 case TLBWI:
13357 mips32_op = OPC_TLBWI;
13358 goto do_cp0;
13359 case TLBWR:
13360 mips32_op = OPC_TLBWR;
13361 goto do_cp0;
13362 case TLBINV:
13363 mips32_op = OPC_TLBINV;
13364 goto do_cp0;
13365 case TLBINVF:
13366 mips32_op = OPC_TLBINVF;
13367 goto do_cp0;
13368 case WAIT:
13369 mips32_op = OPC_WAIT;
13370 goto do_cp0;
13371 case DERET:
13372 mips32_op = OPC_DERET;
13373 goto do_cp0;
13374 case ERET:
13375 mips32_op = OPC_ERET;
13376 do_cp0:
13377 gen_cp0(env, ctx, mips32_op, rt, rs);
13378 break;
13379 default:
13380 goto pool32axf_invalid;
13382 break;
13383 case 0x1d:
13384 switch (minor) {
13385 case DI:
13386 check_cp0_enabled(ctx);
13388 TCGv t0 = tcg_temp_new();
13390 save_cpu_state(ctx, 1);
13391 gen_helper_di(t0, cpu_env);
13392 gen_store_gpr(t0, rs);
13393 /* Stop translation as we may have switched the execution mode */
13394 ctx->bstate = BS_STOP;
13395 tcg_temp_free(t0);
13397 break;
13398 case EI:
13399 check_cp0_enabled(ctx);
13401 TCGv t0 = tcg_temp_new();
13403 save_cpu_state(ctx, 1);
13404 gen_helper_ei(t0, cpu_env);
13405 gen_store_gpr(t0, rs);
13406 /* Stop translation as we may have switched the execution mode */
13407 ctx->bstate = BS_STOP;
13408 tcg_temp_free(t0);
13410 break;
13411 default:
13412 goto pool32axf_invalid;
13414 break;
13415 #endif
13416 case 0x2d:
13417 switch (minor) {
13418 case SYNC:
13419 gen_sync(extract32(ctx->opcode, 16, 5));
13420 break;
13421 case SYSCALL:
13422 generate_exception_end(ctx, EXCP_SYSCALL);
13423 break;
13424 case SDBBP:
13425 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
13426 gen_helper_do_semihosting(cpu_env);
13427 } else {
13428 check_insn(ctx, ISA_MIPS32);
13429 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13430 generate_exception_end(ctx, EXCP_RI);
13431 } else {
13432 generate_exception_end(ctx, EXCP_DBp);
13435 break;
13436 default:
13437 goto pool32axf_invalid;
13439 break;
13440 case 0x01:
13441 switch (minor & 3) {
13442 case MFHI_ACC:
13443 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
13444 break;
13445 case MFLO_ACC:
13446 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
13447 break;
13448 case MTHI_ACC:
13449 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
13450 break;
13451 case MTLO_ACC:
13452 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
13453 break;
13454 default:
13455 goto pool32axf_invalid;
13457 break;
13458 case 0x35:
13459 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13460 switch (minor) {
13461 case MFHI32:
13462 gen_HILO(ctx, OPC_MFHI, 0, rs);
13463 break;
13464 case MFLO32:
13465 gen_HILO(ctx, OPC_MFLO, 0, rs);
13466 break;
13467 case MTHI32:
13468 gen_HILO(ctx, OPC_MTHI, 0, rs);
13469 break;
13470 case MTLO32:
13471 gen_HILO(ctx, OPC_MTLO, 0, rs);
13472 break;
13473 default:
13474 goto pool32axf_invalid;
13476 break;
13477 default:
13478 pool32axf_invalid:
13479 MIPS_INVAL("pool32axf");
13480 generate_exception_end(ctx, EXCP_RI);
13481 break;
13485 /* Values for microMIPS fmt field. Variable-width, depending on which
13486 formats the instruction supports. */
13488 enum {
13489 FMT_SD_S = 0,
13490 FMT_SD_D = 1,
13492 FMT_SDPS_S = 0,
13493 FMT_SDPS_D = 1,
13494 FMT_SDPS_PS = 2,
13496 FMT_SWL_S = 0,
13497 FMT_SWL_W = 1,
13498 FMT_SWL_L = 2,
13500 FMT_DWL_D = 0,
13501 FMT_DWL_W = 1,
13502 FMT_DWL_L = 2
13505 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
13507 int extension = (ctx->opcode >> 6) & 0x3ff;
13508 uint32_t mips32_op;
13510 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
13511 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
13512 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
13514 switch (extension) {
13515 case FLOAT_1BIT_FMT(CFC1, 0):
13516 mips32_op = OPC_CFC1;
13517 goto do_cp1;
13518 case FLOAT_1BIT_FMT(CTC1, 0):
13519 mips32_op = OPC_CTC1;
13520 goto do_cp1;
13521 case FLOAT_1BIT_FMT(MFC1, 0):
13522 mips32_op = OPC_MFC1;
13523 goto do_cp1;
13524 case FLOAT_1BIT_FMT(MTC1, 0):
13525 mips32_op = OPC_MTC1;
13526 goto do_cp1;
13527 case FLOAT_1BIT_FMT(MFHC1, 0):
13528 mips32_op = OPC_MFHC1;
13529 goto do_cp1;
13530 case FLOAT_1BIT_FMT(MTHC1, 0):
13531 mips32_op = OPC_MTHC1;
13532 do_cp1:
13533 gen_cp1(ctx, mips32_op, rt, rs);
13534 break;
13536 /* Reciprocal square root */
13537 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
13538 mips32_op = OPC_RSQRT_S;
13539 goto do_unaryfp;
13540 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
13541 mips32_op = OPC_RSQRT_D;
13542 goto do_unaryfp;
13544 /* Square root */
13545 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
13546 mips32_op = OPC_SQRT_S;
13547 goto do_unaryfp;
13548 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
13549 mips32_op = OPC_SQRT_D;
13550 goto do_unaryfp;
13552 /* Reciprocal */
13553 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
13554 mips32_op = OPC_RECIP_S;
13555 goto do_unaryfp;
13556 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
13557 mips32_op = OPC_RECIP_D;
13558 goto do_unaryfp;
13560 /* Floor */
13561 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
13562 mips32_op = OPC_FLOOR_L_S;
13563 goto do_unaryfp;
13564 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
13565 mips32_op = OPC_FLOOR_L_D;
13566 goto do_unaryfp;
13567 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
13568 mips32_op = OPC_FLOOR_W_S;
13569 goto do_unaryfp;
13570 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
13571 mips32_op = OPC_FLOOR_W_D;
13572 goto do_unaryfp;
13574 /* Ceiling */
13575 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
13576 mips32_op = OPC_CEIL_L_S;
13577 goto do_unaryfp;
13578 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
13579 mips32_op = OPC_CEIL_L_D;
13580 goto do_unaryfp;
13581 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
13582 mips32_op = OPC_CEIL_W_S;
13583 goto do_unaryfp;
13584 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
13585 mips32_op = OPC_CEIL_W_D;
13586 goto do_unaryfp;
13588 /* Truncation */
13589 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
13590 mips32_op = OPC_TRUNC_L_S;
13591 goto do_unaryfp;
13592 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
13593 mips32_op = OPC_TRUNC_L_D;
13594 goto do_unaryfp;
13595 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
13596 mips32_op = OPC_TRUNC_W_S;
13597 goto do_unaryfp;
13598 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
13599 mips32_op = OPC_TRUNC_W_D;
13600 goto do_unaryfp;
13602 /* Round */
13603 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
13604 mips32_op = OPC_ROUND_L_S;
13605 goto do_unaryfp;
13606 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
13607 mips32_op = OPC_ROUND_L_D;
13608 goto do_unaryfp;
13609 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
13610 mips32_op = OPC_ROUND_W_S;
13611 goto do_unaryfp;
13612 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
13613 mips32_op = OPC_ROUND_W_D;
13614 goto do_unaryfp;
13616 /* Integer to floating-point conversion */
13617 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
13618 mips32_op = OPC_CVT_L_S;
13619 goto do_unaryfp;
13620 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
13621 mips32_op = OPC_CVT_L_D;
13622 goto do_unaryfp;
13623 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
13624 mips32_op = OPC_CVT_W_S;
13625 goto do_unaryfp;
13626 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
13627 mips32_op = OPC_CVT_W_D;
13628 goto do_unaryfp;
13630 /* Paired-foo conversions */
13631 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
13632 mips32_op = OPC_CVT_S_PL;
13633 goto do_unaryfp;
13634 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13635 mips32_op = OPC_CVT_S_PU;
13636 goto do_unaryfp;
13637 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13638 mips32_op = OPC_CVT_PW_PS;
13639 goto do_unaryfp;
13640 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13641 mips32_op = OPC_CVT_PS_PW;
13642 goto do_unaryfp;
13644 /* Floating-point moves */
13645 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13646 mips32_op = OPC_MOV_S;
13647 goto do_unaryfp;
13648 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13649 mips32_op = OPC_MOV_D;
13650 goto do_unaryfp;
13651 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13652 mips32_op = OPC_MOV_PS;
13653 goto do_unaryfp;
13655 /* Absolute value */
13656 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13657 mips32_op = OPC_ABS_S;
13658 goto do_unaryfp;
13659 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13660 mips32_op = OPC_ABS_D;
13661 goto do_unaryfp;
13662 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13663 mips32_op = OPC_ABS_PS;
13664 goto do_unaryfp;
13666 /* Negation */
13667 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13668 mips32_op = OPC_NEG_S;
13669 goto do_unaryfp;
13670 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13671 mips32_op = OPC_NEG_D;
13672 goto do_unaryfp;
13673 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13674 mips32_op = OPC_NEG_PS;
13675 goto do_unaryfp;
13677 /* Reciprocal square root step */
13678 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13679 mips32_op = OPC_RSQRT1_S;
13680 goto do_unaryfp;
13681 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13682 mips32_op = OPC_RSQRT1_D;
13683 goto do_unaryfp;
13684 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13685 mips32_op = OPC_RSQRT1_PS;
13686 goto do_unaryfp;
13688 /* Reciprocal step */
13689 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13690 mips32_op = OPC_RECIP1_S;
13691 goto do_unaryfp;
13692 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13693 mips32_op = OPC_RECIP1_S;
13694 goto do_unaryfp;
13695 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13696 mips32_op = OPC_RECIP1_PS;
13697 goto do_unaryfp;
13699 /* Conversions from double */
13700 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13701 mips32_op = OPC_CVT_D_S;
13702 goto do_unaryfp;
13703 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13704 mips32_op = OPC_CVT_D_W;
13705 goto do_unaryfp;
13706 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13707 mips32_op = OPC_CVT_D_L;
13708 goto do_unaryfp;
13710 /* Conversions from single */
13711 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13712 mips32_op = OPC_CVT_S_D;
13713 goto do_unaryfp;
13714 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13715 mips32_op = OPC_CVT_S_W;
13716 goto do_unaryfp;
13717 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13718 mips32_op = OPC_CVT_S_L;
13719 do_unaryfp:
13720 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13721 break;
13723 /* Conditional moves on floating-point codes */
13724 case COND_FLOAT_MOV(MOVT, 0):
13725 case COND_FLOAT_MOV(MOVT, 1):
13726 case COND_FLOAT_MOV(MOVT, 2):
13727 case COND_FLOAT_MOV(MOVT, 3):
13728 case COND_FLOAT_MOV(MOVT, 4):
13729 case COND_FLOAT_MOV(MOVT, 5):
13730 case COND_FLOAT_MOV(MOVT, 6):
13731 case COND_FLOAT_MOV(MOVT, 7):
13732 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13733 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13734 break;
13735 case COND_FLOAT_MOV(MOVF, 0):
13736 case COND_FLOAT_MOV(MOVF, 1):
13737 case COND_FLOAT_MOV(MOVF, 2):
13738 case COND_FLOAT_MOV(MOVF, 3):
13739 case COND_FLOAT_MOV(MOVF, 4):
13740 case COND_FLOAT_MOV(MOVF, 5):
13741 case COND_FLOAT_MOV(MOVF, 6):
13742 case COND_FLOAT_MOV(MOVF, 7):
13743 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13744 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13745 break;
13746 default:
13747 MIPS_INVAL("pool32fxf");
13748 generate_exception_end(ctx, EXCP_RI);
13749 break;
13753 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
13755 int32_t offset;
13756 uint16_t insn;
13757 int rt, rs, rd, rr;
13758 int16_t imm;
13759 uint32_t op, minor, mips32_op;
13760 uint32_t cond, fmt, cc;
13762 insn = cpu_lduw_code(env, ctx->pc + 2);
13763 ctx->opcode = (ctx->opcode << 16) | insn;
13765 rt = (ctx->opcode >> 21) & 0x1f;
13766 rs = (ctx->opcode >> 16) & 0x1f;
13767 rd = (ctx->opcode >> 11) & 0x1f;
13768 rr = (ctx->opcode >> 6) & 0x1f;
13769 imm = (int16_t) ctx->opcode;
13771 op = (ctx->opcode >> 26) & 0x3f;
13772 switch (op) {
13773 case POOL32A:
13774 minor = ctx->opcode & 0x3f;
13775 switch (minor) {
13776 case 0x00:
13777 minor = (ctx->opcode >> 6) & 0xf;
13778 switch (minor) {
13779 case SLL32:
13780 mips32_op = OPC_SLL;
13781 goto do_shifti;
13782 case SRA:
13783 mips32_op = OPC_SRA;
13784 goto do_shifti;
13785 case SRL32:
13786 mips32_op = OPC_SRL;
13787 goto do_shifti;
13788 case ROTR:
13789 mips32_op = OPC_ROTR;
13790 do_shifti:
13791 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
13792 break;
13793 case SELEQZ:
13794 check_insn(ctx, ISA_MIPS32R6);
13795 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
13796 break;
13797 case SELNEZ:
13798 check_insn(ctx, ISA_MIPS32R6);
13799 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
13800 break;
13801 case R6_RDHWR:
13802 check_insn(ctx, ISA_MIPS32R6);
13803 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
13804 break;
13805 default:
13806 goto pool32a_invalid;
13808 break;
13809 case 0x10:
13810 minor = (ctx->opcode >> 6) & 0xf;
13811 switch (minor) {
13812 /* Arithmetic */
13813 case ADD:
13814 mips32_op = OPC_ADD;
13815 goto do_arith;
13816 case ADDU32:
13817 mips32_op = OPC_ADDU;
13818 goto do_arith;
13819 case SUB:
13820 mips32_op = OPC_SUB;
13821 goto do_arith;
13822 case SUBU32:
13823 mips32_op = OPC_SUBU;
13824 goto do_arith;
13825 case MUL:
13826 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13827 mips32_op = OPC_MUL;
13828 do_arith:
13829 gen_arith(ctx, mips32_op, rd, rs, rt);
13830 break;
13831 /* Shifts */
13832 case SLLV:
13833 mips32_op = OPC_SLLV;
13834 goto do_shift;
13835 case SRLV:
13836 mips32_op = OPC_SRLV;
13837 goto do_shift;
13838 case SRAV:
13839 mips32_op = OPC_SRAV;
13840 goto do_shift;
13841 case ROTRV:
13842 mips32_op = OPC_ROTRV;
13843 do_shift:
13844 gen_shift(ctx, mips32_op, rd, rs, rt);
13845 break;
13846 /* Logical operations */
13847 case AND:
13848 mips32_op = OPC_AND;
13849 goto do_logic;
13850 case OR32:
13851 mips32_op = OPC_OR;
13852 goto do_logic;
13853 case NOR:
13854 mips32_op = OPC_NOR;
13855 goto do_logic;
13856 case XOR32:
13857 mips32_op = OPC_XOR;
13858 do_logic:
13859 gen_logic(ctx, mips32_op, rd, rs, rt);
13860 break;
13861 /* Set less than */
13862 case SLT:
13863 mips32_op = OPC_SLT;
13864 goto do_slt;
13865 case SLTU:
13866 mips32_op = OPC_SLTU;
13867 do_slt:
13868 gen_slt(ctx, mips32_op, rd, rs, rt);
13869 break;
13870 default:
13871 goto pool32a_invalid;
13873 break;
13874 case 0x18:
13875 minor = (ctx->opcode >> 6) & 0xf;
13876 switch (minor) {
13877 /* Conditional moves */
13878 case MOVN: /* MUL */
13879 if (ctx->insn_flags & ISA_MIPS32R6) {
13880 /* MUL */
13881 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
13882 } else {
13883 /* MOVN */
13884 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
13886 break;
13887 case MOVZ: /* MUH */
13888 if (ctx->insn_flags & ISA_MIPS32R6) {
13889 /* MUH */
13890 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
13891 } else {
13892 /* MOVZ */
13893 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
13895 break;
13896 case MULU:
13897 check_insn(ctx, ISA_MIPS32R6);
13898 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
13899 break;
13900 case MUHU:
13901 check_insn(ctx, ISA_MIPS32R6);
13902 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
13903 break;
13904 case LWXS: /* DIV */
13905 if (ctx->insn_flags & ISA_MIPS32R6) {
13906 /* DIV */
13907 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
13908 } else {
13909 /* LWXS */
13910 gen_ldxs(ctx, rs, rt, rd);
13912 break;
13913 case MOD:
13914 check_insn(ctx, ISA_MIPS32R6);
13915 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
13916 break;
13917 case R6_DIVU:
13918 check_insn(ctx, ISA_MIPS32R6);
13919 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
13920 break;
13921 case MODU:
13922 check_insn(ctx, ISA_MIPS32R6);
13923 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
13924 break;
13925 default:
13926 goto pool32a_invalid;
13928 break;
13929 case INS:
13930 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
13931 return;
13932 case LSA:
13933 check_insn(ctx, ISA_MIPS32R6);
13934 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
13935 extract32(ctx->opcode, 9, 2));
13936 break;
13937 case ALIGN:
13938 check_insn(ctx, ISA_MIPS32R6);
13939 gen_align(ctx, OPC_ALIGN, rd, rs, rt,
13940 extract32(ctx->opcode, 9, 2));
13941 break;
13942 case EXT:
13943 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
13944 return;
13945 case POOL32AXF:
13946 gen_pool32axf(env, ctx, rt, rs);
13947 break;
13948 case BREAK32:
13949 generate_exception_end(ctx, EXCP_BREAK);
13950 break;
13951 case SIGRIE:
13952 check_insn(ctx, ISA_MIPS32R6);
13953 generate_exception_end(ctx, EXCP_RI);
13954 break;
13955 default:
13956 pool32a_invalid:
13957 MIPS_INVAL("pool32a");
13958 generate_exception_end(ctx, EXCP_RI);
13959 break;
13961 break;
13962 case POOL32B:
13963 minor = (ctx->opcode >> 12) & 0xf;
13964 switch (minor) {
13965 case CACHE:
13966 check_cp0_enabled(ctx);
13967 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
13968 gen_cache_operation(ctx, rt, rs, imm);
13970 break;
13971 case LWC2:
13972 case SWC2:
13973 /* COP2: Not implemented. */
13974 generate_exception_err(ctx, EXCP_CpU, 2);
13975 break;
13976 #ifdef TARGET_MIPS64
13977 case LDP:
13978 case SDP:
13979 check_insn(ctx, ISA_MIPS3);
13980 check_mips_64(ctx);
13981 /* Fallthrough */
13982 #endif
13983 case LWP:
13984 case SWP:
13985 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13986 break;
13987 #ifdef TARGET_MIPS64
13988 case LDM:
13989 case SDM:
13990 check_insn(ctx, ISA_MIPS3);
13991 check_mips_64(ctx);
13992 /* Fallthrough */
13993 #endif
13994 case LWM32:
13995 case SWM32:
13996 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13997 break;
13998 default:
13999 MIPS_INVAL("pool32b");
14000 generate_exception_end(ctx, EXCP_RI);
14001 break;
14003 break;
14004 case POOL32F:
14005 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14006 minor = ctx->opcode & 0x3f;
14007 check_cp1_enabled(ctx);
14008 switch (minor) {
14009 case ALNV_PS:
14010 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14011 mips32_op = OPC_ALNV_PS;
14012 goto do_madd;
14013 case MADD_S:
14014 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14015 mips32_op = OPC_MADD_S;
14016 goto do_madd;
14017 case MADD_D:
14018 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14019 mips32_op = OPC_MADD_D;
14020 goto do_madd;
14021 case MADD_PS:
14022 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14023 mips32_op = OPC_MADD_PS;
14024 goto do_madd;
14025 case MSUB_S:
14026 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14027 mips32_op = OPC_MSUB_S;
14028 goto do_madd;
14029 case MSUB_D:
14030 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14031 mips32_op = OPC_MSUB_D;
14032 goto do_madd;
14033 case MSUB_PS:
14034 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14035 mips32_op = OPC_MSUB_PS;
14036 goto do_madd;
14037 case NMADD_S:
14038 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14039 mips32_op = OPC_NMADD_S;
14040 goto do_madd;
14041 case NMADD_D:
14042 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14043 mips32_op = OPC_NMADD_D;
14044 goto do_madd;
14045 case NMADD_PS:
14046 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14047 mips32_op = OPC_NMADD_PS;
14048 goto do_madd;
14049 case NMSUB_S:
14050 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14051 mips32_op = OPC_NMSUB_S;
14052 goto do_madd;
14053 case NMSUB_D:
14054 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14055 mips32_op = OPC_NMSUB_D;
14056 goto do_madd;
14057 case NMSUB_PS:
14058 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14059 mips32_op = OPC_NMSUB_PS;
14060 do_madd:
14061 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
14062 break;
14063 case CABS_COND_FMT:
14064 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14065 cond = (ctx->opcode >> 6) & 0xf;
14066 cc = (ctx->opcode >> 13) & 0x7;
14067 fmt = (ctx->opcode >> 10) & 0x3;
14068 switch (fmt) {
14069 case 0x0:
14070 gen_cmpabs_s(ctx, cond, rt, rs, cc);
14071 break;
14072 case 0x1:
14073 gen_cmpabs_d(ctx, cond, rt, rs, cc);
14074 break;
14075 case 0x2:
14076 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
14077 break;
14078 default:
14079 goto pool32f_invalid;
14081 break;
14082 case C_COND_FMT:
14083 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14084 cond = (ctx->opcode >> 6) & 0xf;
14085 cc = (ctx->opcode >> 13) & 0x7;
14086 fmt = (ctx->opcode >> 10) & 0x3;
14087 switch (fmt) {
14088 case 0x0:
14089 gen_cmp_s(ctx, cond, rt, rs, cc);
14090 break;
14091 case 0x1:
14092 gen_cmp_d(ctx, cond, rt, rs, cc);
14093 break;
14094 case 0x2:
14095 gen_cmp_ps(ctx, cond, rt, rs, cc);
14096 break;
14097 default:
14098 goto pool32f_invalid;
14100 break;
14101 case CMP_CONDN_S:
14102 check_insn(ctx, ISA_MIPS32R6);
14103 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14104 break;
14105 case CMP_CONDN_D:
14106 check_insn(ctx, ISA_MIPS32R6);
14107 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14108 break;
14109 case POOL32FXF:
14110 gen_pool32fxf(ctx, rt, rs);
14111 break;
14112 case 0x00:
14113 /* PLL foo */
14114 switch ((ctx->opcode >> 6) & 0x7) {
14115 case PLL_PS:
14116 mips32_op = OPC_PLL_PS;
14117 goto do_ps;
14118 case PLU_PS:
14119 mips32_op = OPC_PLU_PS;
14120 goto do_ps;
14121 case PUL_PS:
14122 mips32_op = OPC_PUL_PS;
14123 goto do_ps;
14124 case PUU_PS:
14125 mips32_op = OPC_PUU_PS;
14126 goto do_ps;
14127 case CVT_PS_S:
14128 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14129 mips32_op = OPC_CVT_PS_S;
14130 do_ps:
14131 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14132 break;
14133 default:
14134 goto pool32f_invalid;
14136 break;
14137 case MIN_FMT:
14138 check_insn(ctx, ISA_MIPS32R6);
14139 switch ((ctx->opcode >> 9) & 0x3) {
14140 case FMT_SDPS_S:
14141 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
14142 break;
14143 case FMT_SDPS_D:
14144 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
14145 break;
14146 default:
14147 goto pool32f_invalid;
14149 break;
14150 case 0x08:
14151 /* [LS][WDU]XC1 */
14152 switch ((ctx->opcode >> 6) & 0x7) {
14153 case LWXC1:
14154 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14155 mips32_op = OPC_LWXC1;
14156 goto do_ldst_cp1;
14157 case SWXC1:
14158 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14159 mips32_op = OPC_SWXC1;
14160 goto do_ldst_cp1;
14161 case LDXC1:
14162 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14163 mips32_op = OPC_LDXC1;
14164 goto do_ldst_cp1;
14165 case SDXC1:
14166 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14167 mips32_op = OPC_SDXC1;
14168 goto do_ldst_cp1;
14169 case LUXC1:
14170 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14171 mips32_op = OPC_LUXC1;
14172 goto do_ldst_cp1;
14173 case SUXC1:
14174 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14175 mips32_op = OPC_SUXC1;
14176 do_ldst_cp1:
14177 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
14178 break;
14179 default:
14180 goto pool32f_invalid;
14182 break;
14183 case MAX_FMT:
14184 check_insn(ctx, ISA_MIPS32R6);
14185 switch ((ctx->opcode >> 9) & 0x3) {
14186 case FMT_SDPS_S:
14187 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
14188 break;
14189 case FMT_SDPS_D:
14190 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
14191 break;
14192 default:
14193 goto pool32f_invalid;
14195 break;
14196 case 0x18:
14197 /* 3D insns */
14198 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14199 fmt = (ctx->opcode >> 9) & 0x3;
14200 switch ((ctx->opcode >> 6) & 0x7) {
14201 case RSQRT2_FMT:
14202 switch (fmt) {
14203 case FMT_SDPS_S:
14204 mips32_op = OPC_RSQRT2_S;
14205 goto do_3d;
14206 case FMT_SDPS_D:
14207 mips32_op = OPC_RSQRT2_D;
14208 goto do_3d;
14209 case FMT_SDPS_PS:
14210 mips32_op = OPC_RSQRT2_PS;
14211 goto do_3d;
14212 default:
14213 goto pool32f_invalid;
14215 break;
14216 case RECIP2_FMT:
14217 switch (fmt) {
14218 case FMT_SDPS_S:
14219 mips32_op = OPC_RECIP2_S;
14220 goto do_3d;
14221 case FMT_SDPS_D:
14222 mips32_op = OPC_RECIP2_D;
14223 goto do_3d;
14224 case FMT_SDPS_PS:
14225 mips32_op = OPC_RECIP2_PS;
14226 goto do_3d;
14227 default:
14228 goto pool32f_invalid;
14230 break;
14231 case ADDR_PS:
14232 mips32_op = OPC_ADDR_PS;
14233 goto do_3d;
14234 case MULR_PS:
14235 mips32_op = OPC_MULR_PS;
14236 do_3d:
14237 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14238 break;
14239 default:
14240 goto pool32f_invalid;
14242 break;
14243 case 0x20:
14244 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
14245 cc = (ctx->opcode >> 13) & 0x7;
14246 fmt = (ctx->opcode >> 9) & 0x3;
14247 switch ((ctx->opcode >> 6) & 0x7) {
14248 case MOVF_FMT: /* RINT_FMT */
14249 if (ctx->insn_flags & ISA_MIPS32R6) {
14250 /* RINT_FMT */
14251 switch (fmt) {
14252 case FMT_SDPS_S:
14253 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14254 break;
14255 case FMT_SDPS_D:
14256 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14257 break;
14258 default:
14259 goto pool32f_invalid;
14261 } else {
14262 /* MOVF_FMT */
14263 switch (fmt) {
14264 case FMT_SDPS_S:
14265 gen_movcf_s(ctx, rs, rt, cc, 0);
14266 break;
14267 case FMT_SDPS_D:
14268 gen_movcf_d(ctx, rs, rt, cc, 0);
14269 break;
14270 case FMT_SDPS_PS:
14271 check_ps(ctx);
14272 gen_movcf_ps(ctx, rs, rt, cc, 0);
14273 break;
14274 default:
14275 goto pool32f_invalid;
14278 break;
14279 case MOVT_FMT: /* CLASS_FMT */
14280 if (ctx->insn_flags & ISA_MIPS32R6) {
14281 /* CLASS_FMT */
14282 switch (fmt) {
14283 case FMT_SDPS_S:
14284 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14285 break;
14286 case FMT_SDPS_D:
14287 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14288 break;
14289 default:
14290 goto pool32f_invalid;
14292 } else {
14293 /* MOVT_FMT */
14294 switch (fmt) {
14295 case FMT_SDPS_S:
14296 gen_movcf_s(ctx, rs, rt, cc, 1);
14297 break;
14298 case FMT_SDPS_D:
14299 gen_movcf_d(ctx, rs, rt, cc, 1);
14300 break;
14301 case FMT_SDPS_PS:
14302 check_ps(ctx);
14303 gen_movcf_ps(ctx, rs, rt, cc, 1);
14304 break;
14305 default:
14306 goto pool32f_invalid;
14309 break;
14310 case PREFX:
14311 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14312 break;
14313 default:
14314 goto pool32f_invalid;
14316 break;
14317 #define FINSN_3ARG_SDPS(prfx) \
14318 switch ((ctx->opcode >> 8) & 0x3) { \
14319 case FMT_SDPS_S: \
14320 mips32_op = OPC_##prfx##_S; \
14321 goto do_fpop; \
14322 case FMT_SDPS_D: \
14323 mips32_op = OPC_##prfx##_D; \
14324 goto do_fpop; \
14325 case FMT_SDPS_PS: \
14326 check_ps(ctx); \
14327 mips32_op = OPC_##prfx##_PS; \
14328 goto do_fpop; \
14329 default: \
14330 goto pool32f_invalid; \
14332 case MINA_FMT:
14333 check_insn(ctx, ISA_MIPS32R6);
14334 switch ((ctx->opcode >> 9) & 0x3) {
14335 case FMT_SDPS_S:
14336 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14337 break;
14338 case FMT_SDPS_D:
14339 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14340 break;
14341 default:
14342 goto pool32f_invalid;
14344 break;
14345 case MAXA_FMT:
14346 check_insn(ctx, ISA_MIPS32R6);
14347 switch ((ctx->opcode >> 9) & 0x3) {
14348 case FMT_SDPS_S:
14349 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14350 break;
14351 case FMT_SDPS_D:
14352 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14353 break;
14354 default:
14355 goto pool32f_invalid;
14357 break;
14358 case 0x30:
14359 /* regular FP ops */
14360 switch ((ctx->opcode >> 6) & 0x3) {
14361 case ADD_FMT:
14362 FINSN_3ARG_SDPS(ADD);
14363 break;
14364 case SUB_FMT:
14365 FINSN_3ARG_SDPS(SUB);
14366 break;
14367 case MUL_FMT:
14368 FINSN_3ARG_SDPS(MUL);
14369 break;
14370 case DIV_FMT:
14371 fmt = (ctx->opcode >> 8) & 0x3;
14372 if (fmt == 1) {
14373 mips32_op = OPC_DIV_D;
14374 } else if (fmt == 0) {
14375 mips32_op = OPC_DIV_S;
14376 } else {
14377 goto pool32f_invalid;
14379 goto do_fpop;
14380 default:
14381 goto pool32f_invalid;
14383 break;
14384 case 0x38:
14385 /* cmovs */
14386 switch ((ctx->opcode >> 6) & 0x7) {
14387 case MOVN_FMT: /* SELNEZ_FMT */
14388 if (ctx->insn_flags & ISA_MIPS32R6) {
14389 /* SELNEZ_FMT */
14390 switch ((ctx->opcode >> 9) & 0x3) {
14391 case FMT_SDPS_S:
14392 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14393 break;
14394 case FMT_SDPS_D:
14395 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
14396 break;
14397 default:
14398 goto pool32f_invalid;
14400 } else {
14401 /* MOVN_FMT */
14402 FINSN_3ARG_SDPS(MOVN);
14404 break;
14405 case MOVN_FMT_04:
14406 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14407 FINSN_3ARG_SDPS(MOVN);
14408 break;
14409 case MOVZ_FMT: /* SELEQZ_FMT */
14410 if (ctx->insn_flags & ISA_MIPS32R6) {
14411 /* SELEQZ_FMT */
14412 switch ((ctx->opcode >> 9) & 0x3) {
14413 case FMT_SDPS_S:
14414 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
14415 break;
14416 case FMT_SDPS_D:
14417 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
14418 break;
14419 default:
14420 goto pool32f_invalid;
14422 } else {
14423 /* MOVZ_FMT */
14424 FINSN_3ARG_SDPS(MOVZ);
14426 break;
14427 case MOVZ_FMT_05:
14428 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14429 FINSN_3ARG_SDPS(MOVZ);
14430 break;
14431 case SEL_FMT:
14432 check_insn(ctx, ISA_MIPS32R6);
14433 switch ((ctx->opcode >> 9) & 0x3) {
14434 case FMT_SDPS_S:
14435 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
14436 break;
14437 case FMT_SDPS_D:
14438 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
14439 break;
14440 default:
14441 goto pool32f_invalid;
14443 break;
14444 case MADDF_FMT:
14445 check_insn(ctx, ISA_MIPS32R6);
14446 switch ((ctx->opcode >> 9) & 0x3) {
14447 case FMT_SDPS_S:
14448 mips32_op = OPC_MADDF_S;
14449 goto do_fpop;
14450 case FMT_SDPS_D:
14451 mips32_op = OPC_MADDF_D;
14452 goto do_fpop;
14453 default:
14454 goto pool32f_invalid;
14456 break;
14457 case MSUBF_FMT:
14458 check_insn(ctx, ISA_MIPS32R6);
14459 switch ((ctx->opcode >> 9) & 0x3) {
14460 case FMT_SDPS_S:
14461 mips32_op = OPC_MSUBF_S;
14462 goto do_fpop;
14463 case FMT_SDPS_D:
14464 mips32_op = OPC_MSUBF_D;
14465 goto do_fpop;
14466 default:
14467 goto pool32f_invalid;
14469 break;
14470 default:
14471 goto pool32f_invalid;
14473 break;
14474 do_fpop:
14475 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14476 break;
14477 default:
14478 pool32f_invalid:
14479 MIPS_INVAL("pool32f");
14480 generate_exception_end(ctx, EXCP_RI);
14481 break;
14483 } else {
14484 generate_exception_err(ctx, EXCP_CpU, 1);
14486 break;
14487 case POOL32I:
14488 minor = (ctx->opcode >> 21) & 0x1f;
14489 switch (minor) {
14490 case BLTZ:
14491 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14492 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
14493 break;
14494 case BLTZAL:
14495 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14496 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
14497 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14498 break;
14499 case BLTZALS:
14500 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14501 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
14502 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14503 break;
14504 case BGEZ:
14505 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14506 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
14507 break;
14508 case BGEZAL:
14509 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14510 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
14511 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14512 break;
14513 case BGEZALS:
14514 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14515 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
14516 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14517 break;
14518 case BLEZ:
14519 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14520 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
14521 break;
14522 case BGTZ:
14523 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14524 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
14525 break;
14527 /* Traps */
14528 case TLTI: /* BC1EQZC */
14529 if (ctx->insn_flags & ISA_MIPS32R6) {
14530 /* BC1EQZC */
14531 check_cp1_enabled(ctx);
14532 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
14533 } else {
14534 /* TLTI */
14535 mips32_op = OPC_TLTI;
14536 goto do_trapi;
14538 break;
14539 case TGEI: /* BC1NEZC */
14540 if (ctx->insn_flags & ISA_MIPS32R6) {
14541 /* BC1NEZC */
14542 check_cp1_enabled(ctx);
14543 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
14544 } else {
14545 /* TGEI */
14546 mips32_op = OPC_TGEI;
14547 goto do_trapi;
14549 break;
14550 case TLTIU:
14551 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14552 mips32_op = OPC_TLTIU;
14553 goto do_trapi;
14554 case TGEIU:
14555 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14556 mips32_op = OPC_TGEIU;
14557 goto do_trapi;
14558 case TNEI: /* SYNCI */
14559 if (ctx->insn_flags & ISA_MIPS32R6) {
14560 /* SYNCI */
14561 /* Break the TB to be able to sync copied instructions
14562 immediately */
14563 ctx->bstate = BS_STOP;
14564 } else {
14565 /* TNEI */
14566 mips32_op = OPC_TNEI;
14567 goto do_trapi;
14569 break;
14570 case TEQI:
14571 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14572 mips32_op = OPC_TEQI;
14573 do_trapi:
14574 gen_trap(ctx, mips32_op, rs, -1, imm);
14575 break;
14577 case BNEZC:
14578 case BEQZC:
14579 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14580 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
14581 4, rs, 0, imm << 1, 0);
14582 /* Compact branches don't have a delay slot, so just let
14583 the normal delay slot handling take us to the branch
14584 target. */
14585 break;
14586 case LUI:
14587 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14588 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
14589 break;
14590 case SYNCI:
14591 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14592 /* Break the TB to be able to sync copied instructions
14593 immediately */
14594 ctx->bstate = BS_STOP;
14595 break;
14596 case BC2F:
14597 case BC2T:
14598 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14599 /* COP2: Not implemented. */
14600 generate_exception_err(ctx, EXCP_CpU, 2);
14601 break;
14602 case BC1F:
14603 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14604 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
14605 goto do_cp1branch;
14606 case BC1T:
14607 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14608 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
14609 goto do_cp1branch;
14610 case BC1ANY4F:
14611 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14612 mips32_op = OPC_BC1FANY4;
14613 goto do_cp1mips3d;
14614 case BC1ANY4T:
14615 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14616 mips32_op = OPC_BC1TANY4;
14617 do_cp1mips3d:
14618 check_cop1x(ctx);
14619 check_insn(ctx, ASE_MIPS3D);
14620 /* Fall through */
14621 do_cp1branch:
14622 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14623 check_cp1_enabled(ctx);
14624 gen_compute_branch1(ctx, mips32_op,
14625 (ctx->opcode >> 18) & 0x7, imm << 1);
14626 } else {
14627 generate_exception_err(ctx, EXCP_CpU, 1);
14629 break;
14630 case BPOSGE64:
14631 case BPOSGE32:
14632 /* MIPS DSP: not implemented */
14633 /* Fall through */
14634 default:
14635 MIPS_INVAL("pool32i");
14636 generate_exception_end(ctx, EXCP_RI);
14637 break;
14639 break;
14640 case POOL32C:
14641 minor = (ctx->opcode >> 12) & 0xf;
14642 offset = sextract32(ctx->opcode, 0,
14643 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
14644 switch (minor) {
14645 case LWL:
14646 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14647 mips32_op = OPC_LWL;
14648 goto do_ld_lr;
14649 case SWL:
14650 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14651 mips32_op = OPC_SWL;
14652 goto do_st_lr;
14653 case LWR:
14654 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14655 mips32_op = OPC_LWR;
14656 goto do_ld_lr;
14657 case SWR:
14658 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14659 mips32_op = OPC_SWR;
14660 goto do_st_lr;
14661 #if defined(TARGET_MIPS64)
14662 case LDL:
14663 check_insn(ctx, ISA_MIPS3);
14664 check_mips_64(ctx);
14665 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14666 mips32_op = OPC_LDL;
14667 goto do_ld_lr;
14668 case SDL:
14669 check_insn(ctx, ISA_MIPS3);
14670 check_mips_64(ctx);
14671 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14672 mips32_op = OPC_SDL;
14673 goto do_st_lr;
14674 case LDR:
14675 check_insn(ctx, ISA_MIPS3);
14676 check_mips_64(ctx);
14677 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14678 mips32_op = OPC_LDR;
14679 goto do_ld_lr;
14680 case SDR:
14681 check_insn(ctx, ISA_MIPS3);
14682 check_mips_64(ctx);
14683 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14684 mips32_op = OPC_SDR;
14685 goto do_st_lr;
14686 case LWU:
14687 check_insn(ctx, ISA_MIPS3);
14688 check_mips_64(ctx);
14689 mips32_op = OPC_LWU;
14690 goto do_ld_lr;
14691 case LLD:
14692 check_insn(ctx, ISA_MIPS3);
14693 check_mips_64(ctx);
14694 mips32_op = OPC_LLD;
14695 goto do_ld_lr;
14696 #endif
14697 case LL:
14698 mips32_op = OPC_LL;
14699 goto do_ld_lr;
14700 do_ld_lr:
14701 gen_ld(ctx, mips32_op, rt, rs, offset);
14702 break;
14703 do_st_lr:
14704 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
14705 break;
14706 case SC:
14707 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
14708 break;
14709 #if defined(TARGET_MIPS64)
14710 case SCD:
14711 check_insn(ctx, ISA_MIPS3);
14712 check_mips_64(ctx);
14713 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
14714 break;
14715 #endif
14716 case PREF:
14717 /* Treat as no-op */
14718 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
14719 /* hint codes 24-31 are reserved and signal RI */
14720 generate_exception(ctx, EXCP_RI);
14722 break;
14723 default:
14724 MIPS_INVAL("pool32c");
14725 generate_exception_end(ctx, EXCP_RI);
14726 break;
14728 break;
14729 case ADDI32: /* AUI, LUI */
14730 if (ctx->insn_flags & ISA_MIPS32R6) {
14731 /* AUI, LUI */
14732 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
14733 } else {
14734 /* ADDI32 */
14735 mips32_op = OPC_ADDI;
14736 goto do_addi;
14738 break;
14739 case ADDIU32:
14740 mips32_op = OPC_ADDIU;
14741 do_addi:
14742 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
14743 break;
14745 /* Logical operations */
14746 case ORI32:
14747 mips32_op = OPC_ORI;
14748 goto do_logici;
14749 case XORI32:
14750 mips32_op = OPC_XORI;
14751 goto do_logici;
14752 case ANDI32:
14753 mips32_op = OPC_ANDI;
14754 do_logici:
14755 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
14756 break;
14758 /* Set less than immediate */
14759 case SLTI32:
14760 mips32_op = OPC_SLTI;
14761 goto do_slti;
14762 case SLTIU32:
14763 mips32_op = OPC_SLTIU;
14764 do_slti:
14765 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
14766 break;
14767 case JALX32:
14768 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14769 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14770 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
14771 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14772 break;
14773 case JALS32: /* BOVC, BEQC, BEQZALC */
14774 if (ctx->insn_flags & ISA_MIPS32R6) {
14775 if (rs >= rt) {
14776 /* BOVC */
14777 mips32_op = OPC_BOVC;
14778 } else if (rs < rt && rs == 0) {
14779 /* BEQZALC */
14780 mips32_op = OPC_BEQZALC;
14781 } else {
14782 /* BEQC */
14783 mips32_op = OPC_BEQC;
14785 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14786 } else {
14787 /* JALS32 */
14788 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
14789 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
14790 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14792 break;
14793 case BEQ32: /* BC */
14794 if (ctx->insn_flags & ISA_MIPS32R6) {
14795 /* BC */
14796 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
14797 sextract32(ctx->opcode << 1, 0, 27));
14798 } else {
14799 /* BEQ32 */
14800 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
14802 break;
14803 case BNE32: /* BALC */
14804 if (ctx->insn_flags & ISA_MIPS32R6) {
14805 /* BALC */
14806 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
14807 sextract32(ctx->opcode << 1, 0, 27));
14808 } else {
14809 /* BNE32 */
14810 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
14812 break;
14813 case J32: /* BGTZC, BLTZC, BLTC */
14814 if (ctx->insn_flags & ISA_MIPS32R6) {
14815 if (rs == 0 && rt != 0) {
14816 /* BGTZC */
14817 mips32_op = OPC_BGTZC;
14818 } else if (rs != 0 && rt != 0 && rs == rt) {
14819 /* BLTZC */
14820 mips32_op = OPC_BLTZC;
14821 } else {
14822 /* BLTC */
14823 mips32_op = OPC_BLTC;
14825 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14826 } else {
14827 /* J32 */
14828 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
14829 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14831 break;
14832 case JAL32: /* BLEZC, BGEZC, BGEC */
14833 if (ctx->insn_flags & ISA_MIPS32R6) {
14834 if (rs == 0 && rt != 0) {
14835 /* BLEZC */
14836 mips32_op = OPC_BLEZC;
14837 } else if (rs != 0 && rt != 0 && rs == rt) {
14838 /* BGEZC */
14839 mips32_op = OPC_BGEZC;
14840 } else {
14841 /* BGEC */
14842 mips32_op = OPC_BGEC;
14844 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14845 } else {
14846 /* JAL32 */
14847 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
14848 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14849 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14851 break;
14852 /* Floating point (COP1) */
14853 case LWC132:
14854 mips32_op = OPC_LWC1;
14855 goto do_cop1;
14856 case LDC132:
14857 mips32_op = OPC_LDC1;
14858 goto do_cop1;
14859 case SWC132:
14860 mips32_op = OPC_SWC1;
14861 goto do_cop1;
14862 case SDC132:
14863 mips32_op = OPC_SDC1;
14864 do_cop1:
14865 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
14866 break;
14867 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14868 if (ctx->insn_flags & ISA_MIPS32R6) {
14869 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14870 switch ((ctx->opcode >> 16) & 0x1f) {
14871 case ADDIUPC_00 ... ADDIUPC_07:
14872 gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
14873 break;
14874 case AUIPC:
14875 gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
14876 break;
14877 case ALUIPC:
14878 gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
14879 break;
14880 case LWPC_08 ... LWPC_0F:
14881 gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
14882 break;
14883 default:
14884 generate_exception(ctx, EXCP_RI);
14885 break;
14887 } else {
14888 /* ADDIUPC */
14889 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
14890 int offset = SIMM(ctx->opcode, 0, 23) << 2;
14892 gen_addiupc(ctx, reg, offset, 0, 0);
14894 break;
14895 case BNVC: /* BNEC, BNEZALC */
14896 check_insn(ctx, ISA_MIPS32R6);
14897 if (rs >= rt) {
14898 /* BNVC */
14899 mips32_op = OPC_BNVC;
14900 } else if (rs < rt && rs == 0) {
14901 /* BNEZALC */
14902 mips32_op = OPC_BNEZALC;
14903 } else {
14904 /* BNEC */
14905 mips32_op = OPC_BNEC;
14907 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14908 break;
14909 case R6_BNEZC: /* JIALC */
14910 check_insn(ctx, ISA_MIPS32R6);
14911 if (rt != 0) {
14912 /* BNEZC */
14913 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
14914 sextract32(ctx->opcode << 1, 0, 22));
14915 } else {
14916 /* JIALC */
14917 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
14919 break;
14920 case R6_BEQZC: /* JIC */
14921 check_insn(ctx, ISA_MIPS32R6);
14922 if (rt != 0) {
14923 /* BEQZC */
14924 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
14925 sextract32(ctx->opcode << 1, 0, 22));
14926 } else {
14927 /* JIC */
14928 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
14930 break;
14931 case BLEZALC: /* BGEZALC, BGEUC */
14932 check_insn(ctx, ISA_MIPS32R6);
14933 if (rs == 0 && rt != 0) {
14934 /* BLEZALC */
14935 mips32_op = OPC_BLEZALC;
14936 } else if (rs != 0 && rt != 0 && rs == rt) {
14937 /* BGEZALC */
14938 mips32_op = OPC_BGEZALC;
14939 } else {
14940 /* BGEUC */
14941 mips32_op = OPC_BGEUC;
14943 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14944 break;
14945 case BGTZALC: /* BLTZALC, BLTUC */
14946 check_insn(ctx, ISA_MIPS32R6);
14947 if (rs == 0 && rt != 0) {
14948 /* BGTZALC */
14949 mips32_op = OPC_BGTZALC;
14950 } else if (rs != 0 && rt != 0 && rs == rt) {
14951 /* BLTZALC */
14952 mips32_op = OPC_BLTZALC;
14953 } else {
14954 /* BLTUC */
14955 mips32_op = OPC_BLTUC;
14957 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14958 break;
14959 /* Loads and stores */
14960 case LB32:
14961 mips32_op = OPC_LB;
14962 goto do_ld;
14963 case LBU32:
14964 mips32_op = OPC_LBU;
14965 goto do_ld;
14966 case LH32:
14967 mips32_op = OPC_LH;
14968 goto do_ld;
14969 case LHU32:
14970 mips32_op = OPC_LHU;
14971 goto do_ld;
14972 case LW32:
14973 mips32_op = OPC_LW;
14974 goto do_ld;
14975 #ifdef TARGET_MIPS64
14976 case LD32:
14977 check_insn(ctx, ISA_MIPS3);
14978 check_mips_64(ctx);
14979 mips32_op = OPC_LD;
14980 goto do_ld;
14981 case SD32:
14982 check_insn(ctx, ISA_MIPS3);
14983 check_mips_64(ctx);
14984 mips32_op = OPC_SD;
14985 goto do_st;
14986 #endif
14987 case SB32:
14988 mips32_op = OPC_SB;
14989 goto do_st;
14990 case SH32:
14991 mips32_op = OPC_SH;
14992 goto do_st;
14993 case SW32:
14994 mips32_op = OPC_SW;
14995 goto do_st;
14996 do_ld:
14997 gen_ld(ctx, mips32_op, rt, rs, imm);
14998 break;
14999 do_st:
15000 gen_st(ctx, mips32_op, rt, rs, imm);
15001 break;
15002 default:
15003 generate_exception_end(ctx, EXCP_RI);
15004 break;
15008 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
15010 uint32_t op;
15012 /* make sure instructions are on a halfword boundary */
15013 if (ctx->pc & 0x1) {
15014 env->CP0_BadVAddr = ctx->pc;
15015 generate_exception_end(ctx, EXCP_AdEL);
15016 return 2;
15019 op = (ctx->opcode >> 10) & 0x3f;
15020 /* Enforce properly-sized instructions in a delay slot */
15021 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
15022 switch (op & 0x7) { /* MSB-3..MSB-5 */
15023 case 0:
15024 /* POOL32A, POOL32B, POOL32I, POOL32C */
15025 case 4:
15026 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
15027 case 5:
15028 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
15029 case 6:
15030 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
15031 case 7:
15032 /* LB32, LH32, LWC132, LDC132, LW32 */
15033 if (ctx->hflags & MIPS_HFLAG_BDS16) {
15034 generate_exception_end(ctx, EXCP_RI);
15035 return 2;
15037 break;
15038 case 1:
15039 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
15040 case 2:
15041 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
15042 case 3:
15043 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
15044 if (ctx->hflags & MIPS_HFLAG_BDS32) {
15045 generate_exception_end(ctx, EXCP_RI);
15046 return 2;
15048 break;
15052 switch (op) {
15053 case POOL16A:
15055 int rd = mmreg(uMIPS_RD(ctx->opcode));
15056 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
15057 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
15058 uint32_t opc = 0;
15060 switch (ctx->opcode & 0x1) {
15061 case ADDU16:
15062 opc = OPC_ADDU;
15063 break;
15064 case SUBU16:
15065 opc = OPC_SUBU;
15066 break;
15068 if (ctx->insn_flags & ISA_MIPS32R6) {
15069 /* In the Release 6 the register number location in
15070 * the instruction encoding has changed.
15072 gen_arith(ctx, opc, rs1, rd, rs2);
15073 } else {
15074 gen_arith(ctx, opc, rd, rs1, rs2);
15077 break;
15078 case POOL16B:
15080 int rd = mmreg(uMIPS_RD(ctx->opcode));
15081 int rs = mmreg(uMIPS_RS(ctx->opcode));
15082 int amount = (ctx->opcode >> 1) & 0x7;
15083 uint32_t opc = 0;
15084 amount = amount == 0 ? 8 : amount;
15086 switch (ctx->opcode & 0x1) {
15087 case SLL16:
15088 opc = OPC_SLL;
15089 break;
15090 case SRL16:
15091 opc = OPC_SRL;
15092 break;
15095 gen_shift_imm(ctx, opc, rd, rs, amount);
15097 break;
15098 case POOL16C:
15099 if (ctx->insn_flags & ISA_MIPS32R6) {
15100 gen_pool16c_r6_insn(ctx);
15101 } else {
15102 gen_pool16c_insn(ctx);
15104 break;
15105 case LWGP16:
15107 int rd = mmreg(uMIPS_RD(ctx->opcode));
15108 int rb = 28; /* GP */
15109 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
15111 gen_ld(ctx, OPC_LW, rd, rb, offset);
15113 break;
15114 case POOL16F:
15115 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15116 if (ctx->opcode & 1) {
15117 generate_exception_end(ctx, EXCP_RI);
15118 } else {
15119 /* MOVEP */
15120 int enc_dest = uMIPS_RD(ctx->opcode);
15121 int enc_rt = uMIPS_RS2(ctx->opcode);
15122 int enc_rs = uMIPS_RS1(ctx->opcode);
15123 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15125 break;
15126 case LBU16:
15128 int rd = mmreg(uMIPS_RD(ctx->opcode));
15129 int rb = mmreg(uMIPS_RS(ctx->opcode));
15130 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15131 offset = (offset == 0xf ? -1 : offset);
15133 gen_ld(ctx, OPC_LBU, rd, rb, offset);
15135 break;
15136 case LHU16:
15138 int rd = mmreg(uMIPS_RD(ctx->opcode));
15139 int rb = mmreg(uMIPS_RS(ctx->opcode));
15140 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15142 gen_ld(ctx, OPC_LHU, rd, rb, offset);
15144 break;
15145 case LWSP16:
15147 int rd = (ctx->opcode >> 5) & 0x1f;
15148 int rb = 29; /* SP */
15149 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15151 gen_ld(ctx, OPC_LW, rd, rb, offset);
15153 break;
15154 case LW16:
15156 int rd = mmreg(uMIPS_RD(ctx->opcode));
15157 int rb = mmreg(uMIPS_RS(ctx->opcode));
15158 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15160 gen_ld(ctx, OPC_LW, rd, rb, offset);
15162 break;
15163 case SB16:
15165 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15166 int rb = mmreg(uMIPS_RS(ctx->opcode));
15167 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15169 gen_st(ctx, OPC_SB, rd, rb, offset);
15171 break;
15172 case SH16:
15174 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15175 int rb = mmreg(uMIPS_RS(ctx->opcode));
15176 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15178 gen_st(ctx, OPC_SH, rd, rb, offset);
15180 break;
15181 case SWSP16:
15183 int rd = (ctx->opcode >> 5) & 0x1f;
15184 int rb = 29; /* SP */
15185 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15187 gen_st(ctx, OPC_SW, rd, rb, offset);
15189 break;
15190 case SW16:
15192 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15193 int rb = mmreg(uMIPS_RS(ctx->opcode));
15194 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15196 gen_st(ctx, OPC_SW, rd, rb, offset);
15198 break;
15199 case MOVE16:
15201 int rd = uMIPS_RD5(ctx->opcode);
15202 int rs = uMIPS_RS5(ctx->opcode);
15204 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
15206 break;
15207 case ANDI16:
15208 gen_andi16(ctx);
15209 break;
15210 case POOL16D:
15211 switch (ctx->opcode & 0x1) {
15212 case ADDIUS5:
15213 gen_addius5(ctx);
15214 break;
15215 case ADDIUSP:
15216 gen_addiusp(ctx);
15217 break;
15219 break;
15220 case POOL16E:
15221 switch (ctx->opcode & 0x1) {
15222 case ADDIUR2:
15223 gen_addiur2(ctx);
15224 break;
15225 case ADDIUR1SP:
15226 gen_addiur1sp(ctx);
15227 break;
15229 break;
15230 case B16: /* BC16 */
15231 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
15232 sextract32(ctx->opcode, 0, 10) << 1,
15233 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15234 break;
15235 case BNEZ16: /* BNEZC16 */
15236 case BEQZ16: /* BEQZC16 */
15237 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
15238 mmreg(uMIPS_RD(ctx->opcode)),
15239 0, sextract32(ctx->opcode, 0, 7) << 1,
15240 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15242 break;
15243 case LI16:
15245 int reg = mmreg(uMIPS_RD(ctx->opcode));
15246 int imm = ZIMM(ctx->opcode, 0, 7);
15248 imm = (imm == 0x7f ? -1 : imm);
15249 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15251 break;
15252 case RES_29:
15253 case RES_31:
15254 case RES_39:
15255 generate_exception_end(ctx, EXCP_RI);
15256 break;
15257 default:
15258 decode_micromips32_opc(env, ctx);
15259 return 4;
15262 return 2;
15265 /* SmartMIPS extension to MIPS32 */
15267 #if defined(TARGET_MIPS64)
15269 /* MDMX extension to MIPS64 */
15271 #endif
15273 /* MIPSDSP functions. */
15274 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
15275 int rd, int base, int offset)
15277 TCGv t0;
15279 check_dsp(ctx);
15280 t0 = tcg_temp_new();
15282 if (base == 0) {
15283 gen_load_gpr(t0, offset);
15284 } else if (offset == 0) {
15285 gen_load_gpr(t0, base);
15286 } else {
15287 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
15290 switch (opc) {
15291 case OPC_LBUX:
15292 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
15293 gen_store_gpr(t0, rd);
15294 break;
15295 case OPC_LHX:
15296 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
15297 gen_store_gpr(t0, rd);
15298 break;
15299 case OPC_LWX:
15300 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
15301 gen_store_gpr(t0, rd);
15302 break;
15303 #if defined(TARGET_MIPS64)
15304 case OPC_LDX:
15305 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
15306 gen_store_gpr(t0, rd);
15307 break;
15308 #endif
15310 tcg_temp_free(t0);
15313 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
15314 int ret, int v1, int v2)
15316 TCGv v1_t;
15317 TCGv v2_t;
15319 if (ret == 0) {
15320 /* Treat as NOP. */
15321 return;
15324 v1_t = tcg_temp_new();
15325 v2_t = tcg_temp_new();
15327 gen_load_gpr(v1_t, v1);
15328 gen_load_gpr(v2_t, v2);
15330 switch (op1) {
15331 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
15332 case OPC_MULT_G_2E:
15333 check_dspr2(ctx);
15334 switch (op2) {
15335 case OPC_ADDUH_QB:
15336 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
15337 break;
15338 case OPC_ADDUH_R_QB:
15339 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15340 break;
15341 case OPC_ADDQH_PH:
15342 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
15343 break;
15344 case OPC_ADDQH_R_PH:
15345 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15346 break;
15347 case OPC_ADDQH_W:
15348 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
15349 break;
15350 case OPC_ADDQH_R_W:
15351 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15352 break;
15353 case OPC_SUBUH_QB:
15354 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
15355 break;
15356 case OPC_SUBUH_R_QB:
15357 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15358 break;
15359 case OPC_SUBQH_PH:
15360 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
15361 break;
15362 case OPC_SUBQH_R_PH:
15363 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15364 break;
15365 case OPC_SUBQH_W:
15366 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
15367 break;
15368 case OPC_SUBQH_R_W:
15369 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15370 break;
15372 break;
15373 case OPC_ABSQ_S_PH_DSP:
15374 switch (op2) {
15375 case OPC_ABSQ_S_QB:
15376 check_dspr2(ctx);
15377 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
15378 break;
15379 case OPC_ABSQ_S_PH:
15380 check_dsp(ctx);
15381 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
15382 break;
15383 case OPC_ABSQ_S_W:
15384 check_dsp(ctx);
15385 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
15386 break;
15387 case OPC_PRECEQ_W_PHL:
15388 check_dsp(ctx);
15389 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
15390 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15391 break;
15392 case OPC_PRECEQ_W_PHR:
15393 check_dsp(ctx);
15394 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
15395 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
15396 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15397 break;
15398 case OPC_PRECEQU_PH_QBL:
15399 check_dsp(ctx);
15400 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
15401 break;
15402 case OPC_PRECEQU_PH_QBR:
15403 check_dsp(ctx);
15404 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
15405 break;
15406 case OPC_PRECEQU_PH_QBLA:
15407 check_dsp(ctx);
15408 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
15409 break;
15410 case OPC_PRECEQU_PH_QBRA:
15411 check_dsp(ctx);
15412 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
15413 break;
15414 case OPC_PRECEU_PH_QBL:
15415 check_dsp(ctx);
15416 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
15417 break;
15418 case OPC_PRECEU_PH_QBR:
15419 check_dsp(ctx);
15420 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
15421 break;
15422 case OPC_PRECEU_PH_QBLA:
15423 check_dsp(ctx);
15424 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
15425 break;
15426 case OPC_PRECEU_PH_QBRA:
15427 check_dsp(ctx);
15428 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
15429 break;
15431 break;
15432 case OPC_ADDU_QB_DSP:
15433 switch (op2) {
15434 case OPC_ADDQ_PH:
15435 check_dsp(ctx);
15436 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15437 break;
15438 case OPC_ADDQ_S_PH:
15439 check_dsp(ctx);
15440 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15441 break;
15442 case OPC_ADDQ_S_W:
15443 check_dsp(ctx);
15444 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15445 break;
15446 case OPC_ADDU_QB:
15447 check_dsp(ctx);
15448 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15449 break;
15450 case OPC_ADDU_S_QB:
15451 check_dsp(ctx);
15452 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15453 break;
15454 case OPC_ADDU_PH:
15455 check_dspr2(ctx);
15456 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15457 break;
15458 case OPC_ADDU_S_PH:
15459 check_dspr2(ctx);
15460 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15461 break;
15462 case OPC_SUBQ_PH:
15463 check_dsp(ctx);
15464 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15465 break;
15466 case OPC_SUBQ_S_PH:
15467 check_dsp(ctx);
15468 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15469 break;
15470 case OPC_SUBQ_S_W:
15471 check_dsp(ctx);
15472 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15473 break;
15474 case OPC_SUBU_QB:
15475 check_dsp(ctx);
15476 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15477 break;
15478 case OPC_SUBU_S_QB:
15479 check_dsp(ctx);
15480 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15481 break;
15482 case OPC_SUBU_PH:
15483 check_dspr2(ctx);
15484 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15485 break;
15486 case OPC_SUBU_S_PH:
15487 check_dspr2(ctx);
15488 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15489 break;
15490 case OPC_ADDSC:
15491 check_dsp(ctx);
15492 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15493 break;
15494 case OPC_ADDWC:
15495 check_dsp(ctx);
15496 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15497 break;
15498 case OPC_MODSUB:
15499 check_dsp(ctx);
15500 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
15501 break;
15502 case OPC_RADDU_W_QB:
15503 check_dsp(ctx);
15504 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
15505 break;
15507 break;
15508 case OPC_CMPU_EQ_QB_DSP:
15509 switch (op2) {
15510 case OPC_PRECR_QB_PH:
15511 check_dspr2(ctx);
15512 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15513 break;
15514 case OPC_PRECRQ_QB_PH:
15515 check_dsp(ctx);
15516 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15517 break;
15518 case OPC_PRECR_SRA_PH_W:
15519 check_dspr2(ctx);
15521 TCGv_i32 sa_t = tcg_const_i32(v2);
15522 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
15523 cpu_gpr[ret]);
15524 tcg_temp_free_i32(sa_t);
15525 break;
15527 case OPC_PRECR_SRA_R_PH_W:
15528 check_dspr2(ctx);
15530 TCGv_i32 sa_t = tcg_const_i32(v2);
15531 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
15532 cpu_gpr[ret]);
15533 tcg_temp_free_i32(sa_t);
15534 break;
15536 case OPC_PRECRQ_PH_W:
15537 check_dsp(ctx);
15538 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
15539 break;
15540 case OPC_PRECRQ_RS_PH_W:
15541 check_dsp(ctx);
15542 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15543 break;
15544 case OPC_PRECRQU_S_QB_PH:
15545 check_dsp(ctx);
15546 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15547 break;
15549 break;
15550 #ifdef TARGET_MIPS64
15551 case OPC_ABSQ_S_QH_DSP:
15552 switch (op2) {
15553 case OPC_PRECEQ_L_PWL:
15554 check_dsp(ctx);
15555 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
15556 break;
15557 case OPC_PRECEQ_L_PWR:
15558 check_dsp(ctx);
15559 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
15560 break;
15561 case OPC_PRECEQ_PW_QHL:
15562 check_dsp(ctx);
15563 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
15564 break;
15565 case OPC_PRECEQ_PW_QHR:
15566 check_dsp(ctx);
15567 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
15568 break;
15569 case OPC_PRECEQ_PW_QHLA:
15570 check_dsp(ctx);
15571 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
15572 break;
15573 case OPC_PRECEQ_PW_QHRA:
15574 check_dsp(ctx);
15575 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
15576 break;
15577 case OPC_PRECEQU_QH_OBL:
15578 check_dsp(ctx);
15579 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
15580 break;
15581 case OPC_PRECEQU_QH_OBR:
15582 check_dsp(ctx);
15583 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
15584 break;
15585 case OPC_PRECEQU_QH_OBLA:
15586 check_dsp(ctx);
15587 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
15588 break;
15589 case OPC_PRECEQU_QH_OBRA:
15590 check_dsp(ctx);
15591 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
15592 break;
15593 case OPC_PRECEU_QH_OBL:
15594 check_dsp(ctx);
15595 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
15596 break;
15597 case OPC_PRECEU_QH_OBR:
15598 check_dsp(ctx);
15599 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
15600 break;
15601 case OPC_PRECEU_QH_OBLA:
15602 check_dsp(ctx);
15603 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
15604 break;
15605 case OPC_PRECEU_QH_OBRA:
15606 check_dsp(ctx);
15607 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
15608 break;
15609 case OPC_ABSQ_S_OB:
15610 check_dspr2(ctx);
15611 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
15612 break;
15613 case OPC_ABSQ_S_PW:
15614 check_dsp(ctx);
15615 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
15616 break;
15617 case OPC_ABSQ_S_QH:
15618 check_dsp(ctx);
15619 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
15620 break;
15622 break;
15623 case OPC_ADDU_OB_DSP:
15624 switch (op2) {
15625 case OPC_RADDU_L_OB:
15626 check_dsp(ctx);
15627 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
15628 break;
15629 case OPC_SUBQ_PW:
15630 check_dsp(ctx);
15631 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15632 break;
15633 case OPC_SUBQ_S_PW:
15634 check_dsp(ctx);
15635 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15636 break;
15637 case OPC_SUBQ_QH:
15638 check_dsp(ctx);
15639 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15640 break;
15641 case OPC_SUBQ_S_QH:
15642 check_dsp(ctx);
15643 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15644 break;
15645 case OPC_SUBU_OB:
15646 check_dsp(ctx);
15647 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15648 break;
15649 case OPC_SUBU_S_OB:
15650 check_dsp(ctx);
15651 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15652 break;
15653 case OPC_SUBU_QH:
15654 check_dspr2(ctx);
15655 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15656 break;
15657 case OPC_SUBU_S_QH:
15658 check_dspr2(ctx);
15659 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15660 break;
15661 case OPC_SUBUH_OB:
15662 check_dspr2(ctx);
15663 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
15664 break;
15665 case OPC_SUBUH_R_OB:
15666 check_dspr2(ctx);
15667 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15668 break;
15669 case OPC_ADDQ_PW:
15670 check_dsp(ctx);
15671 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15672 break;
15673 case OPC_ADDQ_S_PW:
15674 check_dsp(ctx);
15675 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15676 break;
15677 case OPC_ADDQ_QH:
15678 check_dsp(ctx);
15679 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15680 break;
15681 case OPC_ADDQ_S_QH:
15682 check_dsp(ctx);
15683 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15684 break;
15685 case OPC_ADDU_OB:
15686 check_dsp(ctx);
15687 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15688 break;
15689 case OPC_ADDU_S_OB:
15690 check_dsp(ctx);
15691 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15692 break;
15693 case OPC_ADDU_QH:
15694 check_dspr2(ctx);
15695 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15696 break;
15697 case OPC_ADDU_S_QH:
15698 check_dspr2(ctx);
15699 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15700 break;
15701 case OPC_ADDUH_OB:
15702 check_dspr2(ctx);
15703 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
15704 break;
15705 case OPC_ADDUH_R_OB:
15706 check_dspr2(ctx);
15707 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15708 break;
15710 break;
15711 case OPC_CMPU_EQ_OB_DSP:
15712 switch (op2) {
15713 case OPC_PRECR_OB_QH:
15714 check_dspr2(ctx);
15715 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15716 break;
15717 case OPC_PRECR_SRA_QH_PW:
15718 check_dspr2(ctx);
15720 TCGv_i32 ret_t = tcg_const_i32(ret);
15721 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
15722 tcg_temp_free_i32(ret_t);
15723 break;
15725 case OPC_PRECR_SRA_R_QH_PW:
15726 check_dspr2(ctx);
15728 TCGv_i32 sa_v = tcg_const_i32(ret);
15729 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
15730 tcg_temp_free_i32(sa_v);
15731 break;
15733 case OPC_PRECRQ_OB_QH:
15734 check_dsp(ctx);
15735 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15736 break;
15737 case OPC_PRECRQ_PW_L:
15738 check_dsp(ctx);
15739 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
15740 break;
15741 case OPC_PRECRQ_QH_PW:
15742 check_dsp(ctx);
15743 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
15744 break;
15745 case OPC_PRECRQ_RS_QH_PW:
15746 check_dsp(ctx);
15747 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15748 break;
15749 case OPC_PRECRQU_S_OB_QH:
15750 check_dsp(ctx);
15751 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15752 break;
15754 break;
15755 #endif
15758 tcg_temp_free(v1_t);
15759 tcg_temp_free(v2_t);
15762 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
15763 int ret, int v1, int v2)
15765 uint32_t op2;
15766 TCGv t0;
15767 TCGv v1_t;
15768 TCGv v2_t;
15770 if (ret == 0) {
15771 /* Treat as NOP. */
15772 return;
15775 t0 = tcg_temp_new();
15776 v1_t = tcg_temp_new();
15777 v2_t = tcg_temp_new();
15779 tcg_gen_movi_tl(t0, v1);
15780 gen_load_gpr(v1_t, v1);
15781 gen_load_gpr(v2_t, v2);
15783 switch (opc) {
15784 case OPC_SHLL_QB_DSP:
15786 op2 = MASK_SHLL_QB(ctx->opcode);
15787 switch (op2) {
15788 case OPC_SHLL_QB:
15789 check_dsp(ctx);
15790 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
15791 break;
15792 case OPC_SHLLV_QB:
15793 check_dsp(ctx);
15794 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15795 break;
15796 case OPC_SHLL_PH:
15797 check_dsp(ctx);
15798 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15799 break;
15800 case OPC_SHLLV_PH:
15801 check_dsp(ctx);
15802 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15803 break;
15804 case OPC_SHLL_S_PH:
15805 check_dsp(ctx);
15806 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15807 break;
15808 case OPC_SHLLV_S_PH:
15809 check_dsp(ctx);
15810 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15811 break;
15812 case OPC_SHLL_S_W:
15813 check_dsp(ctx);
15814 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
15815 break;
15816 case OPC_SHLLV_S_W:
15817 check_dsp(ctx);
15818 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15819 break;
15820 case OPC_SHRL_QB:
15821 check_dsp(ctx);
15822 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
15823 break;
15824 case OPC_SHRLV_QB:
15825 check_dsp(ctx);
15826 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
15827 break;
15828 case OPC_SHRL_PH:
15829 check_dspr2(ctx);
15830 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
15831 break;
15832 case OPC_SHRLV_PH:
15833 check_dspr2(ctx);
15834 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
15835 break;
15836 case OPC_SHRA_QB:
15837 check_dspr2(ctx);
15838 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
15839 break;
15840 case OPC_SHRA_R_QB:
15841 check_dspr2(ctx);
15842 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
15843 break;
15844 case OPC_SHRAV_QB:
15845 check_dspr2(ctx);
15846 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
15847 break;
15848 case OPC_SHRAV_R_QB:
15849 check_dspr2(ctx);
15850 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
15851 break;
15852 case OPC_SHRA_PH:
15853 check_dsp(ctx);
15854 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
15855 break;
15856 case OPC_SHRA_R_PH:
15857 check_dsp(ctx);
15858 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
15859 break;
15860 case OPC_SHRAV_PH:
15861 check_dsp(ctx);
15862 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
15863 break;
15864 case OPC_SHRAV_R_PH:
15865 check_dsp(ctx);
15866 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
15867 break;
15868 case OPC_SHRA_R_W:
15869 check_dsp(ctx);
15870 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
15871 break;
15872 case OPC_SHRAV_R_W:
15873 check_dsp(ctx);
15874 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
15875 break;
15876 default: /* Invalid */
15877 MIPS_INVAL("MASK SHLL.QB");
15878 generate_exception_end(ctx, EXCP_RI);
15879 break;
15881 break;
15883 #ifdef TARGET_MIPS64
15884 case OPC_SHLL_OB_DSP:
15885 op2 = MASK_SHLL_OB(ctx->opcode);
15886 switch (op2) {
15887 case OPC_SHLL_PW:
15888 check_dsp(ctx);
15889 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15890 break;
15891 case OPC_SHLLV_PW:
15892 check_dsp(ctx);
15893 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15894 break;
15895 case OPC_SHLL_S_PW:
15896 check_dsp(ctx);
15897 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15898 break;
15899 case OPC_SHLLV_S_PW:
15900 check_dsp(ctx);
15901 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15902 break;
15903 case OPC_SHLL_OB:
15904 check_dsp(ctx);
15905 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
15906 break;
15907 case OPC_SHLLV_OB:
15908 check_dsp(ctx);
15909 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15910 break;
15911 case OPC_SHLL_QH:
15912 check_dsp(ctx);
15913 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15914 break;
15915 case OPC_SHLLV_QH:
15916 check_dsp(ctx);
15917 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15918 break;
15919 case OPC_SHLL_S_QH:
15920 check_dsp(ctx);
15921 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15922 break;
15923 case OPC_SHLLV_S_QH:
15924 check_dsp(ctx);
15925 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15926 break;
15927 case OPC_SHRA_OB:
15928 check_dspr2(ctx);
15929 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
15930 break;
15931 case OPC_SHRAV_OB:
15932 check_dspr2(ctx);
15933 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
15934 break;
15935 case OPC_SHRA_R_OB:
15936 check_dspr2(ctx);
15937 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
15938 break;
15939 case OPC_SHRAV_R_OB:
15940 check_dspr2(ctx);
15941 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
15942 break;
15943 case OPC_SHRA_PW:
15944 check_dsp(ctx);
15945 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
15946 break;
15947 case OPC_SHRAV_PW:
15948 check_dsp(ctx);
15949 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
15950 break;
15951 case OPC_SHRA_R_PW:
15952 check_dsp(ctx);
15953 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
15954 break;
15955 case OPC_SHRAV_R_PW:
15956 check_dsp(ctx);
15957 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
15958 break;
15959 case OPC_SHRA_QH:
15960 check_dsp(ctx);
15961 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
15962 break;
15963 case OPC_SHRAV_QH:
15964 check_dsp(ctx);
15965 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
15966 break;
15967 case OPC_SHRA_R_QH:
15968 check_dsp(ctx);
15969 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
15970 break;
15971 case OPC_SHRAV_R_QH:
15972 check_dsp(ctx);
15973 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
15974 break;
15975 case OPC_SHRL_OB:
15976 check_dsp(ctx);
15977 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
15978 break;
15979 case OPC_SHRLV_OB:
15980 check_dsp(ctx);
15981 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
15982 break;
15983 case OPC_SHRL_QH:
15984 check_dspr2(ctx);
15985 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
15986 break;
15987 case OPC_SHRLV_QH:
15988 check_dspr2(ctx);
15989 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
15990 break;
15991 default: /* Invalid */
15992 MIPS_INVAL("MASK SHLL.OB");
15993 generate_exception_end(ctx, EXCP_RI);
15994 break;
15996 break;
15997 #endif
16000 tcg_temp_free(t0);
16001 tcg_temp_free(v1_t);
16002 tcg_temp_free(v2_t);
16005 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
16006 int ret, int v1, int v2, int check_ret)
16008 TCGv_i32 t0;
16009 TCGv v1_t;
16010 TCGv v2_t;
16012 if ((ret == 0) && (check_ret == 1)) {
16013 /* Treat as NOP. */
16014 return;
16017 t0 = tcg_temp_new_i32();
16018 v1_t = tcg_temp_new();
16019 v2_t = tcg_temp_new();
16021 tcg_gen_movi_i32(t0, ret);
16022 gen_load_gpr(v1_t, v1);
16023 gen_load_gpr(v2_t, v2);
16025 switch (op1) {
16026 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
16027 * the same mask and op1. */
16028 case OPC_MULT_G_2E:
16029 check_dspr2(ctx);
16030 switch (op2) {
16031 case OPC_MUL_PH:
16032 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16033 break;
16034 case OPC_MUL_S_PH:
16035 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16036 break;
16037 case OPC_MULQ_S_W:
16038 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16039 break;
16040 case OPC_MULQ_RS_W:
16041 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16042 break;
16044 break;
16045 case OPC_DPA_W_PH_DSP:
16046 switch (op2) {
16047 case OPC_DPAU_H_QBL:
16048 check_dsp(ctx);
16049 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
16050 break;
16051 case OPC_DPAU_H_QBR:
16052 check_dsp(ctx);
16053 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
16054 break;
16055 case OPC_DPSU_H_QBL:
16056 check_dsp(ctx);
16057 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
16058 break;
16059 case OPC_DPSU_H_QBR:
16060 check_dsp(ctx);
16061 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
16062 break;
16063 case OPC_DPA_W_PH:
16064 check_dspr2(ctx);
16065 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
16066 break;
16067 case OPC_DPAX_W_PH:
16068 check_dspr2(ctx);
16069 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
16070 break;
16071 case OPC_DPAQ_S_W_PH:
16072 check_dsp(ctx);
16073 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16074 break;
16075 case OPC_DPAQX_S_W_PH:
16076 check_dspr2(ctx);
16077 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16078 break;
16079 case OPC_DPAQX_SA_W_PH:
16080 check_dspr2(ctx);
16081 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16082 break;
16083 case OPC_DPS_W_PH:
16084 check_dspr2(ctx);
16085 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
16086 break;
16087 case OPC_DPSX_W_PH:
16088 check_dspr2(ctx);
16089 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
16090 break;
16091 case OPC_DPSQ_S_W_PH:
16092 check_dsp(ctx);
16093 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16094 break;
16095 case OPC_DPSQX_S_W_PH:
16096 check_dspr2(ctx);
16097 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16098 break;
16099 case OPC_DPSQX_SA_W_PH:
16100 check_dspr2(ctx);
16101 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16102 break;
16103 case OPC_MULSAQ_S_W_PH:
16104 check_dsp(ctx);
16105 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16106 break;
16107 case OPC_DPAQ_SA_L_W:
16108 check_dsp(ctx);
16109 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16110 break;
16111 case OPC_DPSQ_SA_L_W:
16112 check_dsp(ctx);
16113 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16114 break;
16115 case OPC_MAQ_S_W_PHL:
16116 check_dsp(ctx);
16117 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
16118 break;
16119 case OPC_MAQ_S_W_PHR:
16120 check_dsp(ctx);
16121 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
16122 break;
16123 case OPC_MAQ_SA_W_PHL:
16124 check_dsp(ctx);
16125 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
16126 break;
16127 case OPC_MAQ_SA_W_PHR:
16128 check_dsp(ctx);
16129 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
16130 break;
16131 case OPC_MULSA_W_PH:
16132 check_dspr2(ctx);
16133 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
16134 break;
16136 break;
16137 #ifdef TARGET_MIPS64
16138 case OPC_DPAQ_W_QH_DSP:
16140 int ac = ret & 0x03;
16141 tcg_gen_movi_i32(t0, ac);
16143 switch (op2) {
16144 case OPC_DMADD:
16145 check_dsp(ctx);
16146 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
16147 break;
16148 case OPC_DMADDU:
16149 check_dsp(ctx);
16150 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
16151 break;
16152 case OPC_DMSUB:
16153 check_dsp(ctx);
16154 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
16155 break;
16156 case OPC_DMSUBU:
16157 check_dsp(ctx);
16158 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
16159 break;
16160 case OPC_DPA_W_QH:
16161 check_dspr2(ctx);
16162 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
16163 break;
16164 case OPC_DPAQ_S_W_QH:
16165 check_dsp(ctx);
16166 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16167 break;
16168 case OPC_DPAQ_SA_L_PW:
16169 check_dsp(ctx);
16170 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16171 break;
16172 case OPC_DPAU_H_OBL:
16173 check_dsp(ctx);
16174 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
16175 break;
16176 case OPC_DPAU_H_OBR:
16177 check_dsp(ctx);
16178 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
16179 break;
16180 case OPC_DPS_W_QH:
16181 check_dspr2(ctx);
16182 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
16183 break;
16184 case OPC_DPSQ_S_W_QH:
16185 check_dsp(ctx);
16186 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16187 break;
16188 case OPC_DPSQ_SA_L_PW:
16189 check_dsp(ctx);
16190 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16191 break;
16192 case OPC_DPSU_H_OBL:
16193 check_dsp(ctx);
16194 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
16195 break;
16196 case OPC_DPSU_H_OBR:
16197 check_dsp(ctx);
16198 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
16199 break;
16200 case OPC_MAQ_S_L_PWL:
16201 check_dsp(ctx);
16202 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
16203 break;
16204 case OPC_MAQ_S_L_PWR:
16205 check_dsp(ctx);
16206 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
16207 break;
16208 case OPC_MAQ_S_W_QHLL:
16209 check_dsp(ctx);
16210 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
16211 break;
16212 case OPC_MAQ_SA_W_QHLL:
16213 check_dsp(ctx);
16214 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
16215 break;
16216 case OPC_MAQ_S_W_QHLR:
16217 check_dsp(ctx);
16218 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
16219 break;
16220 case OPC_MAQ_SA_W_QHLR:
16221 check_dsp(ctx);
16222 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
16223 break;
16224 case OPC_MAQ_S_W_QHRL:
16225 check_dsp(ctx);
16226 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
16227 break;
16228 case OPC_MAQ_SA_W_QHRL:
16229 check_dsp(ctx);
16230 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
16231 break;
16232 case OPC_MAQ_S_W_QHRR:
16233 check_dsp(ctx);
16234 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
16235 break;
16236 case OPC_MAQ_SA_W_QHRR:
16237 check_dsp(ctx);
16238 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
16239 break;
16240 case OPC_MULSAQ_S_L_PW:
16241 check_dsp(ctx);
16242 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
16243 break;
16244 case OPC_MULSAQ_S_W_QH:
16245 check_dsp(ctx);
16246 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16247 break;
16250 break;
16251 #endif
16252 case OPC_ADDU_QB_DSP:
16253 switch (op2) {
16254 case OPC_MULEU_S_PH_QBL:
16255 check_dsp(ctx);
16256 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16257 break;
16258 case OPC_MULEU_S_PH_QBR:
16259 check_dsp(ctx);
16260 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16261 break;
16262 case OPC_MULQ_RS_PH:
16263 check_dsp(ctx);
16264 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16265 break;
16266 case OPC_MULEQ_S_W_PHL:
16267 check_dsp(ctx);
16268 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16269 break;
16270 case OPC_MULEQ_S_W_PHR:
16271 check_dsp(ctx);
16272 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16273 break;
16274 case OPC_MULQ_S_PH:
16275 check_dspr2(ctx);
16276 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16277 break;
16279 break;
16280 #ifdef TARGET_MIPS64
16281 case OPC_ADDU_OB_DSP:
16282 switch (op2) {
16283 case OPC_MULEQ_S_PW_QHL:
16284 check_dsp(ctx);
16285 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16286 break;
16287 case OPC_MULEQ_S_PW_QHR:
16288 check_dsp(ctx);
16289 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16290 break;
16291 case OPC_MULEU_S_QH_OBL:
16292 check_dsp(ctx);
16293 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16294 break;
16295 case OPC_MULEU_S_QH_OBR:
16296 check_dsp(ctx);
16297 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16298 break;
16299 case OPC_MULQ_RS_QH:
16300 check_dsp(ctx);
16301 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16302 break;
16304 break;
16305 #endif
16308 tcg_temp_free_i32(t0);
16309 tcg_temp_free(v1_t);
16310 tcg_temp_free(v2_t);
16313 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16314 int ret, int val)
16316 int16_t imm;
16317 TCGv t0;
16318 TCGv val_t;
16320 if (ret == 0) {
16321 /* Treat as NOP. */
16322 return;
16325 t0 = tcg_temp_new();
16326 val_t = tcg_temp_new();
16327 gen_load_gpr(val_t, val);
16329 switch (op1) {
16330 case OPC_ABSQ_S_PH_DSP:
16331 switch (op2) {
16332 case OPC_BITREV:
16333 check_dsp(ctx);
16334 gen_helper_bitrev(cpu_gpr[ret], val_t);
16335 break;
16336 case OPC_REPL_QB:
16337 check_dsp(ctx);
16339 target_long result;
16340 imm = (ctx->opcode >> 16) & 0xFF;
16341 result = (uint32_t)imm << 24 |
16342 (uint32_t)imm << 16 |
16343 (uint32_t)imm << 8 |
16344 (uint32_t)imm;
16345 result = (int32_t)result;
16346 tcg_gen_movi_tl(cpu_gpr[ret], result);
16348 break;
16349 case OPC_REPLV_QB:
16350 check_dsp(ctx);
16351 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16352 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16353 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16354 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16355 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16356 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16357 break;
16358 case OPC_REPL_PH:
16359 check_dsp(ctx);
16361 imm = (ctx->opcode >> 16) & 0x03FF;
16362 imm = (int16_t)(imm << 6) >> 6;
16363 tcg_gen_movi_tl(cpu_gpr[ret], \
16364 (target_long)((int32_t)imm << 16 | \
16365 (uint16_t)imm));
16367 break;
16368 case OPC_REPLV_PH:
16369 check_dsp(ctx);
16370 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16371 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16372 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16373 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16374 break;
16376 break;
16377 #ifdef TARGET_MIPS64
16378 case OPC_ABSQ_S_QH_DSP:
16379 switch (op2) {
16380 case OPC_REPL_OB:
16381 check_dsp(ctx);
16383 target_long temp;
16385 imm = (ctx->opcode >> 16) & 0xFF;
16386 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
16387 temp = (temp << 16) | temp;
16388 temp = (temp << 32) | temp;
16389 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16390 break;
16392 case OPC_REPL_PW:
16393 check_dsp(ctx);
16395 target_long temp;
16397 imm = (ctx->opcode >> 16) & 0x03FF;
16398 imm = (int16_t)(imm << 6) >> 6;
16399 temp = ((target_long)imm << 32) \
16400 | ((target_long)imm & 0xFFFFFFFF);
16401 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16402 break;
16404 case OPC_REPL_QH:
16405 check_dsp(ctx);
16407 target_long temp;
16409 imm = (ctx->opcode >> 16) & 0x03FF;
16410 imm = (int16_t)(imm << 6) >> 6;
16412 temp = ((uint64_t)(uint16_t)imm << 48) |
16413 ((uint64_t)(uint16_t)imm << 32) |
16414 ((uint64_t)(uint16_t)imm << 16) |
16415 (uint64_t)(uint16_t)imm;
16416 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16417 break;
16419 case OPC_REPLV_OB:
16420 check_dsp(ctx);
16421 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16422 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16423 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16424 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16425 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16426 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16427 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16428 break;
16429 case OPC_REPLV_PW:
16430 check_dsp(ctx);
16431 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
16432 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16433 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16434 break;
16435 case OPC_REPLV_QH:
16436 check_dsp(ctx);
16437 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16438 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16439 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16440 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16441 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16442 break;
16444 break;
16445 #endif
16447 tcg_temp_free(t0);
16448 tcg_temp_free(val_t);
16451 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
16452 uint32_t op1, uint32_t op2,
16453 int ret, int v1, int v2, int check_ret)
16455 TCGv t1;
16456 TCGv v1_t;
16457 TCGv v2_t;
16459 if ((ret == 0) && (check_ret == 1)) {
16460 /* Treat as NOP. */
16461 return;
16464 t1 = tcg_temp_new();
16465 v1_t = tcg_temp_new();
16466 v2_t = tcg_temp_new();
16468 gen_load_gpr(v1_t, v1);
16469 gen_load_gpr(v2_t, v2);
16471 switch (op1) {
16472 case OPC_CMPU_EQ_QB_DSP:
16473 switch (op2) {
16474 case OPC_CMPU_EQ_QB:
16475 check_dsp(ctx);
16476 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
16477 break;
16478 case OPC_CMPU_LT_QB:
16479 check_dsp(ctx);
16480 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
16481 break;
16482 case OPC_CMPU_LE_QB:
16483 check_dsp(ctx);
16484 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
16485 break;
16486 case OPC_CMPGU_EQ_QB:
16487 check_dsp(ctx);
16488 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
16489 break;
16490 case OPC_CMPGU_LT_QB:
16491 check_dsp(ctx);
16492 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
16493 break;
16494 case OPC_CMPGU_LE_QB:
16495 check_dsp(ctx);
16496 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
16497 break;
16498 case OPC_CMPGDU_EQ_QB:
16499 check_dspr2(ctx);
16500 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
16501 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16502 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16503 tcg_gen_shli_tl(t1, t1, 24);
16504 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16505 break;
16506 case OPC_CMPGDU_LT_QB:
16507 check_dspr2(ctx);
16508 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
16509 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16510 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16511 tcg_gen_shli_tl(t1, t1, 24);
16512 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16513 break;
16514 case OPC_CMPGDU_LE_QB:
16515 check_dspr2(ctx);
16516 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
16517 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16518 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16519 tcg_gen_shli_tl(t1, t1, 24);
16520 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16521 break;
16522 case OPC_CMP_EQ_PH:
16523 check_dsp(ctx);
16524 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
16525 break;
16526 case OPC_CMP_LT_PH:
16527 check_dsp(ctx);
16528 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
16529 break;
16530 case OPC_CMP_LE_PH:
16531 check_dsp(ctx);
16532 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
16533 break;
16534 case OPC_PICK_QB:
16535 check_dsp(ctx);
16536 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16537 break;
16538 case OPC_PICK_PH:
16539 check_dsp(ctx);
16540 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16541 break;
16542 case OPC_PACKRL_PH:
16543 check_dsp(ctx);
16544 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
16545 break;
16547 break;
16548 #ifdef TARGET_MIPS64
16549 case OPC_CMPU_EQ_OB_DSP:
16550 switch (op2) {
16551 case OPC_CMP_EQ_PW:
16552 check_dsp(ctx);
16553 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
16554 break;
16555 case OPC_CMP_LT_PW:
16556 check_dsp(ctx);
16557 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
16558 break;
16559 case OPC_CMP_LE_PW:
16560 check_dsp(ctx);
16561 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
16562 break;
16563 case OPC_CMP_EQ_QH:
16564 check_dsp(ctx);
16565 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
16566 break;
16567 case OPC_CMP_LT_QH:
16568 check_dsp(ctx);
16569 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
16570 break;
16571 case OPC_CMP_LE_QH:
16572 check_dsp(ctx);
16573 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
16574 break;
16575 case OPC_CMPGDU_EQ_OB:
16576 check_dspr2(ctx);
16577 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16578 break;
16579 case OPC_CMPGDU_LT_OB:
16580 check_dspr2(ctx);
16581 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16582 break;
16583 case OPC_CMPGDU_LE_OB:
16584 check_dspr2(ctx);
16585 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16586 break;
16587 case OPC_CMPGU_EQ_OB:
16588 check_dsp(ctx);
16589 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
16590 break;
16591 case OPC_CMPGU_LT_OB:
16592 check_dsp(ctx);
16593 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
16594 break;
16595 case OPC_CMPGU_LE_OB:
16596 check_dsp(ctx);
16597 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
16598 break;
16599 case OPC_CMPU_EQ_OB:
16600 check_dsp(ctx);
16601 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
16602 break;
16603 case OPC_CMPU_LT_OB:
16604 check_dsp(ctx);
16605 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
16606 break;
16607 case OPC_CMPU_LE_OB:
16608 check_dsp(ctx);
16609 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
16610 break;
16611 case OPC_PACKRL_PW:
16612 check_dsp(ctx);
16613 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
16614 break;
16615 case OPC_PICK_OB:
16616 check_dsp(ctx);
16617 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16618 break;
16619 case OPC_PICK_PW:
16620 check_dsp(ctx);
16621 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16622 break;
16623 case OPC_PICK_QH:
16624 check_dsp(ctx);
16625 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16626 break;
16628 break;
16629 #endif
16632 tcg_temp_free(t1);
16633 tcg_temp_free(v1_t);
16634 tcg_temp_free(v2_t);
16637 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
16638 uint32_t op1, int rt, int rs, int sa)
16640 TCGv t0;
16642 check_dspr2(ctx);
16644 if (rt == 0) {
16645 /* Treat as NOP. */
16646 return;
16649 t0 = tcg_temp_new();
16650 gen_load_gpr(t0, rs);
16652 switch (op1) {
16653 case OPC_APPEND_DSP:
16654 switch (MASK_APPEND(ctx->opcode)) {
16655 case OPC_APPEND:
16656 if (sa != 0) {
16657 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
16659 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16660 break;
16661 case OPC_PREPEND:
16662 if (sa != 0) {
16663 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
16664 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16665 tcg_gen_shli_tl(t0, t0, 32 - sa);
16666 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16668 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16669 break;
16670 case OPC_BALIGN:
16671 sa &= 3;
16672 if (sa != 0 && sa != 2) {
16673 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16674 tcg_gen_ext32u_tl(t0, t0);
16675 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
16676 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16678 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16679 break;
16680 default: /* Invalid */
16681 MIPS_INVAL("MASK APPEND");
16682 generate_exception_end(ctx, EXCP_RI);
16683 break;
16685 break;
16686 #ifdef TARGET_MIPS64
16687 case OPC_DAPPEND_DSP:
16688 switch (MASK_DAPPEND(ctx->opcode)) {
16689 case OPC_DAPPEND:
16690 if (sa != 0) {
16691 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
16693 break;
16694 case OPC_PREPENDD:
16695 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
16696 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
16697 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
16698 break;
16699 case OPC_PREPENDW:
16700 if (sa != 0) {
16701 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16702 tcg_gen_shli_tl(t0, t0, 64 - sa);
16703 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16705 break;
16706 case OPC_DBALIGN:
16707 sa &= 7;
16708 if (sa != 0 && sa != 2 && sa != 4) {
16709 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16710 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
16711 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16713 break;
16714 default: /* Invalid */
16715 MIPS_INVAL("MASK DAPPEND");
16716 generate_exception_end(ctx, EXCP_RI);
16717 break;
16719 break;
16720 #endif
16722 tcg_temp_free(t0);
16725 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16726 int ret, int v1, int v2, int check_ret)
16729 TCGv t0;
16730 TCGv t1;
16731 TCGv v1_t;
16732 TCGv v2_t;
16733 int16_t imm;
16735 if ((ret == 0) && (check_ret == 1)) {
16736 /* Treat as NOP. */
16737 return;
16740 t0 = tcg_temp_new();
16741 t1 = tcg_temp_new();
16742 v1_t = tcg_temp_new();
16743 v2_t = tcg_temp_new();
16745 gen_load_gpr(v1_t, v1);
16746 gen_load_gpr(v2_t, v2);
16748 switch (op1) {
16749 case OPC_EXTR_W_DSP:
16750 check_dsp(ctx);
16751 switch (op2) {
16752 case OPC_EXTR_W:
16753 tcg_gen_movi_tl(t0, v2);
16754 tcg_gen_movi_tl(t1, v1);
16755 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
16756 break;
16757 case OPC_EXTR_R_W:
16758 tcg_gen_movi_tl(t0, v2);
16759 tcg_gen_movi_tl(t1, v1);
16760 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16761 break;
16762 case OPC_EXTR_RS_W:
16763 tcg_gen_movi_tl(t0, v2);
16764 tcg_gen_movi_tl(t1, v1);
16765 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16766 break;
16767 case OPC_EXTR_S_H:
16768 tcg_gen_movi_tl(t0, v2);
16769 tcg_gen_movi_tl(t1, v1);
16770 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16771 break;
16772 case OPC_EXTRV_S_H:
16773 tcg_gen_movi_tl(t0, v2);
16774 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
16775 break;
16776 case OPC_EXTRV_W:
16777 tcg_gen_movi_tl(t0, v2);
16778 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16779 break;
16780 case OPC_EXTRV_R_W:
16781 tcg_gen_movi_tl(t0, v2);
16782 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16783 break;
16784 case OPC_EXTRV_RS_W:
16785 tcg_gen_movi_tl(t0, v2);
16786 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16787 break;
16788 case OPC_EXTP:
16789 tcg_gen_movi_tl(t0, v2);
16790 tcg_gen_movi_tl(t1, v1);
16791 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
16792 break;
16793 case OPC_EXTPV:
16794 tcg_gen_movi_tl(t0, v2);
16795 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
16796 break;
16797 case OPC_EXTPDP:
16798 tcg_gen_movi_tl(t0, v2);
16799 tcg_gen_movi_tl(t1, v1);
16800 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
16801 break;
16802 case OPC_EXTPDPV:
16803 tcg_gen_movi_tl(t0, v2);
16804 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16805 break;
16806 case OPC_SHILO:
16807 imm = (ctx->opcode >> 20) & 0x3F;
16808 tcg_gen_movi_tl(t0, ret);
16809 tcg_gen_movi_tl(t1, imm);
16810 gen_helper_shilo(t0, t1, cpu_env);
16811 break;
16812 case OPC_SHILOV:
16813 tcg_gen_movi_tl(t0, ret);
16814 gen_helper_shilo(t0, v1_t, cpu_env);
16815 break;
16816 case OPC_MTHLIP:
16817 tcg_gen_movi_tl(t0, ret);
16818 gen_helper_mthlip(t0, v1_t, cpu_env);
16819 break;
16820 case OPC_WRDSP:
16821 imm = (ctx->opcode >> 11) & 0x3FF;
16822 tcg_gen_movi_tl(t0, imm);
16823 gen_helper_wrdsp(v1_t, t0, cpu_env);
16824 break;
16825 case OPC_RDDSP:
16826 imm = (ctx->opcode >> 16) & 0x03FF;
16827 tcg_gen_movi_tl(t0, imm);
16828 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
16829 break;
16831 break;
16832 #ifdef TARGET_MIPS64
16833 case OPC_DEXTR_W_DSP:
16834 check_dsp(ctx);
16835 switch (op2) {
16836 case OPC_DMTHLIP:
16837 tcg_gen_movi_tl(t0, ret);
16838 gen_helper_dmthlip(v1_t, t0, cpu_env);
16839 break;
16840 case OPC_DSHILO:
16842 int shift = (ctx->opcode >> 19) & 0x7F;
16843 int ac = (ctx->opcode >> 11) & 0x03;
16844 tcg_gen_movi_tl(t0, shift);
16845 tcg_gen_movi_tl(t1, ac);
16846 gen_helper_dshilo(t0, t1, cpu_env);
16847 break;
16849 case OPC_DSHILOV:
16851 int ac = (ctx->opcode >> 11) & 0x03;
16852 tcg_gen_movi_tl(t0, ac);
16853 gen_helper_dshilo(v1_t, t0, cpu_env);
16854 break;
16856 case OPC_DEXTP:
16857 tcg_gen_movi_tl(t0, v2);
16858 tcg_gen_movi_tl(t1, v1);
16860 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
16861 break;
16862 case OPC_DEXTPV:
16863 tcg_gen_movi_tl(t0, v2);
16864 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
16865 break;
16866 case OPC_DEXTPDP:
16867 tcg_gen_movi_tl(t0, v2);
16868 tcg_gen_movi_tl(t1, v1);
16869 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
16870 break;
16871 case OPC_DEXTPDPV:
16872 tcg_gen_movi_tl(t0, v2);
16873 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16874 break;
16875 case OPC_DEXTR_L:
16876 tcg_gen_movi_tl(t0, v2);
16877 tcg_gen_movi_tl(t1, v1);
16878 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
16879 break;
16880 case OPC_DEXTR_R_L:
16881 tcg_gen_movi_tl(t0, v2);
16882 tcg_gen_movi_tl(t1, v1);
16883 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
16884 break;
16885 case OPC_DEXTR_RS_L:
16886 tcg_gen_movi_tl(t0, v2);
16887 tcg_gen_movi_tl(t1, v1);
16888 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
16889 break;
16890 case OPC_DEXTR_W:
16891 tcg_gen_movi_tl(t0, v2);
16892 tcg_gen_movi_tl(t1, v1);
16893 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
16894 break;
16895 case OPC_DEXTR_R_W:
16896 tcg_gen_movi_tl(t0, v2);
16897 tcg_gen_movi_tl(t1, v1);
16898 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16899 break;
16900 case OPC_DEXTR_RS_W:
16901 tcg_gen_movi_tl(t0, v2);
16902 tcg_gen_movi_tl(t1, v1);
16903 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16904 break;
16905 case OPC_DEXTR_S_H:
16906 tcg_gen_movi_tl(t0, v2);
16907 tcg_gen_movi_tl(t1, v1);
16908 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16909 break;
16910 case OPC_DEXTRV_S_H:
16911 tcg_gen_movi_tl(t0, v2);
16912 tcg_gen_movi_tl(t1, v1);
16913 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16914 break;
16915 case OPC_DEXTRV_L:
16916 tcg_gen_movi_tl(t0, v2);
16917 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16918 break;
16919 case OPC_DEXTRV_R_L:
16920 tcg_gen_movi_tl(t0, v2);
16921 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16922 break;
16923 case OPC_DEXTRV_RS_L:
16924 tcg_gen_movi_tl(t0, v2);
16925 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16926 break;
16927 case OPC_DEXTRV_W:
16928 tcg_gen_movi_tl(t0, v2);
16929 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16930 break;
16931 case OPC_DEXTRV_R_W:
16932 tcg_gen_movi_tl(t0, v2);
16933 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16934 break;
16935 case OPC_DEXTRV_RS_W:
16936 tcg_gen_movi_tl(t0, v2);
16937 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16938 break;
16940 break;
16941 #endif
16944 tcg_temp_free(t0);
16945 tcg_temp_free(t1);
16946 tcg_temp_free(v1_t);
16947 tcg_temp_free(v2_t);
16950 /* End MIPSDSP functions. */
16952 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
16954 int rs, rt, rd, sa;
16955 uint32_t op1, op2;
16957 rs = (ctx->opcode >> 21) & 0x1f;
16958 rt = (ctx->opcode >> 16) & 0x1f;
16959 rd = (ctx->opcode >> 11) & 0x1f;
16960 sa = (ctx->opcode >> 6) & 0x1f;
16962 op1 = MASK_SPECIAL(ctx->opcode);
16963 switch (op1) {
16964 case OPC_LSA:
16965 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
16966 break;
16967 case OPC_MULT ... OPC_DIVU:
16968 op2 = MASK_R6_MULDIV(ctx->opcode);
16969 switch (op2) {
16970 case R6_OPC_MUL:
16971 case R6_OPC_MUH:
16972 case R6_OPC_MULU:
16973 case R6_OPC_MUHU:
16974 case R6_OPC_DIV:
16975 case R6_OPC_MOD:
16976 case R6_OPC_DIVU:
16977 case R6_OPC_MODU:
16978 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16979 break;
16980 default:
16981 MIPS_INVAL("special_r6 muldiv");
16982 generate_exception_end(ctx, EXCP_RI);
16983 break;
16985 break;
16986 case OPC_SELEQZ:
16987 case OPC_SELNEZ:
16988 gen_cond_move(ctx, op1, rd, rs, rt);
16989 break;
16990 case R6_OPC_CLO:
16991 case R6_OPC_CLZ:
16992 if (rt == 0 && sa == 1) {
16993 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16994 We need additionally to check other fields */
16995 gen_cl(ctx, op1, rd, rs);
16996 } else {
16997 generate_exception_end(ctx, EXCP_RI);
16999 break;
17000 case R6_OPC_SDBBP:
17001 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17002 gen_helper_do_semihosting(cpu_env);
17003 } else {
17004 if (ctx->hflags & MIPS_HFLAG_SBRI) {
17005 generate_exception_end(ctx, EXCP_RI);
17006 } else {
17007 generate_exception_end(ctx, EXCP_DBp);
17010 break;
17011 #if defined(TARGET_MIPS64)
17012 case OPC_DLSA:
17013 check_mips_64(ctx);
17014 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
17015 break;
17016 case R6_OPC_DCLO:
17017 case R6_OPC_DCLZ:
17018 if (rt == 0 && sa == 1) {
17019 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17020 We need additionally to check other fields */
17021 check_mips_64(ctx);
17022 gen_cl(ctx, op1, rd, rs);
17023 } else {
17024 generate_exception_end(ctx, EXCP_RI);
17026 break;
17027 case OPC_DMULT ... OPC_DDIVU:
17028 op2 = MASK_R6_MULDIV(ctx->opcode);
17029 switch (op2) {
17030 case R6_OPC_DMUL:
17031 case R6_OPC_DMUH:
17032 case R6_OPC_DMULU:
17033 case R6_OPC_DMUHU:
17034 case R6_OPC_DDIV:
17035 case R6_OPC_DMOD:
17036 case R6_OPC_DDIVU:
17037 case R6_OPC_DMODU:
17038 check_mips_64(ctx);
17039 gen_r6_muldiv(ctx, op2, rd, rs, rt);
17040 break;
17041 default:
17042 MIPS_INVAL("special_r6 muldiv");
17043 generate_exception_end(ctx, EXCP_RI);
17044 break;
17046 break;
17047 #endif
17048 default: /* Invalid */
17049 MIPS_INVAL("special_r6");
17050 generate_exception_end(ctx, EXCP_RI);
17051 break;
17055 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
17057 int rs, rt, rd, sa;
17058 uint32_t op1;
17060 rs = (ctx->opcode >> 21) & 0x1f;
17061 rt = (ctx->opcode >> 16) & 0x1f;
17062 rd = (ctx->opcode >> 11) & 0x1f;
17063 sa = (ctx->opcode >> 6) & 0x1f;
17065 op1 = MASK_SPECIAL(ctx->opcode);
17066 switch (op1) {
17067 case OPC_MOVN: /* Conditional move */
17068 case OPC_MOVZ:
17069 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
17070 INSN_LOONGSON2E | INSN_LOONGSON2F);
17071 gen_cond_move(ctx, op1, rd, rs, rt);
17072 break;
17073 case OPC_MFHI: /* Move from HI/LO */
17074 case OPC_MFLO:
17075 gen_HILO(ctx, op1, rs & 3, rd);
17076 break;
17077 case OPC_MTHI:
17078 case OPC_MTLO: /* Move to HI/LO */
17079 gen_HILO(ctx, op1, rd & 3, rs);
17080 break;
17081 case OPC_MOVCI:
17082 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
17083 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17084 check_cp1_enabled(ctx);
17085 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
17086 (ctx->opcode >> 16) & 1);
17087 } else {
17088 generate_exception_err(ctx, EXCP_CpU, 1);
17090 break;
17091 case OPC_MULT:
17092 case OPC_MULTU:
17093 if (sa) {
17094 check_insn(ctx, INSN_VR54XX);
17095 op1 = MASK_MUL_VR54XX(ctx->opcode);
17096 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
17097 } else {
17098 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17100 break;
17101 case OPC_DIV:
17102 case OPC_DIVU:
17103 gen_muldiv(ctx, op1, 0, rs, rt);
17104 break;
17105 #if defined(TARGET_MIPS64)
17106 case OPC_DMULT ... OPC_DDIVU:
17107 check_insn(ctx, ISA_MIPS3);
17108 check_mips_64(ctx);
17109 gen_muldiv(ctx, op1, 0, rs, rt);
17110 break;
17111 #endif
17112 case OPC_JR:
17113 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17114 break;
17115 case OPC_SPIM:
17116 #ifdef MIPS_STRICT_STANDARD
17117 MIPS_INVAL("SPIM");
17118 generate_exception_end(ctx, EXCP_RI);
17119 #else
17120 /* Implemented as RI exception for now. */
17121 MIPS_INVAL("spim (unofficial)");
17122 generate_exception_end(ctx, EXCP_RI);
17123 #endif
17124 break;
17125 default: /* Invalid */
17126 MIPS_INVAL("special_legacy");
17127 generate_exception_end(ctx, EXCP_RI);
17128 break;
17132 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
17134 int rs, rt, rd, sa;
17135 uint32_t op1;
17137 rs = (ctx->opcode >> 21) & 0x1f;
17138 rt = (ctx->opcode >> 16) & 0x1f;
17139 rd = (ctx->opcode >> 11) & 0x1f;
17140 sa = (ctx->opcode >> 6) & 0x1f;
17142 op1 = MASK_SPECIAL(ctx->opcode);
17143 switch (op1) {
17144 case OPC_SLL: /* Shift with immediate */
17145 if (sa == 5 && rd == 0 &&
17146 rs == 0 && rt == 0) { /* PAUSE */
17147 if ((ctx->insn_flags & ISA_MIPS32R6) &&
17148 (ctx->hflags & MIPS_HFLAG_BMASK)) {
17149 generate_exception_end(ctx, EXCP_RI);
17150 break;
17153 /* Fallthrough */
17154 case OPC_SRA:
17155 gen_shift_imm(ctx, op1, rd, rt, sa);
17156 break;
17157 case OPC_SRL:
17158 switch ((ctx->opcode >> 21) & 0x1f) {
17159 case 1:
17160 /* rotr is decoded as srl on non-R2 CPUs */
17161 if (ctx->insn_flags & ISA_MIPS32R2) {
17162 op1 = OPC_ROTR;
17164 /* Fallthrough */
17165 case 0:
17166 gen_shift_imm(ctx, op1, rd, rt, sa);
17167 break;
17168 default:
17169 generate_exception_end(ctx, EXCP_RI);
17170 break;
17172 break;
17173 case OPC_ADD ... OPC_SUBU:
17174 gen_arith(ctx, op1, rd, rs, rt);
17175 break;
17176 case OPC_SLLV: /* Shifts */
17177 case OPC_SRAV:
17178 gen_shift(ctx, op1, rd, rs, rt);
17179 break;
17180 case OPC_SRLV:
17181 switch ((ctx->opcode >> 6) & 0x1f) {
17182 case 1:
17183 /* rotrv is decoded as srlv on non-R2 CPUs */
17184 if (ctx->insn_flags & ISA_MIPS32R2) {
17185 op1 = OPC_ROTRV;
17187 /* Fallthrough */
17188 case 0:
17189 gen_shift(ctx, op1, rd, rs, rt);
17190 break;
17191 default:
17192 generate_exception_end(ctx, EXCP_RI);
17193 break;
17195 break;
17196 case OPC_SLT: /* Set on less than */
17197 case OPC_SLTU:
17198 gen_slt(ctx, op1, rd, rs, rt);
17199 break;
17200 case OPC_AND: /* Logic*/
17201 case OPC_OR:
17202 case OPC_NOR:
17203 case OPC_XOR:
17204 gen_logic(ctx, op1, rd, rs, rt);
17205 break;
17206 case OPC_JALR:
17207 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17208 break;
17209 case OPC_TGE ... OPC_TEQ: /* Traps */
17210 case OPC_TNE:
17211 check_insn(ctx, ISA_MIPS2);
17212 gen_trap(ctx, op1, rs, rt, -1);
17213 break;
17214 case OPC_LSA: /* OPC_PMON */
17215 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17216 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17217 decode_opc_special_r6(env, ctx);
17218 } else {
17219 /* Pmon entry point, also R4010 selsl */
17220 #ifdef MIPS_STRICT_STANDARD
17221 MIPS_INVAL("PMON / selsl");
17222 generate_exception_end(ctx, EXCP_RI);
17223 #else
17224 gen_helper_0e0i(pmon, sa);
17225 #endif
17227 break;
17228 case OPC_SYSCALL:
17229 generate_exception_end(ctx, EXCP_SYSCALL);
17230 break;
17231 case OPC_BREAK:
17232 generate_exception_end(ctx, EXCP_BREAK);
17233 break;
17234 case OPC_SYNC:
17235 check_insn(ctx, ISA_MIPS2);
17236 gen_sync(extract32(ctx->opcode, 6, 5));
17237 break;
17239 #if defined(TARGET_MIPS64)
17240 /* MIPS64 specific opcodes */
17241 case OPC_DSLL:
17242 case OPC_DSRA:
17243 case OPC_DSLL32:
17244 case OPC_DSRA32:
17245 check_insn(ctx, ISA_MIPS3);
17246 check_mips_64(ctx);
17247 gen_shift_imm(ctx, op1, rd, rt, sa);
17248 break;
17249 case OPC_DSRL:
17250 switch ((ctx->opcode >> 21) & 0x1f) {
17251 case 1:
17252 /* drotr is decoded as dsrl on non-R2 CPUs */
17253 if (ctx->insn_flags & ISA_MIPS32R2) {
17254 op1 = OPC_DROTR;
17256 /* Fallthrough */
17257 case 0:
17258 check_insn(ctx, ISA_MIPS3);
17259 check_mips_64(ctx);
17260 gen_shift_imm(ctx, op1, rd, rt, sa);
17261 break;
17262 default:
17263 generate_exception_end(ctx, EXCP_RI);
17264 break;
17266 break;
17267 case OPC_DSRL32:
17268 switch ((ctx->opcode >> 21) & 0x1f) {
17269 case 1:
17270 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
17271 if (ctx->insn_flags & ISA_MIPS32R2) {
17272 op1 = OPC_DROTR32;
17274 /* Fallthrough */
17275 case 0:
17276 check_insn(ctx, ISA_MIPS3);
17277 check_mips_64(ctx);
17278 gen_shift_imm(ctx, op1, rd, rt, sa);
17279 break;
17280 default:
17281 generate_exception_end(ctx, EXCP_RI);
17282 break;
17284 break;
17285 case OPC_DADD ... OPC_DSUBU:
17286 check_insn(ctx, ISA_MIPS3);
17287 check_mips_64(ctx);
17288 gen_arith(ctx, op1, rd, rs, rt);
17289 break;
17290 case OPC_DSLLV:
17291 case OPC_DSRAV:
17292 check_insn(ctx, ISA_MIPS3);
17293 check_mips_64(ctx);
17294 gen_shift(ctx, op1, rd, rs, rt);
17295 break;
17296 case OPC_DSRLV:
17297 switch ((ctx->opcode >> 6) & 0x1f) {
17298 case 1:
17299 /* drotrv is decoded as dsrlv on non-R2 CPUs */
17300 if (ctx->insn_flags & ISA_MIPS32R2) {
17301 op1 = OPC_DROTRV;
17303 /* Fallthrough */
17304 case 0:
17305 check_insn(ctx, ISA_MIPS3);
17306 check_mips_64(ctx);
17307 gen_shift(ctx, op1, rd, rs, rt);
17308 break;
17309 default:
17310 generate_exception_end(ctx, EXCP_RI);
17311 break;
17313 break;
17314 case OPC_DLSA:
17315 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17316 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17317 decode_opc_special_r6(env, ctx);
17319 break;
17320 #endif
17321 default:
17322 if (ctx->insn_flags & ISA_MIPS32R6) {
17323 decode_opc_special_r6(env, ctx);
17324 } else {
17325 decode_opc_special_legacy(env, ctx);
17330 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
17332 int rs, rt, rd;
17333 uint32_t op1;
17335 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17337 rs = (ctx->opcode >> 21) & 0x1f;
17338 rt = (ctx->opcode >> 16) & 0x1f;
17339 rd = (ctx->opcode >> 11) & 0x1f;
17341 op1 = MASK_SPECIAL2(ctx->opcode);
17342 switch (op1) {
17343 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
17344 case OPC_MSUB ... OPC_MSUBU:
17345 check_insn(ctx, ISA_MIPS32);
17346 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17347 break;
17348 case OPC_MUL:
17349 gen_arith(ctx, op1, rd, rs, rt);
17350 break;
17351 case OPC_DIV_G_2F:
17352 case OPC_DIVU_G_2F:
17353 case OPC_MULT_G_2F:
17354 case OPC_MULTU_G_2F:
17355 case OPC_MOD_G_2F:
17356 case OPC_MODU_G_2F:
17357 check_insn(ctx, INSN_LOONGSON2F);
17358 gen_loongson_integer(ctx, op1, rd, rs, rt);
17359 break;
17360 case OPC_CLO:
17361 case OPC_CLZ:
17362 check_insn(ctx, ISA_MIPS32);
17363 gen_cl(ctx, op1, rd, rs);
17364 break;
17365 case OPC_SDBBP:
17366 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17367 gen_helper_do_semihosting(cpu_env);
17368 } else {
17369 /* XXX: not clear which exception should be raised
17370 * when in debug mode...
17372 check_insn(ctx, ISA_MIPS32);
17373 generate_exception_end(ctx, EXCP_DBp);
17375 break;
17376 #if defined(TARGET_MIPS64)
17377 case OPC_DCLO:
17378 case OPC_DCLZ:
17379 check_insn(ctx, ISA_MIPS64);
17380 check_mips_64(ctx);
17381 gen_cl(ctx, op1, rd, rs);
17382 break;
17383 case OPC_DMULT_G_2F:
17384 case OPC_DMULTU_G_2F:
17385 case OPC_DDIV_G_2F:
17386 case OPC_DDIVU_G_2F:
17387 case OPC_DMOD_G_2F:
17388 case OPC_DMODU_G_2F:
17389 check_insn(ctx, INSN_LOONGSON2F);
17390 gen_loongson_integer(ctx, op1, rd, rs, rt);
17391 break;
17392 #endif
17393 default: /* Invalid */
17394 MIPS_INVAL("special2_legacy");
17395 generate_exception_end(ctx, EXCP_RI);
17396 break;
17400 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
17402 int rs, rt, rd, sa;
17403 uint32_t op1, op2;
17404 int16_t imm;
17406 rs = (ctx->opcode >> 21) & 0x1f;
17407 rt = (ctx->opcode >> 16) & 0x1f;
17408 rd = (ctx->opcode >> 11) & 0x1f;
17409 sa = (ctx->opcode >> 6) & 0x1f;
17410 imm = (int16_t)ctx->opcode >> 7;
17412 op1 = MASK_SPECIAL3(ctx->opcode);
17413 switch (op1) {
17414 case R6_OPC_PREF:
17415 if (rt >= 24) {
17416 /* hint codes 24-31 are reserved and signal RI */
17417 generate_exception_end(ctx, EXCP_RI);
17419 /* Treat as NOP. */
17420 break;
17421 case R6_OPC_CACHE:
17422 check_cp0_enabled(ctx);
17423 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17424 gen_cache_operation(ctx, rt, rs, imm);
17426 break;
17427 case R6_OPC_SC:
17428 gen_st_cond(ctx, op1, rt, rs, imm);
17429 break;
17430 case R6_OPC_LL:
17431 gen_ld(ctx, op1, rt, rs, imm);
17432 break;
17433 case OPC_BSHFL:
17435 if (rd == 0) {
17436 /* Treat as NOP. */
17437 break;
17439 op2 = MASK_BSHFL(ctx->opcode);
17440 switch (op2) {
17441 case OPC_ALIGN ... OPC_ALIGN_END:
17442 gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3);
17443 break;
17444 case OPC_BITSWAP:
17445 gen_bitswap(ctx, op2, rd, rt);
17446 break;
17449 break;
17450 #if defined(TARGET_MIPS64)
17451 case R6_OPC_SCD:
17452 gen_st_cond(ctx, op1, rt, rs, imm);
17453 break;
17454 case R6_OPC_LLD:
17455 gen_ld(ctx, op1, rt, rs, imm);
17456 break;
17457 case OPC_DBSHFL:
17458 check_mips_64(ctx);
17460 if (rd == 0) {
17461 /* Treat as NOP. */
17462 break;
17464 op2 = MASK_DBSHFL(ctx->opcode);
17465 switch (op2) {
17466 case OPC_DALIGN ... OPC_DALIGN_END:
17467 gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7);
17468 break;
17469 case OPC_DBITSWAP:
17470 gen_bitswap(ctx, op2, rd, rt);
17471 break;
17475 break;
17476 #endif
17477 default: /* Invalid */
17478 MIPS_INVAL("special3_r6");
17479 generate_exception_end(ctx, EXCP_RI);
17480 break;
17484 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
17486 int rs, rt, rd;
17487 uint32_t op1, op2;
17489 rs = (ctx->opcode >> 21) & 0x1f;
17490 rt = (ctx->opcode >> 16) & 0x1f;
17491 rd = (ctx->opcode >> 11) & 0x1f;
17493 op1 = MASK_SPECIAL3(ctx->opcode);
17494 switch (op1) {
17495 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
17496 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
17497 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
17498 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
17499 * the same mask and op1. */
17500 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
17501 op2 = MASK_ADDUH_QB(ctx->opcode);
17502 switch (op2) {
17503 case OPC_ADDUH_QB:
17504 case OPC_ADDUH_R_QB:
17505 case OPC_ADDQH_PH:
17506 case OPC_ADDQH_R_PH:
17507 case OPC_ADDQH_W:
17508 case OPC_ADDQH_R_W:
17509 case OPC_SUBUH_QB:
17510 case OPC_SUBUH_R_QB:
17511 case OPC_SUBQH_PH:
17512 case OPC_SUBQH_R_PH:
17513 case OPC_SUBQH_W:
17514 case OPC_SUBQH_R_W:
17515 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17516 break;
17517 case OPC_MUL_PH:
17518 case OPC_MUL_S_PH:
17519 case OPC_MULQ_S_W:
17520 case OPC_MULQ_RS_W:
17521 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17522 break;
17523 default:
17524 MIPS_INVAL("MASK ADDUH.QB");
17525 generate_exception_end(ctx, EXCP_RI);
17526 break;
17528 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
17529 gen_loongson_integer(ctx, op1, rd, rs, rt);
17530 } else {
17531 generate_exception_end(ctx, EXCP_RI);
17533 break;
17534 case OPC_LX_DSP:
17535 op2 = MASK_LX(ctx->opcode);
17536 switch (op2) {
17537 #if defined(TARGET_MIPS64)
17538 case OPC_LDX:
17539 #endif
17540 case OPC_LBUX:
17541 case OPC_LHX:
17542 case OPC_LWX:
17543 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
17544 break;
17545 default: /* Invalid */
17546 MIPS_INVAL("MASK LX");
17547 generate_exception_end(ctx, EXCP_RI);
17548 break;
17550 break;
17551 case OPC_ABSQ_S_PH_DSP:
17552 op2 = MASK_ABSQ_S_PH(ctx->opcode);
17553 switch (op2) {
17554 case OPC_ABSQ_S_QB:
17555 case OPC_ABSQ_S_PH:
17556 case OPC_ABSQ_S_W:
17557 case OPC_PRECEQ_W_PHL:
17558 case OPC_PRECEQ_W_PHR:
17559 case OPC_PRECEQU_PH_QBL:
17560 case OPC_PRECEQU_PH_QBR:
17561 case OPC_PRECEQU_PH_QBLA:
17562 case OPC_PRECEQU_PH_QBRA:
17563 case OPC_PRECEU_PH_QBL:
17564 case OPC_PRECEU_PH_QBR:
17565 case OPC_PRECEU_PH_QBLA:
17566 case OPC_PRECEU_PH_QBRA:
17567 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17568 break;
17569 case OPC_BITREV:
17570 case OPC_REPL_QB:
17571 case OPC_REPLV_QB:
17572 case OPC_REPL_PH:
17573 case OPC_REPLV_PH:
17574 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17575 break;
17576 default:
17577 MIPS_INVAL("MASK ABSQ_S.PH");
17578 generate_exception_end(ctx, EXCP_RI);
17579 break;
17581 break;
17582 case OPC_ADDU_QB_DSP:
17583 op2 = MASK_ADDU_QB(ctx->opcode);
17584 switch (op2) {
17585 case OPC_ADDQ_PH:
17586 case OPC_ADDQ_S_PH:
17587 case OPC_ADDQ_S_W:
17588 case OPC_ADDU_QB:
17589 case OPC_ADDU_S_QB:
17590 case OPC_ADDU_PH:
17591 case OPC_ADDU_S_PH:
17592 case OPC_SUBQ_PH:
17593 case OPC_SUBQ_S_PH:
17594 case OPC_SUBQ_S_W:
17595 case OPC_SUBU_QB:
17596 case OPC_SUBU_S_QB:
17597 case OPC_SUBU_PH:
17598 case OPC_SUBU_S_PH:
17599 case OPC_ADDSC:
17600 case OPC_ADDWC:
17601 case OPC_MODSUB:
17602 case OPC_RADDU_W_QB:
17603 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17604 break;
17605 case OPC_MULEU_S_PH_QBL:
17606 case OPC_MULEU_S_PH_QBR:
17607 case OPC_MULQ_RS_PH:
17608 case OPC_MULEQ_S_W_PHL:
17609 case OPC_MULEQ_S_W_PHR:
17610 case OPC_MULQ_S_PH:
17611 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17612 break;
17613 default: /* Invalid */
17614 MIPS_INVAL("MASK ADDU.QB");
17615 generate_exception_end(ctx, EXCP_RI);
17616 break;
17619 break;
17620 case OPC_CMPU_EQ_QB_DSP:
17621 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
17622 switch (op2) {
17623 case OPC_PRECR_SRA_PH_W:
17624 case OPC_PRECR_SRA_R_PH_W:
17625 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17626 break;
17627 case OPC_PRECR_QB_PH:
17628 case OPC_PRECRQ_QB_PH:
17629 case OPC_PRECRQ_PH_W:
17630 case OPC_PRECRQ_RS_PH_W:
17631 case OPC_PRECRQU_S_QB_PH:
17632 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17633 break;
17634 case OPC_CMPU_EQ_QB:
17635 case OPC_CMPU_LT_QB:
17636 case OPC_CMPU_LE_QB:
17637 case OPC_CMP_EQ_PH:
17638 case OPC_CMP_LT_PH:
17639 case OPC_CMP_LE_PH:
17640 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17641 break;
17642 case OPC_CMPGU_EQ_QB:
17643 case OPC_CMPGU_LT_QB:
17644 case OPC_CMPGU_LE_QB:
17645 case OPC_CMPGDU_EQ_QB:
17646 case OPC_CMPGDU_LT_QB:
17647 case OPC_CMPGDU_LE_QB:
17648 case OPC_PICK_QB:
17649 case OPC_PICK_PH:
17650 case OPC_PACKRL_PH:
17651 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17652 break;
17653 default: /* Invalid */
17654 MIPS_INVAL("MASK CMPU.EQ.QB");
17655 generate_exception_end(ctx, EXCP_RI);
17656 break;
17658 break;
17659 case OPC_SHLL_QB_DSP:
17660 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17661 break;
17662 case OPC_DPA_W_PH_DSP:
17663 op2 = MASK_DPA_W_PH(ctx->opcode);
17664 switch (op2) {
17665 case OPC_DPAU_H_QBL:
17666 case OPC_DPAU_H_QBR:
17667 case OPC_DPSU_H_QBL:
17668 case OPC_DPSU_H_QBR:
17669 case OPC_DPA_W_PH:
17670 case OPC_DPAX_W_PH:
17671 case OPC_DPAQ_S_W_PH:
17672 case OPC_DPAQX_S_W_PH:
17673 case OPC_DPAQX_SA_W_PH:
17674 case OPC_DPS_W_PH:
17675 case OPC_DPSX_W_PH:
17676 case OPC_DPSQ_S_W_PH:
17677 case OPC_DPSQX_S_W_PH:
17678 case OPC_DPSQX_SA_W_PH:
17679 case OPC_MULSAQ_S_W_PH:
17680 case OPC_DPAQ_SA_L_W:
17681 case OPC_DPSQ_SA_L_W:
17682 case OPC_MAQ_S_W_PHL:
17683 case OPC_MAQ_S_W_PHR:
17684 case OPC_MAQ_SA_W_PHL:
17685 case OPC_MAQ_SA_W_PHR:
17686 case OPC_MULSA_W_PH:
17687 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17688 break;
17689 default: /* Invalid */
17690 MIPS_INVAL("MASK DPAW.PH");
17691 generate_exception_end(ctx, EXCP_RI);
17692 break;
17694 break;
17695 case OPC_INSV_DSP:
17696 op2 = MASK_INSV(ctx->opcode);
17697 switch (op2) {
17698 case OPC_INSV:
17699 check_dsp(ctx);
17701 TCGv t0, t1;
17703 if (rt == 0) {
17704 break;
17707 t0 = tcg_temp_new();
17708 t1 = tcg_temp_new();
17710 gen_load_gpr(t0, rt);
17711 gen_load_gpr(t1, rs);
17713 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
17715 tcg_temp_free(t0);
17716 tcg_temp_free(t1);
17717 break;
17719 default: /* Invalid */
17720 MIPS_INVAL("MASK INSV");
17721 generate_exception_end(ctx, EXCP_RI);
17722 break;
17724 break;
17725 case OPC_APPEND_DSP:
17726 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17727 break;
17728 case OPC_EXTR_W_DSP:
17729 op2 = MASK_EXTR_W(ctx->opcode);
17730 switch (op2) {
17731 case OPC_EXTR_W:
17732 case OPC_EXTR_R_W:
17733 case OPC_EXTR_RS_W:
17734 case OPC_EXTR_S_H:
17735 case OPC_EXTRV_S_H:
17736 case OPC_EXTRV_W:
17737 case OPC_EXTRV_R_W:
17738 case OPC_EXTRV_RS_W:
17739 case OPC_EXTP:
17740 case OPC_EXTPV:
17741 case OPC_EXTPDP:
17742 case OPC_EXTPDPV:
17743 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17744 break;
17745 case OPC_RDDSP:
17746 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
17747 break;
17748 case OPC_SHILO:
17749 case OPC_SHILOV:
17750 case OPC_MTHLIP:
17751 case OPC_WRDSP:
17752 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17753 break;
17754 default: /* Invalid */
17755 MIPS_INVAL("MASK EXTR.W");
17756 generate_exception_end(ctx, EXCP_RI);
17757 break;
17759 break;
17760 #if defined(TARGET_MIPS64)
17761 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
17762 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
17763 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
17764 check_insn(ctx, INSN_LOONGSON2E);
17765 gen_loongson_integer(ctx, op1, rd, rs, rt);
17766 break;
17767 case OPC_ABSQ_S_QH_DSP:
17768 op2 = MASK_ABSQ_S_QH(ctx->opcode);
17769 switch (op2) {
17770 case OPC_PRECEQ_L_PWL:
17771 case OPC_PRECEQ_L_PWR:
17772 case OPC_PRECEQ_PW_QHL:
17773 case OPC_PRECEQ_PW_QHR:
17774 case OPC_PRECEQ_PW_QHLA:
17775 case OPC_PRECEQ_PW_QHRA:
17776 case OPC_PRECEQU_QH_OBL:
17777 case OPC_PRECEQU_QH_OBR:
17778 case OPC_PRECEQU_QH_OBLA:
17779 case OPC_PRECEQU_QH_OBRA:
17780 case OPC_PRECEU_QH_OBL:
17781 case OPC_PRECEU_QH_OBR:
17782 case OPC_PRECEU_QH_OBLA:
17783 case OPC_PRECEU_QH_OBRA:
17784 case OPC_ABSQ_S_OB:
17785 case OPC_ABSQ_S_PW:
17786 case OPC_ABSQ_S_QH:
17787 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17788 break;
17789 case OPC_REPL_OB:
17790 case OPC_REPL_PW:
17791 case OPC_REPL_QH:
17792 case OPC_REPLV_OB:
17793 case OPC_REPLV_PW:
17794 case OPC_REPLV_QH:
17795 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17796 break;
17797 default: /* Invalid */
17798 MIPS_INVAL("MASK ABSQ_S.QH");
17799 generate_exception_end(ctx, EXCP_RI);
17800 break;
17802 break;
17803 case OPC_ADDU_OB_DSP:
17804 op2 = MASK_ADDU_OB(ctx->opcode);
17805 switch (op2) {
17806 case OPC_RADDU_L_OB:
17807 case OPC_SUBQ_PW:
17808 case OPC_SUBQ_S_PW:
17809 case OPC_SUBQ_QH:
17810 case OPC_SUBQ_S_QH:
17811 case OPC_SUBU_OB:
17812 case OPC_SUBU_S_OB:
17813 case OPC_SUBU_QH:
17814 case OPC_SUBU_S_QH:
17815 case OPC_SUBUH_OB:
17816 case OPC_SUBUH_R_OB:
17817 case OPC_ADDQ_PW:
17818 case OPC_ADDQ_S_PW:
17819 case OPC_ADDQ_QH:
17820 case OPC_ADDQ_S_QH:
17821 case OPC_ADDU_OB:
17822 case OPC_ADDU_S_OB:
17823 case OPC_ADDU_QH:
17824 case OPC_ADDU_S_QH:
17825 case OPC_ADDUH_OB:
17826 case OPC_ADDUH_R_OB:
17827 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17828 break;
17829 case OPC_MULEQ_S_PW_QHL:
17830 case OPC_MULEQ_S_PW_QHR:
17831 case OPC_MULEU_S_QH_OBL:
17832 case OPC_MULEU_S_QH_OBR:
17833 case OPC_MULQ_RS_QH:
17834 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17835 break;
17836 default: /* Invalid */
17837 MIPS_INVAL("MASK ADDU.OB");
17838 generate_exception_end(ctx, EXCP_RI);
17839 break;
17841 break;
17842 case OPC_CMPU_EQ_OB_DSP:
17843 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
17844 switch (op2) {
17845 case OPC_PRECR_SRA_QH_PW:
17846 case OPC_PRECR_SRA_R_QH_PW:
17847 /* Return value is rt. */
17848 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17849 break;
17850 case OPC_PRECR_OB_QH:
17851 case OPC_PRECRQ_OB_QH:
17852 case OPC_PRECRQ_PW_L:
17853 case OPC_PRECRQ_QH_PW:
17854 case OPC_PRECRQ_RS_QH_PW:
17855 case OPC_PRECRQU_S_OB_QH:
17856 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17857 break;
17858 case OPC_CMPU_EQ_OB:
17859 case OPC_CMPU_LT_OB:
17860 case OPC_CMPU_LE_OB:
17861 case OPC_CMP_EQ_QH:
17862 case OPC_CMP_LT_QH:
17863 case OPC_CMP_LE_QH:
17864 case OPC_CMP_EQ_PW:
17865 case OPC_CMP_LT_PW:
17866 case OPC_CMP_LE_PW:
17867 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17868 break;
17869 case OPC_CMPGDU_EQ_OB:
17870 case OPC_CMPGDU_LT_OB:
17871 case OPC_CMPGDU_LE_OB:
17872 case OPC_CMPGU_EQ_OB:
17873 case OPC_CMPGU_LT_OB:
17874 case OPC_CMPGU_LE_OB:
17875 case OPC_PACKRL_PW:
17876 case OPC_PICK_OB:
17877 case OPC_PICK_PW:
17878 case OPC_PICK_QH:
17879 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17880 break;
17881 default: /* Invalid */
17882 MIPS_INVAL("MASK CMPU_EQ.OB");
17883 generate_exception_end(ctx, EXCP_RI);
17884 break;
17886 break;
17887 case OPC_DAPPEND_DSP:
17888 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17889 break;
17890 case OPC_DEXTR_W_DSP:
17891 op2 = MASK_DEXTR_W(ctx->opcode);
17892 switch (op2) {
17893 case OPC_DEXTP:
17894 case OPC_DEXTPDP:
17895 case OPC_DEXTPDPV:
17896 case OPC_DEXTPV:
17897 case OPC_DEXTR_L:
17898 case OPC_DEXTR_R_L:
17899 case OPC_DEXTR_RS_L:
17900 case OPC_DEXTR_W:
17901 case OPC_DEXTR_R_W:
17902 case OPC_DEXTR_RS_W:
17903 case OPC_DEXTR_S_H:
17904 case OPC_DEXTRV_L:
17905 case OPC_DEXTRV_R_L:
17906 case OPC_DEXTRV_RS_L:
17907 case OPC_DEXTRV_S_H:
17908 case OPC_DEXTRV_W:
17909 case OPC_DEXTRV_R_W:
17910 case OPC_DEXTRV_RS_W:
17911 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17912 break;
17913 case OPC_DMTHLIP:
17914 case OPC_DSHILO:
17915 case OPC_DSHILOV:
17916 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17917 break;
17918 default: /* Invalid */
17919 MIPS_INVAL("MASK EXTR.W");
17920 generate_exception_end(ctx, EXCP_RI);
17921 break;
17923 break;
17924 case OPC_DPAQ_W_QH_DSP:
17925 op2 = MASK_DPAQ_W_QH(ctx->opcode);
17926 switch (op2) {
17927 case OPC_DPAU_H_OBL:
17928 case OPC_DPAU_H_OBR:
17929 case OPC_DPSU_H_OBL:
17930 case OPC_DPSU_H_OBR:
17931 case OPC_DPA_W_QH:
17932 case OPC_DPAQ_S_W_QH:
17933 case OPC_DPS_W_QH:
17934 case OPC_DPSQ_S_W_QH:
17935 case OPC_MULSAQ_S_W_QH:
17936 case OPC_DPAQ_SA_L_PW:
17937 case OPC_DPSQ_SA_L_PW:
17938 case OPC_MULSAQ_S_L_PW:
17939 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17940 break;
17941 case OPC_MAQ_S_W_QHLL:
17942 case OPC_MAQ_S_W_QHLR:
17943 case OPC_MAQ_S_W_QHRL:
17944 case OPC_MAQ_S_W_QHRR:
17945 case OPC_MAQ_SA_W_QHLL:
17946 case OPC_MAQ_SA_W_QHLR:
17947 case OPC_MAQ_SA_W_QHRL:
17948 case OPC_MAQ_SA_W_QHRR:
17949 case OPC_MAQ_S_L_PWL:
17950 case OPC_MAQ_S_L_PWR:
17951 case OPC_DMADD:
17952 case OPC_DMADDU:
17953 case OPC_DMSUB:
17954 case OPC_DMSUBU:
17955 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17956 break;
17957 default: /* Invalid */
17958 MIPS_INVAL("MASK DPAQ.W.QH");
17959 generate_exception_end(ctx, EXCP_RI);
17960 break;
17962 break;
17963 case OPC_DINSV_DSP:
17964 op2 = MASK_INSV(ctx->opcode);
17965 switch (op2) {
17966 case OPC_DINSV:
17968 TCGv t0, t1;
17970 if (rt == 0) {
17971 break;
17973 check_dsp(ctx);
17975 t0 = tcg_temp_new();
17976 t1 = tcg_temp_new();
17978 gen_load_gpr(t0, rt);
17979 gen_load_gpr(t1, rs);
17981 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
17983 tcg_temp_free(t0);
17984 tcg_temp_free(t1);
17985 break;
17987 default: /* Invalid */
17988 MIPS_INVAL("MASK DINSV");
17989 generate_exception_end(ctx, EXCP_RI);
17990 break;
17992 break;
17993 case OPC_SHLL_OB_DSP:
17994 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17995 break;
17996 #endif
17997 default: /* Invalid */
17998 MIPS_INVAL("special3_legacy");
17999 generate_exception_end(ctx, EXCP_RI);
18000 break;
18004 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
18006 int rs, rt, rd, sa;
18007 uint32_t op1, op2;
18009 rs = (ctx->opcode >> 21) & 0x1f;
18010 rt = (ctx->opcode >> 16) & 0x1f;
18011 rd = (ctx->opcode >> 11) & 0x1f;
18012 sa = (ctx->opcode >> 6) & 0x1f;
18014 op1 = MASK_SPECIAL3(ctx->opcode);
18015 switch (op1) {
18016 case OPC_EXT:
18017 case OPC_INS:
18018 check_insn(ctx, ISA_MIPS32R2);
18019 gen_bitops(ctx, op1, rt, rs, sa, rd);
18020 break;
18021 case OPC_BSHFL:
18022 op2 = MASK_BSHFL(ctx->opcode);
18023 switch (op2) {
18024 case OPC_ALIGN ... OPC_ALIGN_END:
18025 case OPC_BITSWAP:
18026 check_insn(ctx, ISA_MIPS32R6);
18027 decode_opc_special3_r6(env, ctx);
18028 break;
18029 default:
18030 check_insn(ctx, ISA_MIPS32R2);
18031 gen_bshfl(ctx, op2, rt, rd);
18032 break;
18034 break;
18035 #if defined(TARGET_MIPS64)
18036 case OPC_DEXTM ... OPC_DEXT:
18037 case OPC_DINSM ... OPC_DINS:
18038 check_insn(ctx, ISA_MIPS64R2);
18039 check_mips_64(ctx);
18040 gen_bitops(ctx, op1, rt, rs, sa, rd);
18041 break;
18042 case OPC_DBSHFL:
18043 op2 = MASK_DBSHFL(ctx->opcode);
18044 switch (op2) {
18045 case OPC_DALIGN ... OPC_DALIGN_END:
18046 case OPC_DBITSWAP:
18047 check_insn(ctx, ISA_MIPS32R6);
18048 decode_opc_special3_r6(env, ctx);
18049 break;
18050 default:
18051 check_insn(ctx, ISA_MIPS64R2);
18052 check_mips_64(ctx);
18053 op2 = MASK_DBSHFL(ctx->opcode);
18054 gen_bshfl(ctx, op2, rt, rd);
18055 break;
18057 break;
18058 #endif
18059 case OPC_RDHWR:
18060 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
18061 break;
18062 case OPC_FORK:
18063 check_insn(ctx, ASE_MT);
18065 TCGv t0 = tcg_temp_new();
18066 TCGv t1 = tcg_temp_new();
18068 gen_load_gpr(t0, rt);
18069 gen_load_gpr(t1, rs);
18070 gen_helper_fork(t0, t1);
18071 tcg_temp_free(t0);
18072 tcg_temp_free(t1);
18074 break;
18075 case OPC_YIELD:
18076 check_insn(ctx, ASE_MT);
18078 TCGv t0 = tcg_temp_new();
18080 gen_load_gpr(t0, rs);
18081 gen_helper_yield(t0, cpu_env, t0);
18082 gen_store_gpr(t0, rd);
18083 tcg_temp_free(t0);
18085 break;
18086 default:
18087 if (ctx->insn_flags & ISA_MIPS32R6) {
18088 decode_opc_special3_r6(env, ctx);
18089 } else {
18090 decode_opc_special3_legacy(env, ctx);
18095 /* MIPS SIMD Architecture (MSA) */
18096 static inline int check_msa_access(DisasContext *ctx)
18098 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
18099 !(ctx->hflags & MIPS_HFLAG_F64))) {
18100 generate_exception_end(ctx, EXCP_RI);
18101 return 0;
18104 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
18105 if (ctx->insn_flags & ASE_MSA) {
18106 generate_exception_end(ctx, EXCP_MSADIS);
18107 return 0;
18108 } else {
18109 generate_exception_end(ctx, EXCP_RI);
18110 return 0;
18113 return 1;
18116 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
18118 /* generates tcg ops to check if any element is 0 */
18119 /* Note this function only works with MSA_WRLEN = 128 */
18120 uint64_t eval_zero_or_big = 0;
18121 uint64_t eval_big = 0;
18122 TCGv_i64 t0 = tcg_temp_new_i64();
18123 TCGv_i64 t1 = tcg_temp_new_i64();
18124 switch (df) {
18125 case DF_BYTE:
18126 eval_zero_or_big = 0x0101010101010101ULL;
18127 eval_big = 0x8080808080808080ULL;
18128 break;
18129 case DF_HALF:
18130 eval_zero_or_big = 0x0001000100010001ULL;
18131 eval_big = 0x8000800080008000ULL;
18132 break;
18133 case DF_WORD:
18134 eval_zero_or_big = 0x0000000100000001ULL;
18135 eval_big = 0x8000000080000000ULL;
18136 break;
18137 case DF_DOUBLE:
18138 eval_zero_or_big = 0x0000000000000001ULL;
18139 eval_big = 0x8000000000000000ULL;
18140 break;
18142 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
18143 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
18144 tcg_gen_andi_i64(t0, t0, eval_big);
18145 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
18146 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
18147 tcg_gen_andi_i64(t1, t1, eval_big);
18148 tcg_gen_or_i64(t0, t0, t1);
18149 /* if all bits are zero then all elements are not zero */
18150 /* if some bit is non-zero then some element is zero */
18151 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
18152 tcg_gen_trunc_i64_tl(tresult, t0);
18153 tcg_temp_free_i64(t0);
18154 tcg_temp_free_i64(t1);
18157 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
18159 uint8_t df = (ctx->opcode >> 21) & 0x3;
18160 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18161 int64_t s16 = (int16_t)ctx->opcode;
18163 check_msa_access(ctx);
18165 if (ctx->hflags & MIPS_HFLAG_BMASK) {
18166 generate_exception_end(ctx, EXCP_RI);
18167 return;
18169 switch (op1) {
18170 case OPC_BZ_V:
18171 case OPC_BNZ_V:
18173 TCGv_i64 t0 = tcg_temp_new_i64();
18174 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
18175 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
18176 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
18177 tcg_gen_trunc_i64_tl(bcond, t0);
18178 tcg_temp_free_i64(t0);
18180 break;
18181 case OPC_BZ_B:
18182 case OPC_BZ_H:
18183 case OPC_BZ_W:
18184 case OPC_BZ_D:
18185 gen_check_zero_element(bcond, df, wt);
18186 break;
18187 case OPC_BNZ_B:
18188 case OPC_BNZ_H:
18189 case OPC_BNZ_W:
18190 case OPC_BNZ_D:
18191 gen_check_zero_element(bcond, df, wt);
18192 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
18193 break;
18196 ctx->btarget = ctx->pc + (s16 << 2) + 4;
18198 ctx->hflags |= MIPS_HFLAG_BC;
18199 ctx->hflags |= MIPS_HFLAG_BDS32;
18202 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
18204 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
18205 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
18206 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18207 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18209 TCGv_i32 twd = tcg_const_i32(wd);
18210 TCGv_i32 tws = tcg_const_i32(ws);
18211 TCGv_i32 ti8 = tcg_const_i32(i8);
18213 switch (MASK_MSA_I8(ctx->opcode)) {
18214 case OPC_ANDI_B:
18215 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
18216 break;
18217 case OPC_ORI_B:
18218 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
18219 break;
18220 case OPC_NORI_B:
18221 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
18222 break;
18223 case OPC_XORI_B:
18224 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
18225 break;
18226 case OPC_BMNZI_B:
18227 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
18228 break;
18229 case OPC_BMZI_B:
18230 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
18231 break;
18232 case OPC_BSELI_B:
18233 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
18234 break;
18235 case OPC_SHF_B:
18236 case OPC_SHF_H:
18237 case OPC_SHF_W:
18239 uint8_t df = (ctx->opcode >> 24) & 0x3;
18240 if (df == DF_DOUBLE) {
18241 generate_exception_end(ctx, EXCP_RI);
18242 } else {
18243 TCGv_i32 tdf = tcg_const_i32(df);
18244 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
18245 tcg_temp_free_i32(tdf);
18248 break;
18249 default:
18250 MIPS_INVAL("MSA instruction");
18251 generate_exception_end(ctx, EXCP_RI);
18252 break;
18255 tcg_temp_free_i32(twd);
18256 tcg_temp_free_i32(tws);
18257 tcg_temp_free_i32(ti8);
18260 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
18262 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18263 uint8_t df = (ctx->opcode >> 21) & 0x3;
18264 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
18265 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
18266 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18267 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18269 TCGv_i32 tdf = tcg_const_i32(df);
18270 TCGv_i32 twd = tcg_const_i32(wd);
18271 TCGv_i32 tws = tcg_const_i32(ws);
18272 TCGv_i32 timm = tcg_temp_new_i32();
18273 tcg_gen_movi_i32(timm, u5);
18275 switch (MASK_MSA_I5(ctx->opcode)) {
18276 case OPC_ADDVI_df:
18277 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
18278 break;
18279 case OPC_SUBVI_df:
18280 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
18281 break;
18282 case OPC_MAXI_S_df:
18283 tcg_gen_movi_i32(timm, s5);
18284 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
18285 break;
18286 case OPC_MAXI_U_df:
18287 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
18288 break;
18289 case OPC_MINI_S_df:
18290 tcg_gen_movi_i32(timm, s5);
18291 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
18292 break;
18293 case OPC_MINI_U_df:
18294 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
18295 break;
18296 case OPC_CEQI_df:
18297 tcg_gen_movi_i32(timm, s5);
18298 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
18299 break;
18300 case OPC_CLTI_S_df:
18301 tcg_gen_movi_i32(timm, s5);
18302 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
18303 break;
18304 case OPC_CLTI_U_df:
18305 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
18306 break;
18307 case OPC_CLEI_S_df:
18308 tcg_gen_movi_i32(timm, s5);
18309 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
18310 break;
18311 case OPC_CLEI_U_df:
18312 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
18313 break;
18314 case OPC_LDI_df:
18316 int32_t s10 = sextract32(ctx->opcode, 11, 10);
18317 tcg_gen_movi_i32(timm, s10);
18318 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
18320 break;
18321 default:
18322 MIPS_INVAL("MSA instruction");
18323 generate_exception_end(ctx, EXCP_RI);
18324 break;
18327 tcg_temp_free_i32(tdf);
18328 tcg_temp_free_i32(twd);
18329 tcg_temp_free_i32(tws);
18330 tcg_temp_free_i32(timm);
18333 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
18335 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18336 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
18337 uint32_t df = 0, m = 0;
18338 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18339 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18341 TCGv_i32 tdf;
18342 TCGv_i32 tm;
18343 TCGv_i32 twd;
18344 TCGv_i32 tws;
18346 if ((dfm & 0x40) == 0x00) {
18347 m = dfm & 0x3f;
18348 df = DF_DOUBLE;
18349 } else if ((dfm & 0x60) == 0x40) {
18350 m = dfm & 0x1f;
18351 df = DF_WORD;
18352 } else if ((dfm & 0x70) == 0x60) {
18353 m = dfm & 0x0f;
18354 df = DF_HALF;
18355 } else if ((dfm & 0x78) == 0x70) {
18356 m = dfm & 0x7;
18357 df = DF_BYTE;
18358 } else {
18359 generate_exception_end(ctx, EXCP_RI);
18360 return;
18363 tdf = tcg_const_i32(df);
18364 tm = tcg_const_i32(m);
18365 twd = tcg_const_i32(wd);
18366 tws = tcg_const_i32(ws);
18368 switch (MASK_MSA_BIT(ctx->opcode)) {
18369 case OPC_SLLI_df:
18370 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
18371 break;
18372 case OPC_SRAI_df:
18373 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
18374 break;
18375 case OPC_SRLI_df:
18376 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
18377 break;
18378 case OPC_BCLRI_df:
18379 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
18380 break;
18381 case OPC_BSETI_df:
18382 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
18383 break;
18384 case OPC_BNEGI_df:
18385 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
18386 break;
18387 case OPC_BINSLI_df:
18388 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
18389 break;
18390 case OPC_BINSRI_df:
18391 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
18392 break;
18393 case OPC_SAT_S_df:
18394 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
18395 break;
18396 case OPC_SAT_U_df:
18397 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
18398 break;
18399 case OPC_SRARI_df:
18400 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
18401 break;
18402 case OPC_SRLRI_df:
18403 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
18404 break;
18405 default:
18406 MIPS_INVAL("MSA instruction");
18407 generate_exception_end(ctx, EXCP_RI);
18408 break;
18411 tcg_temp_free_i32(tdf);
18412 tcg_temp_free_i32(tm);
18413 tcg_temp_free_i32(twd);
18414 tcg_temp_free_i32(tws);
18417 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
18419 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18420 uint8_t df = (ctx->opcode >> 21) & 0x3;
18421 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18422 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18423 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18425 TCGv_i32 tdf = tcg_const_i32(df);
18426 TCGv_i32 twd = tcg_const_i32(wd);
18427 TCGv_i32 tws = tcg_const_i32(ws);
18428 TCGv_i32 twt = tcg_const_i32(wt);
18430 switch (MASK_MSA_3R(ctx->opcode)) {
18431 case OPC_SLL_df:
18432 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
18433 break;
18434 case OPC_ADDV_df:
18435 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
18436 break;
18437 case OPC_CEQ_df:
18438 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
18439 break;
18440 case OPC_ADD_A_df:
18441 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
18442 break;
18443 case OPC_SUBS_S_df:
18444 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
18445 break;
18446 case OPC_MULV_df:
18447 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
18448 break;
18449 case OPC_SLD_df:
18450 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
18451 break;
18452 case OPC_VSHF_df:
18453 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
18454 break;
18455 case OPC_SRA_df:
18456 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
18457 break;
18458 case OPC_SUBV_df:
18459 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
18460 break;
18461 case OPC_ADDS_A_df:
18462 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
18463 break;
18464 case OPC_SUBS_U_df:
18465 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
18466 break;
18467 case OPC_MADDV_df:
18468 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
18469 break;
18470 case OPC_SPLAT_df:
18471 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
18472 break;
18473 case OPC_SRAR_df:
18474 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
18475 break;
18476 case OPC_SRL_df:
18477 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
18478 break;
18479 case OPC_MAX_S_df:
18480 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
18481 break;
18482 case OPC_CLT_S_df:
18483 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
18484 break;
18485 case OPC_ADDS_S_df:
18486 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
18487 break;
18488 case OPC_SUBSUS_U_df:
18489 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
18490 break;
18491 case OPC_MSUBV_df:
18492 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
18493 break;
18494 case OPC_PCKEV_df:
18495 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
18496 break;
18497 case OPC_SRLR_df:
18498 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
18499 break;
18500 case OPC_BCLR_df:
18501 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
18502 break;
18503 case OPC_MAX_U_df:
18504 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
18505 break;
18506 case OPC_CLT_U_df:
18507 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
18508 break;
18509 case OPC_ADDS_U_df:
18510 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
18511 break;
18512 case OPC_SUBSUU_S_df:
18513 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
18514 break;
18515 case OPC_PCKOD_df:
18516 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
18517 break;
18518 case OPC_BSET_df:
18519 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
18520 break;
18521 case OPC_MIN_S_df:
18522 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
18523 break;
18524 case OPC_CLE_S_df:
18525 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
18526 break;
18527 case OPC_AVE_S_df:
18528 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
18529 break;
18530 case OPC_ASUB_S_df:
18531 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
18532 break;
18533 case OPC_DIV_S_df:
18534 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
18535 break;
18536 case OPC_ILVL_df:
18537 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
18538 break;
18539 case OPC_BNEG_df:
18540 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
18541 break;
18542 case OPC_MIN_U_df:
18543 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
18544 break;
18545 case OPC_CLE_U_df:
18546 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
18547 break;
18548 case OPC_AVE_U_df:
18549 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
18550 break;
18551 case OPC_ASUB_U_df:
18552 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
18553 break;
18554 case OPC_DIV_U_df:
18555 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
18556 break;
18557 case OPC_ILVR_df:
18558 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
18559 break;
18560 case OPC_BINSL_df:
18561 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
18562 break;
18563 case OPC_MAX_A_df:
18564 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
18565 break;
18566 case OPC_AVER_S_df:
18567 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
18568 break;
18569 case OPC_MOD_S_df:
18570 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
18571 break;
18572 case OPC_ILVEV_df:
18573 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
18574 break;
18575 case OPC_BINSR_df:
18576 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
18577 break;
18578 case OPC_MIN_A_df:
18579 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
18580 break;
18581 case OPC_AVER_U_df:
18582 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
18583 break;
18584 case OPC_MOD_U_df:
18585 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
18586 break;
18587 case OPC_ILVOD_df:
18588 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
18589 break;
18591 case OPC_DOTP_S_df:
18592 case OPC_DOTP_U_df:
18593 case OPC_DPADD_S_df:
18594 case OPC_DPADD_U_df:
18595 case OPC_DPSUB_S_df:
18596 case OPC_HADD_S_df:
18597 case OPC_DPSUB_U_df:
18598 case OPC_HADD_U_df:
18599 case OPC_HSUB_S_df:
18600 case OPC_HSUB_U_df:
18601 if (df == DF_BYTE) {
18602 generate_exception_end(ctx, EXCP_RI);
18603 break;
18605 switch (MASK_MSA_3R(ctx->opcode)) {
18606 case OPC_DOTP_S_df:
18607 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
18608 break;
18609 case OPC_DOTP_U_df:
18610 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
18611 break;
18612 case OPC_DPADD_S_df:
18613 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
18614 break;
18615 case OPC_DPADD_U_df:
18616 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
18617 break;
18618 case OPC_DPSUB_S_df:
18619 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
18620 break;
18621 case OPC_HADD_S_df:
18622 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
18623 break;
18624 case OPC_DPSUB_U_df:
18625 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
18626 break;
18627 case OPC_HADD_U_df:
18628 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
18629 break;
18630 case OPC_HSUB_S_df:
18631 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
18632 break;
18633 case OPC_HSUB_U_df:
18634 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
18635 break;
18637 break;
18638 default:
18639 MIPS_INVAL("MSA instruction");
18640 generate_exception_end(ctx, EXCP_RI);
18641 break;
18643 tcg_temp_free_i32(twd);
18644 tcg_temp_free_i32(tws);
18645 tcg_temp_free_i32(twt);
18646 tcg_temp_free_i32(tdf);
18649 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
18651 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
18652 uint8_t source = (ctx->opcode >> 11) & 0x1f;
18653 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
18654 TCGv telm = tcg_temp_new();
18655 TCGv_i32 tsr = tcg_const_i32(source);
18656 TCGv_i32 tdt = tcg_const_i32(dest);
18658 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
18659 case OPC_CTCMSA:
18660 gen_load_gpr(telm, source);
18661 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
18662 break;
18663 case OPC_CFCMSA:
18664 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
18665 gen_store_gpr(telm, dest);
18666 break;
18667 case OPC_MOVE_V:
18668 gen_helper_msa_move_v(cpu_env, tdt, tsr);
18669 break;
18670 default:
18671 MIPS_INVAL("MSA instruction");
18672 generate_exception_end(ctx, EXCP_RI);
18673 break;
18676 tcg_temp_free(telm);
18677 tcg_temp_free_i32(tdt);
18678 tcg_temp_free_i32(tsr);
18681 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
18682 uint32_t n)
18684 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18685 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18686 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18688 TCGv_i32 tws = tcg_const_i32(ws);
18689 TCGv_i32 twd = tcg_const_i32(wd);
18690 TCGv_i32 tn = tcg_const_i32(n);
18691 TCGv_i32 tdf = tcg_const_i32(df);
18693 switch (MASK_MSA_ELM(ctx->opcode)) {
18694 case OPC_SLDI_df:
18695 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
18696 break;
18697 case OPC_SPLATI_df:
18698 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
18699 break;
18700 case OPC_INSVE_df:
18701 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
18702 break;
18703 case OPC_COPY_S_df:
18704 case OPC_COPY_U_df:
18705 case OPC_INSERT_df:
18706 #if !defined(TARGET_MIPS64)
18707 /* Double format valid only for MIPS64 */
18708 if (df == DF_DOUBLE) {
18709 generate_exception_end(ctx, EXCP_RI);
18710 break;
18712 #endif
18713 switch (MASK_MSA_ELM(ctx->opcode)) {
18714 case OPC_COPY_S_df:
18715 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
18716 break;
18717 case OPC_COPY_U_df:
18718 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
18719 break;
18720 case OPC_INSERT_df:
18721 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
18722 break;
18724 break;
18725 default:
18726 MIPS_INVAL("MSA instruction");
18727 generate_exception_end(ctx, EXCP_RI);
18729 tcg_temp_free_i32(twd);
18730 tcg_temp_free_i32(tws);
18731 tcg_temp_free_i32(tn);
18732 tcg_temp_free_i32(tdf);
18735 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
18737 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
18738 uint32_t df = 0, n = 0;
18740 if ((dfn & 0x30) == 0x00) {
18741 n = dfn & 0x0f;
18742 df = DF_BYTE;
18743 } else if ((dfn & 0x38) == 0x20) {
18744 n = dfn & 0x07;
18745 df = DF_HALF;
18746 } else if ((dfn & 0x3c) == 0x30) {
18747 n = dfn & 0x03;
18748 df = DF_WORD;
18749 } else if ((dfn & 0x3e) == 0x38) {
18750 n = dfn & 0x01;
18751 df = DF_DOUBLE;
18752 } else if (dfn == 0x3E) {
18753 /* CTCMSA, CFCMSA, MOVE.V */
18754 gen_msa_elm_3e(env, ctx);
18755 return;
18756 } else {
18757 generate_exception_end(ctx, EXCP_RI);
18758 return;
18761 gen_msa_elm_df(env, ctx, df, n);
18764 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
18766 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18767 uint8_t df = (ctx->opcode >> 21) & 0x1;
18768 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18769 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18770 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18772 TCGv_i32 twd = tcg_const_i32(wd);
18773 TCGv_i32 tws = tcg_const_i32(ws);
18774 TCGv_i32 twt = tcg_const_i32(wt);
18775 TCGv_i32 tdf = tcg_temp_new_i32();
18777 /* adjust df value for floating-point instruction */
18778 tcg_gen_movi_i32(tdf, df + 2);
18780 switch (MASK_MSA_3RF(ctx->opcode)) {
18781 case OPC_FCAF_df:
18782 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
18783 break;
18784 case OPC_FADD_df:
18785 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
18786 break;
18787 case OPC_FCUN_df:
18788 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
18789 break;
18790 case OPC_FSUB_df:
18791 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
18792 break;
18793 case OPC_FCOR_df:
18794 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
18795 break;
18796 case OPC_FCEQ_df:
18797 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
18798 break;
18799 case OPC_FMUL_df:
18800 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
18801 break;
18802 case OPC_FCUNE_df:
18803 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
18804 break;
18805 case OPC_FCUEQ_df:
18806 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
18807 break;
18808 case OPC_FDIV_df:
18809 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
18810 break;
18811 case OPC_FCNE_df:
18812 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
18813 break;
18814 case OPC_FCLT_df:
18815 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
18816 break;
18817 case OPC_FMADD_df:
18818 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
18819 break;
18820 case OPC_MUL_Q_df:
18821 tcg_gen_movi_i32(tdf, df + 1);
18822 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
18823 break;
18824 case OPC_FCULT_df:
18825 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
18826 break;
18827 case OPC_FMSUB_df:
18828 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
18829 break;
18830 case OPC_MADD_Q_df:
18831 tcg_gen_movi_i32(tdf, df + 1);
18832 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
18833 break;
18834 case OPC_FCLE_df:
18835 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
18836 break;
18837 case OPC_MSUB_Q_df:
18838 tcg_gen_movi_i32(tdf, df + 1);
18839 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
18840 break;
18841 case OPC_FCULE_df:
18842 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
18843 break;
18844 case OPC_FEXP2_df:
18845 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
18846 break;
18847 case OPC_FSAF_df:
18848 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
18849 break;
18850 case OPC_FEXDO_df:
18851 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
18852 break;
18853 case OPC_FSUN_df:
18854 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
18855 break;
18856 case OPC_FSOR_df:
18857 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
18858 break;
18859 case OPC_FSEQ_df:
18860 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
18861 break;
18862 case OPC_FTQ_df:
18863 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
18864 break;
18865 case OPC_FSUNE_df:
18866 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
18867 break;
18868 case OPC_FSUEQ_df:
18869 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
18870 break;
18871 case OPC_FSNE_df:
18872 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
18873 break;
18874 case OPC_FSLT_df:
18875 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
18876 break;
18877 case OPC_FMIN_df:
18878 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
18879 break;
18880 case OPC_MULR_Q_df:
18881 tcg_gen_movi_i32(tdf, df + 1);
18882 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
18883 break;
18884 case OPC_FSULT_df:
18885 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
18886 break;
18887 case OPC_FMIN_A_df:
18888 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
18889 break;
18890 case OPC_MADDR_Q_df:
18891 tcg_gen_movi_i32(tdf, df + 1);
18892 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
18893 break;
18894 case OPC_FSLE_df:
18895 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
18896 break;
18897 case OPC_FMAX_df:
18898 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
18899 break;
18900 case OPC_MSUBR_Q_df:
18901 tcg_gen_movi_i32(tdf, df + 1);
18902 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
18903 break;
18904 case OPC_FSULE_df:
18905 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
18906 break;
18907 case OPC_FMAX_A_df:
18908 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
18909 break;
18910 default:
18911 MIPS_INVAL("MSA instruction");
18912 generate_exception_end(ctx, EXCP_RI);
18913 break;
18916 tcg_temp_free_i32(twd);
18917 tcg_temp_free_i32(tws);
18918 tcg_temp_free_i32(twt);
18919 tcg_temp_free_i32(tdf);
18922 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
18924 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18925 (op & (0x7 << 18)))
18926 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18927 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18928 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18929 uint8_t df = (ctx->opcode >> 16) & 0x3;
18930 TCGv_i32 twd = tcg_const_i32(wd);
18931 TCGv_i32 tws = tcg_const_i32(ws);
18932 TCGv_i32 twt = tcg_const_i32(wt);
18933 TCGv_i32 tdf = tcg_const_i32(df);
18935 switch (MASK_MSA_2R(ctx->opcode)) {
18936 case OPC_FILL_df:
18937 #if !defined(TARGET_MIPS64)
18938 /* Double format valid only for MIPS64 */
18939 if (df == DF_DOUBLE) {
18940 generate_exception_end(ctx, EXCP_RI);
18941 break;
18943 #endif
18944 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
18945 break;
18946 case OPC_PCNT_df:
18947 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
18948 break;
18949 case OPC_NLOC_df:
18950 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
18951 break;
18952 case OPC_NLZC_df:
18953 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
18954 break;
18955 default:
18956 MIPS_INVAL("MSA instruction");
18957 generate_exception_end(ctx, EXCP_RI);
18958 break;
18961 tcg_temp_free_i32(twd);
18962 tcg_temp_free_i32(tws);
18963 tcg_temp_free_i32(twt);
18964 tcg_temp_free_i32(tdf);
18967 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
18969 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18970 (op & (0xf << 17)))
18971 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18972 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18973 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18974 uint8_t df = (ctx->opcode >> 16) & 0x1;
18975 TCGv_i32 twd = tcg_const_i32(wd);
18976 TCGv_i32 tws = tcg_const_i32(ws);
18977 TCGv_i32 twt = tcg_const_i32(wt);
18978 /* adjust df value for floating-point instruction */
18979 TCGv_i32 tdf = tcg_const_i32(df + 2);
18981 switch (MASK_MSA_2RF(ctx->opcode)) {
18982 case OPC_FCLASS_df:
18983 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
18984 break;
18985 case OPC_FTRUNC_S_df:
18986 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
18987 break;
18988 case OPC_FTRUNC_U_df:
18989 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
18990 break;
18991 case OPC_FSQRT_df:
18992 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
18993 break;
18994 case OPC_FRSQRT_df:
18995 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
18996 break;
18997 case OPC_FRCP_df:
18998 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
18999 break;
19000 case OPC_FRINT_df:
19001 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
19002 break;
19003 case OPC_FLOG2_df:
19004 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
19005 break;
19006 case OPC_FEXUPL_df:
19007 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
19008 break;
19009 case OPC_FEXUPR_df:
19010 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
19011 break;
19012 case OPC_FFQL_df:
19013 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
19014 break;
19015 case OPC_FFQR_df:
19016 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
19017 break;
19018 case OPC_FTINT_S_df:
19019 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
19020 break;
19021 case OPC_FTINT_U_df:
19022 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
19023 break;
19024 case OPC_FFINT_S_df:
19025 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
19026 break;
19027 case OPC_FFINT_U_df:
19028 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
19029 break;
19032 tcg_temp_free_i32(twd);
19033 tcg_temp_free_i32(tws);
19034 tcg_temp_free_i32(twt);
19035 tcg_temp_free_i32(tdf);
19038 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
19040 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
19041 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19042 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19043 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19044 TCGv_i32 twd = tcg_const_i32(wd);
19045 TCGv_i32 tws = tcg_const_i32(ws);
19046 TCGv_i32 twt = tcg_const_i32(wt);
19048 switch (MASK_MSA_VEC(ctx->opcode)) {
19049 case OPC_AND_V:
19050 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
19051 break;
19052 case OPC_OR_V:
19053 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
19054 break;
19055 case OPC_NOR_V:
19056 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
19057 break;
19058 case OPC_XOR_V:
19059 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
19060 break;
19061 case OPC_BMNZ_V:
19062 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
19063 break;
19064 case OPC_BMZ_V:
19065 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
19066 break;
19067 case OPC_BSEL_V:
19068 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
19069 break;
19070 default:
19071 MIPS_INVAL("MSA instruction");
19072 generate_exception_end(ctx, EXCP_RI);
19073 break;
19076 tcg_temp_free_i32(twd);
19077 tcg_temp_free_i32(tws);
19078 tcg_temp_free_i32(twt);
19081 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
19083 switch (MASK_MSA_VEC(ctx->opcode)) {
19084 case OPC_AND_V:
19085 case OPC_OR_V:
19086 case OPC_NOR_V:
19087 case OPC_XOR_V:
19088 case OPC_BMNZ_V:
19089 case OPC_BMZ_V:
19090 case OPC_BSEL_V:
19091 gen_msa_vec_v(env, ctx);
19092 break;
19093 case OPC_MSA_2R:
19094 gen_msa_2r(env, ctx);
19095 break;
19096 case OPC_MSA_2RF:
19097 gen_msa_2rf(env, ctx);
19098 break;
19099 default:
19100 MIPS_INVAL("MSA instruction");
19101 generate_exception_end(ctx, EXCP_RI);
19102 break;
19106 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
19108 uint32_t opcode = ctx->opcode;
19109 check_insn(ctx, ASE_MSA);
19110 check_msa_access(ctx);
19112 switch (MASK_MSA_MINOR(opcode)) {
19113 case OPC_MSA_I8_00:
19114 case OPC_MSA_I8_01:
19115 case OPC_MSA_I8_02:
19116 gen_msa_i8(env, ctx);
19117 break;
19118 case OPC_MSA_I5_06:
19119 case OPC_MSA_I5_07:
19120 gen_msa_i5(env, ctx);
19121 break;
19122 case OPC_MSA_BIT_09:
19123 case OPC_MSA_BIT_0A:
19124 gen_msa_bit(env, ctx);
19125 break;
19126 case OPC_MSA_3R_0D:
19127 case OPC_MSA_3R_0E:
19128 case OPC_MSA_3R_0F:
19129 case OPC_MSA_3R_10:
19130 case OPC_MSA_3R_11:
19131 case OPC_MSA_3R_12:
19132 case OPC_MSA_3R_13:
19133 case OPC_MSA_3R_14:
19134 case OPC_MSA_3R_15:
19135 gen_msa_3r(env, ctx);
19136 break;
19137 case OPC_MSA_ELM:
19138 gen_msa_elm(env, ctx);
19139 break;
19140 case OPC_MSA_3RF_1A:
19141 case OPC_MSA_3RF_1B:
19142 case OPC_MSA_3RF_1C:
19143 gen_msa_3rf(env, ctx);
19144 break;
19145 case OPC_MSA_VEC:
19146 gen_msa_vec(env, ctx);
19147 break;
19148 case OPC_LD_B:
19149 case OPC_LD_H:
19150 case OPC_LD_W:
19151 case OPC_LD_D:
19152 case OPC_ST_B:
19153 case OPC_ST_H:
19154 case OPC_ST_W:
19155 case OPC_ST_D:
19157 int32_t s10 = sextract32(ctx->opcode, 16, 10);
19158 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
19159 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19160 uint8_t df = (ctx->opcode >> 0) & 0x3;
19162 TCGv_i32 twd = tcg_const_i32(wd);
19163 TCGv taddr = tcg_temp_new();
19164 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
19166 switch (MASK_MSA_MINOR(opcode)) {
19167 case OPC_LD_B:
19168 gen_helper_msa_ld_b(cpu_env, twd, taddr);
19169 break;
19170 case OPC_LD_H:
19171 gen_helper_msa_ld_h(cpu_env, twd, taddr);
19172 break;
19173 case OPC_LD_W:
19174 gen_helper_msa_ld_w(cpu_env, twd, taddr);
19175 break;
19176 case OPC_LD_D:
19177 gen_helper_msa_ld_d(cpu_env, twd, taddr);
19178 break;
19179 case OPC_ST_B:
19180 gen_helper_msa_st_b(cpu_env, twd, taddr);
19181 break;
19182 case OPC_ST_H:
19183 gen_helper_msa_st_h(cpu_env, twd, taddr);
19184 break;
19185 case OPC_ST_W:
19186 gen_helper_msa_st_w(cpu_env, twd, taddr);
19187 break;
19188 case OPC_ST_D:
19189 gen_helper_msa_st_d(cpu_env, twd, taddr);
19190 break;
19193 tcg_temp_free_i32(twd);
19194 tcg_temp_free(taddr);
19196 break;
19197 default:
19198 MIPS_INVAL("MSA instruction");
19199 generate_exception_end(ctx, EXCP_RI);
19200 break;
19205 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
19207 int32_t offset;
19208 int rs, rt, rd, sa;
19209 uint32_t op, op1;
19210 int16_t imm;
19212 /* make sure instructions are on a word boundary */
19213 if (ctx->pc & 0x3) {
19214 env->CP0_BadVAddr = ctx->pc;
19215 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
19216 return;
19219 /* Handle blikely not taken case */
19220 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
19221 TCGLabel *l1 = gen_new_label();
19223 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
19224 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
19225 gen_goto_tb(ctx, 1, ctx->pc + 4);
19226 gen_set_label(l1);
19229 op = MASK_OP_MAJOR(ctx->opcode);
19230 rs = (ctx->opcode >> 21) & 0x1f;
19231 rt = (ctx->opcode >> 16) & 0x1f;
19232 rd = (ctx->opcode >> 11) & 0x1f;
19233 sa = (ctx->opcode >> 6) & 0x1f;
19234 imm = (int16_t)ctx->opcode;
19235 switch (op) {
19236 case OPC_SPECIAL:
19237 decode_opc_special(env, ctx);
19238 break;
19239 case OPC_SPECIAL2:
19240 decode_opc_special2_legacy(env, ctx);
19241 break;
19242 case OPC_SPECIAL3:
19243 decode_opc_special3(env, ctx);
19244 break;
19245 case OPC_REGIMM:
19246 op1 = MASK_REGIMM(ctx->opcode);
19247 switch (op1) {
19248 case OPC_BLTZL: /* REGIMM branches */
19249 case OPC_BGEZL:
19250 case OPC_BLTZALL:
19251 case OPC_BGEZALL:
19252 check_insn(ctx, ISA_MIPS2);
19253 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19254 /* Fallthrough */
19255 case OPC_BLTZ:
19256 case OPC_BGEZ:
19257 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19258 break;
19259 case OPC_BLTZAL:
19260 case OPC_BGEZAL:
19261 if (ctx->insn_flags & ISA_MIPS32R6) {
19262 if (rs == 0) {
19263 /* OPC_NAL, OPC_BAL */
19264 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
19265 } else {
19266 generate_exception_end(ctx, EXCP_RI);
19268 } else {
19269 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19271 break;
19272 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
19273 case OPC_TNEI:
19274 check_insn(ctx, ISA_MIPS2);
19275 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19276 gen_trap(ctx, op1, rs, -1, imm);
19277 break;
19278 case OPC_SIGRIE:
19279 check_insn(ctx, ISA_MIPS32R6);
19280 generate_exception_end(ctx, EXCP_RI);
19281 break;
19282 case OPC_SYNCI:
19283 check_insn(ctx, ISA_MIPS32R2);
19284 /* Break the TB to be able to sync copied instructions
19285 immediately */
19286 ctx->bstate = BS_STOP;
19287 break;
19288 case OPC_BPOSGE32: /* MIPS DSP branch */
19289 #if defined(TARGET_MIPS64)
19290 case OPC_BPOSGE64:
19291 #endif
19292 check_dsp(ctx);
19293 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
19294 break;
19295 #if defined(TARGET_MIPS64)
19296 case OPC_DAHI:
19297 check_insn(ctx, ISA_MIPS32R6);
19298 check_mips_64(ctx);
19299 if (rs != 0) {
19300 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
19302 break;
19303 case OPC_DATI:
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 << 48);
19309 break;
19310 #endif
19311 default: /* Invalid */
19312 MIPS_INVAL("regimm");
19313 generate_exception_end(ctx, EXCP_RI);
19314 break;
19316 break;
19317 case OPC_CP0:
19318 check_cp0_enabled(ctx);
19319 op1 = MASK_CP0(ctx->opcode);
19320 switch (op1) {
19321 case OPC_MFC0:
19322 case OPC_MTC0:
19323 case OPC_MFTR:
19324 case OPC_MTTR:
19325 case OPC_MFHC0:
19326 case OPC_MTHC0:
19327 #if defined(TARGET_MIPS64)
19328 case OPC_DMFC0:
19329 case OPC_DMTC0:
19330 #endif
19331 #ifndef CONFIG_USER_ONLY
19332 gen_cp0(env, ctx, op1, rt, rd);
19333 #endif /* !CONFIG_USER_ONLY */
19334 break;
19335 case OPC_C0_FIRST ... OPC_C0_LAST:
19336 #ifndef CONFIG_USER_ONLY
19337 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
19338 #endif /* !CONFIG_USER_ONLY */
19339 break;
19340 case OPC_MFMC0:
19341 #ifndef CONFIG_USER_ONLY
19343 uint32_t op2;
19344 TCGv t0 = tcg_temp_new();
19346 op2 = MASK_MFMC0(ctx->opcode);
19347 switch (op2) {
19348 case OPC_DMT:
19349 check_insn(ctx, ASE_MT);
19350 gen_helper_dmt(t0);
19351 gen_store_gpr(t0, rt);
19352 break;
19353 case OPC_EMT:
19354 check_insn(ctx, ASE_MT);
19355 gen_helper_emt(t0);
19356 gen_store_gpr(t0, rt);
19357 break;
19358 case OPC_DVPE:
19359 check_insn(ctx, ASE_MT);
19360 gen_helper_dvpe(t0, cpu_env);
19361 gen_store_gpr(t0, rt);
19362 break;
19363 case OPC_EVPE:
19364 check_insn(ctx, ASE_MT);
19365 gen_helper_evpe(t0, cpu_env);
19366 gen_store_gpr(t0, rt);
19367 break;
19368 case OPC_DVP:
19369 check_insn(ctx, ISA_MIPS32R6);
19370 if (ctx->vp) {
19371 gen_helper_dvp(t0, cpu_env);
19372 gen_store_gpr(t0, rt);
19374 break;
19375 case OPC_EVP:
19376 check_insn(ctx, ISA_MIPS32R6);
19377 if (ctx->vp) {
19378 gen_helper_evp(t0, cpu_env);
19379 gen_store_gpr(t0, rt);
19381 break;
19382 case OPC_DI:
19383 check_insn(ctx, ISA_MIPS32R2);
19384 save_cpu_state(ctx, 1);
19385 gen_helper_di(t0, cpu_env);
19386 gen_store_gpr(t0, rt);
19387 /* Stop translation as we may have switched
19388 the execution mode. */
19389 ctx->bstate = BS_STOP;
19390 break;
19391 case OPC_EI:
19392 check_insn(ctx, ISA_MIPS32R2);
19393 save_cpu_state(ctx, 1);
19394 gen_helper_ei(t0, cpu_env);
19395 gen_store_gpr(t0, rt);
19396 /* Stop translation as we may have switched
19397 the execution mode. */
19398 ctx->bstate = BS_STOP;
19399 break;
19400 default: /* Invalid */
19401 MIPS_INVAL("mfmc0");
19402 generate_exception_end(ctx, EXCP_RI);
19403 break;
19405 tcg_temp_free(t0);
19407 #endif /* !CONFIG_USER_ONLY */
19408 break;
19409 case OPC_RDPGPR:
19410 check_insn(ctx, ISA_MIPS32R2);
19411 gen_load_srsgpr(rt, rd);
19412 break;
19413 case OPC_WRPGPR:
19414 check_insn(ctx, ISA_MIPS32R2);
19415 gen_store_srsgpr(rt, rd);
19416 break;
19417 default:
19418 MIPS_INVAL("cp0");
19419 generate_exception_end(ctx, EXCP_RI);
19420 break;
19422 break;
19423 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
19424 if (ctx->insn_flags & ISA_MIPS32R6) {
19425 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
19426 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19427 } else {
19428 /* OPC_ADDI */
19429 /* Arithmetic with immediate opcode */
19430 gen_arith_imm(ctx, op, rt, rs, imm);
19432 break;
19433 case OPC_ADDIU:
19434 gen_arith_imm(ctx, op, rt, rs, imm);
19435 break;
19436 case OPC_SLTI: /* Set on less than with immediate opcode */
19437 case OPC_SLTIU:
19438 gen_slt_imm(ctx, op, rt, rs, imm);
19439 break;
19440 case OPC_ANDI: /* Arithmetic with immediate opcode */
19441 case OPC_LUI: /* OPC_AUI */
19442 case OPC_ORI:
19443 case OPC_XORI:
19444 gen_logic_imm(ctx, op, rt, rs, imm);
19445 break;
19446 case OPC_J ... OPC_JAL: /* Jump */
19447 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19448 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19449 break;
19450 /* Branch */
19451 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
19452 if (ctx->insn_flags & ISA_MIPS32R6) {
19453 if (rt == 0) {
19454 generate_exception_end(ctx, EXCP_RI);
19455 break;
19457 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
19458 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19459 } else {
19460 /* OPC_BLEZL */
19461 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19463 break;
19464 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
19465 if (ctx->insn_flags & ISA_MIPS32R6) {
19466 if (rt == 0) {
19467 generate_exception_end(ctx, EXCP_RI);
19468 break;
19470 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
19471 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19472 } else {
19473 /* OPC_BGTZL */
19474 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19476 break;
19477 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
19478 if (rt == 0) {
19479 /* OPC_BLEZ */
19480 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19481 } else {
19482 check_insn(ctx, ISA_MIPS32R6);
19483 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
19484 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19486 break;
19487 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
19488 if (rt == 0) {
19489 /* OPC_BGTZ */
19490 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19491 } else {
19492 check_insn(ctx, ISA_MIPS32R6);
19493 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
19494 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19496 break;
19497 case OPC_BEQL:
19498 case OPC_BNEL:
19499 check_insn(ctx, ISA_MIPS2);
19500 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19501 /* Fallthrough */
19502 case OPC_BEQ:
19503 case OPC_BNE:
19504 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19505 break;
19506 case OPC_LL: /* Load and stores */
19507 check_insn(ctx, ISA_MIPS2);
19508 /* Fallthrough */
19509 case OPC_LWL:
19510 case OPC_LWR:
19511 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19512 /* Fallthrough */
19513 case OPC_LB ... OPC_LH:
19514 case OPC_LW ... OPC_LHU:
19515 gen_ld(ctx, op, rt, rs, imm);
19516 break;
19517 case OPC_SWL:
19518 case OPC_SWR:
19519 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19520 /* fall through */
19521 case OPC_SB ... OPC_SH:
19522 case OPC_SW:
19523 gen_st(ctx, op, rt, rs, imm);
19524 break;
19525 case OPC_SC:
19526 check_insn(ctx, ISA_MIPS2);
19527 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19528 gen_st_cond(ctx, op, rt, rs, imm);
19529 break;
19530 case OPC_CACHE:
19531 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19532 check_cp0_enabled(ctx);
19533 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
19534 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
19535 gen_cache_operation(ctx, rt, rs, imm);
19537 /* Treat as NOP. */
19538 break;
19539 case OPC_PREF:
19540 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19541 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
19542 /* Treat as NOP. */
19543 break;
19545 /* Floating point (COP1). */
19546 case OPC_LWC1:
19547 case OPC_LDC1:
19548 case OPC_SWC1:
19549 case OPC_SDC1:
19550 gen_cop1_ldst(ctx, op, rt, rs, imm);
19551 break;
19553 case OPC_CP1:
19554 op1 = MASK_CP1(ctx->opcode);
19556 switch (op1) {
19557 case OPC_MFHC1:
19558 case OPC_MTHC1:
19559 check_cp1_enabled(ctx);
19560 check_insn(ctx, ISA_MIPS32R2);
19561 case OPC_MFC1:
19562 case OPC_CFC1:
19563 case OPC_MTC1:
19564 case OPC_CTC1:
19565 check_cp1_enabled(ctx);
19566 gen_cp1(ctx, op1, rt, rd);
19567 break;
19568 #if defined(TARGET_MIPS64)
19569 case OPC_DMFC1:
19570 case OPC_DMTC1:
19571 check_cp1_enabled(ctx);
19572 check_insn(ctx, ISA_MIPS3);
19573 check_mips_64(ctx);
19574 gen_cp1(ctx, op1, rt, rd);
19575 break;
19576 #endif
19577 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
19578 check_cp1_enabled(ctx);
19579 if (ctx->insn_flags & ISA_MIPS32R6) {
19580 /* OPC_BC1EQZ */
19581 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19582 rt, imm << 2, 4);
19583 } else {
19584 /* OPC_BC1ANY2 */
19585 check_cop1x(ctx);
19586 check_insn(ctx, ASE_MIPS3D);
19587 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19588 (rt >> 2) & 0x7, imm << 2);
19590 break;
19591 case OPC_BC1NEZ:
19592 check_cp1_enabled(ctx);
19593 check_insn(ctx, ISA_MIPS32R6);
19594 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19595 rt, imm << 2, 4);
19596 break;
19597 case OPC_BC1ANY4:
19598 check_cp1_enabled(ctx);
19599 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19600 check_cop1x(ctx);
19601 check_insn(ctx, ASE_MIPS3D);
19602 /* fall through */
19603 case OPC_BC1:
19604 check_cp1_enabled(ctx);
19605 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19606 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19607 (rt >> 2) & 0x7, imm << 2);
19608 break;
19609 case OPC_PS_FMT:
19610 check_ps(ctx);
19611 /* fall through */
19612 case OPC_S_FMT:
19613 case OPC_D_FMT:
19614 check_cp1_enabled(ctx);
19615 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19616 (imm >> 8) & 0x7);
19617 break;
19618 case OPC_W_FMT:
19619 case OPC_L_FMT:
19621 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
19622 check_cp1_enabled(ctx);
19623 if (ctx->insn_flags & ISA_MIPS32R6) {
19624 switch (r6_op) {
19625 case R6_OPC_CMP_AF_S:
19626 case R6_OPC_CMP_UN_S:
19627 case R6_OPC_CMP_EQ_S:
19628 case R6_OPC_CMP_UEQ_S:
19629 case R6_OPC_CMP_LT_S:
19630 case R6_OPC_CMP_ULT_S:
19631 case R6_OPC_CMP_LE_S:
19632 case R6_OPC_CMP_ULE_S:
19633 case R6_OPC_CMP_SAF_S:
19634 case R6_OPC_CMP_SUN_S:
19635 case R6_OPC_CMP_SEQ_S:
19636 case R6_OPC_CMP_SEUQ_S:
19637 case R6_OPC_CMP_SLT_S:
19638 case R6_OPC_CMP_SULT_S:
19639 case R6_OPC_CMP_SLE_S:
19640 case R6_OPC_CMP_SULE_S:
19641 case R6_OPC_CMP_OR_S:
19642 case R6_OPC_CMP_UNE_S:
19643 case R6_OPC_CMP_NE_S:
19644 case R6_OPC_CMP_SOR_S:
19645 case R6_OPC_CMP_SUNE_S:
19646 case R6_OPC_CMP_SNE_S:
19647 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19648 break;
19649 case R6_OPC_CMP_AF_D:
19650 case R6_OPC_CMP_UN_D:
19651 case R6_OPC_CMP_EQ_D:
19652 case R6_OPC_CMP_UEQ_D:
19653 case R6_OPC_CMP_LT_D:
19654 case R6_OPC_CMP_ULT_D:
19655 case R6_OPC_CMP_LE_D:
19656 case R6_OPC_CMP_ULE_D:
19657 case R6_OPC_CMP_SAF_D:
19658 case R6_OPC_CMP_SUN_D:
19659 case R6_OPC_CMP_SEQ_D:
19660 case R6_OPC_CMP_SEUQ_D:
19661 case R6_OPC_CMP_SLT_D:
19662 case R6_OPC_CMP_SULT_D:
19663 case R6_OPC_CMP_SLE_D:
19664 case R6_OPC_CMP_SULE_D:
19665 case R6_OPC_CMP_OR_D:
19666 case R6_OPC_CMP_UNE_D:
19667 case R6_OPC_CMP_NE_D:
19668 case R6_OPC_CMP_SOR_D:
19669 case R6_OPC_CMP_SUNE_D:
19670 case R6_OPC_CMP_SNE_D:
19671 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19672 break;
19673 default:
19674 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
19675 rt, rd, sa, (imm >> 8) & 0x7);
19677 break;
19679 } else {
19680 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19681 (imm >> 8) & 0x7);
19683 break;
19685 case OPC_BZ_V:
19686 case OPC_BNZ_V:
19687 case OPC_BZ_B:
19688 case OPC_BZ_H:
19689 case OPC_BZ_W:
19690 case OPC_BZ_D:
19691 case OPC_BNZ_B:
19692 case OPC_BNZ_H:
19693 case OPC_BNZ_W:
19694 case OPC_BNZ_D:
19695 check_insn(ctx, ASE_MSA);
19696 gen_msa_branch(env, ctx, op1);
19697 break;
19698 default:
19699 MIPS_INVAL("cp1");
19700 generate_exception_end(ctx, EXCP_RI);
19701 break;
19703 break;
19705 /* Compact branches [R6] and COP2 [non-R6] */
19706 case OPC_BC: /* OPC_LWC2 */
19707 case OPC_BALC: /* OPC_SWC2 */
19708 if (ctx->insn_flags & ISA_MIPS32R6) {
19709 /* OPC_BC, OPC_BALC */
19710 gen_compute_compact_branch(ctx, op, 0, 0,
19711 sextract32(ctx->opcode << 2, 0, 28));
19712 } else {
19713 /* OPC_LWC2, OPC_SWC2 */
19714 /* COP2: Not implemented. */
19715 generate_exception_err(ctx, EXCP_CpU, 2);
19717 break;
19718 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
19719 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
19720 if (ctx->insn_flags & ISA_MIPS32R6) {
19721 if (rs != 0) {
19722 /* OPC_BEQZC, OPC_BNEZC */
19723 gen_compute_compact_branch(ctx, op, rs, 0,
19724 sextract32(ctx->opcode << 2, 0, 23));
19725 } else {
19726 /* OPC_JIC, OPC_JIALC */
19727 gen_compute_compact_branch(ctx, op, 0, rt, imm);
19729 } else {
19730 /* OPC_LWC2, OPC_SWC2 */
19731 /* COP2: Not implemented. */
19732 generate_exception_err(ctx, EXCP_CpU, 2);
19734 break;
19735 case OPC_CP2:
19736 check_insn(ctx, INSN_LOONGSON2F);
19737 /* Note that these instructions use different fields. */
19738 gen_loongson_multimedia(ctx, sa, rd, rt);
19739 break;
19741 case OPC_CP3:
19742 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19743 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19744 check_cp1_enabled(ctx);
19745 op1 = MASK_CP3(ctx->opcode);
19746 switch (op1) {
19747 case OPC_LUXC1:
19748 case OPC_SUXC1:
19749 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19750 /* Fallthrough */
19751 case OPC_LWXC1:
19752 case OPC_LDXC1:
19753 case OPC_SWXC1:
19754 case OPC_SDXC1:
19755 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19756 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
19757 break;
19758 case OPC_PREFX:
19759 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19760 /* Treat as NOP. */
19761 break;
19762 case OPC_ALNV_PS:
19763 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19764 /* Fallthrough */
19765 case OPC_MADD_S:
19766 case OPC_MADD_D:
19767 case OPC_MADD_PS:
19768 case OPC_MSUB_S:
19769 case OPC_MSUB_D:
19770 case OPC_MSUB_PS:
19771 case OPC_NMADD_S:
19772 case OPC_NMADD_D:
19773 case OPC_NMADD_PS:
19774 case OPC_NMSUB_S:
19775 case OPC_NMSUB_D:
19776 case OPC_NMSUB_PS:
19777 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19778 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
19779 break;
19780 default:
19781 MIPS_INVAL("cp3");
19782 generate_exception_end(ctx, EXCP_RI);
19783 break;
19785 } else {
19786 generate_exception_err(ctx, EXCP_CpU, 1);
19788 break;
19790 #if defined(TARGET_MIPS64)
19791 /* MIPS64 opcodes */
19792 case OPC_LDL ... OPC_LDR:
19793 case OPC_LLD:
19794 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19795 /* fall through */
19796 case OPC_LWU:
19797 case OPC_LD:
19798 check_insn(ctx, ISA_MIPS3);
19799 check_mips_64(ctx);
19800 gen_ld(ctx, op, rt, rs, imm);
19801 break;
19802 case OPC_SDL ... OPC_SDR:
19803 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19804 /* fall through */
19805 case OPC_SD:
19806 check_insn(ctx, ISA_MIPS3);
19807 check_mips_64(ctx);
19808 gen_st(ctx, op, rt, rs, imm);
19809 break;
19810 case OPC_SCD:
19811 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19812 check_insn(ctx, ISA_MIPS3);
19813 check_mips_64(ctx);
19814 gen_st_cond(ctx, op, rt, rs, imm);
19815 break;
19816 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
19817 if (ctx->insn_flags & ISA_MIPS32R6) {
19818 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
19819 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19820 } else {
19821 /* OPC_DADDI */
19822 check_insn(ctx, ISA_MIPS3);
19823 check_mips_64(ctx);
19824 gen_arith_imm(ctx, op, rt, rs, imm);
19826 break;
19827 case OPC_DADDIU:
19828 check_insn(ctx, ISA_MIPS3);
19829 check_mips_64(ctx);
19830 gen_arith_imm(ctx, op, rt, rs, imm);
19831 break;
19832 #else
19833 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
19834 if (ctx->insn_flags & ISA_MIPS32R6) {
19835 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19836 } else {
19837 MIPS_INVAL("major opcode");
19838 generate_exception_end(ctx, EXCP_RI);
19840 break;
19841 #endif
19842 case OPC_DAUI: /* OPC_JALX */
19843 if (ctx->insn_flags & ISA_MIPS32R6) {
19844 #if defined(TARGET_MIPS64)
19845 /* OPC_DAUI */
19846 check_mips_64(ctx);
19847 if (rs == 0) {
19848 generate_exception(ctx, EXCP_RI);
19849 } else if (rt != 0) {
19850 TCGv t0 = tcg_temp_new();
19851 gen_load_gpr(t0, rs);
19852 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
19853 tcg_temp_free(t0);
19855 #else
19856 generate_exception_end(ctx, EXCP_RI);
19857 MIPS_INVAL("major opcode");
19858 #endif
19859 } else {
19860 /* OPC_JALX */
19861 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
19862 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19863 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19865 break;
19866 case OPC_MSA: /* OPC_MDMX */
19867 /* MDMX: Not implemented. */
19868 gen_msa(env, ctx);
19869 break;
19870 case OPC_PCREL:
19871 check_insn(ctx, ISA_MIPS32R6);
19872 gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
19873 break;
19874 default: /* Invalid */
19875 MIPS_INVAL("major opcode");
19876 generate_exception_end(ctx, EXCP_RI);
19877 break;
19881 void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
19883 MIPSCPU *cpu = mips_env_get_cpu(env);
19884 CPUState *cs = CPU(cpu);
19885 DisasContext ctx;
19886 target_ulong pc_start;
19887 target_ulong next_page_start;
19888 int num_insns;
19889 int max_insns;
19890 int insn_bytes;
19891 int is_slot;
19893 pc_start = tb->pc;
19894 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
19895 ctx.pc = pc_start;
19896 ctx.saved_pc = -1;
19897 ctx.singlestep_enabled = cs->singlestep_enabled;
19898 ctx.insn_flags = env->insn_flags;
19899 ctx.CP0_Config1 = env->CP0_Config1;
19900 ctx.tb = tb;
19901 ctx.bstate = BS_NONE;
19902 ctx.btarget = 0;
19903 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
19904 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
19905 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
19906 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
19907 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
19908 ctx.PAMask = env->PAMask;
19909 ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
19910 ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
19911 ctx.cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
19912 /* Restore delay slot state from the tb context. */
19913 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
19914 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
19915 ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
19916 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
19917 ctx.vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
19918 ctx.mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
19919 ctx.nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
19920 ctx.abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
19921 restore_cpu_state(env, &ctx);
19922 #ifdef CONFIG_USER_ONLY
19923 ctx.mem_idx = MIPS_HFLAG_UM;
19924 #else
19925 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
19926 #endif
19927 ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
19928 MO_UNALN : MO_ALIGN;
19929 num_insns = 0;
19930 max_insns = tb->cflags & CF_COUNT_MASK;
19931 if (max_insns == 0) {
19932 max_insns = CF_COUNT_MASK;
19934 if (max_insns > TCG_MAX_INSNS) {
19935 max_insns = TCG_MAX_INSNS;
19938 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
19939 gen_tb_start(tb);
19940 while (ctx.bstate == BS_NONE) {
19941 tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
19942 num_insns++;
19944 if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
19945 save_cpu_state(&ctx, 1);
19946 ctx.bstate = BS_BRANCH;
19947 gen_helper_raise_exception_debug(cpu_env);
19948 /* The address covered by the breakpoint must be included in
19949 [tb->pc, tb->pc + tb->size) in order to for it to be
19950 properly cleared -- thus we increment the PC here so that
19951 the logic setting tb->size below does the right thing. */
19952 ctx.pc += 4;
19953 goto done_generating;
19956 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
19957 gen_io_start();
19960 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
19961 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
19962 ctx.opcode = cpu_ldl_code(env, ctx.pc);
19963 insn_bytes = 4;
19964 decode_opc(env, &ctx);
19965 } else if (ctx.insn_flags & ASE_MICROMIPS) {
19966 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19967 insn_bytes = decode_micromips_opc(env, &ctx);
19968 } else if (ctx.insn_flags & ASE_MIPS16) {
19969 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19970 insn_bytes = decode_mips16_opc(env, &ctx);
19971 } else {
19972 generate_exception_end(&ctx, EXCP_RI);
19973 break;
19976 if (ctx.hflags & MIPS_HFLAG_BMASK) {
19977 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
19978 MIPS_HFLAG_FBNSLOT))) {
19979 /* force to generate branch as there is neither delay nor
19980 forbidden slot */
19981 is_slot = 1;
19983 if ((ctx.hflags & MIPS_HFLAG_M16) &&
19984 (ctx.hflags & MIPS_HFLAG_FBNSLOT)) {
19985 /* Force to generate branch as microMIPS R6 doesn't restrict
19986 branches in the forbidden slot. */
19987 is_slot = 1;
19990 if (is_slot) {
19991 gen_branch(&ctx, insn_bytes);
19993 ctx.pc += insn_bytes;
19995 /* Execute a branch and its delay slot as a single instruction.
19996 This is what GDB expects and is consistent with what the
19997 hardware does (e.g. if a delay slot instruction faults, the
19998 reported PC is the PC of the branch). */
19999 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
20000 break;
20003 if (ctx.pc >= next_page_start) {
20004 break;
20007 if (tcg_op_buf_full()) {
20008 break;
20011 if (num_insns >= max_insns)
20012 break;
20014 if (singlestep)
20015 break;
20017 if (tb->cflags & CF_LAST_IO) {
20018 gen_io_end();
20020 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
20021 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
20022 gen_helper_raise_exception_debug(cpu_env);
20023 } else {
20024 switch (ctx.bstate) {
20025 case BS_STOP:
20026 gen_goto_tb(&ctx, 0, ctx.pc);
20027 break;
20028 case BS_NONE:
20029 save_cpu_state(&ctx, 0);
20030 gen_goto_tb(&ctx, 0, ctx.pc);
20031 break;
20032 case BS_EXCP:
20033 tcg_gen_exit_tb(0);
20034 break;
20035 case BS_BRANCH:
20036 default:
20037 break;
20040 done_generating:
20041 gen_tb_end(tb, num_insns);
20043 tb->size = ctx.pc - pc_start;
20044 tb->icount = num_insns;
20046 #ifdef DEBUG_DISAS
20047 LOG_DISAS("\n");
20048 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
20049 && qemu_log_in_addr_range(pc_start)) {
20050 qemu_log_lock();
20051 qemu_log("IN: %s\n", lookup_symbol(pc_start));
20052 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
20053 qemu_log("\n");
20054 qemu_log_unlock();
20056 #endif
20059 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
20060 int flags)
20062 int i;
20063 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
20065 #define printfpr(fp) \
20066 do { \
20067 if (is_fpu64) \
20068 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20069 " fd:%13g fs:%13g psu: %13g\n", \
20070 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
20071 (double)(fp)->fd, \
20072 (double)(fp)->fs[FP_ENDIAN_IDX], \
20073 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
20074 else { \
20075 fpr_t tmp; \
20076 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
20077 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
20078 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20079 " fd:%13g fs:%13g psu:%13g\n", \
20080 tmp.w[FP_ENDIAN_IDX], tmp.d, \
20081 (double)tmp.fd, \
20082 (double)tmp.fs[FP_ENDIAN_IDX], \
20083 (double)tmp.fs[!FP_ENDIAN_IDX]); \
20085 } while(0)
20088 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
20089 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
20090 get_float_exception_flags(&env->active_fpu.fp_status));
20091 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
20092 fpu_fprintf(f, "%3s: ", fregnames[i]);
20093 printfpr(&env->active_fpu.fpr[i]);
20096 #undef printfpr
20099 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
20100 int flags)
20102 MIPSCPU *cpu = MIPS_CPU(cs);
20103 CPUMIPSState *env = &cpu->env;
20104 int i;
20106 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
20107 " LO=0x" TARGET_FMT_lx " ds %04x "
20108 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
20109 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
20110 env->hflags, env->btarget, env->bcond);
20111 for (i = 0; i < 32; i++) {
20112 if ((i & 3) == 0)
20113 cpu_fprintf(f, "GPR%02d:", i);
20114 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
20115 if ((i & 3) == 3)
20116 cpu_fprintf(f, "\n");
20119 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
20120 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
20121 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
20122 PRIx64 "\n",
20123 env->CP0_Config0, env->CP0_Config1, env->lladdr);
20124 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
20125 env->CP0_Config2, env->CP0_Config3);
20126 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
20127 env->CP0_Config4, env->CP0_Config5);
20128 if (env->hflags & MIPS_HFLAG_FPU)
20129 fpu_dump_state(env, f, cpu_fprintf, flags);
20132 void mips_tcg_init(void)
20134 int i;
20135 static int inited;
20137 /* Initialize various static tables. */
20138 if (inited)
20139 return;
20141 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
20142 tcg_ctx.tcg_env = cpu_env;
20144 TCGV_UNUSED(cpu_gpr[0]);
20145 for (i = 1; i < 32; i++)
20146 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
20147 offsetof(CPUMIPSState, active_tc.gpr[i]),
20148 regnames[i]);
20150 for (i = 0; i < 32; i++) {
20151 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
20152 msa_wr_d[i * 2] =
20153 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
20154 /* The scalar floating-point unit (FPU) registers are mapped on
20155 * the MSA vector registers. */
20156 fpu_f64[i] = msa_wr_d[i * 2];
20157 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
20158 msa_wr_d[i * 2 + 1] =
20159 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
20162 cpu_PC = tcg_global_mem_new(cpu_env,
20163 offsetof(CPUMIPSState, active_tc.PC), "PC");
20164 for (i = 0; i < MIPS_DSP_ACC; i++) {
20165 cpu_HI[i] = tcg_global_mem_new(cpu_env,
20166 offsetof(CPUMIPSState, active_tc.HI[i]),
20167 regnames_HI[i]);
20168 cpu_LO[i] = tcg_global_mem_new(cpu_env,
20169 offsetof(CPUMIPSState, active_tc.LO[i]),
20170 regnames_LO[i]);
20172 cpu_dspctrl = tcg_global_mem_new(cpu_env,
20173 offsetof(CPUMIPSState, active_tc.DSPControl),
20174 "DSPControl");
20175 bcond = tcg_global_mem_new(cpu_env,
20176 offsetof(CPUMIPSState, bcond), "bcond");
20177 btarget = tcg_global_mem_new(cpu_env,
20178 offsetof(CPUMIPSState, btarget), "btarget");
20179 hflags = tcg_global_mem_new_i32(cpu_env,
20180 offsetof(CPUMIPSState, hflags), "hflags");
20182 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
20183 offsetof(CPUMIPSState, active_fpu.fcr0),
20184 "fcr0");
20185 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
20186 offsetof(CPUMIPSState, active_fpu.fcr31),
20187 "fcr31");
20189 inited = 1;
20192 #include "translate_init.c"
20194 MIPSCPU *cpu_mips_init(const char *cpu_model)
20196 MIPSCPU *cpu;
20197 CPUMIPSState *env;
20198 const mips_def_t *def;
20200 def = cpu_mips_find_by_name(cpu_model);
20201 if (!def)
20202 return NULL;
20203 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
20204 env = &cpu->env;
20205 env->cpu_model = def;
20206 env->exception_base = (int32_t)0xBFC00000;
20208 #ifndef CONFIG_USER_ONLY
20209 mmu_init(env, def);
20210 #endif
20211 fpu_init(env, def);
20212 mvp_init(env, def);
20214 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
20216 return cpu;
20219 bool cpu_supports_cps_smp(const char *cpu_model)
20221 const mips_def_t *def = cpu_mips_find_by_name(cpu_model);
20222 if (!def) {
20223 return false;
20226 return (def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
20229 bool cpu_supports_isa(const char *cpu_model, unsigned int isa)
20231 const mips_def_t *def = cpu_mips_find_by_name(cpu_model);
20232 if (!def) {
20233 return false;
20236 return (def->insn_flags & isa) != 0;
20239 void cpu_set_exception_base(int vp_index, target_ulong address)
20241 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
20242 vp->env.exception_base = address;
20245 void cpu_state_reset(CPUMIPSState *env)
20247 MIPSCPU *cpu = mips_env_get_cpu(env);
20248 CPUState *cs = CPU(cpu);
20250 /* Reset registers to their default values */
20251 env->CP0_PRid = env->cpu_model->CP0_PRid;
20252 env->CP0_Config0 = env->cpu_model->CP0_Config0;
20253 #ifdef TARGET_WORDS_BIGENDIAN
20254 env->CP0_Config0 |= (1 << CP0C0_BE);
20255 #endif
20256 env->CP0_Config1 = env->cpu_model->CP0_Config1;
20257 env->CP0_Config2 = env->cpu_model->CP0_Config2;
20258 env->CP0_Config3 = env->cpu_model->CP0_Config3;
20259 env->CP0_Config4 = env->cpu_model->CP0_Config4;
20260 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
20261 env->CP0_Config5 = env->cpu_model->CP0_Config5;
20262 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
20263 env->CP0_Config6 = env->cpu_model->CP0_Config6;
20264 env->CP0_Config7 = env->cpu_model->CP0_Config7;
20265 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
20266 << env->cpu_model->CP0_LLAddr_shift;
20267 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
20268 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
20269 env->CCRes = env->cpu_model->CCRes;
20270 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
20271 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
20272 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
20273 env->current_tc = 0;
20274 env->SEGBITS = env->cpu_model->SEGBITS;
20275 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
20276 #if defined(TARGET_MIPS64)
20277 if (env->cpu_model->insn_flags & ISA_MIPS3) {
20278 env->SEGMask |= 3ULL << 62;
20280 #endif
20281 env->PABITS = env->cpu_model->PABITS;
20282 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
20283 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
20284 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
20285 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
20286 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
20287 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
20288 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
20289 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
20290 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
20291 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
20292 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
20293 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
20294 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
20295 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
20296 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
20297 env->msair = env->cpu_model->MSAIR;
20298 env->insn_flags = env->cpu_model->insn_flags;
20300 #if defined(CONFIG_USER_ONLY)
20301 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
20302 # ifdef TARGET_MIPS64
20303 /* Enable 64-bit register mode. */
20304 env->CP0_Status |= (1 << CP0St_PX);
20305 # endif
20306 # ifdef TARGET_ABI_MIPSN64
20307 /* Enable 64-bit address mode. */
20308 env->CP0_Status |= (1 << CP0St_UX);
20309 # endif
20310 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
20311 hardware registers. */
20312 env->CP0_HWREna |= 0x0000000F;
20313 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
20314 env->CP0_Status |= (1 << CP0St_CU1);
20316 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
20317 env->CP0_Status |= (1 << CP0St_MX);
20319 # if defined(TARGET_MIPS64)
20320 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
20321 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
20322 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
20323 env->CP0_Status |= (1 << CP0St_FR);
20325 # endif
20326 #else
20327 if (env->hflags & MIPS_HFLAG_BMASK) {
20328 /* If the exception was raised from a delay slot,
20329 come back to the jump. */
20330 env->CP0_ErrorEPC = (env->active_tc.PC
20331 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
20332 } else {
20333 env->CP0_ErrorEPC = env->active_tc.PC;
20335 env->active_tc.PC = env->exception_base;
20336 env->CP0_Random = env->tlb->nb_tlb - 1;
20337 env->tlb->tlb_in_use = env->tlb->nb_tlb;
20338 env->CP0_Wired = 0;
20339 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
20340 env->CP0_EBase = (cs->cpu_index & 0x3FF);
20341 if (kvm_enabled()) {
20342 env->CP0_EBase |= 0x40000000;
20343 } else {
20344 env->CP0_EBase |= 0x80000000;
20346 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
20347 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
20349 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
20350 0x3ff : 0xff;
20351 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
20352 /* vectored interrupts not implemented, timer on int 7,
20353 no performance counters. */
20354 env->CP0_IntCtl = 0xe0000000;
20356 int i;
20358 for (i = 0; i < 7; i++) {
20359 env->CP0_WatchLo[i] = 0;
20360 env->CP0_WatchHi[i] = 0x80000000;
20362 env->CP0_WatchLo[7] = 0;
20363 env->CP0_WatchHi[7] = 0;
20365 /* Count register increments in debug mode, EJTAG version 1 */
20366 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
20368 cpu_mips_store_count(env, 1);
20370 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
20371 int i;
20373 /* Only TC0 on VPE 0 starts as active. */
20374 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
20375 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
20376 env->tcs[i].CP0_TCHalt = 1;
20378 env->active_tc.CP0_TCHalt = 1;
20379 cs->halted = 1;
20381 if (cs->cpu_index == 0) {
20382 /* VPE0 starts up enabled. */
20383 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
20384 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
20386 /* TC0 starts up unhalted. */
20387 cs->halted = 0;
20388 env->active_tc.CP0_TCHalt = 0;
20389 env->tcs[0].CP0_TCHalt = 0;
20390 /* With thread 0 active. */
20391 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
20392 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
20395 #endif
20396 if ((env->insn_flags & ISA_MIPS32R6) &&
20397 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
20398 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
20399 env->CP0_Status |= (1 << CP0St_FR);
20402 /* MSA */
20403 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
20404 msa_reset(env);
20407 compute_hflags(env);
20408 restore_fp_status(env);
20409 restore_pamask(env);
20410 cs->exception_index = EXCP_NONE;
20412 if (semihosting_get_argc()) {
20413 /* UHI interface can be used to obtain argc and argv */
20414 env->active_tc.gpr[4] = -1;
20418 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
20419 target_ulong *data)
20421 env->active_tc.PC = data[0];
20422 env->hflags &= ~MIPS_HFLAG_BMASK;
20423 env->hflags |= data[1];
20424 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
20425 case MIPS_HFLAG_BR:
20426 break;
20427 case MIPS_HFLAG_BC:
20428 case MIPS_HFLAG_BL:
20429 case MIPS_HFLAG_B:
20430 env->btarget = data[2];
20431 break;