target-mips: make ITC Configuration Tags accessible to the CPU
[qemu/ar7.git] / target-mips / translate.c
blob592e4e3cd03cda9663771d7ab6d8f26838d9787b
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 "tcg-op.h"
28 #include "exec/cpu_ldst.h"
30 #include "exec/helper-proto.h"
31 #include "exec/helper-gen.h"
32 #include "sysemu/kvm.h"
33 #include "exec/semihost.h"
35 #include "trace-tcg.h"
36 #include "exec/log.h"
38 #define MIPS_DEBUG_DISAS 0
40 /* MIPS major opcodes */
41 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
43 enum {
44 /* indirect opcode tables */
45 OPC_SPECIAL = (0x00 << 26),
46 OPC_REGIMM = (0x01 << 26),
47 OPC_CP0 = (0x10 << 26),
48 OPC_CP1 = (0x11 << 26),
49 OPC_CP2 = (0x12 << 26),
50 OPC_CP3 = (0x13 << 26),
51 OPC_SPECIAL2 = (0x1C << 26),
52 OPC_SPECIAL3 = (0x1F << 26),
53 /* arithmetic with immediate */
54 OPC_ADDI = (0x08 << 26),
55 OPC_ADDIU = (0x09 << 26),
56 OPC_SLTI = (0x0A << 26),
57 OPC_SLTIU = (0x0B << 26),
58 /* logic with immediate */
59 OPC_ANDI = (0x0C << 26),
60 OPC_ORI = (0x0D << 26),
61 OPC_XORI = (0x0E << 26),
62 OPC_LUI = (0x0F << 26),
63 /* arithmetic with immediate */
64 OPC_DADDI = (0x18 << 26),
65 OPC_DADDIU = (0x19 << 26),
66 /* Jump and branches */
67 OPC_J = (0x02 << 26),
68 OPC_JAL = (0x03 << 26),
69 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
70 OPC_BEQL = (0x14 << 26),
71 OPC_BNE = (0x05 << 26),
72 OPC_BNEL = (0x15 << 26),
73 OPC_BLEZ = (0x06 << 26),
74 OPC_BLEZL = (0x16 << 26),
75 OPC_BGTZ = (0x07 << 26),
76 OPC_BGTZL = (0x17 << 26),
77 OPC_JALX = (0x1D << 26),
78 OPC_DAUI = (0x1D << 26),
79 /* Load and stores */
80 OPC_LDL = (0x1A << 26),
81 OPC_LDR = (0x1B << 26),
82 OPC_LB = (0x20 << 26),
83 OPC_LH = (0x21 << 26),
84 OPC_LWL = (0x22 << 26),
85 OPC_LW = (0x23 << 26),
86 OPC_LWPC = OPC_LW | 0x5,
87 OPC_LBU = (0x24 << 26),
88 OPC_LHU = (0x25 << 26),
89 OPC_LWR = (0x26 << 26),
90 OPC_LWU = (0x27 << 26),
91 OPC_SB = (0x28 << 26),
92 OPC_SH = (0x29 << 26),
93 OPC_SWL = (0x2A << 26),
94 OPC_SW = (0x2B << 26),
95 OPC_SDL = (0x2C << 26),
96 OPC_SDR = (0x2D << 26),
97 OPC_SWR = (0x2E << 26),
98 OPC_LL = (0x30 << 26),
99 OPC_LLD = (0x34 << 26),
100 OPC_LD = (0x37 << 26),
101 OPC_LDPC = OPC_LD | 0x5,
102 OPC_SC = (0x38 << 26),
103 OPC_SCD = (0x3C << 26),
104 OPC_SD = (0x3F << 26),
105 /* Floating point load/store */
106 OPC_LWC1 = (0x31 << 26),
107 OPC_LWC2 = (0x32 << 26),
108 OPC_LDC1 = (0x35 << 26),
109 OPC_LDC2 = (0x36 << 26),
110 OPC_SWC1 = (0x39 << 26),
111 OPC_SWC2 = (0x3A << 26),
112 OPC_SDC1 = (0x3D << 26),
113 OPC_SDC2 = (0x3E << 26),
114 /* Compact Branches */
115 OPC_BLEZALC = (0x06 << 26),
116 OPC_BGEZALC = (0x06 << 26),
117 OPC_BGEUC = (0x06 << 26),
118 OPC_BGTZALC = (0x07 << 26),
119 OPC_BLTZALC = (0x07 << 26),
120 OPC_BLTUC = (0x07 << 26),
121 OPC_BOVC = (0x08 << 26),
122 OPC_BEQZALC = (0x08 << 26),
123 OPC_BEQC = (0x08 << 26),
124 OPC_BLEZC = (0x16 << 26),
125 OPC_BGEZC = (0x16 << 26),
126 OPC_BGEC = (0x16 << 26),
127 OPC_BGTZC = (0x17 << 26),
128 OPC_BLTZC = (0x17 << 26),
129 OPC_BLTC = (0x17 << 26),
130 OPC_BNVC = (0x18 << 26),
131 OPC_BNEZALC = (0x18 << 26),
132 OPC_BNEC = (0x18 << 26),
133 OPC_BC = (0x32 << 26),
134 OPC_BEQZC = (0x36 << 26),
135 OPC_JIC = (0x36 << 26),
136 OPC_BALC = (0x3A << 26),
137 OPC_BNEZC = (0x3E << 26),
138 OPC_JIALC = (0x3E << 26),
139 /* MDMX ASE specific */
140 OPC_MDMX = (0x1E << 26),
141 /* MSA ASE, same as MDMX */
142 OPC_MSA = OPC_MDMX,
143 /* Cache and prefetch */
144 OPC_CACHE = (0x2F << 26),
145 OPC_PREF = (0x33 << 26),
146 /* PC-relative address computation / loads */
147 OPC_PCREL = (0x3B << 26),
150 /* PC-relative address computation / loads */
151 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
152 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
153 enum {
154 /* Instructions determined by bits 19 and 20 */
155 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
156 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
157 OPC_LWUPC = OPC_PCREL | (2 << 19),
159 /* Instructions determined by bits 16 ... 20 */
160 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
161 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
163 /* Other */
164 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
167 /* MIPS special opcodes */
168 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
170 enum {
171 /* Shifts */
172 OPC_SLL = 0x00 | OPC_SPECIAL,
173 /* NOP is SLL r0, r0, 0 */
174 /* SSNOP is SLL r0, r0, 1 */
175 /* EHB is SLL r0, r0, 3 */
176 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
177 OPC_ROTR = OPC_SRL | (1 << 21),
178 OPC_SRA = 0x03 | OPC_SPECIAL,
179 OPC_SLLV = 0x04 | OPC_SPECIAL,
180 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
181 OPC_ROTRV = OPC_SRLV | (1 << 6),
182 OPC_SRAV = 0x07 | OPC_SPECIAL,
183 OPC_DSLLV = 0x14 | OPC_SPECIAL,
184 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
185 OPC_DROTRV = OPC_DSRLV | (1 << 6),
186 OPC_DSRAV = 0x17 | OPC_SPECIAL,
187 OPC_DSLL = 0x38 | OPC_SPECIAL,
188 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
189 OPC_DROTR = OPC_DSRL | (1 << 21),
190 OPC_DSRA = 0x3B | OPC_SPECIAL,
191 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
192 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
193 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
194 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
195 /* Multiplication / division */
196 OPC_MULT = 0x18 | OPC_SPECIAL,
197 OPC_MULTU = 0x19 | OPC_SPECIAL,
198 OPC_DIV = 0x1A | OPC_SPECIAL,
199 OPC_DIVU = 0x1B | OPC_SPECIAL,
200 OPC_DMULT = 0x1C | OPC_SPECIAL,
201 OPC_DMULTU = 0x1D | OPC_SPECIAL,
202 OPC_DDIV = 0x1E | OPC_SPECIAL,
203 OPC_DDIVU = 0x1F | OPC_SPECIAL,
205 /* 2 registers arithmetic / logic */
206 OPC_ADD = 0x20 | OPC_SPECIAL,
207 OPC_ADDU = 0x21 | OPC_SPECIAL,
208 OPC_SUB = 0x22 | OPC_SPECIAL,
209 OPC_SUBU = 0x23 | OPC_SPECIAL,
210 OPC_AND = 0x24 | OPC_SPECIAL,
211 OPC_OR = 0x25 | OPC_SPECIAL,
212 OPC_XOR = 0x26 | OPC_SPECIAL,
213 OPC_NOR = 0x27 | OPC_SPECIAL,
214 OPC_SLT = 0x2A | OPC_SPECIAL,
215 OPC_SLTU = 0x2B | OPC_SPECIAL,
216 OPC_DADD = 0x2C | OPC_SPECIAL,
217 OPC_DADDU = 0x2D | OPC_SPECIAL,
218 OPC_DSUB = 0x2E | OPC_SPECIAL,
219 OPC_DSUBU = 0x2F | OPC_SPECIAL,
220 /* Jumps */
221 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
222 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
223 /* Traps */
224 OPC_TGE = 0x30 | OPC_SPECIAL,
225 OPC_TGEU = 0x31 | OPC_SPECIAL,
226 OPC_TLT = 0x32 | OPC_SPECIAL,
227 OPC_TLTU = 0x33 | OPC_SPECIAL,
228 OPC_TEQ = 0x34 | OPC_SPECIAL,
229 OPC_TNE = 0x36 | OPC_SPECIAL,
230 /* HI / LO registers load & stores */
231 OPC_MFHI = 0x10 | OPC_SPECIAL,
232 OPC_MTHI = 0x11 | OPC_SPECIAL,
233 OPC_MFLO = 0x12 | OPC_SPECIAL,
234 OPC_MTLO = 0x13 | OPC_SPECIAL,
235 /* Conditional moves */
236 OPC_MOVZ = 0x0A | OPC_SPECIAL,
237 OPC_MOVN = 0x0B | OPC_SPECIAL,
239 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
240 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
242 OPC_MOVCI = 0x01 | OPC_SPECIAL,
244 /* Special */
245 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
246 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
247 OPC_BREAK = 0x0D | OPC_SPECIAL,
248 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
249 OPC_SYNC = 0x0F | OPC_SPECIAL,
251 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
252 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
253 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
254 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
257 /* R6 Multiply and Divide instructions have the same Opcode
258 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
259 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
261 enum {
262 R6_OPC_MUL = OPC_MULT | (2 << 6),
263 R6_OPC_MUH = OPC_MULT | (3 << 6),
264 R6_OPC_MULU = OPC_MULTU | (2 << 6),
265 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
266 R6_OPC_DIV = OPC_DIV | (2 << 6),
267 R6_OPC_MOD = OPC_DIV | (3 << 6),
268 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
269 R6_OPC_MODU = OPC_DIVU | (3 << 6),
271 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
272 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
273 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
274 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
275 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
276 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
277 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
278 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
280 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
281 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
282 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
283 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
284 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
286 OPC_LSA = 0x05 | OPC_SPECIAL,
287 OPC_DLSA = 0x15 | OPC_SPECIAL,
290 /* Multiplication variants of the vr54xx. */
291 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
293 enum {
294 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
295 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
296 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
297 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
298 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
299 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
300 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
301 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
302 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
303 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
304 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
305 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
306 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
307 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
310 /* REGIMM (rt field) opcodes */
311 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
313 enum {
314 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
315 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
316 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
317 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
318 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
319 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
320 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
321 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
322 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
323 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
324 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
325 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
326 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
327 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
328 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
329 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
331 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
332 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
335 /* Special2 opcodes */
336 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
338 enum {
339 /* Multiply & xxx operations */
340 OPC_MADD = 0x00 | OPC_SPECIAL2,
341 OPC_MADDU = 0x01 | OPC_SPECIAL2,
342 OPC_MUL = 0x02 | OPC_SPECIAL2,
343 OPC_MSUB = 0x04 | OPC_SPECIAL2,
344 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
345 /* Loongson 2F */
346 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
347 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
348 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
349 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
350 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
351 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
352 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
353 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
354 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
355 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
356 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
357 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
358 /* Misc */
359 OPC_CLZ = 0x20 | OPC_SPECIAL2,
360 OPC_CLO = 0x21 | OPC_SPECIAL2,
361 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
362 OPC_DCLO = 0x25 | OPC_SPECIAL2,
363 /* Special */
364 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
367 /* Special3 opcodes */
368 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
370 enum {
371 OPC_EXT = 0x00 | OPC_SPECIAL3,
372 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
373 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
374 OPC_DEXT = 0x03 | OPC_SPECIAL3,
375 OPC_INS = 0x04 | OPC_SPECIAL3,
376 OPC_DINSM = 0x05 | OPC_SPECIAL3,
377 OPC_DINSU = 0x06 | OPC_SPECIAL3,
378 OPC_DINS = 0x07 | OPC_SPECIAL3,
379 OPC_FORK = 0x08 | OPC_SPECIAL3,
380 OPC_YIELD = 0x09 | OPC_SPECIAL3,
381 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
382 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
383 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
385 /* Loongson 2E */
386 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
387 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
388 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
389 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
390 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
391 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
392 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
393 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
394 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
395 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
396 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
397 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
399 /* MIPS DSP Load */
400 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
401 /* MIPS DSP Arithmetic */
402 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
403 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
404 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
405 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
406 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
407 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
408 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
409 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
410 /* MIPS DSP GPR-Based Shift Sub-class */
411 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
412 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
413 /* MIPS DSP Multiply Sub-class insns */
414 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
415 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
416 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
417 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
418 /* DSP Bit/Manipulation Sub-class */
419 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
420 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
421 /* MIPS DSP Append Sub-class */
422 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
423 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
424 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
425 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
426 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
428 /* R6 */
429 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
430 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
431 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
432 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
433 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
434 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
437 /* BSHFL opcodes */
438 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
440 enum {
441 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
442 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
443 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
444 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
445 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
446 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
449 /* DBSHFL opcodes */
450 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
452 enum {
453 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
454 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
455 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
456 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
457 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
460 /* MIPS DSP REGIMM opcodes */
461 enum {
462 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
463 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
466 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
467 /* MIPS DSP Load */
468 enum {
469 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
470 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
471 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
472 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
475 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
476 enum {
477 /* MIPS DSP Arithmetic Sub-class */
478 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
479 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
480 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
481 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
482 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
483 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
484 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
485 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
486 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
487 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
488 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
489 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
490 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
491 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
492 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
493 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
494 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
495 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
496 /* MIPS DSP Multiply Sub-class insns */
497 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
498 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
499 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
500 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
501 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
502 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
505 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
506 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
507 enum {
508 /* MIPS DSP Arithmetic Sub-class */
509 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
510 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
511 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
512 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
513 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
514 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
515 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
516 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
517 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
518 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
519 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
520 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
521 /* MIPS DSP Multiply Sub-class insns */
522 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
523 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
524 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
525 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
528 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
529 enum {
530 /* MIPS DSP Arithmetic Sub-class */
531 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
532 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
533 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
534 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
535 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
536 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
537 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
538 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
539 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
540 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
541 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
542 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
543 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
544 /* DSP Bit/Manipulation Sub-class */
545 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
546 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
547 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
548 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
549 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
552 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
553 enum {
554 /* MIPS DSP Arithmetic Sub-class */
555 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
556 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
557 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
558 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
559 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
560 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
561 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
562 /* DSP Compare-Pick Sub-class */
563 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
564 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
565 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
566 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
567 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
568 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
569 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
570 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
571 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
572 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
573 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
574 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
575 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
576 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
577 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
580 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
581 enum {
582 /* MIPS DSP GPR-Based Shift Sub-class */
583 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
584 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
585 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
586 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
587 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
588 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
589 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
590 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
591 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
592 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
593 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
594 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
595 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
596 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
597 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
598 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
599 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
600 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
601 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
602 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
603 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
604 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
607 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
608 enum {
609 /* MIPS DSP Multiply Sub-class insns */
610 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
611 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
612 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
613 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
614 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
615 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
616 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
617 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
618 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
619 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
620 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
621 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
622 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
623 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
624 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
625 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
626 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
627 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
628 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
629 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
630 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
631 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
634 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
635 enum {
636 /* DSP Bit/Manipulation Sub-class */
637 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
640 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
641 enum {
642 /* MIPS DSP Append Sub-class */
643 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
644 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
645 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
648 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
649 enum {
650 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
651 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
652 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
653 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
654 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
655 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
656 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
657 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
658 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
659 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
660 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
661 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
662 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
663 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
664 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
665 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
666 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
667 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
670 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Arithmetic Sub-class */
673 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
674 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
675 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
676 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
677 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
678 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
679 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
680 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
681 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
682 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
683 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
684 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
685 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
686 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
687 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
688 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
689 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
690 /* DSP Bit/Manipulation Sub-class */
691 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
692 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
693 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
694 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
695 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
699 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
700 enum {
701 /* MIPS DSP Multiply Sub-class insns */
702 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
703 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
704 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
705 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
706 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
707 /* MIPS DSP Arithmetic Sub-class */
708 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
709 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
710 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
711 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
712 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
713 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
714 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
715 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
716 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
717 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
718 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
719 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
720 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
721 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
722 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
723 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
724 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
725 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
726 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
727 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
728 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
731 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
732 enum {
733 /* DSP Compare-Pick Sub-class */
734 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
735 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
736 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
737 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
738 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
739 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
740 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
741 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
742 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
743 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
744 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
745 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
746 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
747 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
748 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
749 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
750 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
751 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
752 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
753 /* MIPS DSP Arithmetic Sub-class */
754 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
755 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
756 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
764 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
765 enum {
766 /* DSP Append Sub-class */
767 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
768 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
769 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
770 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
773 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
774 enum {
775 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
776 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
777 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
778 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
779 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
780 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
781 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
782 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
783 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
784 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
785 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
786 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
787 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
788 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
789 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
790 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
791 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
792 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
793 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
794 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
795 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
796 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
799 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
800 enum {
801 /* DSP Bit/Manipulation Sub-class */
802 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
805 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
806 enum {
807 /* MIPS DSP Multiply Sub-class insns */
808 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
809 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
810 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
811 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
812 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
813 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
814 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
815 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
816 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
817 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
818 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
819 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
820 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
821 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
822 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
823 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
824 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
825 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
826 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
827 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
828 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
829 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
830 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
836 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
837 enum {
838 /* MIPS DSP GPR-Based Shift Sub-class */
839 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
840 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
841 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
842 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
843 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
844 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
845 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
846 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
847 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
848 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
849 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
850 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
851 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
852 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
853 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
854 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
855 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
856 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
857 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
858 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
859 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
860 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
861 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
867 /* Coprocessor 0 (rs field) */
868 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
870 enum {
871 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
872 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
873 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
874 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
875 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
876 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
877 OPC_MFTR = (0x08 << 21) | OPC_CP0,
878 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
879 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
880 OPC_MTTR = (0x0C << 21) | OPC_CP0,
881 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
882 OPC_C0 = (0x10 << 21) | OPC_CP0,
883 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
884 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
887 /* MFMC0 opcodes */
888 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
890 enum {
891 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
892 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
893 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
894 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
895 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
896 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
897 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
898 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
901 /* Coprocessor 0 (with rs == C0) */
902 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
904 enum {
905 OPC_TLBR = 0x01 | OPC_C0,
906 OPC_TLBWI = 0x02 | OPC_C0,
907 OPC_TLBINV = 0x03 | OPC_C0,
908 OPC_TLBINVF = 0x04 | OPC_C0,
909 OPC_TLBWR = 0x06 | OPC_C0,
910 OPC_TLBP = 0x08 | OPC_C0,
911 OPC_RFE = 0x10 | OPC_C0,
912 OPC_ERET = 0x18 | OPC_C0,
913 OPC_DERET = 0x1F | OPC_C0,
914 OPC_WAIT = 0x20 | OPC_C0,
917 /* Coprocessor 1 (rs field) */
918 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
920 /* Values for the fmt field in FP instructions */
921 enum {
922 /* 0 - 15 are reserved */
923 FMT_S = 16, /* single fp */
924 FMT_D = 17, /* double fp */
925 FMT_E = 18, /* extended fp */
926 FMT_Q = 19, /* quad fp */
927 FMT_W = 20, /* 32-bit fixed */
928 FMT_L = 21, /* 64-bit fixed */
929 FMT_PS = 22, /* paired single fp */
930 /* 23 - 31 are reserved */
933 enum {
934 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
935 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
936 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
937 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
938 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
939 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
940 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
941 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
942 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
943 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
944 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
945 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
946 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
947 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
948 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
949 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
950 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
951 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
952 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
953 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
954 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
955 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
956 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
957 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
958 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
959 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
960 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
961 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
962 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
963 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
966 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
967 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
969 enum {
970 OPC_BC1F = (0x00 << 16) | OPC_BC1,
971 OPC_BC1T = (0x01 << 16) | OPC_BC1,
972 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
973 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
976 enum {
977 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
978 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
981 enum {
982 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
983 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
986 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
988 enum {
989 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
990 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
991 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
992 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
993 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
994 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
995 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
996 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
997 OPC_BC2 = (0x08 << 21) | OPC_CP2,
998 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
999 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1002 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1004 enum {
1005 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1006 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1007 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1008 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1009 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1010 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1011 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1012 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1014 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1015 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1016 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1018 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1019 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1020 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1021 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1023 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1024 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1025 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1026 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1027 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1028 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1029 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1030 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1032 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1033 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1034 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1035 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1036 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1037 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1038 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1039 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1041 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1042 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1043 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1044 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1045 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1046 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1048 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1049 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1050 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1051 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1052 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1053 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1055 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1056 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1057 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1058 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1059 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1060 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1062 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1063 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1064 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1065 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1066 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1067 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1069 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1070 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1071 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1072 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1073 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1074 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1076 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1077 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1078 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1079 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1080 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1081 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1083 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1084 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1085 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1086 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1087 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1088 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1090 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1091 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1092 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1093 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1094 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1095 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1099 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1101 enum {
1102 OPC_LWXC1 = 0x00 | OPC_CP3,
1103 OPC_LDXC1 = 0x01 | OPC_CP3,
1104 OPC_LUXC1 = 0x05 | OPC_CP3,
1105 OPC_SWXC1 = 0x08 | OPC_CP3,
1106 OPC_SDXC1 = 0x09 | OPC_CP3,
1107 OPC_SUXC1 = 0x0D | OPC_CP3,
1108 OPC_PREFX = 0x0F | OPC_CP3,
1109 OPC_ALNV_PS = 0x1E | OPC_CP3,
1110 OPC_MADD_S = 0x20 | OPC_CP3,
1111 OPC_MADD_D = 0x21 | OPC_CP3,
1112 OPC_MADD_PS = 0x26 | OPC_CP3,
1113 OPC_MSUB_S = 0x28 | OPC_CP3,
1114 OPC_MSUB_D = 0x29 | OPC_CP3,
1115 OPC_MSUB_PS = 0x2E | OPC_CP3,
1116 OPC_NMADD_S = 0x30 | OPC_CP3,
1117 OPC_NMADD_D = 0x31 | OPC_CP3,
1118 OPC_NMADD_PS= 0x36 | OPC_CP3,
1119 OPC_NMSUB_S = 0x38 | OPC_CP3,
1120 OPC_NMSUB_D = 0x39 | OPC_CP3,
1121 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1124 /* MSA Opcodes */
1125 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1126 enum {
1127 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1128 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1129 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1130 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1131 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1132 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1133 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1134 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1135 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1136 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1137 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1138 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1139 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1140 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1141 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1142 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1143 OPC_MSA_ELM = 0x19 | OPC_MSA,
1144 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1145 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1146 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1147 OPC_MSA_VEC = 0x1E | OPC_MSA,
1149 /* MI10 instruction */
1150 OPC_LD_B = (0x20) | OPC_MSA,
1151 OPC_LD_H = (0x21) | OPC_MSA,
1152 OPC_LD_W = (0x22) | OPC_MSA,
1153 OPC_LD_D = (0x23) | OPC_MSA,
1154 OPC_ST_B = (0x24) | OPC_MSA,
1155 OPC_ST_H = (0x25) | OPC_MSA,
1156 OPC_ST_W = (0x26) | OPC_MSA,
1157 OPC_ST_D = (0x27) | OPC_MSA,
1160 enum {
1161 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1162 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1163 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1164 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1165 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1166 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1167 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1168 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1169 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1170 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1171 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1172 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1173 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1175 /* I8 instruction */
1176 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1177 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1178 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1179 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1180 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1181 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1182 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1183 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1184 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1185 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1187 /* VEC/2R/2RF instruction */
1188 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1189 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1190 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1191 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1192 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1193 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1194 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1196 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1197 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1199 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1200 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1201 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1202 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1203 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1205 /* 2RF instruction df(bit 16) = _w, _d */
1206 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1207 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1208 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1209 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1210 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1211 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1212 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1213 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1214 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1215 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1216 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1217 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1218 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1219 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1220 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1221 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1223 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1224 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1225 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1226 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1227 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1228 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1229 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1230 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1231 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1232 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1233 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1234 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1235 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1236 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1237 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1238 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1239 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1240 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1241 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1242 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1243 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1244 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1245 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1246 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1247 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1248 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1249 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1250 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1251 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1252 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1253 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1254 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1255 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1256 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1257 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1258 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1259 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1260 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1261 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1262 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1263 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1264 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1265 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1266 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1267 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1268 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1269 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1270 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1271 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1272 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1273 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1274 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1275 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1276 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1277 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1278 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1279 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1280 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1281 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1282 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1283 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1284 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1285 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1286 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1288 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1289 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1290 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1291 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1292 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1293 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1294 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1295 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1296 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1297 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1299 /* 3RF instruction _df(bit 21) = _w, _d */
1300 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1301 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1302 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1303 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1304 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1305 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1306 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1307 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1308 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1309 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1310 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1311 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1312 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1313 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1314 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1315 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1316 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1317 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1318 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1319 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1320 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1321 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1322 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1323 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1324 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1325 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1326 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1327 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1328 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1329 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1330 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1331 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1332 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1333 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1334 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1335 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1336 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1337 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1338 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1339 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1340 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1342 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1343 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1344 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1345 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1346 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1347 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1348 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1349 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1350 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1351 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1352 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1353 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1354 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1357 /* global register indices */
1358 static TCGv_env cpu_env;
1359 static TCGv cpu_gpr[32], cpu_PC;
1360 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1361 static TCGv cpu_dspctrl, btarget, bcond;
1362 static TCGv_i32 hflags;
1363 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1364 static TCGv_i64 fpu_f64[32];
1365 static TCGv_i64 msa_wr_d[64];
1367 #include "exec/gen-icount.h"
1369 #define gen_helper_0e0i(name, arg) do { \
1370 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1371 gen_helper_##name(cpu_env, helper_tmp); \
1372 tcg_temp_free_i32(helper_tmp); \
1373 } while(0)
1375 #define gen_helper_0e1i(name, arg1, arg2) do { \
1376 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1377 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1378 tcg_temp_free_i32(helper_tmp); \
1379 } while(0)
1381 #define gen_helper_1e0i(name, ret, arg1) do { \
1382 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1383 gen_helper_##name(ret, cpu_env, helper_tmp); \
1384 tcg_temp_free_i32(helper_tmp); \
1385 } while(0)
1387 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1388 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1389 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1390 tcg_temp_free_i32(helper_tmp); \
1391 } while(0)
1393 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1394 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1395 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1396 tcg_temp_free_i32(helper_tmp); \
1397 } while(0)
1399 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1400 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1401 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1402 tcg_temp_free_i32(helper_tmp); \
1403 } while(0)
1405 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1406 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1407 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1408 tcg_temp_free_i32(helper_tmp); \
1409 } while(0)
1411 typedef struct DisasContext {
1412 struct TranslationBlock *tb;
1413 target_ulong pc, saved_pc;
1414 uint32_t opcode;
1415 int singlestep_enabled;
1416 int insn_flags;
1417 int32_t CP0_Config1;
1418 /* Routine used to access memory */
1419 int mem_idx;
1420 TCGMemOp default_tcg_memop_mask;
1421 uint32_t hflags, saved_hflags;
1422 int bstate;
1423 target_ulong btarget;
1424 bool ulri;
1425 int kscrexist;
1426 bool rxi;
1427 int ie;
1428 bool bi;
1429 bool bp;
1430 uint64_t PAMask;
1431 bool mvh;
1432 int CP0_LLAddr_shift;
1433 bool ps;
1434 bool vp;
1435 bool cmgcr;
1436 } DisasContext;
1438 enum {
1439 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1440 * exception condition */
1441 BS_STOP = 1, /* We want to stop translation for any reason */
1442 BS_BRANCH = 2, /* We reached a branch condition */
1443 BS_EXCP = 3, /* We reached an exception condition */
1446 static const char * const regnames[] = {
1447 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1448 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1449 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1450 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1453 static const char * const regnames_HI[] = {
1454 "HI0", "HI1", "HI2", "HI3",
1457 static const char * const regnames_LO[] = {
1458 "LO0", "LO1", "LO2", "LO3",
1461 static const char * const fregnames[] = {
1462 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1463 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1464 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1465 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1468 static const char * const msaregnames[] = {
1469 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1470 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1471 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1472 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1473 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1474 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1475 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1476 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1477 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1478 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1479 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1480 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1481 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1482 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1483 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1484 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1487 #define LOG_DISAS(...) \
1488 do { \
1489 if (MIPS_DEBUG_DISAS) { \
1490 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1492 } while (0)
1494 #define MIPS_INVAL(op) \
1495 do { \
1496 if (MIPS_DEBUG_DISAS) { \
1497 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1498 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
1499 ctx->pc, ctx->opcode, op, ctx->opcode >> 26, \
1500 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
1502 } while (0)
1504 /* General purpose registers moves. */
1505 static inline void gen_load_gpr (TCGv t, int reg)
1507 if (reg == 0)
1508 tcg_gen_movi_tl(t, 0);
1509 else
1510 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1513 static inline void gen_store_gpr (TCGv t, int reg)
1515 if (reg != 0)
1516 tcg_gen_mov_tl(cpu_gpr[reg], t);
1519 /* Moves to/from shadow registers. */
1520 static inline void gen_load_srsgpr (int from, int to)
1522 TCGv t0 = tcg_temp_new();
1524 if (from == 0)
1525 tcg_gen_movi_tl(t0, 0);
1526 else {
1527 TCGv_i32 t2 = tcg_temp_new_i32();
1528 TCGv_ptr addr = tcg_temp_new_ptr();
1530 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1531 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1532 tcg_gen_andi_i32(t2, t2, 0xf);
1533 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1534 tcg_gen_ext_i32_ptr(addr, t2);
1535 tcg_gen_add_ptr(addr, cpu_env, addr);
1537 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1538 tcg_temp_free_ptr(addr);
1539 tcg_temp_free_i32(t2);
1541 gen_store_gpr(t0, to);
1542 tcg_temp_free(t0);
1545 static inline void gen_store_srsgpr (int from, int to)
1547 if (to != 0) {
1548 TCGv t0 = tcg_temp_new();
1549 TCGv_i32 t2 = tcg_temp_new_i32();
1550 TCGv_ptr addr = tcg_temp_new_ptr();
1552 gen_load_gpr(t0, from);
1553 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1554 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1555 tcg_gen_andi_i32(t2, t2, 0xf);
1556 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1557 tcg_gen_ext_i32_ptr(addr, t2);
1558 tcg_gen_add_ptr(addr, cpu_env, addr);
1560 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1561 tcg_temp_free_ptr(addr);
1562 tcg_temp_free_i32(t2);
1563 tcg_temp_free(t0);
1567 /* Tests */
1568 static inline void gen_save_pc(target_ulong pc)
1570 tcg_gen_movi_tl(cpu_PC, pc);
1573 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1575 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1576 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1577 gen_save_pc(ctx->pc);
1578 ctx->saved_pc = ctx->pc;
1580 if (ctx->hflags != ctx->saved_hflags) {
1581 tcg_gen_movi_i32(hflags, ctx->hflags);
1582 ctx->saved_hflags = ctx->hflags;
1583 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1584 case MIPS_HFLAG_BR:
1585 break;
1586 case MIPS_HFLAG_BC:
1587 case MIPS_HFLAG_BL:
1588 case MIPS_HFLAG_B:
1589 tcg_gen_movi_tl(btarget, ctx->btarget);
1590 break;
1595 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1597 ctx->saved_hflags = ctx->hflags;
1598 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1599 case MIPS_HFLAG_BR:
1600 break;
1601 case MIPS_HFLAG_BC:
1602 case MIPS_HFLAG_BL:
1603 case MIPS_HFLAG_B:
1604 ctx->btarget = env->btarget;
1605 break;
1609 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1611 TCGv_i32 texcp = tcg_const_i32(excp);
1612 TCGv_i32 terr = tcg_const_i32(err);
1613 save_cpu_state(ctx, 1);
1614 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1615 tcg_temp_free_i32(terr);
1616 tcg_temp_free_i32(texcp);
1617 ctx->bstate = BS_EXCP;
1620 static inline void generate_exception(DisasContext *ctx, int excp)
1622 gen_helper_0e0i(raise_exception, excp);
1625 static inline void generate_exception_end(DisasContext *ctx, int excp)
1627 generate_exception_err(ctx, excp, 0);
1630 /* Floating point register moves. */
1631 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1633 if (ctx->hflags & MIPS_HFLAG_FRE) {
1634 generate_exception(ctx, EXCP_RI);
1636 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1639 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1641 TCGv_i64 t64;
1642 if (ctx->hflags & MIPS_HFLAG_FRE) {
1643 generate_exception(ctx, EXCP_RI);
1645 t64 = tcg_temp_new_i64();
1646 tcg_gen_extu_i32_i64(t64, t);
1647 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1648 tcg_temp_free_i64(t64);
1651 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1653 if (ctx->hflags & MIPS_HFLAG_F64) {
1654 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1655 } else {
1656 gen_load_fpr32(ctx, t, reg | 1);
1660 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1662 if (ctx->hflags & MIPS_HFLAG_F64) {
1663 TCGv_i64 t64 = tcg_temp_new_i64();
1664 tcg_gen_extu_i32_i64(t64, t);
1665 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1666 tcg_temp_free_i64(t64);
1667 } else {
1668 gen_store_fpr32(ctx, t, reg | 1);
1672 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1674 if (ctx->hflags & MIPS_HFLAG_F64) {
1675 tcg_gen_mov_i64(t, fpu_f64[reg]);
1676 } else {
1677 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1681 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1683 if (ctx->hflags & MIPS_HFLAG_F64) {
1684 tcg_gen_mov_i64(fpu_f64[reg], t);
1685 } else {
1686 TCGv_i64 t0;
1687 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1688 t0 = tcg_temp_new_i64();
1689 tcg_gen_shri_i64(t0, t, 32);
1690 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1691 tcg_temp_free_i64(t0);
1695 static inline int get_fp_bit (int cc)
1697 if (cc)
1698 return 24 + cc;
1699 else
1700 return 23;
1703 /* Addresses computation */
1704 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1706 tcg_gen_add_tl(ret, arg0, arg1);
1708 #if defined(TARGET_MIPS64)
1709 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1710 tcg_gen_ext32s_i64(ret, ret);
1712 #endif
1715 /* Addresses computation (translation time) */
1716 static target_long addr_add(DisasContext *ctx, target_long base,
1717 target_long offset)
1719 target_long sum = base + offset;
1721 #if defined(TARGET_MIPS64)
1722 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1723 sum = (int32_t)sum;
1725 #endif
1726 return sum;
1729 /* Sign-extract the low 32-bits to a target_long. */
1730 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
1732 #if defined(TARGET_MIPS64)
1733 tcg_gen_ext32s_i64(ret, arg);
1734 #else
1735 tcg_gen_extrl_i64_i32(ret, arg);
1736 #endif
1739 /* Sign-extract the high 32-bits to a target_long. */
1740 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
1742 #if defined(TARGET_MIPS64)
1743 tcg_gen_sari_i64(ret, arg, 32);
1744 #else
1745 tcg_gen_extrh_i64_i32(ret, arg);
1746 #endif
1749 static inline void check_cp0_enabled(DisasContext *ctx)
1751 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1752 generate_exception_err(ctx, EXCP_CpU, 0);
1755 static inline void check_cp1_enabled(DisasContext *ctx)
1757 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1758 generate_exception_err(ctx, EXCP_CpU, 1);
1761 /* Verify that the processor is running with COP1X instructions enabled.
1762 This is associated with the nabla symbol in the MIPS32 and MIPS64
1763 opcode tables. */
1765 static inline void check_cop1x(DisasContext *ctx)
1767 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1768 generate_exception_end(ctx, EXCP_RI);
1771 /* Verify that the processor is running with 64-bit floating-point
1772 operations enabled. */
1774 static inline void check_cp1_64bitmode(DisasContext *ctx)
1776 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1777 generate_exception_end(ctx, EXCP_RI);
1781 * Verify if floating point register is valid; an operation is not defined
1782 * if bit 0 of any register specification is set and the FR bit in the
1783 * Status register equals zero, since the register numbers specify an
1784 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1785 * in the Status register equals one, both even and odd register numbers
1786 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1788 * Multiple 64 bit wide registers can be checked by calling
1789 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1791 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1793 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1794 generate_exception_end(ctx, EXCP_RI);
1797 /* Verify that the processor is running with DSP instructions enabled.
1798 This is enabled by CP0 Status register MX(24) bit.
1801 static inline void check_dsp(DisasContext *ctx)
1803 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1804 if (ctx->insn_flags & ASE_DSP) {
1805 generate_exception_end(ctx, EXCP_DSPDIS);
1806 } else {
1807 generate_exception_end(ctx, EXCP_RI);
1812 static inline void check_dspr2(DisasContext *ctx)
1814 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1815 if (ctx->insn_flags & ASE_DSP) {
1816 generate_exception_end(ctx, EXCP_DSPDIS);
1817 } else {
1818 generate_exception_end(ctx, EXCP_RI);
1823 /* This code generates a "reserved instruction" exception if the
1824 CPU does not support the instruction set corresponding to flags. */
1825 static inline void check_insn(DisasContext *ctx, int flags)
1827 if (unlikely(!(ctx->insn_flags & flags))) {
1828 generate_exception_end(ctx, EXCP_RI);
1832 /* This code generates a "reserved instruction" exception if the
1833 CPU has corresponding flag set which indicates that the instruction
1834 has been removed. */
1835 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1837 if (unlikely(ctx->insn_flags & flags)) {
1838 generate_exception_end(ctx, EXCP_RI);
1842 /* This code generates a "reserved instruction" exception if the
1843 CPU does not support 64-bit paired-single (PS) floating point data type */
1844 static inline void check_ps(DisasContext *ctx)
1846 if (unlikely(!ctx->ps)) {
1847 generate_exception(ctx, EXCP_RI);
1849 check_cp1_64bitmode(ctx);
1852 #ifdef TARGET_MIPS64
1853 /* This code generates a "reserved instruction" exception if 64-bit
1854 instructions are not enabled. */
1855 static inline void check_mips_64(DisasContext *ctx)
1857 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1858 generate_exception_end(ctx, EXCP_RI);
1860 #endif
1862 #ifndef CONFIG_USER_ONLY
1863 static inline void check_mvh(DisasContext *ctx)
1865 if (unlikely(!ctx->mvh)) {
1866 generate_exception(ctx, EXCP_RI);
1869 #endif
1871 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1872 calling interface for 32 and 64-bit FPRs. No sense in changing
1873 all callers for gen_load_fpr32 when we need the CTX parameter for
1874 this one use. */
1875 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1876 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1877 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1878 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1879 int ft, int fs, int cc) \
1881 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1882 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1883 switch (ifmt) { \
1884 case FMT_PS: \
1885 check_ps(ctx); \
1886 break; \
1887 case FMT_D: \
1888 if (abs) { \
1889 check_cop1x(ctx); \
1891 check_cp1_registers(ctx, fs | ft); \
1892 break; \
1893 case FMT_S: \
1894 if (abs) { \
1895 check_cop1x(ctx); \
1897 break; \
1899 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1900 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1901 switch (n) { \
1902 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1903 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1904 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1905 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1906 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1907 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1908 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1909 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1910 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1911 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1912 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1913 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1914 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1915 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1916 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1917 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1918 default: abort(); \
1920 tcg_temp_free_i##bits (fp0); \
1921 tcg_temp_free_i##bits (fp1); \
1924 FOP_CONDS(, 0, d, FMT_D, 64)
1925 FOP_CONDS(abs, 1, d, FMT_D, 64)
1926 FOP_CONDS(, 0, s, FMT_S, 32)
1927 FOP_CONDS(abs, 1, s, FMT_S, 32)
1928 FOP_CONDS(, 0, ps, FMT_PS, 64)
1929 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1930 #undef FOP_CONDS
1932 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1933 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1934 int ft, int fs, int fd) \
1936 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1937 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1938 if (ifmt == FMT_D) { \
1939 check_cp1_registers(ctx, fs | ft | fd); \
1941 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1942 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1943 switch (n) { \
1944 case 0: \
1945 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1946 break; \
1947 case 1: \
1948 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1949 break; \
1950 case 2: \
1951 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1952 break; \
1953 case 3: \
1954 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1955 break; \
1956 case 4: \
1957 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1958 break; \
1959 case 5: \
1960 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1961 break; \
1962 case 6: \
1963 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1964 break; \
1965 case 7: \
1966 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1967 break; \
1968 case 8: \
1969 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1970 break; \
1971 case 9: \
1972 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1973 break; \
1974 case 10: \
1975 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1976 break; \
1977 case 11: \
1978 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1979 break; \
1980 case 12: \
1981 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1982 break; \
1983 case 13: \
1984 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1985 break; \
1986 case 14: \
1987 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1988 break; \
1989 case 15: \
1990 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1991 break; \
1992 case 17: \
1993 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1994 break; \
1995 case 18: \
1996 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1997 break; \
1998 case 19: \
1999 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2000 break; \
2001 case 25: \
2002 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2003 break; \
2004 case 26: \
2005 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2006 break; \
2007 case 27: \
2008 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2009 break; \
2010 default: \
2011 abort(); \
2013 STORE; \
2014 tcg_temp_free_i ## bits (fp0); \
2015 tcg_temp_free_i ## bits (fp1); \
2018 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2019 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2020 #undef FOP_CONDNS
2021 #undef gen_ldcmp_fpr32
2022 #undef gen_ldcmp_fpr64
2024 /* load/store instructions. */
2025 #ifdef CONFIG_USER_ONLY
2026 #define OP_LD_ATOMIC(insn,fname) \
2027 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2029 TCGv t0 = tcg_temp_new(); \
2030 tcg_gen_mov_tl(t0, arg1); \
2031 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2032 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2033 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2034 tcg_temp_free(t0); \
2036 #else
2037 #define OP_LD_ATOMIC(insn,fname) \
2038 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2040 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
2042 #endif
2043 OP_LD_ATOMIC(ll,ld32s);
2044 #if defined(TARGET_MIPS64)
2045 OP_LD_ATOMIC(lld,ld64);
2046 #endif
2047 #undef OP_LD_ATOMIC
2049 #ifdef CONFIG_USER_ONLY
2050 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2051 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2053 TCGv t0 = tcg_temp_new(); \
2054 TCGLabel *l1 = gen_new_label(); \
2055 TCGLabel *l2 = gen_new_label(); \
2057 tcg_gen_andi_tl(t0, arg2, almask); \
2058 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2059 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2060 generate_exception(ctx, EXCP_AdES); \
2061 gen_set_label(l1); \
2062 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2063 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2064 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2065 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2066 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2067 generate_exception_end(ctx, EXCP_SC); \
2068 gen_set_label(l2); \
2069 tcg_gen_movi_tl(t0, 0); \
2070 gen_store_gpr(t0, rt); \
2071 tcg_temp_free(t0); \
2073 #else
2074 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2075 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2077 TCGv t0 = tcg_temp_new(); \
2078 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
2079 gen_store_gpr(t0, rt); \
2080 tcg_temp_free(t0); \
2082 #endif
2083 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2084 #if defined(TARGET_MIPS64)
2085 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2086 #endif
2087 #undef OP_ST_ATOMIC
2089 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2090 int base, int16_t offset)
2092 if (base == 0) {
2093 tcg_gen_movi_tl(addr, offset);
2094 } else if (offset == 0) {
2095 gen_load_gpr(addr, base);
2096 } else {
2097 tcg_gen_movi_tl(addr, offset);
2098 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2102 static target_ulong pc_relative_pc (DisasContext *ctx)
2104 target_ulong pc = ctx->pc;
2106 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2107 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2109 pc -= branch_bytes;
2112 pc &= ~(target_ulong)3;
2113 return pc;
2116 /* Load */
2117 static void gen_ld(DisasContext *ctx, uint32_t opc,
2118 int rt, int base, int16_t offset)
2120 TCGv t0, t1, t2;
2122 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2123 /* Loongson CPU uses a load to zero register for prefetch.
2124 We emulate it as a NOP. On other CPU we must perform the
2125 actual memory access. */
2126 return;
2129 t0 = tcg_temp_new();
2130 gen_base_offset_addr(ctx, t0, base, offset);
2132 switch (opc) {
2133 #if defined(TARGET_MIPS64)
2134 case OPC_LWU:
2135 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL |
2136 ctx->default_tcg_memop_mask);
2137 gen_store_gpr(t0, rt);
2138 break;
2139 case OPC_LD:
2140 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
2141 ctx->default_tcg_memop_mask);
2142 gen_store_gpr(t0, rt);
2143 break;
2144 case OPC_LLD:
2145 case R6_OPC_LLD:
2146 op_ld_lld(t0, t0, ctx);
2147 gen_store_gpr(t0, rt);
2148 break;
2149 case OPC_LDL:
2150 t1 = tcg_temp_new();
2151 /* Do a byte access to possibly trigger a page
2152 fault with the unaligned address. */
2153 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2154 tcg_gen_andi_tl(t1, t0, 7);
2155 #ifndef TARGET_WORDS_BIGENDIAN
2156 tcg_gen_xori_tl(t1, t1, 7);
2157 #endif
2158 tcg_gen_shli_tl(t1, t1, 3);
2159 tcg_gen_andi_tl(t0, t0, ~7);
2160 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2161 tcg_gen_shl_tl(t0, t0, t1);
2162 t2 = tcg_const_tl(-1);
2163 tcg_gen_shl_tl(t2, t2, t1);
2164 gen_load_gpr(t1, rt);
2165 tcg_gen_andc_tl(t1, t1, t2);
2166 tcg_temp_free(t2);
2167 tcg_gen_or_tl(t0, t0, t1);
2168 tcg_temp_free(t1);
2169 gen_store_gpr(t0, rt);
2170 break;
2171 case OPC_LDR:
2172 t1 = tcg_temp_new();
2173 /* Do a byte access to possibly trigger a page
2174 fault with the unaligned address. */
2175 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2176 tcg_gen_andi_tl(t1, t0, 7);
2177 #ifdef TARGET_WORDS_BIGENDIAN
2178 tcg_gen_xori_tl(t1, t1, 7);
2179 #endif
2180 tcg_gen_shli_tl(t1, t1, 3);
2181 tcg_gen_andi_tl(t0, t0, ~7);
2182 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2183 tcg_gen_shr_tl(t0, t0, t1);
2184 tcg_gen_xori_tl(t1, t1, 63);
2185 t2 = tcg_const_tl(0xfffffffffffffffeull);
2186 tcg_gen_shl_tl(t2, t2, t1);
2187 gen_load_gpr(t1, rt);
2188 tcg_gen_and_tl(t1, t1, t2);
2189 tcg_temp_free(t2);
2190 tcg_gen_or_tl(t0, t0, t1);
2191 tcg_temp_free(t1);
2192 gen_store_gpr(t0, rt);
2193 break;
2194 case OPC_LDPC:
2195 t1 = tcg_const_tl(pc_relative_pc(ctx));
2196 gen_op_addr_add(ctx, t0, t0, t1);
2197 tcg_temp_free(t1);
2198 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2199 gen_store_gpr(t0, rt);
2200 break;
2201 #endif
2202 case OPC_LWPC:
2203 t1 = tcg_const_tl(pc_relative_pc(ctx));
2204 gen_op_addr_add(ctx, t0, t0, t1);
2205 tcg_temp_free(t1);
2206 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2207 gen_store_gpr(t0, rt);
2208 break;
2209 case OPC_LW:
2210 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
2211 ctx->default_tcg_memop_mask);
2212 gen_store_gpr(t0, rt);
2213 break;
2214 case OPC_LH:
2215 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
2216 ctx->default_tcg_memop_mask);
2217 gen_store_gpr(t0, rt);
2218 break;
2219 case OPC_LHU:
2220 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW |
2221 ctx->default_tcg_memop_mask);
2222 gen_store_gpr(t0, rt);
2223 break;
2224 case OPC_LB:
2225 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
2226 gen_store_gpr(t0, rt);
2227 break;
2228 case OPC_LBU:
2229 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
2230 gen_store_gpr(t0, rt);
2231 break;
2232 case OPC_LWL:
2233 t1 = tcg_temp_new();
2234 /* Do a byte access to possibly trigger a page
2235 fault with the unaligned address. */
2236 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2237 tcg_gen_andi_tl(t1, t0, 3);
2238 #ifndef TARGET_WORDS_BIGENDIAN
2239 tcg_gen_xori_tl(t1, t1, 3);
2240 #endif
2241 tcg_gen_shli_tl(t1, t1, 3);
2242 tcg_gen_andi_tl(t0, t0, ~3);
2243 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2244 tcg_gen_shl_tl(t0, t0, t1);
2245 t2 = tcg_const_tl(-1);
2246 tcg_gen_shl_tl(t2, t2, t1);
2247 gen_load_gpr(t1, rt);
2248 tcg_gen_andc_tl(t1, t1, t2);
2249 tcg_temp_free(t2);
2250 tcg_gen_or_tl(t0, t0, t1);
2251 tcg_temp_free(t1);
2252 tcg_gen_ext32s_tl(t0, t0);
2253 gen_store_gpr(t0, rt);
2254 break;
2255 case OPC_LWR:
2256 t1 = tcg_temp_new();
2257 /* Do a byte access to possibly trigger a page
2258 fault with the unaligned address. */
2259 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2260 tcg_gen_andi_tl(t1, t0, 3);
2261 #ifdef TARGET_WORDS_BIGENDIAN
2262 tcg_gen_xori_tl(t1, t1, 3);
2263 #endif
2264 tcg_gen_shli_tl(t1, t1, 3);
2265 tcg_gen_andi_tl(t0, t0, ~3);
2266 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2267 tcg_gen_shr_tl(t0, t0, t1);
2268 tcg_gen_xori_tl(t1, t1, 31);
2269 t2 = tcg_const_tl(0xfffffffeull);
2270 tcg_gen_shl_tl(t2, t2, t1);
2271 gen_load_gpr(t1, rt);
2272 tcg_gen_and_tl(t1, t1, t2);
2273 tcg_temp_free(t2);
2274 tcg_gen_or_tl(t0, t0, t1);
2275 tcg_temp_free(t1);
2276 tcg_gen_ext32s_tl(t0, t0);
2277 gen_store_gpr(t0, rt);
2278 break;
2279 case OPC_LL:
2280 case R6_OPC_LL:
2281 op_ld_ll(t0, t0, ctx);
2282 gen_store_gpr(t0, rt);
2283 break;
2285 tcg_temp_free(t0);
2288 /* Store */
2289 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2290 int base, int16_t offset)
2292 TCGv t0 = tcg_temp_new();
2293 TCGv t1 = tcg_temp_new();
2295 gen_base_offset_addr(ctx, t0, base, offset);
2296 gen_load_gpr(t1, rt);
2297 switch (opc) {
2298 #if defined(TARGET_MIPS64)
2299 case OPC_SD:
2300 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
2301 ctx->default_tcg_memop_mask);
2302 break;
2303 case OPC_SDL:
2304 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
2305 break;
2306 case OPC_SDR:
2307 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2308 break;
2309 #endif
2310 case OPC_SW:
2311 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
2312 ctx->default_tcg_memop_mask);
2313 break;
2314 case OPC_SH:
2315 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
2316 ctx->default_tcg_memop_mask);
2317 break;
2318 case OPC_SB:
2319 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2320 break;
2321 case OPC_SWL:
2322 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2323 break;
2324 case OPC_SWR:
2325 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2326 break;
2328 tcg_temp_free(t0);
2329 tcg_temp_free(t1);
2333 /* Store conditional */
2334 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2335 int base, int16_t offset)
2337 TCGv t0, t1;
2339 #ifdef CONFIG_USER_ONLY
2340 t0 = tcg_temp_local_new();
2341 t1 = tcg_temp_local_new();
2342 #else
2343 t0 = tcg_temp_new();
2344 t1 = tcg_temp_new();
2345 #endif
2346 gen_base_offset_addr(ctx, t0, base, offset);
2347 gen_load_gpr(t1, rt);
2348 switch (opc) {
2349 #if defined(TARGET_MIPS64)
2350 case OPC_SCD:
2351 case R6_OPC_SCD:
2352 op_st_scd(t1, t0, rt, ctx);
2353 break;
2354 #endif
2355 case OPC_SC:
2356 case R6_OPC_SC:
2357 op_st_sc(t1, t0, rt, ctx);
2358 break;
2360 tcg_temp_free(t1);
2361 tcg_temp_free(t0);
2364 /* Load and store */
2365 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2366 int base, int16_t offset)
2368 TCGv t0 = tcg_temp_new();
2370 gen_base_offset_addr(ctx, t0, base, offset);
2371 /* Don't do NOP if destination is zero: we must perform the actual
2372 memory access. */
2373 switch (opc) {
2374 case OPC_LWC1:
2376 TCGv_i32 fp0 = tcg_temp_new_i32();
2377 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2378 ctx->default_tcg_memop_mask);
2379 gen_store_fpr32(ctx, fp0, ft);
2380 tcg_temp_free_i32(fp0);
2382 break;
2383 case OPC_SWC1:
2385 TCGv_i32 fp0 = tcg_temp_new_i32();
2386 gen_load_fpr32(ctx, fp0, ft);
2387 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2388 ctx->default_tcg_memop_mask);
2389 tcg_temp_free_i32(fp0);
2391 break;
2392 case OPC_LDC1:
2394 TCGv_i64 fp0 = tcg_temp_new_i64();
2395 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2396 ctx->default_tcg_memop_mask);
2397 gen_store_fpr64(ctx, fp0, ft);
2398 tcg_temp_free_i64(fp0);
2400 break;
2401 case OPC_SDC1:
2403 TCGv_i64 fp0 = tcg_temp_new_i64();
2404 gen_load_fpr64(ctx, fp0, ft);
2405 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2406 ctx->default_tcg_memop_mask);
2407 tcg_temp_free_i64(fp0);
2409 break;
2410 default:
2411 MIPS_INVAL("flt_ldst");
2412 generate_exception_end(ctx, EXCP_RI);
2413 goto out;
2415 out:
2416 tcg_temp_free(t0);
2419 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2420 int rs, int16_t imm)
2422 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2423 check_cp1_enabled(ctx);
2424 switch (op) {
2425 case OPC_LDC1:
2426 case OPC_SDC1:
2427 check_insn(ctx, ISA_MIPS2);
2428 /* Fallthrough */
2429 default:
2430 gen_flt_ldst(ctx, op, rt, rs, imm);
2432 } else {
2433 generate_exception_err(ctx, EXCP_CpU, 1);
2437 /* Arithmetic with immediate operand */
2438 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2439 int rt, int rs, int16_t imm)
2441 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2443 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2444 /* If no destination, treat it as a NOP.
2445 For addi, we must generate the overflow exception when needed. */
2446 return;
2448 switch (opc) {
2449 case OPC_ADDI:
2451 TCGv t0 = tcg_temp_local_new();
2452 TCGv t1 = tcg_temp_new();
2453 TCGv t2 = tcg_temp_new();
2454 TCGLabel *l1 = gen_new_label();
2456 gen_load_gpr(t1, rs);
2457 tcg_gen_addi_tl(t0, t1, uimm);
2458 tcg_gen_ext32s_tl(t0, t0);
2460 tcg_gen_xori_tl(t1, t1, ~uimm);
2461 tcg_gen_xori_tl(t2, t0, uimm);
2462 tcg_gen_and_tl(t1, t1, t2);
2463 tcg_temp_free(t2);
2464 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2465 tcg_temp_free(t1);
2466 /* operands of same sign, result different sign */
2467 generate_exception(ctx, EXCP_OVERFLOW);
2468 gen_set_label(l1);
2469 tcg_gen_ext32s_tl(t0, t0);
2470 gen_store_gpr(t0, rt);
2471 tcg_temp_free(t0);
2473 break;
2474 case OPC_ADDIU:
2475 if (rs != 0) {
2476 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2477 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2478 } else {
2479 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2481 break;
2482 #if defined(TARGET_MIPS64)
2483 case OPC_DADDI:
2485 TCGv t0 = tcg_temp_local_new();
2486 TCGv t1 = tcg_temp_new();
2487 TCGv t2 = tcg_temp_new();
2488 TCGLabel *l1 = gen_new_label();
2490 gen_load_gpr(t1, rs);
2491 tcg_gen_addi_tl(t0, t1, uimm);
2493 tcg_gen_xori_tl(t1, t1, ~uimm);
2494 tcg_gen_xori_tl(t2, t0, uimm);
2495 tcg_gen_and_tl(t1, t1, t2);
2496 tcg_temp_free(t2);
2497 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2498 tcg_temp_free(t1);
2499 /* operands of same sign, result different sign */
2500 generate_exception(ctx, EXCP_OVERFLOW);
2501 gen_set_label(l1);
2502 gen_store_gpr(t0, rt);
2503 tcg_temp_free(t0);
2505 break;
2506 case OPC_DADDIU:
2507 if (rs != 0) {
2508 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2509 } else {
2510 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2512 break;
2513 #endif
2517 /* Logic with immediate operand */
2518 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2519 int rt, int rs, int16_t imm)
2521 target_ulong uimm;
2523 if (rt == 0) {
2524 /* If no destination, treat it as a NOP. */
2525 return;
2527 uimm = (uint16_t)imm;
2528 switch (opc) {
2529 case OPC_ANDI:
2530 if (likely(rs != 0))
2531 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2532 else
2533 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2534 break;
2535 case OPC_ORI:
2536 if (rs != 0)
2537 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2538 else
2539 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2540 break;
2541 case OPC_XORI:
2542 if (likely(rs != 0))
2543 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2544 else
2545 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2546 break;
2547 case OPC_LUI:
2548 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2549 /* OPC_AUI */
2550 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2551 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2552 } else {
2553 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2555 break;
2557 default:
2558 break;
2562 /* Set on less than with immediate operand */
2563 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2564 int rt, int rs, int16_t imm)
2566 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2567 TCGv t0;
2569 if (rt == 0) {
2570 /* If no destination, treat it as a NOP. */
2571 return;
2573 t0 = tcg_temp_new();
2574 gen_load_gpr(t0, rs);
2575 switch (opc) {
2576 case OPC_SLTI:
2577 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2578 break;
2579 case OPC_SLTIU:
2580 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2581 break;
2583 tcg_temp_free(t0);
2586 /* Shifts with immediate operand */
2587 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2588 int rt, int rs, int16_t imm)
2590 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2591 TCGv t0;
2593 if (rt == 0) {
2594 /* If no destination, treat it as a NOP. */
2595 return;
2598 t0 = tcg_temp_new();
2599 gen_load_gpr(t0, rs);
2600 switch (opc) {
2601 case OPC_SLL:
2602 tcg_gen_shli_tl(t0, t0, uimm);
2603 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2604 break;
2605 case OPC_SRA:
2606 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2607 break;
2608 case OPC_SRL:
2609 if (uimm != 0) {
2610 tcg_gen_ext32u_tl(t0, t0);
2611 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2612 } else {
2613 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2615 break;
2616 case OPC_ROTR:
2617 if (uimm != 0) {
2618 TCGv_i32 t1 = tcg_temp_new_i32();
2620 tcg_gen_trunc_tl_i32(t1, t0);
2621 tcg_gen_rotri_i32(t1, t1, uimm);
2622 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2623 tcg_temp_free_i32(t1);
2624 } else {
2625 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2627 break;
2628 #if defined(TARGET_MIPS64)
2629 case OPC_DSLL:
2630 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2631 break;
2632 case OPC_DSRA:
2633 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2634 break;
2635 case OPC_DSRL:
2636 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2637 break;
2638 case OPC_DROTR:
2639 if (uimm != 0) {
2640 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2641 } else {
2642 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2644 break;
2645 case OPC_DSLL32:
2646 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2647 break;
2648 case OPC_DSRA32:
2649 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2650 break;
2651 case OPC_DSRL32:
2652 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2653 break;
2654 case OPC_DROTR32:
2655 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2656 break;
2657 #endif
2659 tcg_temp_free(t0);
2662 /* Arithmetic */
2663 static void gen_arith(DisasContext *ctx, uint32_t opc,
2664 int rd, int rs, int rt)
2666 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2667 && opc != OPC_DADD && opc != OPC_DSUB) {
2668 /* If no destination, treat it as a NOP.
2669 For add & sub, we must generate the overflow exception when needed. */
2670 return;
2673 switch (opc) {
2674 case OPC_ADD:
2676 TCGv t0 = tcg_temp_local_new();
2677 TCGv t1 = tcg_temp_new();
2678 TCGv t2 = tcg_temp_new();
2679 TCGLabel *l1 = gen_new_label();
2681 gen_load_gpr(t1, rs);
2682 gen_load_gpr(t2, rt);
2683 tcg_gen_add_tl(t0, t1, t2);
2684 tcg_gen_ext32s_tl(t0, t0);
2685 tcg_gen_xor_tl(t1, t1, t2);
2686 tcg_gen_xor_tl(t2, t0, t2);
2687 tcg_gen_andc_tl(t1, t2, t1);
2688 tcg_temp_free(t2);
2689 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2690 tcg_temp_free(t1);
2691 /* operands of same sign, result different sign */
2692 generate_exception(ctx, EXCP_OVERFLOW);
2693 gen_set_label(l1);
2694 gen_store_gpr(t0, rd);
2695 tcg_temp_free(t0);
2697 break;
2698 case OPC_ADDU:
2699 if (rs != 0 && rt != 0) {
2700 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2701 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2702 } else if (rs == 0 && rt != 0) {
2703 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2704 } else if (rs != 0 && rt == 0) {
2705 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2706 } else {
2707 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2709 break;
2710 case OPC_SUB:
2712 TCGv t0 = tcg_temp_local_new();
2713 TCGv t1 = tcg_temp_new();
2714 TCGv t2 = tcg_temp_new();
2715 TCGLabel *l1 = gen_new_label();
2717 gen_load_gpr(t1, rs);
2718 gen_load_gpr(t2, rt);
2719 tcg_gen_sub_tl(t0, t1, t2);
2720 tcg_gen_ext32s_tl(t0, t0);
2721 tcg_gen_xor_tl(t2, t1, t2);
2722 tcg_gen_xor_tl(t1, t0, t1);
2723 tcg_gen_and_tl(t1, t1, t2);
2724 tcg_temp_free(t2);
2725 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2726 tcg_temp_free(t1);
2727 /* operands of different sign, first operand and result different sign */
2728 generate_exception(ctx, EXCP_OVERFLOW);
2729 gen_set_label(l1);
2730 gen_store_gpr(t0, rd);
2731 tcg_temp_free(t0);
2733 break;
2734 case OPC_SUBU:
2735 if (rs != 0 && rt != 0) {
2736 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2737 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2738 } else if (rs == 0 && rt != 0) {
2739 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2740 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2741 } else if (rs != 0 && rt == 0) {
2742 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2743 } else {
2744 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2746 break;
2747 #if defined(TARGET_MIPS64)
2748 case OPC_DADD:
2750 TCGv t0 = tcg_temp_local_new();
2751 TCGv t1 = tcg_temp_new();
2752 TCGv t2 = tcg_temp_new();
2753 TCGLabel *l1 = gen_new_label();
2755 gen_load_gpr(t1, rs);
2756 gen_load_gpr(t2, rt);
2757 tcg_gen_add_tl(t0, t1, t2);
2758 tcg_gen_xor_tl(t1, t1, t2);
2759 tcg_gen_xor_tl(t2, t0, t2);
2760 tcg_gen_andc_tl(t1, t2, t1);
2761 tcg_temp_free(t2);
2762 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2763 tcg_temp_free(t1);
2764 /* operands of same sign, result different sign */
2765 generate_exception(ctx, EXCP_OVERFLOW);
2766 gen_set_label(l1);
2767 gen_store_gpr(t0, rd);
2768 tcg_temp_free(t0);
2770 break;
2771 case OPC_DADDU:
2772 if (rs != 0 && rt != 0) {
2773 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2774 } else if (rs == 0 && rt != 0) {
2775 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2776 } else if (rs != 0 && rt == 0) {
2777 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2778 } else {
2779 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2781 break;
2782 case OPC_DSUB:
2784 TCGv t0 = tcg_temp_local_new();
2785 TCGv t1 = tcg_temp_new();
2786 TCGv t2 = tcg_temp_new();
2787 TCGLabel *l1 = gen_new_label();
2789 gen_load_gpr(t1, rs);
2790 gen_load_gpr(t2, rt);
2791 tcg_gen_sub_tl(t0, t1, t2);
2792 tcg_gen_xor_tl(t2, t1, t2);
2793 tcg_gen_xor_tl(t1, t0, t1);
2794 tcg_gen_and_tl(t1, t1, t2);
2795 tcg_temp_free(t2);
2796 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2797 tcg_temp_free(t1);
2798 /* operands of different sign, first operand and result different sign */
2799 generate_exception(ctx, EXCP_OVERFLOW);
2800 gen_set_label(l1);
2801 gen_store_gpr(t0, rd);
2802 tcg_temp_free(t0);
2804 break;
2805 case OPC_DSUBU:
2806 if (rs != 0 && rt != 0) {
2807 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2808 } else if (rs == 0 && rt != 0) {
2809 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2810 } else if (rs != 0 && rt == 0) {
2811 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2812 } else {
2813 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2815 break;
2816 #endif
2817 case OPC_MUL:
2818 if (likely(rs != 0 && rt != 0)) {
2819 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2820 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2821 } else {
2822 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2824 break;
2828 /* Conditional move */
2829 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2830 int rd, int rs, int rt)
2832 TCGv t0, t1, t2;
2834 if (rd == 0) {
2835 /* If no destination, treat it as a NOP. */
2836 return;
2839 t0 = tcg_temp_new();
2840 gen_load_gpr(t0, rt);
2841 t1 = tcg_const_tl(0);
2842 t2 = tcg_temp_new();
2843 gen_load_gpr(t2, rs);
2844 switch (opc) {
2845 case OPC_MOVN:
2846 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2847 break;
2848 case OPC_MOVZ:
2849 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2850 break;
2851 case OPC_SELNEZ:
2852 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2853 break;
2854 case OPC_SELEQZ:
2855 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2856 break;
2858 tcg_temp_free(t2);
2859 tcg_temp_free(t1);
2860 tcg_temp_free(t0);
2863 /* Logic */
2864 static void gen_logic(DisasContext *ctx, uint32_t opc,
2865 int rd, int rs, int rt)
2867 if (rd == 0) {
2868 /* If no destination, treat it as a NOP. */
2869 return;
2872 switch (opc) {
2873 case OPC_AND:
2874 if (likely(rs != 0 && rt != 0)) {
2875 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2876 } else {
2877 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2879 break;
2880 case OPC_NOR:
2881 if (rs != 0 && rt != 0) {
2882 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2883 } else if (rs == 0 && rt != 0) {
2884 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2885 } else if (rs != 0 && rt == 0) {
2886 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2887 } else {
2888 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2890 break;
2891 case OPC_OR:
2892 if (likely(rs != 0 && rt != 0)) {
2893 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2894 } else if (rs == 0 && rt != 0) {
2895 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2896 } else if (rs != 0 && rt == 0) {
2897 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2898 } else {
2899 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2901 break;
2902 case OPC_XOR:
2903 if (likely(rs != 0 && rt != 0)) {
2904 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2905 } else if (rs == 0 && rt != 0) {
2906 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2907 } else if (rs != 0 && rt == 0) {
2908 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2909 } else {
2910 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2912 break;
2916 /* Set on lower than */
2917 static void gen_slt(DisasContext *ctx, uint32_t opc,
2918 int rd, int rs, int rt)
2920 TCGv t0, t1;
2922 if (rd == 0) {
2923 /* If no destination, treat it as a NOP. */
2924 return;
2927 t0 = tcg_temp_new();
2928 t1 = tcg_temp_new();
2929 gen_load_gpr(t0, rs);
2930 gen_load_gpr(t1, rt);
2931 switch (opc) {
2932 case OPC_SLT:
2933 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2934 break;
2935 case OPC_SLTU:
2936 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2937 break;
2939 tcg_temp_free(t0);
2940 tcg_temp_free(t1);
2943 /* Shifts */
2944 static void gen_shift(DisasContext *ctx, uint32_t opc,
2945 int rd, int rs, int rt)
2947 TCGv t0, t1;
2949 if (rd == 0) {
2950 /* If no destination, treat it as a NOP.
2951 For add & sub, we must generate the overflow exception when needed. */
2952 return;
2955 t0 = tcg_temp_new();
2956 t1 = tcg_temp_new();
2957 gen_load_gpr(t0, rs);
2958 gen_load_gpr(t1, rt);
2959 switch (opc) {
2960 case OPC_SLLV:
2961 tcg_gen_andi_tl(t0, t0, 0x1f);
2962 tcg_gen_shl_tl(t0, t1, t0);
2963 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2964 break;
2965 case OPC_SRAV:
2966 tcg_gen_andi_tl(t0, t0, 0x1f);
2967 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2968 break;
2969 case OPC_SRLV:
2970 tcg_gen_ext32u_tl(t1, t1);
2971 tcg_gen_andi_tl(t0, t0, 0x1f);
2972 tcg_gen_shr_tl(t0, t1, t0);
2973 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2974 break;
2975 case OPC_ROTRV:
2977 TCGv_i32 t2 = tcg_temp_new_i32();
2978 TCGv_i32 t3 = tcg_temp_new_i32();
2980 tcg_gen_trunc_tl_i32(t2, t0);
2981 tcg_gen_trunc_tl_i32(t3, t1);
2982 tcg_gen_andi_i32(t2, t2, 0x1f);
2983 tcg_gen_rotr_i32(t2, t3, t2);
2984 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2985 tcg_temp_free_i32(t2);
2986 tcg_temp_free_i32(t3);
2988 break;
2989 #if defined(TARGET_MIPS64)
2990 case OPC_DSLLV:
2991 tcg_gen_andi_tl(t0, t0, 0x3f);
2992 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2993 break;
2994 case OPC_DSRAV:
2995 tcg_gen_andi_tl(t0, t0, 0x3f);
2996 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2997 break;
2998 case OPC_DSRLV:
2999 tcg_gen_andi_tl(t0, t0, 0x3f);
3000 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3001 break;
3002 case OPC_DROTRV:
3003 tcg_gen_andi_tl(t0, t0, 0x3f);
3004 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3005 break;
3006 #endif
3008 tcg_temp_free(t0);
3009 tcg_temp_free(t1);
3012 /* Arithmetic on HI/LO registers */
3013 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3015 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3016 /* Treat as NOP. */
3017 return;
3020 if (acc != 0) {
3021 check_dsp(ctx);
3024 switch (opc) {
3025 case OPC_MFHI:
3026 #if defined(TARGET_MIPS64)
3027 if (acc != 0) {
3028 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3029 } else
3030 #endif
3032 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3034 break;
3035 case OPC_MFLO:
3036 #if defined(TARGET_MIPS64)
3037 if (acc != 0) {
3038 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3039 } else
3040 #endif
3042 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3044 break;
3045 case OPC_MTHI:
3046 if (reg != 0) {
3047 #if defined(TARGET_MIPS64)
3048 if (acc != 0) {
3049 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3050 } else
3051 #endif
3053 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3055 } else {
3056 tcg_gen_movi_tl(cpu_HI[acc], 0);
3058 break;
3059 case OPC_MTLO:
3060 if (reg != 0) {
3061 #if defined(TARGET_MIPS64)
3062 if (acc != 0) {
3063 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3064 } else
3065 #endif
3067 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3069 } else {
3070 tcg_gen_movi_tl(cpu_LO[acc], 0);
3072 break;
3076 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3077 TCGMemOp memop)
3079 TCGv t0 = tcg_const_tl(addr);
3080 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3081 gen_store_gpr(t0, reg);
3082 tcg_temp_free(t0);
3085 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3086 int rs)
3088 target_long offset;
3089 target_long addr;
3091 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3092 case OPC_ADDIUPC:
3093 if (rs != 0) {
3094 offset = sextract32(ctx->opcode << 2, 0, 21);
3095 addr = addr_add(ctx, pc, offset);
3096 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3098 break;
3099 case R6_OPC_LWPC:
3100 offset = sextract32(ctx->opcode << 2, 0, 21);
3101 addr = addr_add(ctx, pc, offset);
3102 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3103 break;
3104 #if defined(TARGET_MIPS64)
3105 case OPC_LWUPC:
3106 check_mips_64(ctx);
3107 offset = sextract32(ctx->opcode << 2, 0, 21);
3108 addr = addr_add(ctx, pc, offset);
3109 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3110 break;
3111 #endif
3112 default:
3113 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3114 case OPC_AUIPC:
3115 if (rs != 0) {
3116 offset = sextract32(ctx->opcode, 0, 16) << 16;
3117 addr = addr_add(ctx, pc, offset);
3118 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3120 break;
3121 case OPC_ALUIPC:
3122 if (rs != 0) {
3123 offset = sextract32(ctx->opcode, 0, 16) << 16;
3124 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3125 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3127 break;
3128 #if defined(TARGET_MIPS64)
3129 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3130 case R6_OPC_LDPC + (1 << 16):
3131 case R6_OPC_LDPC + (2 << 16):
3132 case R6_OPC_LDPC + (3 << 16):
3133 check_mips_64(ctx);
3134 offset = sextract32(ctx->opcode << 3, 0, 21);
3135 addr = addr_add(ctx, (pc & ~0x7), offset);
3136 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3137 break;
3138 #endif
3139 default:
3140 MIPS_INVAL("OPC_PCREL");
3141 generate_exception_end(ctx, EXCP_RI);
3142 break;
3144 break;
3148 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3150 TCGv t0, t1;
3152 if (rd == 0) {
3153 /* Treat as NOP. */
3154 return;
3157 t0 = tcg_temp_new();
3158 t1 = tcg_temp_new();
3160 gen_load_gpr(t0, rs);
3161 gen_load_gpr(t1, rt);
3163 switch (opc) {
3164 case R6_OPC_DIV:
3166 TCGv t2 = tcg_temp_new();
3167 TCGv t3 = tcg_temp_new();
3168 tcg_gen_ext32s_tl(t0, t0);
3169 tcg_gen_ext32s_tl(t1, t1);
3170 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3171 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3172 tcg_gen_and_tl(t2, t2, t3);
3173 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3174 tcg_gen_or_tl(t2, t2, t3);
3175 tcg_gen_movi_tl(t3, 0);
3176 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3177 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3178 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3179 tcg_temp_free(t3);
3180 tcg_temp_free(t2);
3182 break;
3183 case R6_OPC_MOD:
3185 TCGv t2 = tcg_temp_new();
3186 TCGv t3 = tcg_temp_new();
3187 tcg_gen_ext32s_tl(t0, t0);
3188 tcg_gen_ext32s_tl(t1, t1);
3189 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3190 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3191 tcg_gen_and_tl(t2, t2, t3);
3192 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3193 tcg_gen_or_tl(t2, t2, t3);
3194 tcg_gen_movi_tl(t3, 0);
3195 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3196 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3197 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3198 tcg_temp_free(t3);
3199 tcg_temp_free(t2);
3201 break;
3202 case R6_OPC_DIVU:
3204 TCGv t2 = tcg_const_tl(0);
3205 TCGv t3 = tcg_const_tl(1);
3206 tcg_gen_ext32u_tl(t0, t0);
3207 tcg_gen_ext32u_tl(t1, t1);
3208 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3209 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3210 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3211 tcg_temp_free(t3);
3212 tcg_temp_free(t2);
3214 break;
3215 case R6_OPC_MODU:
3217 TCGv t2 = tcg_const_tl(0);
3218 TCGv t3 = tcg_const_tl(1);
3219 tcg_gen_ext32u_tl(t0, t0);
3220 tcg_gen_ext32u_tl(t1, t1);
3221 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3222 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3223 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3224 tcg_temp_free(t3);
3225 tcg_temp_free(t2);
3227 break;
3228 case R6_OPC_MUL:
3230 TCGv_i32 t2 = tcg_temp_new_i32();
3231 TCGv_i32 t3 = tcg_temp_new_i32();
3232 tcg_gen_trunc_tl_i32(t2, t0);
3233 tcg_gen_trunc_tl_i32(t3, t1);
3234 tcg_gen_mul_i32(t2, t2, t3);
3235 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3236 tcg_temp_free_i32(t2);
3237 tcg_temp_free_i32(t3);
3239 break;
3240 case R6_OPC_MUH:
3242 TCGv_i32 t2 = tcg_temp_new_i32();
3243 TCGv_i32 t3 = tcg_temp_new_i32();
3244 tcg_gen_trunc_tl_i32(t2, t0);
3245 tcg_gen_trunc_tl_i32(t3, t1);
3246 tcg_gen_muls2_i32(t2, t3, t2, t3);
3247 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3248 tcg_temp_free_i32(t2);
3249 tcg_temp_free_i32(t3);
3251 break;
3252 case R6_OPC_MULU:
3254 TCGv_i32 t2 = tcg_temp_new_i32();
3255 TCGv_i32 t3 = tcg_temp_new_i32();
3256 tcg_gen_trunc_tl_i32(t2, t0);
3257 tcg_gen_trunc_tl_i32(t3, t1);
3258 tcg_gen_mul_i32(t2, t2, t3);
3259 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3260 tcg_temp_free_i32(t2);
3261 tcg_temp_free_i32(t3);
3263 break;
3264 case R6_OPC_MUHU:
3266 TCGv_i32 t2 = tcg_temp_new_i32();
3267 TCGv_i32 t3 = tcg_temp_new_i32();
3268 tcg_gen_trunc_tl_i32(t2, t0);
3269 tcg_gen_trunc_tl_i32(t3, t1);
3270 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3271 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3272 tcg_temp_free_i32(t2);
3273 tcg_temp_free_i32(t3);
3275 break;
3276 #if defined(TARGET_MIPS64)
3277 case R6_OPC_DDIV:
3279 TCGv t2 = tcg_temp_new();
3280 TCGv t3 = tcg_temp_new();
3281 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3282 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3283 tcg_gen_and_tl(t2, t2, t3);
3284 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3285 tcg_gen_or_tl(t2, t2, t3);
3286 tcg_gen_movi_tl(t3, 0);
3287 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3288 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3289 tcg_temp_free(t3);
3290 tcg_temp_free(t2);
3292 break;
3293 case R6_OPC_DMOD:
3295 TCGv t2 = tcg_temp_new();
3296 TCGv t3 = tcg_temp_new();
3297 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3298 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3299 tcg_gen_and_tl(t2, t2, t3);
3300 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3301 tcg_gen_or_tl(t2, t2, t3);
3302 tcg_gen_movi_tl(t3, 0);
3303 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3304 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3305 tcg_temp_free(t3);
3306 tcg_temp_free(t2);
3308 break;
3309 case R6_OPC_DDIVU:
3311 TCGv t2 = tcg_const_tl(0);
3312 TCGv t3 = tcg_const_tl(1);
3313 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3314 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3315 tcg_temp_free(t3);
3316 tcg_temp_free(t2);
3318 break;
3319 case R6_OPC_DMODU:
3321 TCGv t2 = tcg_const_tl(0);
3322 TCGv t3 = tcg_const_tl(1);
3323 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3324 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3325 tcg_temp_free(t3);
3326 tcg_temp_free(t2);
3328 break;
3329 case R6_OPC_DMUL:
3330 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3331 break;
3332 case R6_OPC_DMUH:
3334 TCGv t2 = tcg_temp_new();
3335 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3336 tcg_temp_free(t2);
3338 break;
3339 case R6_OPC_DMULU:
3340 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3341 break;
3342 case R6_OPC_DMUHU:
3344 TCGv t2 = tcg_temp_new();
3345 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3346 tcg_temp_free(t2);
3348 break;
3349 #endif
3350 default:
3351 MIPS_INVAL("r6 mul/div");
3352 generate_exception_end(ctx, EXCP_RI);
3353 goto out;
3355 out:
3356 tcg_temp_free(t0);
3357 tcg_temp_free(t1);
3360 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3361 int acc, int rs, int rt)
3363 TCGv t0, t1;
3365 t0 = tcg_temp_new();
3366 t1 = tcg_temp_new();
3368 gen_load_gpr(t0, rs);
3369 gen_load_gpr(t1, rt);
3371 if (acc != 0) {
3372 check_dsp(ctx);
3375 switch (opc) {
3376 case OPC_DIV:
3378 TCGv t2 = tcg_temp_new();
3379 TCGv t3 = tcg_temp_new();
3380 tcg_gen_ext32s_tl(t0, t0);
3381 tcg_gen_ext32s_tl(t1, t1);
3382 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3383 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3384 tcg_gen_and_tl(t2, t2, t3);
3385 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3386 tcg_gen_or_tl(t2, t2, t3);
3387 tcg_gen_movi_tl(t3, 0);
3388 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3389 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3390 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3391 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3392 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3393 tcg_temp_free(t3);
3394 tcg_temp_free(t2);
3396 break;
3397 case OPC_DIVU:
3399 TCGv t2 = tcg_const_tl(0);
3400 TCGv t3 = tcg_const_tl(1);
3401 tcg_gen_ext32u_tl(t0, t0);
3402 tcg_gen_ext32u_tl(t1, t1);
3403 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3404 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3405 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3406 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3407 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3408 tcg_temp_free(t3);
3409 tcg_temp_free(t2);
3411 break;
3412 case OPC_MULT:
3414 TCGv_i32 t2 = tcg_temp_new_i32();
3415 TCGv_i32 t3 = tcg_temp_new_i32();
3416 tcg_gen_trunc_tl_i32(t2, t0);
3417 tcg_gen_trunc_tl_i32(t3, t1);
3418 tcg_gen_muls2_i32(t2, t3, t2, t3);
3419 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3420 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3421 tcg_temp_free_i32(t2);
3422 tcg_temp_free_i32(t3);
3424 break;
3425 case OPC_MULTU:
3427 TCGv_i32 t2 = tcg_temp_new_i32();
3428 TCGv_i32 t3 = tcg_temp_new_i32();
3429 tcg_gen_trunc_tl_i32(t2, t0);
3430 tcg_gen_trunc_tl_i32(t3, t1);
3431 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3432 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3433 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3434 tcg_temp_free_i32(t2);
3435 tcg_temp_free_i32(t3);
3437 break;
3438 #if defined(TARGET_MIPS64)
3439 case OPC_DDIV:
3441 TCGv t2 = tcg_temp_new();
3442 TCGv t3 = tcg_temp_new();
3443 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3444 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3445 tcg_gen_and_tl(t2, t2, t3);
3446 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3447 tcg_gen_or_tl(t2, t2, t3);
3448 tcg_gen_movi_tl(t3, 0);
3449 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3450 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3451 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3452 tcg_temp_free(t3);
3453 tcg_temp_free(t2);
3455 break;
3456 case OPC_DDIVU:
3458 TCGv t2 = tcg_const_tl(0);
3459 TCGv t3 = tcg_const_tl(1);
3460 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3461 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3462 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3463 tcg_temp_free(t3);
3464 tcg_temp_free(t2);
3466 break;
3467 case OPC_DMULT:
3468 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3469 break;
3470 case OPC_DMULTU:
3471 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3472 break;
3473 #endif
3474 case OPC_MADD:
3476 TCGv_i64 t2 = tcg_temp_new_i64();
3477 TCGv_i64 t3 = tcg_temp_new_i64();
3479 tcg_gen_ext_tl_i64(t2, t0);
3480 tcg_gen_ext_tl_i64(t3, t1);
3481 tcg_gen_mul_i64(t2, t2, t3);
3482 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3483 tcg_gen_add_i64(t2, t2, t3);
3484 tcg_temp_free_i64(t3);
3485 gen_move_low32(cpu_LO[acc], t2);
3486 gen_move_high32(cpu_HI[acc], t2);
3487 tcg_temp_free_i64(t2);
3489 break;
3490 case OPC_MADDU:
3492 TCGv_i64 t2 = tcg_temp_new_i64();
3493 TCGv_i64 t3 = tcg_temp_new_i64();
3495 tcg_gen_ext32u_tl(t0, t0);
3496 tcg_gen_ext32u_tl(t1, t1);
3497 tcg_gen_extu_tl_i64(t2, t0);
3498 tcg_gen_extu_tl_i64(t3, t1);
3499 tcg_gen_mul_i64(t2, t2, t3);
3500 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3501 tcg_gen_add_i64(t2, t2, t3);
3502 tcg_temp_free_i64(t3);
3503 gen_move_low32(cpu_LO[acc], t2);
3504 gen_move_high32(cpu_HI[acc], t2);
3505 tcg_temp_free_i64(t2);
3507 break;
3508 case OPC_MSUB:
3510 TCGv_i64 t2 = tcg_temp_new_i64();
3511 TCGv_i64 t3 = tcg_temp_new_i64();
3513 tcg_gen_ext_tl_i64(t2, t0);
3514 tcg_gen_ext_tl_i64(t3, t1);
3515 tcg_gen_mul_i64(t2, t2, t3);
3516 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3517 tcg_gen_sub_i64(t2, t3, t2);
3518 tcg_temp_free_i64(t3);
3519 gen_move_low32(cpu_LO[acc], t2);
3520 gen_move_high32(cpu_HI[acc], t2);
3521 tcg_temp_free_i64(t2);
3523 break;
3524 case OPC_MSUBU:
3526 TCGv_i64 t2 = tcg_temp_new_i64();
3527 TCGv_i64 t3 = tcg_temp_new_i64();
3529 tcg_gen_ext32u_tl(t0, t0);
3530 tcg_gen_ext32u_tl(t1, t1);
3531 tcg_gen_extu_tl_i64(t2, t0);
3532 tcg_gen_extu_tl_i64(t3, t1);
3533 tcg_gen_mul_i64(t2, t2, t3);
3534 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3535 tcg_gen_sub_i64(t2, t3, t2);
3536 tcg_temp_free_i64(t3);
3537 gen_move_low32(cpu_LO[acc], t2);
3538 gen_move_high32(cpu_HI[acc], t2);
3539 tcg_temp_free_i64(t2);
3541 break;
3542 default:
3543 MIPS_INVAL("mul/div");
3544 generate_exception_end(ctx, EXCP_RI);
3545 goto out;
3547 out:
3548 tcg_temp_free(t0);
3549 tcg_temp_free(t1);
3552 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3553 int rd, int rs, int rt)
3555 TCGv t0 = tcg_temp_new();
3556 TCGv t1 = tcg_temp_new();
3558 gen_load_gpr(t0, rs);
3559 gen_load_gpr(t1, rt);
3561 switch (opc) {
3562 case OPC_VR54XX_MULS:
3563 gen_helper_muls(t0, cpu_env, t0, t1);
3564 break;
3565 case OPC_VR54XX_MULSU:
3566 gen_helper_mulsu(t0, cpu_env, t0, t1);
3567 break;
3568 case OPC_VR54XX_MACC:
3569 gen_helper_macc(t0, cpu_env, t0, t1);
3570 break;
3571 case OPC_VR54XX_MACCU:
3572 gen_helper_maccu(t0, cpu_env, t0, t1);
3573 break;
3574 case OPC_VR54XX_MSAC:
3575 gen_helper_msac(t0, cpu_env, t0, t1);
3576 break;
3577 case OPC_VR54XX_MSACU:
3578 gen_helper_msacu(t0, cpu_env, t0, t1);
3579 break;
3580 case OPC_VR54XX_MULHI:
3581 gen_helper_mulhi(t0, cpu_env, t0, t1);
3582 break;
3583 case OPC_VR54XX_MULHIU:
3584 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3585 break;
3586 case OPC_VR54XX_MULSHI:
3587 gen_helper_mulshi(t0, cpu_env, t0, t1);
3588 break;
3589 case OPC_VR54XX_MULSHIU:
3590 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3591 break;
3592 case OPC_VR54XX_MACCHI:
3593 gen_helper_macchi(t0, cpu_env, t0, t1);
3594 break;
3595 case OPC_VR54XX_MACCHIU:
3596 gen_helper_macchiu(t0, cpu_env, t0, t1);
3597 break;
3598 case OPC_VR54XX_MSACHI:
3599 gen_helper_msachi(t0, cpu_env, t0, t1);
3600 break;
3601 case OPC_VR54XX_MSACHIU:
3602 gen_helper_msachiu(t0, cpu_env, t0, t1);
3603 break;
3604 default:
3605 MIPS_INVAL("mul vr54xx");
3606 generate_exception_end(ctx, EXCP_RI);
3607 goto out;
3609 gen_store_gpr(t0, rd);
3611 out:
3612 tcg_temp_free(t0);
3613 tcg_temp_free(t1);
3616 static void gen_cl (DisasContext *ctx, uint32_t opc,
3617 int rd, int rs)
3619 TCGv t0;
3621 if (rd == 0) {
3622 /* Treat as NOP. */
3623 return;
3625 t0 = tcg_temp_new();
3626 gen_load_gpr(t0, rs);
3627 switch (opc) {
3628 case OPC_CLO:
3629 case R6_OPC_CLO:
3630 gen_helper_clo(cpu_gpr[rd], t0);
3631 break;
3632 case OPC_CLZ:
3633 case R6_OPC_CLZ:
3634 gen_helper_clz(cpu_gpr[rd], t0);
3635 break;
3636 #if defined(TARGET_MIPS64)
3637 case OPC_DCLO:
3638 case R6_OPC_DCLO:
3639 gen_helper_dclo(cpu_gpr[rd], t0);
3640 break;
3641 case OPC_DCLZ:
3642 case R6_OPC_DCLZ:
3643 gen_helper_dclz(cpu_gpr[rd], t0);
3644 break;
3645 #endif
3647 tcg_temp_free(t0);
3650 /* Godson integer instructions */
3651 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3652 int rd, int rs, int rt)
3654 TCGv t0, t1;
3656 if (rd == 0) {
3657 /* Treat as NOP. */
3658 return;
3661 switch (opc) {
3662 case OPC_MULT_G_2E:
3663 case OPC_MULT_G_2F:
3664 case OPC_MULTU_G_2E:
3665 case OPC_MULTU_G_2F:
3666 #if defined(TARGET_MIPS64)
3667 case OPC_DMULT_G_2E:
3668 case OPC_DMULT_G_2F:
3669 case OPC_DMULTU_G_2E:
3670 case OPC_DMULTU_G_2F:
3671 #endif
3672 t0 = tcg_temp_new();
3673 t1 = tcg_temp_new();
3674 break;
3675 default:
3676 t0 = tcg_temp_local_new();
3677 t1 = tcg_temp_local_new();
3678 break;
3681 gen_load_gpr(t0, rs);
3682 gen_load_gpr(t1, rt);
3684 switch (opc) {
3685 case OPC_MULT_G_2E:
3686 case OPC_MULT_G_2F:
3687 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3688 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3689 break;
3690 case OPC_MULTU_G_2E:
3691 case OPC_MULTU_G_2F:
3692 tcg_gen_ext32u_tl(t0, t0);
3693 tcg_gen_ext32u_tl(t1, t1);
3694 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3695 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3696 break;
3697 case OPC_DIV_G_2E:
3698 case OPC_DIV_G_2F:
3700 TCGLabel *l1 = gen_new_label();
3701 TCGLabel *l2 = gen_new_label();
3702 TCGLabel *l3 = gen_new_label();
3703 tcg_gen_ext32s_tl(t0, t0);
3704 tcg_gen_ext32s_tl(t1, t1);
3705 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3706 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3707 tcg_gen_br(l3);
3708 gen_set_label(l1);
3709 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3710 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3711 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3712 tcg_gen_br(l3);
3713 gen_set_label(l2);
3714 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3715 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3716 gen_set_label(l3);
3718 break;
3719 case OPC_DIVU_G_2E:
3720 case OPC_DIVU_G_2F:
3722 TCGLabel *l1 = gen_new_label();
3723 TCGLabel *l2 = gen_new_label();
3724 tcg_gen_ext32u_tl(t0, t0);
3725 tcg_gen_ext32u_tl(t1, t1);
3726 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3727 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3728 tcg_gen_br(l2);
3729 gen_set_label(l1);
3730 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3731 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3732 gen_set_label(l2);
3734 break;
3735 case OPC_MOD_G_2E:
3736 case OPC_MOD_G_2F:
3738 TCGLabel *l1 = gen_new_label();
3739 TCGLabel *l2 = gen_new_label();
3740 TCGLabel *l3 = gen_new_label();
3741 tcg_gen_ext32u_tl(t0, t0);
3742 tcg_gen_ext32u_tl(t1, t1);
3743 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3744 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3745 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3746 gen_set_label(l1);
3747 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3748 tcg_gen_br(l3);
3749 gen_set_label(l2);
3750 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3751 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3752 gen_set_label(l3);
3754 break;
3755 case OPC_MODU_G_2E:
3756 case OPC_MODU_G_2F:
3758 TCGLabel *l1 = gen_new_label();
3759 TCGLabel *l2 = gen_new_label();
3760 tcg_gen_ext32u_tl(t0, t0);
3761 tcg_gen_ext32u_tl(t1, t1);
3762 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3763 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3764 tcg_gen_br(l2);
3765 gen_set_label(l1);
3766 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3767 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3768 gen_set_label(l2);
3770 break;
3771 #if defined(TARGET_MIPS64)
3772 case OPC_DMULT_G_2E:
3773 case OPC_DMULT_G_2F:
3774 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3775 break;
3776 case OPC_DMULTU_G_2E:
3777 case OPC_DMULTU_G_2F:
3778 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3779 break;
3780 case OPC_DDIV_G_2E:
3781 case OPC_DDIV_G_2F:
3783 TCGLabel *l1 = gen_new_label();
3784 TCGLabel *l2 = gen_new_label();
3785 TCGLabel *l3 = gen_new_label();
3786 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3787 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3788 tcg_gen_br(l3);
3789 gen_set_label(l1);
3790 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3791 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3792 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3793 tcg_gen_br(l3);
3794 gen_set_label(l2);
3795 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3796 gen_set_label(l3);
3798 break;
3799 case OPC_DDIVU_G_2E:
3800 case OPC_DDIVU_G_2F:
3802 TCGLabel *l1 = gen_new_label();
3803 TCGLabel *l2 = gen_new_label();
3804 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3805 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3806 tcg_gen_br(l2);
3807 gen_set_label(l1);
3808 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3809 gen_set_label(l2);
3811 break;
3812 case OPC_DMOD_G_2E:
3813 case OPC_DMOD_G_2F:
3815 TCGLabel *l1 = gen_new_label();
3816 TCGLabel *l2 = gen_new_label();
3817 TCGLabel *l3 = gen_new_label();
3818 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3819 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3820 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3821 gen_set_label(l1);
3822 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3823 tcg_gen_br(l3);
3824 gen_set_label(l2);
3825 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3826 gen_set_label(l3);
3828 break;
3829 case OPC_DMODU_G_2E:
3830 case OPC_DMODU_G_2F:
3832 TCGLabel *l1 = gen_new_label();
3833 TCGLabel *l2 = gen_new_label();
3834 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3835 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3836 tcg_gen_br(l2);
3837 gen_set_label(l1);
3838 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3839 gen_set_label(l2);
3841 break;
3842 #endif
3845 tcg_temp_free(t0);
3846 tcg_temp_free(t1);
3849 /* Loongson multimedia instructions */
3850 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3852 uint32_t opc, shift_max;
3853 TCGv_i64 t0, t1;
3855 opc = MASK_LMI(ctx->opcode);
3856 switch (opc) {
3857 case OPC_ADD_CP2:
3858 case OPC_SUB_CP2:
3859 case OPC_DADD_CP2:
3860 case OPC_DSUB_CP2:
3861 t0 = tcg_temp_local_new_i64();
3862 t1 = tcg_temp_local_new_i64();
3863 break;
3864 default:
3865 t0 = tcg_temp_new_i64();
3866 t1 = tcg_temp_new_i64();
3867 break;
3870 gen_load_fpr64(ctx, t0, rs);
3871 gen_load_fpr64(ctx, t1, rt);
3873 #define LMI_HELPER(UP, LO) \
3874 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
3875 #define LMI_HELPER_1(UP, LO) \
3876 case OPC_##UP: gen_helper_##LO(t0, t0); break
3877 #define LMI_DIRECT(UP, LO, OP) \
3878 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
3880 switch (opc) {
3881 LMI_HELPER(PADDSH, paddsh);
3882 LMI_HELPER(PADDUSH, paddush);
3883 LMI_HELPER(PADDH, paddh);
3884 LMI_HELPER(PADDW, paddw);
3885 LMI_HELPER(PADDSB, paddsb);
3886 LMI_HELPER(PADDUSB, paddusb);
3887 LMI_HELPER(PADDB, paddb);
3889 LMI_HELPER(PSUBSH, psubsh);
3890 LMI_HELPER(PSUBUSH, psubush);
3891 LMI_HELPER(PSUBH, psubh);
3892 LMI_HELPER(PSUBW, psubw);
3893 LMI_HELPER(PSUBSB, psubsb);
3894 LMI_HELPER(PSUBUSB, psubusb);
3895 LMI_HELPER(PSUBB, psubb);
3897 LMI_HELPER(PSHUFH, pshufh);
3898 LMI_HELPER(PACKSSWH, packsswh);
3899 LMI_HELPER(PACKSSHB, packsshb);
3900 LMI_HELPER(PACKUSHB, packushb);
3902 LMI_HELPER(PUNPCKLHW, punpcklhw);
3903 LMI_HELPER(PUNPCKHHW, punpckhhw);
3904 LMI_HELPER(PUNPCKLBH, punpcklbh);
3905 LMI_HELPER(PUNPCKHBH, punpckhbh);
3906 LMI_HELPER(PUNPCKLWD, punpcklwd);
3907 LMI_HELPER(PUNPCKHWD, punpckhwd);
3909 LMI_HELPER(PAVGH, pavgh);
3910 LMI_HELPER(PAVGB, pavgb);
3911 LMI_HELPER(PMAXSH, pmaxsh);
3912 LMI_HELPER(PMINSH, pminsh);
3913 LMI_HELPER(PMAXUB, pmaxub);
3914 LMI_HELPER(PMINUB, pminub);
3916 LMI_HELPER(PCMPEQW, pcmpeqw);
3917 LMI_HELPER(PCMPGTW, pcmpgtw);
3918 LMI_HELPER(PCMPEQH, pcmpeqh);
3919 LMI_HELPER(PCMPGTH, pcmpgth);
3920 LMI_HELPER(PCMPEQB, pcmpeqb);
3921 LMI_HELPER(PCMPGTB, pcmpgtb);
3923 LMI_HELPER(PSLLW, psllw);
3924 LMI_HELPER(PSLLH, psllh);
3925 LMI_HELPER(PSRLW, psrlw);
3926 LMI_HELPER(PSRLH, psrlh);
3927 LMI_HELPER(PSRAW, psraw);
3928 LMI_HELPER(PSRAH, psrah);
3930 LMI_HELPER(PMULLH, pmullh);
3931 LMI_HELPER(PMULHH, pmulhh);
3932 LMI_HELPER(PMULHUH, pmulhuh);
3933 LMI_HELPER(PMADDHW, pmaddhw);
3935 LMI_HELPER(PASUBUB, pasubub);
3936 LMI_HELPER_1(BIADD, biadd);
3937 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3939 LMI_DIRECT(PADDD, paddd, add);
3940 LMI_DIRECT(PSUBD, psubd, sub);
3941 LMI_DIRECT(XOR_CP2, xor, xor);
3942 LMI_DIRECT(NOR_CP2, nor, nor);
3943 LMI_DIRECT(AND_CP2, and, and);
3944 LMI_DIRECT(PANDN, pandn, andc);
3945 LMI_DIRECT(OR, or, or);
3947 case OPC_PINSRH_0:
3948 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3949 break;
3950 case OPC_PINSRH_1:
3951 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3952 break;
3953 case OPC_PINSRH_2:
3954 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3955 break;
3956 case OPC_PINSRH_3:
3957 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3958 break;
3960 case OPC_PEXTRH:
3961 tcg_gen_andi_i64(t1, t1, 3);
3962 tcg_gen_shli_i64(t1, t1, 4);
3963 tcg_gen_shr_i64(t0, t0, t1);
3964 tcg_gen_ext16u_i64(t0, t0);
3965 break;
3967 case OPC_ADDU_CP2:
3968 tcg_gen_add_i64(t0, t0, t1);
3969 tcg_gen_ext32s_i64(t0, t0);
3970 break;
3971 case OPC_SUBU_CP2:
3972 tcg_gen_sub_i64(t0, t0, t1);
3973 tcg_gen_ext32s_i64(t0, t0);
3974 break;
3976 case OPC_SLL_CP2:
3977 shift_max = 32;
3978 goto do_shift;
3979 case OPC_SRL_CP2:
3980 shift_max = 32;
3981 goto do_shift;
3982 case OPC_SRA_CP2:
3983 shift_max = 32;
3984 goto do_shift;
3985 case OPC_DSLL_CP2:
3986 shift_max = 64;
3987 goto do_shift;
3988 case OPC_DSRL_CP2:
3989 shift_max = 64;
3990 goto do_shift;
3991 case OPC_DSRA_CP2:
3992 shift_max = 64;
3993 goto do_shift;
3994 do_shift:
3995 /* Make sure shift count isn't TCG undefined behaviour. */
3996 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3998 switch (opc) {
3999 case OPC_SLL_CP2:
4000 case OPC_DSLL_CP2:
4001 tcg_gen_shl_i64(t0, t0, t1);
4002 break;
4003 case OPC_SRA_CP2:
4004 case OPC_DSRA_CP2:
4005 /* Since SRA is UndefinedResult without sign-extended inputs,
4006 we can treat SRA and DSRA the same. */
4007 tcg_gen_sar_i64(t0, t0, t1);
4008 break;
4009 case OPC_SRL_CP2:
4010 /* We want to shift in zeros for SRL; zero-extend first. */
4011 tcg_gen_ext32u_i64(t0, t0);
4012 /* FALLTHRU */
4013 case OPC_DSRL_CP2:
4014 tcg_gen_shr_i64(t0, t0, t1);
4015 break;
4018 if (shift_max == 32) {
4019 tcg_gen_ext32s_i64(t0, t0);
4022 /* Shifts larger than MAX produce zero. */
4023 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4024 tcg_gen_neg_i64(t1, t1);
4025 tcg_gen_and_i64(t0, t0, t1);
4026 break;
4028 case OPC_ADD_CP2:
4029 case OPC_DADD_CP2:
4031 TCGv_i64 t2 = tcg_temp_new_i64();
4032 TCGLabel *lab = gen_new_label();
4034 tcg_gen_mov_i64(t2, t0);
4035 tcg_gen_add_i64(t0, t1, t2);
4036 if (opc == OPC_ADD_CP2) {
4037 tcg_gen_ext32s_i64(t0, t0);
4039 tcg_gen_xor_i64(t1, t1, t2);
4040 tcg_gen_xor_i64(t2, t2, t0);
4041 tcg_gen_andc_i64(t1, t2, t1);
4042 tcg_temp_free_i64(t2);
4043 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4044 generate_exception(ctx, EXCP_OVERFLOW);
4045 gen_set_label(lab);
4046 break;
4049 case OPC_SUB_CP2:
4050 case OPC_DSUB_CP2:
4052 TCGv_i64 t2 = tcg_temp_new_i64();
4053 TCGLabel *lab = gen_new_label();
4055 tcg_gen_mov_i64(t2, t0);
4056 tcg_gen_sub_i64(t0, t1, t2);
4057 if (opc == OPC_SUB_CP2) {
4058 tcg_gen_ext32s_i64(t0, t0);
4060 tcg_gen_xor_i64(t1, t1, t2);
4061 tcg_gen_xor_i64(t2, t2, t0);
4062 tcg_gen_and_i64(t1, t1, t2);
4063 tcg_temp_free_i64(t2);
4064 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4065 generate_exception(ctx, EXCP_OVERFLOW);
4066 gen_set_label(lab);
4067 break;
4070 case OPC_PMULUW:
4071 tcg_gen_ext32u_i64(t0, t0);
4072 tcg_gen_ext32u_i64(t1, t1);
4073 tcg_gen_mul_i64(t0, t0, t1);
4074 break;
4076 case OPC_SEQU_CP2:
4077 case OPC_SEQ_CP2:
4078 case OPC_SLTU_CP2:
4079 case OPC_SLT_CP2:
4080 case OPC_SLEU_CP2:
4081 case OPC_SLE_CP2:
4082 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4083 FD field is the CC field? */
4084 default:
4085 MIPS_INVAL("loongson_cp2");
4086 generate_exception_end(ctx, EXCP_RI);
4087 return;
4090 #undef LMI_HELPER
4091 #undef LMI_DIRECT
4093 gen_store_fpr64(ctx, t0, rd);
4095 tcg_temp_free_i64(t0);
4096 tcg_temp_free_i64(t1);
4099 /* Traps */
4100 static void gen_trap (DisasContext *ctx, uint32_t opc,
4101 int rs, int rt, int16_t imm)
4103 int cond;
4104 TCGv t0 = tcg_temp_new();
4105 TCGv t1 = tcg_temp_new();
4107 cond = 0;
4108 /* Load needed operands */
4109 switch (opc) {
4110 case OPC_TEQ:
4111 case OPC_TGE:
4112 case OPC_TGEU:
4113 case OPC_TLT:
4114 case OPC_TLTU:
4115 case OPC_TNE:
4116 /* Compare two registers */
4117 if (rs != rt) {
4118 gen_load_gpr(t0, rs);
4119 gen_load_gpr(t1, rt);
4120 cond = 1;
4122 break;
4123 case OPC_TEQI:
4124 case OPC_TGEI:
4125 case OPC_TGEIU:
4126 case OPC_TLTI:
4127 case OPC_TLTIU:
4128 case OPC_TNEI:
4129 /* Compare register to immediate */
4130 if (rs != 0 || imm != 0) {
4131 gen_load_gpr(t0, rs);
4132 tcg_gen_movi_tl(t1, (int32_t)imm);
4133 cond = 1;
4135 break;
4137 if (cond == 0) {
4138 switch (opc) {
4139 case OPC_TEQ: /* rs == rs */
4140 case OPC_TEQI: /* r0 == 0 */
4141 case OPC_TGE: /* rs >= rs */
4142 case OPC_TGEI: /* r0 >= 0 */
4143 case OPC_TGEU: /* rs >= rs unsigned */
4144 case OPC_TGEIU: /* r0 >= 0 unsigned */
4145 /* Always trap */
4146 generate_exception_end(ctx, EXCP_TRAP);
4147 break;
4148 case OPC_TLT: /* rs < rs */
4149 case OPC_TLTI: /* r0 < 0 */
4150 case OPC_TLTU: /* rs < rs unsigned */
4151 case OPC_TLTIU: /* r0 < 0 unsigned */
4152 case OPC_TNE: /* rs != rs */
4153 case OPC_TNEI: /* r0 != 0 */
4154 /* Never trap: treat as NOP. */
4155 break;
4157 } else {
4158 TCGLabel *l1 = gen_new_label();
4160 switch (opc) {
4161 case OPC_TEQ:
4162 case OPC_TEQI:
4163 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4164 break;
4165 case OPC_TGE:
4166 case OPC_TGEI:
4167 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4168 break;
4169 case OPC_TGEU:
4170 case OPC_TGEIU:
4171 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4172 break;
4173 case OPC_TLT:
4174 case OPC_TLTI:
4175 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4176 break;
4177 case OPC_TLTU:
4178 case OPC_TLTIU:
4179 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4180 break;
4181 case OPC_TNE:
4182 case OPC_TNEI:
4183 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4184 break;
4186 generate_exception(ctx, EXCP_TRAP);
4187 gen_set_label(l1);
4189 tcg_temp_free(t0);
4190 tcg_temp_free(t1);
4193 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4195 TranslationBlock *tb;
4196 tb = ctx->tb;
4197 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
4198 likely(!ctx->singlestep_enabled)) {
4199 tcg_gen_goto_tb(n);
4200 gen_save_pc(dest);
4201 tcg_gen_exit_tb((uintptr_t)tb + n);
4202 } else {
4203 gen_save_pc(dest);
4204 if (ctx->singlestep_enabled) {
4205 save_cpu_state(ctx, 0);
4206 gen_helper_raise_exception_debug(cpu_env);
4208 tcg_gen_exit_tb(0);
4212 /* Branches (before delay slot) */
4213 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4214 int insn_bytes,
4215 int rs, int rt, int32_t offset,
4216 int delayslot_size)
4218 target_ulong btgt = -1;
4219 int blink = 0;
4220 int bcond_compute = 0;
4221 TCGv t0 = tcg_temp_new();
4222 TCGv t1 = tcg_temp_new();
4224 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4225 #ifdef MIPS_DEBUG_DISAS
4226 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4227 TARGET_FMT_lx "\n", ctx->pc);
4228 #endif
4229 generate_exception_end(ctx, EXCP_RI);
4230 goto out;
4233 /* Load needed operands */
4234 switch (opc) {
4235 case OPC_BEQ:
4236 case OPC_BEQL:
4237 case OPC_BNE:
4238 case OPC_BNEL:
4239 /* Compare two registers */
4240 if (rs != rt) {
4241 gen_load_gpr(t0, rs);
4242 gen_load_gpr(t1, rt);
4243 bcond_compute = 1;
4245 btgt = ctx->pc + insn_bytes + offset;
4246 break;
4247 case OPC_BGEZ:
4248 case OPC_BGEZAL:
4249 case OPC_BGEZALL:
4250 case OPC_BGEZL:
4251 case OPC_BGTZ:
4252 case OPC_BGTZL:
4253 case OPC_BLEZ:
4254 case OPC_BLEZL:
4255 case OPC_BLTZ:
4256 case OPC_BLTZAL:
4257 case OPC_BLTZALL:
4258 case OPC_BLTZL:
4259 /* Compare to zero */
4260 if (rs != 0) {
4261 gen_load_gpr(t0, rs);
4262 bcond_compute = 1;
4264 btgt = ctx->pc + insn_bytes + offset;
4265 break;
4266 case OPC_BPOSGE32:
4267 #if defined(TARGET_MIPS64)
4268 case OPC_BPOSGE64:
4269 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4270 #else
4271 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4272 #endif
4273 bcond_compute = 1;
4274 btgt = ctx->pc + insn_bytes + offset;
4275 break;
4276 case OPC_J:
4277 case OPC_JAL:
4278 case OPC_JALX:
4279 /* Jump to immediate */
4280 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4281 break;
4282 case OPC_JR:
4283 case OPC_JALR:
4284 /* Jump to register */
4285 if (offset != 0 && offset != 16) {
4286 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4287 others are reserved. */
4288 MIPS_INVAL("jump hint");
4289 generate_exception_end(ctx, EXCP_RI);
4290 goto out;
4292 gen_load_gpr(btarget, rs);
4293 break;
4294 default:
4295 MIPS_INVAL("branch/jump");
4296 generate_exception_end(ctx, EXCP_RI);
4297 goto out;
4299 if (bcond_compute == 0) {
4300 /* No condition to be computed */
4301 switch (opc) {
4302 case OPC_BEQ: /* rx == rx */
4303 case OPC_BEQL: /* rx == rx likely */
4304 case OPC_BGEZ: /* 0 >= 0 */
4305 case OPC_BGEZL: /* 0 >= 0 likely */
4306 case OPC_BLEZ: /* 0 <= 0 */
4307 case OPC_BLEZL: /* 0 <= 0 likely */
4308 /* Always take */
4309 ctx->hflags |= MIPS_HFLAG_B;
4310 break;
4311 case OPC_BGEZAL: /* 0 >= 0 */
4312 case OPC_BGEZALL: /* 0 >= 0 likely */
4313 /* Always take and link */
4314 blink = 31;
4315 ctx->hflags |= MIPS_HFLAG_B;
4316 break;
4317 case OPC_BNE: /* rx != rx */
4318 case OPC_BGTZ: /* 0 > 0 */
4319 case OPC_BLTZ: /* 0 < 0 */
4320 /* Treat as NOP. */
4321 goto out;
4322 case OPC_BLTZAL: /* 0 < 0 */
4323 /* Handle as an unconditional branch to get correct delay
4324 slot checking. */
4325 blink = 31;
4326 btgt = ctx->pc + insn_bytes + delayslot_size;
4327 ctx->hflags |= MIPS_HFLAG_B;
4328 break;
4329 case OPC_BLTZALL: /* 0 < 0 likely */
4330 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4331 /* Skip the instruction in the delay slot */
4332 ctx->pc += 4;
4333 goto out;
4334 case OPC_BNEL: /* rx != rx likely */
4335 case OPC_BGTZL: /* 0 > 0 likely */
4336 case OPC_BLTZL: /* 0 < 0 likely */
4337 /* Skip the instruction in the delay slot */
4338 ctx->pc += 4;
4339 goto out;
4340 case OPC_J:
4341 ctx->hflags |= MIPS_HFLAG_B;
4342 break;
4343 case OPC_JALX:
4344 ctx->hflags |= MIPS_HFLAG_BX;
4345 /* Fallthrough */
4346 case OPC_JAL:
4347 blink = 31;
4348 ctx->hflags |= MIPS_HFLAG_B;
4349 break;
4350 case OPC_JR:
4351 ctx->hflags |= MIPS_HFLAG_BR;
4352 break;
4353 case OPC_JALR:
4354 blink = rt;
4355 ctx->hflags |= MIPS_HFLAG_BR;
4356 break;
4357 default:
4358 MIPS_INVAL("branch/jump");
4359 generate_exception_end(ctx, EXCP_RI);
4360 goto out;
4362 } else {
4363 switch (opc) {
4364 case OPC_BEQ:
4365 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4366 goto not_likely;
4367 case OPC_BEQL:
4368 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4369 goto likely;
4370 case OPC_BNE:
4371 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4372 goto not_likely;
4373 case OPC_BNEL:
4374 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4375 goto likely;
4376 case OPC_BGEZ:
4377 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4378 goto not_likely;
4379 case OPC_BGEZL:
4380 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4381 goto likely;
4382 case OPC_BGEZAL:
4383 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4384 blink = 31;
4385 goto not_likely;
4386 case OPC_BGEZALL:
4387 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4388 blink = 31;
4389 goto likely;
4390 case OPC_BGTZ:
4391 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4392 goto not_likely;
4393 case OPC_BGTZL:
4394 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4395 goto likely;
4396 case OPC_BLEZ:
4397 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4398 goto not_likely;
4399 case OPC_BLEZL:
4400 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4401 goto likely;
4402 case OPC_BLTZ:
4403 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4404 goto not_likely;
4405 case OPC_BLTZL:
4406 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4407 goto likely;
4408 case OPC_BPOSGE32:
4409 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4410 goto not_likely;
4411 #if defined(TARGET_MIPS64)
4412 case OPC_BPOSGE64:
4413 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4414 goto not_likely;
4415 #endif
4416 case OPC_BLTZAL:
4417 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4418 blink = 31;
4419 not_likely:
4420 ctx->hflags |= MIPS_HFLAG_BC;
4421 break;
4422 case OPC_BLTZALL:
4423 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4424 blink = 31;
4425 likely:
4426 ctx->hflags |= MIPS_HFLAG_BL;
4427 break;
4428 default:
4429 MIPS_INVAL("conditional branch/jump");
4430 generate_exception_end(ctx, EXCP_RI);
4431 goto out;
4435 ctx->btarget = btgt;
4437 switch (delayslot_size) {
4438 case 2:
4439 ctx->hflags |= MIPS_HFLAG_BDS16;
4440 break;
4441 case 4:
4442 ctx->hflags |= MIPS_HFLAG_BDS32;
4443 break;
4446 if (blink > 0) {
4447 int post_delay = insn_bytes + delayslot_size;
4448 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4450 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4453 out:
4454 if (insn_bytes == 2)
4455 ctx->hflags |= MIPS_HFLAG_B16;
4456 tcg_temp_free(t0);
4457 tcg_temp_free(t1);
4460 /* special3 bitfield operations */
4461 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4462 int rs, int lsb, int msb)
4464 TCGv t0 = tcg_temp_new();
4465 TCGv t1 = tcg_temp_new();
4467 gen_load_gpr(t1, rs);
4468 switch (opc) {
4469 case OPC_EXT:
4470 if (lsb + msb > 31) {
4471 goto fail;
4473 tcg_gen_shri_tl(t0, t1, lsb);
4474 if (msb != 31) {
4475 tcg_gen_andi_tl(t0, t0, (1U << (msb + 1)) - 1);
4476 } else {
4477 tcg_gen_ext32s_tl(t0, t0);
4479 break;
4480 #if defined(TARGET_MIPS64)
4481 case OPC_DEXTU:
4482 lsb += 32;
4483 goto do_dext;
4484 case OPC_DEXTM:
4485 msb += 32;
4486 goto do_dext;
4487 case OPC_DEXT:
4488 do_dext:
4489 if (lsb + msb > 63) {
4490 goto fail;
4492 tcg_gen_shri_tl(t0, t1, lsb);
4493 if (msb != 63) {
4494 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4496 break;
4497 #endif
4498 case OPC_INS:
4499 if (lsb > msb) {
4500 goto fail;
4502 gen_load_gpr(t0, rt);
4503 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4504 tcg_gen_ext32s_tl(t0, t0);
4505 break;
4506 #if defined(TARGET_MIPS64)
4507 case OPC_DINSU:
4508 lsb += 32;
4509 /* FALLTHRU */
4510 case OPC_DINSM:
4511 msb += 32;
4512 /* FALLTHRU */
4513 case OPC_DINS:
4514 if (lsb > msb) {
4515 goto fail;
4517 gen_load_gpr(t0, rt);
4518 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4519 break;
4520 #endif
4521 default:
4522 fail:
4523 MIPS_INVAL("bitops");
4524 generate_exception_end(ctx, EXCP_RI);
4525 tcg_temp_free(t0);
4526 tcg_temp_free(t1);
4527 return;
4529 gen_store_gpr(t0, rt);
4530 tcg_temp_free(t0);
4531 tcg_temp_free(t1);
4534 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4536 TCGv t0;
4538 if (rd == 0) {
4539 /* If no destination, treat it as a NOP. */
4540 return;
4543 t0 = tcg_temp_new();
4544 gen_load_gpr(t0, rt);
4545 switch (op2) {
4546 case OPC_WSBH:
4548 TCGv t1 = tcg_temp_new();
4550 tcg_gen_shri_tl(t1, t0, 8);
4551 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4552 tcg_gen_shli_tl(t0, t0, 8);
4553 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4554 tcg_gen_or_tl(t0, t0, t1);
4555 tcg_temp_free(t1);
4556 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4558 break;
4559 case OPC_SEB:
4560 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4561 break;
4562 case OPC_SEH:
4563 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4564 break;
4565 #if defined(TARGET_MIPS64)
4566 case OPC_DSBH:
4568 TCGv t1 = tcg_temp_new();
4570 tcg_gen_shri_tl(t1, t0, 8);
4571 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4572 tcg_gen_shli_tl(t0, t0, 8);
4573 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4574 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4575 tcg_temp_free(t1);
4577 break;
4578 case OPC_DSHD:
4580 TCGv t1 = tcg_temp_new();
4582 tcg_gen_shri_tl(t1, t0, 16);
4583 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4584 tcg_gen_shli_tl(t0, t0, 16);
4585 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4586 tcg_gen_or_tl(t0, t0, t1);
4587 tcg_gen_shri_tl(t1, t0, 32);
4588 tcg_gen_shli_tl(t0, t0, 32);
4589 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4590 tcg_temp_free(t1);
4592 break;
4593 #endif
4594 default:
4595 MIPS_INVAL("bsfhl");
4596 generate_exception_end(ctx, EXCP_RI);
4597 tcg_temp_free(t0);
4598 return;
4600 tcg_temp_free(t0);
4603 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4604 int imm2)
4606 TCGv t0;
4607 TCGv t1;
4608 if (rd == 0) {
4609 /* Treat as NOP. */
4610 return;
4612 t0 = tcg_temp_new();
4613 t1 = tcg_temp_new();
4614 gen_load_gpr(t0, rs);
4615 gen_load_gpr(t1, rt);
4616 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4617 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4618 if (opc == OPC_LSA) {
4619 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4622 tcg_temp_free(t1);
4623 tcg_temp_free(t0);
4625 return;
4628 static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
4629 int bp)
4631 TCGv t0;
4632 if (rd == 0) {
4633 /* Treat as NOP. */
4634 return;
4636 t0 = tcg_temp_new();
4637 gen_load_gpr(t0, rt);
4638 if (bp == 0) {
4639 switch (opc) {
4640 case OPC_ALIGN:
4641 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4642 break;
4643 #if defined(TARGET_MIPS64)
4644 case OPC_DALIGN:
4645 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4646 break;
4647 #endif
4649 } else {
4650 TCGv t1 = tcg_temp_new();
4651 gen_load_gpr(t1, rs);
4652 switch (opc) {
4653 case OPC_ALIGN:
4655 TCGv_i64 t2 = tcg_temp_new_i64();
4656 tcg_gen_concat_tl_i64(t2, t1, t0);
4657 tcg_gen_shri_i64(t2, t2, 8 * (4 - bp));
4658 gen_move_low32(cpu_gpr[rd], t2);
4659 tcg_temp_free_i64(t2);
4661 break;
4662 #if defined(TARGET_MIPS64)
4663 case OPC_DALIGN:
4664 tcg_gen_shli_tl(t0, t0, 8 * bp);
4665 tcg_gen_shri_tl(t1, t1, 8 * (8 - bp));
4666 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4667 break;
4668 #endif
4670 tcg_temp_free(t1);
4673 tcg_temp_free(t0);
4676 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4678 TCGv t0;
4679 if (rd == 0) {
4680 /* Treat as NOP. */
4681 return;
4683 t0 = tcg_temp_new();
4684 gen_load_gpr(t0, rt);
4685 switch (opc) {
4686 case OPC_BITSWAP:
4687 gen_helper_bitswap(cpu_gpr[rd], t0);
4688 break;
4689 #if defined(TARGET_MIPS64)
4690 case OPC_DBITSWAP:
4691 gen_helper_dbitswap(cpu_gpr[rd], t0);
4692 break;
4693 #endif
4695 tcg_temp_free(t0);
4698 #ifndef CONFIG_USER_ONLY
4699 /* CP0 (MMU and control) */
4700 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4702 TCGv_i64 t0 = tcg_temp_new_i64();
4703 TCGv_i64 t1 = tcg_temp_new_i64();
4705 tcg_gen_ext_tl_i64(t0, arg);
4706 tcg_gen_ld_i64(t1, cpu_env, off);
4707 #if defined(TARGET_MIPS64)
4708 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4709 #else
4710 tcg_gen_concat32_i64(t1, t1, t0);
4711 #endif
4712 tcg_gen_st_i64(t1, cpu_env, off);
4713 tcg_temp_free_i64(t1);
4714 tcg_temp_free_i64(t0);
4717 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4719 TCGv_i64 t0 = tcg_temp_new_i64();
4720 TCGv_i64 t1 = tcg_temp_new_i64();
4722 tcg_gen_ext_tl_i64(t0, arg);
4723 tcg_gen_ld_i64(t1, cpu_env, off);
4724 tcg_gen_concat32_i64(t1, t1, t0);
4725 tcg_gen_st_i64(t1, cpu_env, off);
4726 tcg_temp_free_i64(t1);
4727 tcg_temp_free_i64(t0);
4730 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
4732 TCGv_i64 t0 = tcg_temp_new_i64();
4734 tcg_gen_ld_i64(t0, cpu_env, off);
4735 #if defined(TARGET_MIPS64)
4736 tcg_gen_shri_i64(t0, t0, 30);
4737 #else
4738 tcg_gen_shri_i64(t0, t0, 32);
4739 #endif
4740 gen_move_low32(arg, t0);
4741 tcg_temp_free_i64(t0);
4744 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
4746 TCGv_i64 t0 = tcg_temp_new_i64();
4748 tcg_gen_ld_i64(t0, cpu_env, off);
4749 tcg_gen_shri_i64(t0, t0, 32 + shift);
4750 gen_move_low32(arg, t0);
4751 tcg_temp_free_i64(t0);
4754 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4756 TCGv_i32 t0 = tcg_temp_new_i32();
4758 tcg_gen_ld_i32(t0, cpu_env, off);
4759 tcg_gen_ext_i32_tl(arg, t0);
4760 tcg_temp_free_i32(t0);
4763 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4765 tcg_gen_ld_tl(arg, cpu_env, off);
4766 tcg_gen_ext32s_tl(arg, arg);
4769 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4771 TCGv_i32 t0 = tcg_temp_new_i32();
4773 tcg_gen_trunc_tl_i32(t0, arg);
4774 tcg_gen_st_i32(t0, cpu_env, off);
4775 tcg_temp_free_i32(t0);
4778 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4780 const char *rn = "invalid";
4782 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
4783 goto mfhc0_read_zero;
4786 switch (reg) {
4787 case 2:
4788 switch (sel) {
4789 case 0:
4790 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4791 rn = "EntryLo0";
4792 break;
4793 default:
4794 goto mfhc0_read_zero;
4796 break;
4797 case 3:
4798 switch (sel) {
4799 case 0:
4800 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4801 rn = "EntryLo1";
4802 break;
4803 default:
4804 goto mfhc0_read_zero;
4806 break;
4807 case 17:
4808 switch (sel) {
4809 case 0:
4810 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
4811 ctx->CP0_LLAddr_shift);
4812 rn = "LLAddr";
4813 break;
4814 default:
4815 goto mfhc0_read_zero;
4817 break;
4818 case 28:
4819 switch (sel) {
4820 case 0:
4821 case 2:
4822 case 4:
4823 case 6:
4824 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
4825 rn = "TagLo";
4826 break;
4827 default:
4828 goto mfhc0_read_zero;
4830 break;
4831 default:
4832 goto mfhc0_read_zero;
4835 (void)rn; /* avoid a compiler warning */
4836 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4837 return;
4839 mfhc0_read_zero:
4840 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4841 tcg_gen_movi_tl(arg, 0);
4844 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4846 const char *rn = "invalid";
4847 uint64_t mask = ctx->PAMask >> 36;
4849 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
4850 goto mthc0_nop;
4853 switch (reg) {
4854 case 2:
4855 switch (sel) {
4856 case 0:
4857 tcg_gen_andi_tl(arg, arg, mask);
4858 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4859 rn = "EntryLo0";
4860 break;
4861 default:
4862 goto mthc0_nop;
4864 break;
4865 case 3:
4866 switch (sel) {
4867 case 0:
4868 tcg_gen_andi_tl(arg, arg, mask);
4869 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4870 rn = "EntryLo1";
4871 break;
4872 default:
4873 goto mthc0_nop;
4875 break;
4876 case 17:
4877 switch (sel) {
4878 case 0:
4879 /* LLAddr is read-only (the only exception is bit 0 if LLB is
4880 supported); the CP0_LLAddr_rw_bitmask does not seem to be
4881 relevant for modern MIPS cores supporting MTHC0, therefore
4882 treating MTHC0 to LLAddr as NOP. */
4883 rn = "LLAddr";
4884 break;
4885 default:
4886 goto mthc0_nop;
4888 break;
4889 case 28:
4890 switch (sel) {
4891 case 0:
4892 case 2:
4893 case 4:
4894 case 6:
4895 tcg_gen_andi_tl(arg, arg, mask);
4896 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
4897 rn = "TagLo";
4898 break;
4899 default:
4900 goto mthc0_nop;
4902 break;
4903 default:
4904 goto mthc0_nop;
4907 (void)rn; /* avoid a compiler warning */
4908 mthc0_nop:
4909 LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
4912 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
4914 if (ctx->insn_flags & ISA_MIPS32R6) {
4915 tcg_gen_movi_tl(arg, 0);
4916 } else {
4917 tcg_gen_movi_tl(arg, ~0);
4921 #define CP0_CHECK(c) \
4922 do { \
4923 if (!(c)) { \
4924 goto cp0_unimplemented; \
4926 } while (0)
4928 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4930 const char *rn = "invalid";
4932 if (sel != 0)
4933 check_insn(ctx, ISA_MIPS32);
4935 switch (reg) {
4936 case 0:
4937 switch (sel) {
4938 case 0:
4939 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4940 rn = "Index";
4941 break;
4942 case 1:
4943 CP0_CHECK(ctx->insn_flags & ASE_MT);
4944 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4945 rn = "MVPControl";
4946 break;
4947 case 2:
4948 CP0_CHECK(ctx->insn_flags & ASE_MT);
4949 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4950 rn = "MVPConf0";
4951 break;
4952 case 3:
4953 CP0_CHECK(ctx->insn_flags & ASE_MT);
4954 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4955 rn = "MVPConf1";
4956 break;
4957 case 4:
4958 CP0_CHECK(ctx->vp);
4959 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
4960 rn = "VPControl";
4961 break;
4962 default:
4963 goto cp0_unimplemented;
4965 break;
4966 case 1:
4967 switch (sel) {
4968 case 0:
4969 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
4970 gen_helper_mfc0_random(arg, cpu_env);
4971 rn = "Random";
4972 break;
4973 case 1:
4974 CP0_CHECK(ctx->insn_flags & ASE_MT);
4975 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4976 rn = "VPEControl";
4977 break;
4978 case 2:
4979 CP0_CHECK(ctx->insn_flags & ASE_MT);
4980 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
4981 rn = "VPEConf0";
4982 break;
4983 case 3:
4984 CP0_CHECK(ctx->insn_flags & ASE_MT);
4985 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
4986 rn = "VPEConf1";
4987 break;
4988 case 4:
4989 CP0_CHECK(ctx->insn_flags & ASE_MT);
4990 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
4991 rn = "YQMask";
4992 break;
4993 case 5:
4994 CP0_CHECK(ctx->insn_flags & ASE_MT);
4995 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
4996 rn = "VPESchedule";
4997 break;
4998 case 6:
4999 CP0_CHECK(ctx->insn_flags & ASE_MT);
5000 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5001 rn = "VPEScheFBack";
5002 break;
5003 case 7:
5004 CP0_CHECK(ctx->insn_flags & ASE_MT);
5005 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5006 rn = "VPEOpt";
5007 break;
5008 default:
5009 goto cp0_unimplemented;
5011 break;
5012 case 2:
5013 switch (sel) {
5014 case 0:
5016 TCGv_i64 tmp = tcg_temp_new_i64();
5017 tcg_gen_ld_i64(tmp, cpu_env,
5018 offsetof(CPUMIPSState, CP0_EntryLo0));
5019 #if defined(TARGET_MIPS64)
5020 if (ctx->rxi) {
5021 /* Move RI/XI fields to bits 31:30 */
5022 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5023 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5025 #endif
5026 gen_move_low32(arg, tmp);
5027 tcg_temp_free_i64(tmp);
5029 rn = "EntryLo0";
5030 break;
5031 case 1:
5032 CP0_CHECK(ctx->insn_flags & ASE_MT);
5033 gen_helper_mfc0_tcstatus(arg, cpu_env);
5034 rn = "TCStatus";
5035 break;
5036 case 2:
5037 CP0_CHECK(ctx->insn_flags & ASE_MT);
5038 gen_helper_mfc0_tcbind(arg, cpu_env);
5039 rn = "TCBind";
5040 break;
5041 case 3:
5042 CP0_CHECK(ctx->insn_flags & ASE_MT);
5043 gen_helper_mfc0_tcrestart(arg, cpu_env);
5044 rn = "TCRestart";
5045 break;
5046 case 4:
5047 CP0_CHECK(ctx->insn_flags & ASE_MT);
5048 gen_helper_mfc0_tchalt(arg, cpu_env);
5049 rn = "TCHalt";
5050 break;
5051 case 5:
5052 CP0_CHECK(ctx->insn_flags & ASE_MT);
5053 gen_helper_mfc0_tccontext(arg, cpu_env);
5054 rn = "TCContext";
5055 break;
5056 case 6:
5057 CP0_CHECK(ctx->insn_flags & ASE_MT);
5058 gen_helper_mfc0_tcschedule(arg, cpu_env);
5059 rn = "TCSchedule";
5060 break;
5061 case 7:
5062 CP0_CHECK(ctx->insn_flags & ASE_MT);
5063 gen_helper_mfc0_tcschefback(arg, cpu_env);
5064 rn = "TCScheFBack";
5065 break;
5066 default:
5067 goto cp0_unimplemented;
5069 break;
5070 case 3:
5071 switch (sel) {
5072 case 0:
5074 TCGv_i64 tmp = tcg_temp_new_i64();
5075 tcg_gen_ld_i64(tmp, cpu_env,
5076 offsetof(CPUMIPSState, CP0_EntryLo1));
5077 #if defined(TARGET_MIPS64)
5078 if (ctx->rxi) {
5079 /* Move RI/XI fields to bits 31:30 */
5080 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5081 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5083 #endif
5084 gen_move_low32(arg, tmp);
5085 tcg_temp_free_i64(tmp);
5087 rn = "EntryLo1";
5088 break;
5089 case 1:
5090 CP0_CHECK(ctx->vp);
5091 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5092 rn = "GlobalNumber";
5093 break;
5094 default:
5095 goto cp0_unimplemented;
5097 break;
5098 case 4:
5099 switch (sel) {
5100 case 0:
5101 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5102 tcg_gen_ext32s_tl(arg, arg);
5103 rn = "Context";
5104 break;
5105 case 1:
5106 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5107 rn = "ContextConfig";
5108 goto cp0_unimplemented;
5109 // break;
5110 case 2:
5111 CP0_CHECK(ctx->ulri);
5112 tcg_gen_ld32s_tl(arg, cpu_env,
5113 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5114 rn = "UserLocal";
5115 break;
5116 default:
5117 goto cp0_unimplemented;
5119 break;
5120 case 5:
5121 switch (sel) {
5122 case 0:
5123 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5124 rn = "PageMask";
5125 break;
5126 case 1:
5127 check_insn(ctx, ISA_MIPS32R2);
5128 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5129 rn = "PageGrain";
5130 break;
5131 default:
5132 goto cp0_unimplemented;
5134 break;
5135 case 6:
5136 switch (sel) {
5137 case 0:
5138 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5139 rn = "Wired";
5140 break;
5141 case 1:
5142 check_insn(ctx, ISA_MIPS32R2);
5143 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5144 rn = "SRSConf0";
5145 break;
5146 case 2:
5147 check_insn(ctx, ISA_MIPS32R2);
5148 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5149 rn = "SRSConf1";
5150 break;
5151 case 3:
5152 check_insn(ctx, ISA_MIPS32R2);
5153 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5154 rn = "SRSConf2";
5155 break;
5156 case 4:
5157 check_insn(ctx, ISA_MIPS32R2);
5158 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5159 rn = "SRSConf3";
5160 break;
5161 case 5:
5162 check_insn(ctx, ISA_MIPS32R2);
5163 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5164 rn = "SRSConf4";
5165 break;
5166 default:
5167 goto cp0_unimplemented;
5169 break;
5170 case 7:
5171 switch (sel) {
5172 case 0:
5173 check_insn(ctx, ISA_MIPS32R2);
5174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5175 rn = "HWREna";
5176 break;
5177 default:
5178 goto cp0_unimplemented;
5180 break;
5181 case 8:
5182 switch (sel) {
5183 case 0:
5184 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5185 tcg_gen_ext32s_tl(arg, arg);
5186 rn = "BadVAddr";
5187 break;
5188 case 1:
5189 CP0_CHECK(ctx->bi);
5190 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5191 rn = "BadInstr";
5192 break;
5193 case 2:
5194 CP0_CHECK(ctx->bp);
5195 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5196 rn = "BadInstrP";
5197 break;
5198 default:
5199 goto cp0_unimplemented;
5201 break;
5202 case 9:
5203 switch (sel) {
5204 case 0:
5205 /* Mark as an IO operation because we read the time. */
5206 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5207 gen_io_start();
5209 gen_helper_mfc0_count(arg, cpu_env);
5210 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5211 gen_io_end();
5213 /* Break the TB to be able to take timer interrupts immediately
5214 after reading count. */
5215 ctx->bstate = BS_STOP;
5216 rn = "Count";
5217 break;
5218 /* 6,7 are implementation dependent */
5219 default:
5220 goto cp0_unimplemented;
5222 break;
5223 case 10:
5224 switch (sel) {
5225 case 0:
5226 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5227 tcg_gen_ext32s_tl(arg, arg);
5228 rn = "EntryHi";
5229 break;
5230 default:
5231 goto cp0_unimplemented;
5233 break;
5234 case 11:
5235 switch (sel) {
5236 case 0:
5237 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5238 rn = "Compare";
5239 break;
5240 /* 6,7 are implementation dependent */
5241 default:
5242 goto cp0_unimplemented;
5244 break;
5245 case 12:
5246 switch (sel) {
5247 case 0:
5248 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5249 rn = "Status";
5250 break;
5251 case 1:
5252 check_insn(ctx, ISA_MIPS32R2);
5253 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5254 rn = "IntCtl";
5255 break;
5256 case 2:
5257 check_insn(ctx, ISA_MIPS32R2);
5258 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5259 rn = "SRSCtl";
5260 break;
5261 case 3:
5262 check_insn(ctx, ISA_MIPS32R2);
5263 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5264 rn = "SRSMap";
5265 break;
5266 default:
5267 goto cp0_unimplemented;
5269 break;
5270 case 13:
5271 switch (sel) {
5272 case 0:
5273 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5274 rn = "Cause";
5275 break;
5276 default:
5277 goto cp0_unimplemented;
5279 break;
5280 case 14:
5281 switch (sel) {
5282 case 0:
5283 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5284 tcg_gen_ext32s_tl(arg, arg);
5285 rn = "EPC";
5286 break;
5287 default:
5288 goto cp0_unimplemented;
5290 break;
5291 case 15:
5292 switch (sel) {
5293 case 0:
5294 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5295 rn = "PRid";
5296 break;
5297 case 1:
5298 check_insn(ctx, ISA_MIPS32R2);
5299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5300 rn = "EBase";
5301 break;
5302 case 3:
5303 check_insn(ctx, ISA_MIPS32R2);
5304 CP0_CHECK(ctx->cmgcr);
5305 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
5306 tcg_gen_ext32s_tl(arg, arg);
5307 rn = "CMGCRBase";
5308 break;
5309 default:
5310 goto cp0_unimplemented;
5312 break;
5313 case 16:
5314 switch (sel) {
5315 case 0:
5316 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5317 rn = "Config";
5318 break;
5319 case 1:
5320 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5321 rn = "Config1";
5322 break;
5323 case 2:
5324 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5325 rn = "Config2";
5326 break;
5327 case 3:
5328 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5329 rn = "Config3";
5330 break;
5331 case 4:
5332 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5333 rn = "Config4";
5334 break;
5335 case 5:
5336 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5337 rn = "Config5";
5338 break;
5339 /* 6,7 are implementation dependent */
5340 case 6:
5341 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5342 rn = "Config6";
5343 break;
5344 case 7:
5345 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5346 rn = "Config7";
5347 break;
5348 default:
5349 goto cp0_unimplemented;
5351 break;
5352 case 17:
5353 switch (sel) {
5354 case 0:
5355 gen_helper_mfc0_lladdr(arg, cpu_env);
5356 rn = "LLAddr";
5357 break;
5358 default:
5359 goto cp0_unimplemented;
5361 break;
5362 case 18:
5363 switch (sel) {
5364 case 0 ... 7:
5365 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5366 rn = "WatchLo";
5367 break;
5368 default:
5369 goto cp0_unimplemented;
5371 break;
5372 case 19:
5373 switch (sel) {
5374 case 0 ...7:
5375 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5376 rn = "WatchHi";
5377 break;
5378 default:
5379 goto cp0_unimplemented;
5381 break;
5382 case 20:
5383 switch (sel) {
5384 case 0:
5385 #if defined(TARGET_MIPS64)
5386 check_insn(ctx, ISA_MIPS3);
5387 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5388 tcg_gen_ext32s_tl(arg, arg);
5389 rn = "XContext";
5390 break;
5391 #endif
5392 default:
5393 goto cp0_unimplemented;
5395 break;
5396 case 21:
5397 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5398 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5399 switch (sel) {
5400 case 0:
5401 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5402 rn = "Framemask";
5403 break;
5404 default:
5405 goto cp0_unimplemented;
5407 break;
5408 case 22:
5409 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5410 rn = "'Diagnostic"; /* implementation dependent */
5411 break;
5412 case 23:
5413 switch (sel) {
5414 case 0:
5415 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5416 rn = "Debug";
5417 break;
5418 case 1:
5419 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5420 rn = "TraceControl";
5421 // break;
5422 case 2:
5423 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5424 rn = "TraceControl2";
5425 // break;
5426 case 3:
5427 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5428 rn = "UserTraceData";
5429 // break;
5430 case 4:
5431 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5432 rn = "TraceBPC";
5433 // break;
5434 default:
5435 goto cp0_unimplemented;
5437 break;
5438 case 24:
5439 switch (sel) {
5440 case 0:
5441 /* EJTAG support */
5442 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5443 tcg_gen_ext32s_tl(arg, arg);
5444 rn = "DEPC";
5445 break;
5446 default:
5447 goto cp0_unimplemented;
5449 break;
5450 case 25:
5451 switch (sel) {
5452 case 0:
5453 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5454 rn = "Performance0";
5455 break;
5456 case 1:
5457 // gen_helper_mfc0_performance1(arg);
5458 rn = "Performance1";
5459 // break;
5460 case 2:
5461 // gen_helper_mfc0_performance2(arg);
5462 rn = "Performance2";
5463 // break;
5464 case 3:
5465 // gen_helper_mfc0_performance3(arg);
5466 rn = "Performance3";
5467 // break;
5468 case 4:
5469 // gen_helper_mfc0_performance4(arg);
5470 rn = "Performance4";
5471 // break;
5472 case 5:
5473 // gen_helper_mfc0_performance5(arg);
5474 rn = "Performance5";
5475 // break;
5476 case 6:
5477 // gen_helper_mfc0_performance6(arg);
5478 rn = "Performance6";
5479 // break;
5480 case 7:
5481 // gen_helper_mfc0_performance7(arg);
5482 rn = "Performance7";
5483 // break;
5484 default:
5485 goto cp0_unimplemented;
5487 break;
5488 case 26:
5489 switch (sel) {
5490 case 0:
5491 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
5492 rn = "ErrCtl";
5493 break;
5494 default:
5495 goto cp0_unimplemented;
5497 break;
5498 case 27:
5499 switch (sel) {
5500 case 0 ... 3:
5501 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5502 rn = "CacheErr";
5503 break;
5504 default:
5505 goto cp0_unimplemented;
5507 break;
5508 case 28:
5509 switch (sel) {
5510 case 0:
5511 case 2:
5512 case 4:
5513 case 6:
5515 TCGv_i64 tmp = tcg_temp_new_i64();
5516 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5517 gen_move_low32(arg, tmp);
5518 tcg_temp_free_i64(tmp);
5520 rn = "TagLo";
5521 break;
5522 case 1:
5523 case 3:
5524 case 5:
5525 case 7:
5526 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5527 rn = "DataLo";
5528 break;
5529 default:
5530 goto cp0_unimplemented;
5532 break;
5533 case 29:
5534 switch (sel) {
5535 case 0:
5536 case 2:
5537 case 4:
5538 case 6:
5539 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5540 rn = "TagHi";
5541 break;
5542 case 1:
5543 case 3:
5544 case 5:
5545 case 7:
5546 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5547 rn = "DataHi";
5548 break;
5549 default:
5550 goto cp0_unimplemented;
5552 break;
5553 case 30:
5554 switch (sel) {
5555 case 0:
5556 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5557 tcg_gen_ext32s_tl(arg, arg);
5558 rn = "ErrorEPC";
5559 break;
5560 default:
5561 goto cp0_unimplemented;
5563 break;
5564 case 31:
5565 switch (sel) {
5566 case 0:
5567 /* EJTAG support */
5568 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5569 rn = "DESAVE";
5570 break;
5571 case 2 ... 7:
5572 CP0_CHECK(ctx->kscrexist & (1 << sel));
5573 tcg_gen_ld_tl(arg, cpu_env,
5574 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5575 tcg_gen_ext32s_tl(arg, arg);
5576 rn = "KScratch";
5577 break;
5578 default:
5579 goto cp0_unimplemented;
5581 break;
5582 default:
5583 goto cp0_unimplemented;
5585 (void)rn; /* avoid a compiler warning */
5586 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5587 return;
5589 cp0_unimplemented:
5590 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5591 gen_mfc0_unimplemented(ctx, arg);
5594 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5596 const char *rn = "invalid";
5598 if (sel != 0)
5599 check_insn(ctx, ISA_MIPS32);
5601 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5602 gen_io_start();
5605 switch (reg) {
5606 case 0:
5607 switch (sel) {
5608 case 0:
5609 gen_helper_mtc0_index(cpu_env, arg);
5610 rn = "Index";
5611 break;
5612 case 1:
5613 CP0_CHECK(ctx->insn_flags & ASE_MT);
5614 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5615 rn = "MVPControl";
5616 break;
5617 case 2:
5618 CP0_CHECK(ctx->insn_flags & ASE_MT);
5619 /* ignored */
5620 rn = "MVPConf0";
5621 break;
5622 case 3:
5623 CP0_CHECK(ctx->insn_flags & ASE_MT);
5624 /* ignored */
5625 rn = "MVPConf1";
5626 break;
5627 case 4:
5628 CP0_CHECK(ctx->vp);
5629 /* ignored */
5630 rn = "VPControl";
5631 break;
5632 default:
5633 goto cp0_unimplemented;
5635 break;
5636 case 1:
5637 switch (sel) {
5638 case 0:
5639 /* ignored */
5640 rn = "Random";
5641 break;
5642 case 1:
5643 CP0_CHECK(ctx->insn_flags & ASE_MT);
5644 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5645 rn = "VPEControl";
5646 break;
5647 case 2:
5648 CP0_CHECK(ctx->insn_flags & ASE_MT);
5649 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5650 rn = "VPEConf0";
5651 break;
5652 case 3:
5653 CP0_CHECK(ctx->insn_flags & ASE_MT);
5654 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5655 rn = "VPEConf1";
5656 break;
5657 case 4:
5658 CP0_CHECK(ctx->insn_flags & ASE_MT);
5659 gen_helper_mtc0_yqmask(cpu_env, arg);
5660 rn = "YQMask";
5661 break;
5662 case 5:
5663 CP0_CHECK(ctx->insn_flags & ASE_MT);
5664 tcg_gen_st_tl(arg, cpu_env,
5665 offsetof(CPUMIPSState, CP0_VPESchedule));
5666 rn = "VPESchedule";
5667 break;
5668 case 6:
5669 CP0_CHECK(ctx->insn_flags & ASE_MT);
5670 tcg_gen_st_tl(arg, cpu_env,
5671 offsetof(CPUMIPSState, CP0_VPEScheFBack));
5672 rn = "VPEScheFBack";
5673 break;
5674 case 7:
5675 CP0_CHECK(ctx->insn_flags & ASE_MT);
5676 gen_helper_mtc0_vpeopt(cpu_env, arg);
5677 rn = "VPEOpt";
5678 break;
5679 default:
5680 goto cp0_unimplemented;
5682 break;
5683 case 2:
5684 switch (sel) {
5685 case 0:
5686 gen_helper_mtc0_entrylo0(cpu_env, arg);
5687 rn = "EntryLo0";
5688 break;
5689 case 1:
5690 CP0_CHECK(ctx->insn_flags & ASE_MT);
5691 gen_helper_mtc0_tcstatus(cpu_env, arg);
5692 rn = "TCStatus";
5693 break;
5694 case 2:
5695 CP0_CHECK(ctx->insn_flags & ASE_MT);
5696 gen_helper_mtc0_tcbind(cpu_env, arg);
5697 rn = "TCBind";
5698 break;
5699 case 3:
5700 CP0_CHECK(ctx->insn_flags & ASE_MT);
5701 gen_helper_mtc0_tcrestart(cpu_env, arg);
5702 rn = "TCRestart";
5703 break;
5704 case 4:
5705 CP0_CHECK(ctx->insn_flags & ASE_MT);
5706 gen_helper_mtc0_tchalt(cpu_env, arg);
5707 rn = "TCHalt";
5708 break;
5709 case 5:
5710 CP0_CHECK(ctx->insn_flags & ASE_MT);
5711 gen_helper_mtc0_tccontext(cpu_env, arg);
5712 rn = "TCContext";
5713 break;
5714 case 6:
5715 CP0_CHECK(ctx->insn_flags & ASE_MT);
5716 gen_helper_mtc0_tcschedule(cpu_env, arg);
5717 rn = "TCSchedule";
5718 break;
5719 case 7:
5720 CP0_CHECK(ctx->insn_flags & ASE_MT);
5721 gen_helper_mtc0_tcschefback(cpu_env, arg);
5722 rn = "TCScheFBack";
5723 break;
5724 default:
5725 goto cp0_unimplemented;
5727 break;
5728 case 3:
5729 switch (sel) {
5730 case 0:
5731 gen_helper_mtc0_entrylo1(cpu_env, arg);
5732 rn = "EntryLo1";
5733 break;
5734 case 1:
5735 CP0_CHECK(ctx->vp);
5736 /* ignored */
5737 rn = "GlobalNumber";
5738 break;
5739 default:
5740 goto cp0_unimplemented;
5742 break;
5743 case 4:
5744 switch (sel) {
5745 case 0:
5746 gen_helper_mtc0_context(cpu_env, arg);
5747 rn = "Context";
5748 break;
5749 case 1:
5750 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5751 rn = "ContextConfig";
5752 goto cp0_unimplemented;
5753 // break;
5754 case 2:
5755 CP0_CHECK(ctx->ulri);
5756 tcg_gen_st_tl(arg, cpu_env,
5757 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5758 rn = "UserLocal";
5759 break;
5760 default:
5761 goto cp0_unimplemented;
5763 break;
5764 case 5:
5765 switch (sel) {
5766 case 0:
5767 gen_helper_mtc0_pagemask(cpu_env, arg);
5768 rn = "PageMask";
5769 break;
5770 case 1:
5771 check_insn(ctx, ISA_MIPS32R2);
5772 gen_helper_mtc0_pagegrain(cpu_env, arg);
5773 rn = "PageGrain";
5774 ctx->bstate = BS_STOP;
5775 break;
5776 default:
5777 goto cp0_unimplemented;
5779 break;
5780 case 6:
5781 switch (sel) {
5782 case 0:
5783 gen_helper_mtc0_wired(cpu_env, arg);
5784 rn = "Wired";
5785 break;
5786 case 1:
5787 check_insn(ctx, ISA_MIPS32R2);
5788 gen_helper_mtc0_srsconf0(cpu_env, arg);
5789 rn = "SRSConf0";
5790 break;
5791 case 2:
5792 check_insn(ctx, ISA_MIPS32R2);
5793 gen_helper_mtc0_srsconf1(cpu_env, arg);
5794 rn = "SRSConf1";
5795 break;
5796 case 3:
5797 check_insn(ctx, ISA_MIPS32R2);
5798 gen_helper_mtc0_srsconf2(cpu_env, arg);
5799 rn = "SRSConf2";
5800 break;
5801 case 4:
5802 check_insn(ctx, ISA_MIPS32R2);
5803 gen_helper_mtc0_srsconf3(cpu_env, arg);
5804 rn = "SRSConf3";
5805 break;
5806 case 5:
5807 check_insn(ctx, ISA_MIPS32R2);
5808 gen_helper_mtc0_srsconf4(cpu_env, arg);
5809 rn = "SRSConf4";
5810 break;
5811 default:
5812 goto cp0_unimplemented;
5814 break;
5815 case 7:
5816 switch (sel) {
5817 case 0:
5818 check_insn(ctx, ISA_MIPS32R2);
5819 gen_helper_mtc0_hwrena(cpu_env, arg);
5820 ctx->bstate = BS_STOP;
5821 rn = "HWREna";
5822 break;
5823 default:
5824 goto cp0_unimplemented;
5826 break;
5827 case 8:
5828 switch (sel) {
5829 case 0:
5830 /* ignored */
5831 rn = "BadVAddr";
5832 break;
5833 case 1:
5834 /* ignored */
5835 rn = "BadInstr";
5836 break;
5837 case 2:
5838 /* ignored */
5839 rn = "BadInstrP";
5840 break;
5841 default:
5842 goto cp0_unimplemented;
5844 break;
5845 case 9:
5846 switch (sel) {
5847 case 0:
5848 gen_helper_mtc0_count(cpu_env, arg);
5849 rn = "Count";
5850 break;
5851 /* 6,7 are implementation dependent */
5852 default:
5853 goto cp0_unimplemented;
5855 break;
5856 case 10:
5857 switch (sel) {
5858 case 0:
5859 gen_helper_mtc0_entryhi(cpu_env, arg);
5860 rn = "EntryHi";
5861 break;
5862 default:
5863 goto cp0_unimplemented;
5865 break;
5866 case 11:
5867 switch (sel) {
5868 case 0:
5869 gen_helper_mtc0_compare(cpu_env, arg);
5870 rn = "Compare";
5871 break;
5872 /* 6,7 are implementation dependent */
5873 default:
5874 goto cp0_unimplemented;
5876 break;
5877 case 12:
5878 switch (sel) {
5879 case 0:
5880 save_cpu_state(ctx, 1);
5881 gen_helper_mtc0_status(cpu_env, arg);
5882 /* BS_STOP isn't good enough here, hflags may have changed. */
5883 gen_save_pc(ctx->pc + 4);
5884 ctx->bstate = BS_EXCP;
5885 rn = "Status";
5886 break;
5887 case 1:
5888 check_insn(ctx, ISA_MIPS32R2);
5889 gen_helper_mtc0_intctl(cpu_env, arg);
5890 /* Stop translation as we may have switched the execution mode */
5891 ctx->bstate = BS_STOP;
5892 rn = "IntCtl";
5893 break;
5894 case 2:
5895 check_insn(ctx, ISA_MIPS32R2);
5896 gen_helper_mtc0_srsctl(cpu_env, arg);
5897 /* Stop translation as we may have switched the execution mode */
5898 ctx->bstate = BS_STOP;
5899 rn = "SRSCtl";
5900 break;
5901 case 3:
5902 check_insn(ctx, ISA_MIPS32R2);
5903 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5904 /* Stop translation as we may have switched the execution mode */
5905 ctx->bstate = BS_STOP;
5906 rn = "SRSMap";
5907 break;
5908 default:
5909 goto cp0_unimplemented;
5911 break;
5912 case 13:
5913 switch (sel) {
5914 case 0:
5915 save_cpu_state(ctx, 1);
5916 gen_helper_mtc0_cause(cpu_env, arg);
5917 rn = "Cause";
5918 break;
5919 default:
5920 goto cp0_unimplemented;
5922 break;
5923 case 14:
5924 switch (sel) {
5925 case 0:
5926 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5927 rn = "EPC";
5928 break;
5929 default:
5930 goto cp0_unimplemented;
5932 break;
5933 case 15:
5934 switch (sel) {
5935 case 0:
5936 /* ignored */
5937 rn = "PRid";
5938 break;
5939 case 1:
5940 check_insn(ctx, ISA_MIPS32R2);
5941 gen_helper_mtc0_ebase(cpu_env, arg);
5942 rn = "EBase";
5943 break;
5944 default:
5945 goto cp0_unimplemented;
5947 break;
5948 case 16:
5949 switch (sel) {
5950 case 0:
5951 gen_helper_mtc0_config0(cpu_env, arg);
5952 rn = "Config";
5953 /* Stop translation as we may have switched the execution mode */
5954 ctx->bstate = BS_STOP;
5955 break;
5956 case 1:
5957 /* ignored, read only */
5958 rn = "Config1";
5959 break;
5960 case 2:
5961 gen_helper_mtc0_config2(cpu_env, arg);
5962 rn = "Config2";
5963 /* Stop translation as we may have switched the execution mode */
5964 ctx->bstate = BS_STOP;
5965 break;
5966 case 3:
5967 gen_helper_mtc0_config3(cpu_env, arg);
5968 rn = "Config3";
5969 /* Stop translation as we may have switched the execution mode */
5970 ctx->bstate = BS_STOP;
5971 break;
5972 case 4:
5973 gen_helper_mtc0_config4(cpu_env, arg);
5974 rn = "Config4";
5975 ctx->bstate = BS_STOP;
5976 break;
5977 case 5:
5978 gen_helper_mtc0_config5(cpu_env, arg);
5979 rn = "Config5";
5980 /* Stop translation as we may have switched the execution mode */
5981 ctx->bstate = BS_STOP;
5982 break;
5983 /* 6,7 are implementation dependent */
5984 case 6:
5985 /* ignored */
5986 rn = "Config6";
5987 break;
5988 case 7:
5989 /* ignored */
5990 rn = "Config7";
5991 break;
5992 default:
5993 rn = "Invalid config selector";
5994 goto cp0_unimplemented;
5996 break;
5997 case 17:
5998 switch (sel) {
5999 case 0:
6000 gen_helper_mtc0_lladdr(cpu_env, arg);
6001 rn = "LLAddr";
6002 break;
6003 default:
6004 goto cp0_unimplemented;
6006 break;
6007 case 18:
6008 switch (sel) {
6009 case 0 ... 7:
6010 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6011 rn = "WatchLo";
6012 break;
6013 default:
6014 goto cp0_unimplemented;
6016 break;
6017 case 19:
6018 switch (sel) {
6019 case 0 ... 7:
6020 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6021 rn = "WatchHi";
6022 break;
6023 default:
6024 goto cp0_unimplemented;
6026 break;
6027 case 20:
6028 switch (sel) {
6029 case 0:
6030 #if defined(TARGET_MIPS64)
6031 check_insn(ctx, ISA_MIPS3);
6032 gen_helper_mtc0_xcontext(cpu_env, arg);
6033 rn = "XContext";
6034 break;
6035 #endif
6036 default:
6037 goto cp0_unimplemented;
6039 break;
6040 case 21:
6041 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6042 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6043 switch (sel) {
6044 case 0:
6045 gen_helper_mtc0_framemask(cpu_env, arg);
6046 rn = "Framemask";
6047 break;
6048 default:
6049 goto cp0_unimplemented;
6051 break;
6052 case 22:
6053 /* ignored */
6054 rn = "Diagnostic"; /* implementation dependent */
6055 break;
6056 case 23:
6057 switch (sel) {
6058 case 0:
6059 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6060 /* BS_STOP isn't good enough here, hflags may have changed. */
6061 gen_save_pc(ctx->pc + 4);
6062 ctx->bstate = BS_EXCP;
6063 rn = "Debug";
6064 break;
6065 case 1:
6066 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6067 rn = "TraceControl";
6068 /* Stop translation as we may have switched the execution mode */
6069 ctx->bstate = BS_STOP;
6070 // break;
6071 case 2:
6072 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6073 rn = "TraceControl2";
6074 /* Stop translation as we may have switched the execution mode */
6075 ctx->bstate = BS_STOP;
6076 // break;
6077 case 3:
6078 /* Stop translation as we may have switched the execution mode */
6079 ctx->bstate = BS_STOP;
6080 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6081 rn = "UserTraceData";
6082 /* Stop translation as we may have switched the execution mode */
6083 ctx->bstate = BS_STOP;
6084 // break;
6085 case 4:
6086 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6087 /* Stop translation as we may have switched the execution mode */
6088 ctx->bstate = BS_STOP;
6089 rn = "TraceBPC";
6090 // break;
6091 default:
6092 goto cp0_unimplemented;
6094 break;
6095 case 24:
6096 switch (sel) {
6097 case 0:
6098 /* EJTAG support */
6099 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6100 rn = "DEPC";
6101 break;
6102 default:
6103 goto cp0_unimplemented;
6105 break;
6106 case 25:
6107 switch (sel) {
6108 case 0:
6109 gen_helper_mtc0_performance0(cpu_env, arg);
6110 rn = "Performance0";
6111 break;
6112 case 1:
6113 // gen_helper_mtc0_performance1(arg);
6114 rn = "Performance1";
6115 // break;
6116 case 2:
6117 // gen_helper_mtc0_performance2(arg);
6118 rn = "Performance2";
6119 // break;
6120 case 3:
6121 // gen_helper_mtc0_performance3(arg);
6122 rn = "Performance3";
6123 // break;
6124 case 4:
6125 // gen_helper_mtc0_performance4(arg);
6126 rn = "Performance4";
6127 // break;
6128 case 5:
6129 // gen_helper_mtc0_performance5(arg);
6130 rn = "Performance5";
6131 // break;
6132 case 6:
6133 // gen_helper_mtc0_performance6(arg);
6134 rn = "Performance6";
6135 // break;
6136 case 7:
6137 // gen_helper_mtc0_performance7(arg);
6138 rn = "Performance7";
6139 // break;
6140 default:
6141 goto cp0_unimplemented;
6143 break;
6144 case 26:
6145 switch (sel) {
6146 case 0:
6147 gen_helper_mtc0_errctl(cpu_env, arg);
6148 ctx->bstate = BS_STOP;
6149 rn = "ErrCtl";
6150 break;
6151 default:
6152 goto cp0_unimplemented;
6154 break;
6155 case 27:
6156 switch (sel) {
6157 case 0 ... 3:
6158 /* ignored */
6159 rn = "CacheErr";
6160 break;
6161 default:
6162 goto cp0_unimplemented;
6164 break;
6165 case 28:
6166 switch (sel) {
6167 case 0:
6168 case 2:
6169 case 4:
6170 case 6:
6171 gen_helper_mtc0_taglo(cpu_env, arg);
6172 rn = "TagLo";
6173 break;
6174 case 1:
6175 case 3:
6176 case 5:
6177 case 7:
6178 gen_helper_mtc0_datalo(cpu_env, arg);
6179 rn = "DataLo";
6180 break;
6181 default:
6182 goto cp0_unimplemented;
6184 break;
6185 case 29:
6186 switch (sel) {
6187 case 0:
6188 case 2:
6189 case 4:
6190 case 6:
6191 gen_helper_mtc0_taghi(cpu_env, arg);
6192 rn = "TagHi";
6193 break;
6194 case 1:
6195 case 3:
6196 case 5:
6197 case 7:
6198 gen_helper_mtc0_datahi(cpu_env, arg);
6199 rn = "DataHi";
6200 break;
6201 default:
6202 rn = "invalid sel";
6203 goto cp0_unimplemented;
6205 break;
6206 case 30:
6207 switch (sel) {
6208 case 0:
6209 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6210 rn = "ErrorEPC";
6211 break;
6212 default:
6213 goto cp0_unimplemented;
6215 break;
6216 case 31:
6217 switch (sel) {
6218 case 0:
6219 /* EJTAG support */
6220 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6221 rn = "DESAVE";
6222 break;
6223 case 2 ... 7:
6224 CP0_CHECK(ctx->kscrexist & (1 << sel));
6225 tcg_gen_st_tl(arg, cpu_env,
6226 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6227 rn = "KScratch";
6228 break;
6229 default:
6230 goto cp0_unimplemented;
6232 /* Stop translation as we may have switched the execution mode */
6233 ctx->bstate = BS_STOP;
6234 break;
6235 default:
6236 goto cp0_unimplemented;
6238 (void)rn; /* avoid a compiler warning */
6239 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6240 /* For simplicity assume that all writes can cause interrupts. */
6241 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6242 gen_io_end();
6243 ctx->bstate = BS_STOP;
6245 return;
6247 cp0_unimplemented:
6248 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6251 #if defined(TARGET_MIPS64)
6252 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6254 const char *rn = "invalid";
6256 if (sel != 0)
6257 check_insn(ctx, ISA_MIPS64);
6259 switch (reg) {
6260 case 0:
6261 switch (sel) {
6262 case 0:
6263 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6264 rn = "Index";
6265 break;
6266 case 1:
6267 CP0_CHECK(ctx->insn_flags & ASE_MT);
6268 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6269 rn = "MVPControl";
6270 break;
6271 case 2:
6272 CP0_CHECK(ctx->insn_flags & ASE_MT);
6273 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6274 rn = "MVPConf0";
6275 break;
6276 case 3:
6277 CP0_CHECK(ctx->insn_flags & ASE_MT);
6278 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6279 rn = "MVPConf1";
6280 break;
6281 case 4:
6282 CP0_CHECK(ctx->vp);
6283 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6284 rn = "VPControl";
6285 break;
6286 default:
6287 goto cp0_unimplemented;
6289 break;
6290 case 1:
6291 switch (sel) {
6292 case 0:
6293 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6294 gen_helper_mfc0_random(arg, cpu_env);
6295 rn = "Random";
6296 break;
6297 case 1:
6298 CP0_CHECK(ctx->insn_flags & ASE_MT);
6299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6300 rn = "VPEControl";
6301 break;
6302 case 2:
6303 CP0_CHECK(ctx->insn_flags & ASE_MT);
6304 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6305 rn = "VPEConf0";
6306 break;
6307 case 3:
6308 CP0_CHECK(ctx->insn_flags & ASE_MT);
6309 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6310 rn = "VPEConf1";
6311 break;
6312 case 4:
6313 CP0_CHECK(ctx->insn_flags & ASE_MT);
6314 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6315 rn = "YQMask";
6316 break;
6317 case 5:
6318 CP0_CHECK(ctx->insn_flags & ASE_MT);
6319 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6320 rn = "VPESchedule";
6321 break;
6322 case 6:
6323 CP0_CHECK(ctx->insn_flags & ASE_MT);
6324 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6325 rn = "VPEScheFBack";
6326 break;
6327 case 7:
6328 CP0_CHECK(ctx->insn_flags & ASE_MT);
6329 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6330 rn = "VPEOpt";
6331 break;
6332 default:
6333 goto cp0_unimplemented;
6335 break;
6336 case 2:
6337 switch (sel) {
6338 case 0:
6339 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6340 rn = "EntryLo0";
6341 break;
6342 case 1:
6343 CP0_CHECK(ctx->insn_flags & ASE_MT);
6344 gen_helper_mfc0_tcstatus(arg, cpu_env);
6345 rn = "TCStatus";
6346 break;
6347 case 2:
6348 CP0_CHECK(ctx->insn_flags & ASE_MT);
6349 gen_helper_mfc0_tcbind(arg, cpu_env);
6350 rn = "TCBind";
6351 break;
6352 case 3:
6353 CP0_CHECK(ctx->insn_flags & ASE_MT);
6354 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6355 rn = "TCRestart";
6356 break;
6357 case 4:
6358 CP0_CHECK(ctx->insn_flags & ASE_MT);
6359 gen_helper_dmfc0_tchalt(arg, cpu_env);
6360 rn = "TCHalt";
6361 break;
6362 case 5:
6363 CP0_CHECK(ctx->insn_flags & ASE_MT);
6364 gen_helper_dmfc0_tccontext(arg, cpu_env);
6365 rn = "TCContext";
6366 break;
6367 case 6:
6368 CP0_CHECK(ctx->insn_flags & ASE_MT);
6369 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6370 rn = "TCSchedule";
6371 break;
6372 case 7:
6373 CP0_CHECK(ctx->insn_flags & ASE_MT);
6374 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6375 rn = "TCScheFBack";
6376 break;
6377 default:
6378 goto cp0_unimplemented;
6380 break;
6381 case 3:
6382 switch (sel) {
6383 case 0:
6384 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6385 rn = "EntryLo1";
6386 break;
6387 case 1:
6388 CP0_CHECK(ctx->vp);
6389 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6390 rn = "GlobalNumber";
6391 break;
6392 default:
6393 goto cp0_unimplemented;
6395 break;
6396 case 4:
6397 switch (sel) {
6398 case 0:
6399 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6400 rn = "Context";
6401 break;
6402 case 1:
6403 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6404 rn = "ContextConfig";
6405 goto cp0_unimplemented;
6406 // break;
6407 case 2:
6408 CP0_CHECK(ctx->ulri);
6409 tcg_gen_ld_tl(arg, cpu_env,
6410 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6411 rn = "UserLocal";
6412 break;
6413 default:
6414 goto cp0_unimplemented;
6416 break;
6417 case 5:
6418 switch (sel) {
6419 case 0:
6420 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6421 rn = "PageMask";
6422 break;
6423 case 1:
6424 check_insn(ctx, ISA_MIPS32R2);
6425 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6426 rn = "PageGrain";
6427 break;
6428 default:
6429 goto cp0_unimplemented;
6431 break;
6432 case 6:
6433 switch (sel) {
6434 case 0:
6435 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6436 rn = "Wired";
6437 break;
6438 case 1:
6439 check_insn(ctx, ISA_MIPS32R2);
6440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6441 rn = "SRSConf0";
6442 break;
6443 case 2:
6444 check_insn(ctx, ISA_MIPS32R2);
6445 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6446 rn = "SRSConf1";
6447 break;
6448 case 3:
6449 check_insn(ctx, ISA_MIPS32R2);
6450 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6451 rn = "SRSConf2";
6452 break;
6453 case 4:
6454 check_insn(ctx, ISA_MIPS32R2);
6455 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6456 rn = "SRSConf3";
6457 break;
6458 case 5:
6459 check_insn(ctx, ISA_MIPS32R2);
6460 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6461 rn = "SRSConf4";
6462 break;
6463 default:
6464 goto cp0_unimplemented;
6466 break;
6467 case 7:
6468 switch (sel) {
6469 case 0:
6470 check_insn(ctx, ISA_MIPS32R2);
6471 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6472 rn = "HWREna";
6473 break;
6474 default:
6475 goto cp0_unimplemented;
6477 break;
6478 case 8:
6479 switch (sel) {
6480 case 0:
6481 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6482 rn = "BadVAddr";
6483 break;
6484 case 1:
6485 CP0_CHECK(ctx->bi);
6486 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6487 rn = "BadInstr";
6488 break;
6489 case 2:
6490 CP0_CHECK(ctx->bp);
6491 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6492 rn = "BadInstrP";
6493 break;
6494 default:
6495 goto cp0_unimplemented;
6497 break;
6498 case 9:
6499 switch (sel) {
6500 case 0:
6501 /* Mark as an IO operation because we read the time. */
6502 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6503 gen_io_start();
6505 gen_helper_mfc0_count(arg, cpu_env);
6506 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6507 gen_io_end();
6509 /* Break the TB to be able to take timer interrupts immediately
6510 after reading count. */
6511 ctx->bstate = BS_STOP;
6512 rn = "Count";
6513 break;
6514 /* 6,7 are implementation dependent */
6515 default:
6516 goto cp0_unimplemented;
6518 break;
6519 case 10:
6520 switch (sel) {
6521 case 0:
6522 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6523 rn = "EntryHi";
6524 break;
6525 default:
6526 goto cp0_unimplemented;
6528 break;
6529 case 11:
6530 switch (sel) {
6531 case 0:
6532 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6533 rn = "Compare";
6534 break;
6535 /* 6,7 are implementation dependent */
6536 default:
6537 goto cp0_unimplemented;
6539 break;
6540 case 12:
6541 switch (sel) {
6542 case 0:
6543 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6544 rn = "Status";
6545 break;
6546 case 1:
6547 check_insn(ctx, ISA_MIPS32R2);
6548 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6549 rn = "IntCtl";
6550 break;
6551 case 2:
6552 check_insn(ctx, ISA_MIPS32R2);
6553 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6554 rn = "SRSCtl";
6555 break;
6556 case 3:
6557 check_insn(ctx, ISA_MIPS32R2);
6558 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6559 rn = "SRSMap";
6560 break;
6561 default:
6562 goto cp0_unimplemented;
6564 break;
6565 case 13:
6566 switch (sel) {
6567 case 0:
6568 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6569 rn = "Cause";
6570 break;
6571 default:
6572 goto cp0_unimplemented;
6574 break;
6575 case 14:
6576 switch (sel) {
6577 case 0:
6578 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6579 rn = "EPC";
6580 break;
6581 default:
6582 goto cp0_unimplemented;
6584 break;
6585 case 15:
6586 switch (sel) {
6587 case 0:
6588 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6589 rn = "PRid";
6590 break;
6591 case 1:
6592 check_insn(ctx, ISA_MIPS32R2);
6593 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6594 rn = "EBase";
6595 break;
6596 case 3:
6597 check_insn(ctx, ISA_MIPS32R2);
6598 CP0_CHECK(ctx->cmgcr);
6599 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6600 rn = "CMGCRBase";
6601 break;
6602 default:
6603 goto cp0_unimplemented;
6605 break;
6606 case 16:
6607 switch (sel) {
6608 case 0:
6609 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6610 rn = "Config";
6611 break;
6612 case 1:
6613 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6614 rn = "Config1";
6615 break;
6616 case 2:
6617 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6618 rn = "Config2";
6619 break;
6620 case 3:
6621 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6622 rn = "Config3";
6623 break;
6624 case 4:
6625 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6626 rn = "Config4";
6627 break;
6628 case 5:
6629 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6630 rn = "Config5";
6631 break;
6632 /* 6,7 are implementation dependent */
6633 case 6:
6634 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6635 rn = "Config6";
6636 break;
6637 case 7:
6638 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6639 rn = "Config7";
6640 break;
6641 default:
6642 goto cp0_unimplemented;
6644 break;
6645 case 17:
6646 switch (sel) {
6647 case 0:
6648 gen_helper_dmfc0_lladdr(arg, cpu_env);
6649 rn = "LLAddr";
6650 break;
6651 default:
6652 goto cp0_unimplemented;
6654 break;
6655 case 18:
6656 switch (sel) {
6657 case 0 ... 7:
6658 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6659 rn = "WatchLo";
6660 break;
6661 default:
6662 goto cp0_unimplemented;
6664 break;
6665 case 19:
6666 switch (sel) {
6667 case 0 ... 7:
6668 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6669 rn = "WatchHi";
6670 break;
6671 default:
6672 goto cp0_unimplemented;
6674 break;
6675 case 20:
6676 switch (sel) {
6677 case 0:
6678 check_insn(ctx, ISA_MIPS3);
6679 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6680 rn = "XContext";
6681 break;
6682 default:
6683 goto cp0_unimplemented;
6685 break;
6686 case 21:
6687 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6688 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6689 switch (sel) {
6690 case 0:
6691 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6692 rn = "Framemask";
6693 break;
6694 default:
6695 goto cp0_unimplemented;
6697 break;
6698 case 22:
6699 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6700 rn = "'Diagnostic"; /* implementation dependent */
6701 break;
6702 case 23:
6703 switch (sel) {
6704 case 0:
6705 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6706 rn = "Debug";
6707 break;
6708 case 1:
6709 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6710 rn = "TraceControl";
6711 // break;
6712 case 2:
6713 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6714 rn = "TraceControl2";
6715 // break;
6716 case 3:
6717 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6718 rn = "UserTraceData";
6719 // break;
6720 case 4:
6721 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6722 rn = "TraceBPC";
6723 // break;
6724 default:
6725 goto cp0_unimplemented;
6727 break;
6728 case 24:
6729 switch (sel) {
6730 case 0:
6731 /* EJTAG support */
6732 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6733 rn = "DEPC";
6734 break;
6735 default:
6736 goto cp0_unimplemented;
6738 break;
6739 case 25:
6740 switch (sel) {
6741 case 0:
6742 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6743 rn = "Performance0";
6744 break;
6745 case 1:
6746 // gen_helper_dmfc0_performance1(arg);
6747 rn = "Performance1";
6748 // break;
6749 case 2:
6750 // gen_helper_dmfc0_performance2(arg);
6751 rn = "Performance2";
6752 // break;
6753 case 3:
6754 // gen_helper_dmfc0_performance3(arg);
6755 rn = "Performance3";
6756 // break;
6757 case 4:
6758 // gen_helper_dmfc0_performance4(arg);
6759 rn = "Performance4";
6760 // break;
6761 case 5:
6762 // gen_helper_dmfc0_performance5(arg);
6763 rn = "Performance5";
6764 // break;
6765 case 6:
6766 // gen_helper_dmfc0_performance6(arg);
6767 rn = "Performance6";
6768 // break;
6769 case 7:
6770 // gen_helper_dmfc0_performance7(arg);
6771 rn = "Performance7";
6772 // break;
6773 default:
6774 goto cp0_unimplemented;
6776 break;
6777 case 26:
6778 switch (sel) {
6779 case 0:
6780 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6781 rn = "ErrCtl";
6782 break;
6783 default:
6784 goto cp0_unimplemented;
6786 break;
6787 case 27:
6788 switch (sel) {
6789 /* ignored */
6790 case 0 ... 3:
6791 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6792 rn = "CacheErr";
6793 break;
6794 default:
6795 goto cp0_unimplemented;
6797 break;
6798 case 28:
6799 switch (sel) {
6800 case 0:
6801 case 2:
6802 case 4:
6803 case 6:
6804 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
6805 rn = "TagLo";
6806 break;
6807 case 1:
6808 case 3:
6809 case 5:
6810 case 7:
6811 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6812 rn = "DataLo";
6813 break;
6814 default:
6815 goto cp0_unimplemented;
6817 break;
6818 case 29:
6819 switch (sel) {
6820 case 0:
6821 case 2:
6822 case 4:
6823 case 6:
6824 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6825 rn = "TagHi";
6826 break;
6827 case 1:
6828 case 3:
6829 case 5:
6830 case 7:
6831 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6832 rn = "DataHi";
6833 break;
6834 default:
6835 goto cp0_unimplemented;
6837 break;
6838 case 30:
6839 switch (sel) {
6840 case 0:
6841 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6842 rn = "ErrorEPC";
6843 break;
6844 default:
6845 goto cp0_unimplemented;
6847 break;
6848 case 31:
6849 switch (sel) {
6850 case 0:
6851 /* EJTAG support */
6852 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6853 rn = "DESAVE";
6854 break;
6855 case 2 ... 7:
6856 CP0_CHECK(ctx->kscrexist & (1 << sel));
6857 tcg_gen_ld_tl(arg, cpu_env,
6858 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6859 rn = "KScratch";
6860 break;
6861 default:
6862 goto cp0_unimplemented;
6864 break;
6865 default:
6866 goto cp0_unimplemented;
6868 (void)rn; /* avoid a compiler warning */
6869 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6870 return;
6872 cp0_unimplemented:
6873 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6874 gen_mfc0_unimplemented(ctx, arg);
6877 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6879 const char *rn = "invalid";
6881 if (sel != 0)
6882 check_insn(ctx, ISA_MIPS64);
6884 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6885 gen_io_start();
6888 switch (reg) {
6889 case 0:
6890 switch (sel) {
6891 case 0:
6892 gen_helper_mtc0_index(cpu_env, arg);
6893 rn = "Index";
6894 break;
6895 case 1:
6896 CP0_CHECK(ctx->insn_flags & ASE_MT);
6897 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6898 rn = "MVPControl";
6899 break;
6900 case 2:
6901 CP0_CHECK(ctx->insn_flags & ASE_MT);
6902 /* ignored */
6903 rn = "MVPConf0";
6904 break;
6905 case 3:
6906 CP0_CHECK(ctx->insn_flags & ASE_MT);
6907 /* ignored */
6908 rn = "MVPConf1";
6909 break;
6910 case 4:
6911 CP0_CHECK(ctx->vp);
6912 /* ignored */
6913 rn = "VPControl";
6914 break;
6915 default:
6916 goto cp0_unimplemented;
6918 break;
6919 case 1:
6920 switch (sel) {
6921 case 0:
6922 /* ignored */
6923 rn = "Random";
6924 break;
6925 case 1:
6926 CP0_CHECK(ctx->insn_flags & ASE_MT);
6927 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6928 rn = "VPEControl";
6929 break;
6930 case 2:
6931 CP0_CHECK(ctx->insn_flags & ASE_MT);
6932 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6933 rn = "VPEConf0";
6934 break;
6935 case 3:
6936 CP0_CHECK(ctx->insn_flags & ASE_MT);
6937 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6938 rn = "VPEConf1";
6939 break;
6940 case 4:
6941 CP0_CHECK(ctx->insn_flags & ASE_MT);
6942 gen_helper_mtc0_yqmask(cpu_env, arg);
6943 rn = "YQMask";
6944 break;
6945 case 5:
6946 CP0_CHECK(ctx->insn_flags & ASE_MT);
6947 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6948 rn = "VPESchedule";
6949 break;
6950 case 6:
6951 CP0_CHECK(ctx->insn_flags & ASE_MT);
6952 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6953 rn = "VPEScheFBack";
6954 break;
6955 case 7:
6956 CP0_CHECK(ctx->insn_flags & ASE_MT);
6957 gen_helper_mtc0_vpeopt(cpu_env, arg);
6958 rn = "VPEOpt";
6959 break;
6960 default:
6961 goto cp0_unimplemented;
6963 break;
6964 case 2:
6965 switch (sel) {
6966 case 0:
6967 gen_helper_dmtc0_entrylo0(cpu_env, arg);
6968 rn = "EntryLo0";
6969 break;
6970 case 1:
6971 CP0_CHECK(ctx->insn_flags & ASE_MT);
6972 gen_helper_mtc0_tcstatus(cpu_env, arg);
6973 rn = "TCStatus";
6974 break;
6975 case 2:
6976 CP0_CHECK(ctx->insn_flags & ASE_MT);
6977 gen_helper_mtc0_tcbind(cpu_env, arg);
6978 rn = "TCBind";
6979 break;
6980 case 3:
6981 CP0_CHECK(ctx->insn_flags & ASE_MT);
6982 gen_helper_mtc0_tcrestart(cpu_env, arg);
6983 rn = "TCRestart";
6984 break;
6985 case 4:
6986 CP0_CHECK(ctx->insn_flags & ASE_MT);
6987 gen_helper_mtc0_tchalt(cpu_env, arg);
6988 rn = "TCHalt";
6989 break;
6990 case 5:
6991 CP0_CHECK(ctx->insn_flags & ASE_MT);
6992 gen_helper_mtc0_tccontext(cpu_env, arg);
6993 rn = "TCContext";
6994 break;
6995 case 6:
6996 CP0_CHECK(ctx->insn_flags & ASE_MT);
6997 gen_helper_mtc0_tcschedule(cpu_env, arg);
6998 rn = "TCSchedule";
6999 break;
7000 case 7:
7001 CP0_CHECK(ctx->insn_flags & ASE_MT);
7002 gen_helper_mtc0_tcschefback(cpu_env, arg);
7003 rn = "TCScheFBack";
7004 break;
7005 default:
7006 goto cp0_unimplemented;
7008 break;
7009 case 3:
7010 switch (sel) {
7011 case 0:
7012 gen_helper_dmtc0_entrylo1(cpu_env, arg);
7013 rn = "EntryLo1";
7014 break;
7015 case 1:
7016 CP0_CHECK(ctx->vp);
7017 /* ignored */
7018 rn = "GlobalNumber";
7019 break;
7020 default:
7021 goto cp0_unimplemented;
7023 break;
7024 case 4:
7025 switch (sel) {
7026 case 0:
7027 gen_helper_mtc0_context(cpu_env, arg);
7028 rn = "Context";
7029 break;
7030 case 1:
7031 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7032 rn = "ContextConfig";
7033 goto cp0_unimplemented;
7034 // break;
7035 case 2:
7036 CP0_CHECK(ctx->ulri);
7037 tcg_gen_st_tl(arg, cpu_env,
7038 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7039 rn = "UserLocal";
7040 break;
7041 default:
7042 goto cp0_unimplemented;
7044 break;
7045 case 5:
7046 switch (sel) {
7047 case 0:
7048 gen_helper_mtc0_pagemask(cpu_env, arg);
7049 rn = "PageMask";
7050 break;
7051 case 1:
7052 check_insn(ctx, ISA_MIPS32R2);
7053 gen_helper_mtc0_pagegrain(cpu_env, arg);
7054 rn = "PageGrain";
7055 break;
7056 default:
7057 goto cp0_unimplemented;
7059 break;
7060 case 6:
7061 switch (sel) {
7062 case 0:
7063 gen_helper_mtc0_wired(cpu_env, arg);
7064 rn = "Wired";
7065 break;
7066 case 1:
7067 check_insn(ctx, ISA_MIPS32R2);
7068 gen_helper_mtc0_srsconf0(cpu_env, arg);
7069 rn = "SRSConf0";
7070 break;
7071 case 2:
7072 check_insn(ctx, ISA_MIPS32R2);
7073 gen_helper_mtc0_srsconf1(cpu_env, arg);
7074 rn = "SRSConf1";
7075 break;
7076 case 3:
7077 check_insn(ctx, ISA_MIPS32R2);
7078 gen_helper_mtc0_srsconf2(cpu_env, arg);
7079 rn = "SRSConf2";
7080 break;
7081 case 4:
7082 check_insn(ctx, ISA_MIPS32R2);
7083 gen_helper_mtc0_srsconf3(cpu_env, arg);
7084 rn = "SRSConf3";
7085 break;
7086 case 5:
7087 check_insn(ctx, ISA_MIPS32R2);
7088 gen_helper_mtc0_srsconf4(cpu_env, arg);
7089 rn = "SRSConf4";
7090 break;
7091 default:
7092 goto cp0_unimplemented;
7094 break;
7095 case 7:
7096 switch (sel) {
7097 case 0:
7098 check_insn(ctx, ISA_MIPS32R2);
7099 gen_helper_mtc0_hwrena(cpu_env, arg);
7100 ctx->bstate = BS_STOP;
7101 rn = "HWREna";
7102 break;
7103 default:
7104 goto cp0_unimplemented;
7106 break;
7107 case 8:
7108 switch (sel) {
7109 case 0:
7110 /* ignored */
7111 rn = "BadVAddr";
7112 break;
7113 case 1:
7114 /* ignored */
7115 rn = "BadInstr";
7116 break;
7117 case 2:
7118 /* ignored */
7119 rn = "BadInstrP";
7120 break;
7121 default:
7122 goto cp0_unimplemented;
7124 break;
7125 case 9:
7126 switch (sel) {
7127 case 0:
7128 gen_helper_mtc0_count(cpu_env, arg);
7129 rn = "Count";
7130 break;
7131 /* 6,7 are implementation dependent */
7132 default:
7133 goto cp0_unimplemented;
7135 /* Stop translation as we may have switched the execution mode */
7136 ctx->bstate = BS_STOP;
7137 break;
7138 case 10:
7139 switch (sel) {
7140 case 0:
7141 gen_helper_mtc0_entryhi(cpu_env, arg);
7142 rn = "EntryHi";
7143 break;
7144 default:
7145 goto cp0_unimplemented;
7147 break;
7148 case 11:
7149 switch (sel) {
7150 case 0:
7151 gen_helper_mtc0_compare(cpu_env, arg);
7152 rn = "Compare";
7153 break;
7154 /* 6,7 are implementation dependent */
7155 default:
7156 goto cp0_unimplemented;
7158 /* Stop translation as we may have switched the execution mode */
7159 ctx->bstate = BS_STOP;
7160 break;
7161 case 12:
7162 switch (sel) {
7163 case 0:
7164 save_cpu_state(ctx, 1);
7165 gen_helper_mtc0_status(cpu_env, arg);
7166 /* BS_STOP isn't good enough here, hflags may have changed. */
7167 gen_save_pc(ctx->pc + 4);
7168 ctx->bstate = BS_EXCP;
7169 rn = "Status";
7170 break;
7171 case 1:
7172 check_insn(ctx, ISA_MIPS32R2);
7173 gen_helper_mtc0_intctl(cpu_env, arg);
7174 /* Stop translation as we may have switched the execution mode */
7175 ctx->bstate = BS_STOP;
7176 rn = "IntCtl";
7177 break;
7178 case 2:
7179 check_insn(ctx, ISA_MIPS32R2);
7180 gen_helper_mtc0_srsctl(cpu_env, arg);
7181 /* Stop translation as we may have switched the execution mode */
7182 ctx->bstate = BS_STOP;
7183 rn = "SRSCtl";
7184 break;
7185 case 3:
7186 check_insn(ctx, ISA_MIPS32R2);
7187 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7188 /* Stop translation as we may have switched the execution mode */
7189 ctx->bstate = BS_STOP;
7190 rn = "SRSMap";
7191 break;
7192 default:
7193 goto cp0_unimplemented;
7195 break;
7196 case 13:
7197 switch (sel) {
7198 case 0:
7199 save_cpu_state(ctx, 1);
7200 /* Mark as an IO operation because we may trigger a software
7201 interrupt. */
7202 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7203 gen_io_start();
7205 gen_helper_mtc0_cause(cpu_env, arg);
7206 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7207 gen_io_end();
7209 /* Stop translation as we may have triggered an intetrupt */
7210 ctx->bstate = BS_STOP;
7211 rn = "Cause";
7212 break;
7213 default:
7214 goto cp0_unimplemented;
7216 break;
7217 case 14:
7218 switch (sel) {
7219 case 0:
7220 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7221 rn = "EPC";
7222 break;
7223 default:
7224 goto cp0_unimplemented;
7226 break;
7227 case 15:
7228 switch (sel) {
7229 case 0:
7230 /* ignored */
7231 rn = "PRid";
7232 break;
7233 case 1:
7234 check_insn(ctx, ISA_MIPS32R2);
7235 gen_helper_mtc0_ebase(cpu_env, arg);
7236 rn = "EBase";
7237 break;
7238 default:
7239 goto cp0_unimplemented;
7241 break;
7242 case 16:
7243 switch (sel) {
7244 case 0:
7245 gen_helper_mtc0_config0(cpu_env, arg);
7246 rn = "Config";
7247 /* Stop translation as we may have switched the execution mode */
7248 ctx->bstate = BS_STOP;
7249 break;
7250 case 1:
7251 /* ignored, read only */
7252 rn = "Config1";
7253 break;
7254 case 2:
7255 gen_helper_mtc0_config2(cpu_env, arg);
7256 rn = "Config2";
7257 /* Stop translation as we may have switched the execution mode */
7258 ctx->bstate = BS_STOP;
7259 break;
7260 case 3:
7261 gen_helper_mtc0_config3(cpu_env, arg);
7262 rn = "Config3";
7263 /* Stop translation as we may have switched the execution mode */
7264 ctx->bstate = BS_STOP;
7265 break;
7266 case 4:
7267 /* currently ignored */
7268 rn = "Config4";
7269 break;
7270 case 5:
7271 gen_helper_mtc0_config5(cpu_env, arg);
7272 rn = "Config5";
7273 /* Stop translation as we may have switched the execution mode */
7274 ctx->bstate = BS_STOP;
7275 break;
7276 /* 6,7 are implementation dependent */
7277 default:
7278 rn = "Invalid config selector";
7279 goto cp0_unimplemented;
7281 break;
7282 case 17:
7283 switch (sel) {
7284 case 0:
7285 gen_helper_mtc0_lladdr(cpu_env, arg);
7286 rn = "LLAddr";
7287 break;
7288 default:
7289 goto cp0_unimplemented;
7291 break;
7292 case 18:
7293 switch (sel) {
7294 case 0 ... 7:
7295 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7296 rn = "WatchLo";
7297 break;
7298 default:
7299 goto cp0_unimplemented;
7301 break;
7302 case 19:
7303 switch (sel) {
7304 case 0 ... 7:
7305 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7306 rn = "WatchHi";
7307 break;
7308 default:
7309 goto cp0_unimplemented;
7311 break;
7312 case 20:
7313 switch (sel) {
7314 case 0:
7315 check_insn(ctx, ISA_MIPS3);
7316 gen_helper_mtc0_xcontext(cpu_env, arg);
7317 rn = "XContext";
7318 break;
7319 default:
7320 goto cp0_unimplemented;
7322 break;
7323 case 21:
7324 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7325 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7326 switch (sel) {
7327 case 0:
7328 gen_helper_mtc0_framemask(cpu_env, arg);
7329 rn = "Framemask";
7330 break;
7331 default:
7332 goto cp0_unimplemented;
7334 break;
7335 case 22:
7336 /* ignored */
7337 rn = "Diagnostic"; /* implementation dependent */
7338 break;
7339 case 23:
7340 switch (sel) {
7341 case 0:
7342 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7343 /* BS_STOP isn't good enough here, hflags may have changed. */
7344 gen_save_pc(ctx->pc + 4);
7345 ctx->bstate = BS_EXCP;
7346 rn = "Debug";
7347 break;
7348 case 1:
7349 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7350 /* Stop translation as we may have switched the execution mode */
7351 ctx->bstate = BS_STOP;
7352 rn = "TraceControl";
7353 // break;
7354 case 2:
7355 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7356 /* Stop translation as we may have switched the execution mode */
7357 ctx->bstate = BS_STOP;
7358 rn = "TraceControl2";
7359 // break;
7360 case 3:
7361 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7362 /* Stop translation as we may have switched the execution mode */
7363 ctx->bstate = BS_STOP;
7364 rn = "UserTraceData";
7365 // break;
7366 case 4:
7367 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7368 /* Stop translation as we may have switched the execution mode */
7369 ctx->bstate = BS_STOP;
7370 rn = "TraceBPC";
7371 // break;
7372 default:
7373 goto cp0_unimplemented;
7375 break;
7376 case 24:
7377 switch (sel) {
7378 case 0:
7379 /* EJTAG support */
7380 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7381 rn = "DEPC";
7382 break;
7383 default:
7384 goto cp0_unimplemented;
7386 break;
7387 case 25:
7388 switch (sel) {
7389 case 0:
7390 gen_helper_mtc0_performance0(cpu_env, arg);
7391 rn = "Performance0";
7392 break;
7393 case 1:
7394 // gen_helper_mtc0_performance1(cpu_env, arg);
7395 rn = "Performance1";
7396 // break;
7397 case 2:
7398 // gen_helper_mtc0_performance2(cpu_env, arg);
7399 rn = "Performance2";
7400 // break;
7401 case 3:
7402 // gen_helper_mtc0_performance3(cpu_env, arg);
7403 rn = "Performance3";
7404 // break;
7405 case 4:
7406 // gen_helper_mtc0_performance4(cpu_env, arg);
7407 rn = "Performance4";
7408 // break;
7409 case 5:
7410 // gen_helper_mtc0_performance5(cpu_env, arg);
7411 rn = "Performance5";
7412 // break;
7413 case 6:
7414 // gen_helper_mtc0_performance6(cpu_env, arg);
7415 rn = "Performance6";
7416 // break;
7417 case 7:
7418 // gen_helper_mtc0_performance7(cpu_env, arg);
7419 rn = "Performance7";
7420 // break;
7421 default:
7422 goto cp0_unimplemented;
7424 break;
7425 case 26:
7426 switch (sel) {
7427 case 0:
7428 gen_helper_mtc0_errctl(cpu_env, arg);
7429 ctx->bstate = BS_STOP;
7430 rn = "ErrCtl";
7431 break;
7432 default:
7433 goto cp0_unimplemented;
7435 break;
7436 case 27:
7437 switch (sel) {
7438 case 0 ... 3:
7439 /* ignored */
7440 rn = "CacheErr";
7441 break;
7442 default:
7443 goto cp0_unimplemented;
7445 break;
7446 case 28:
7447 switch (sel) {
7448 case 0:
7449 case 2:
7450 case 4:
7451 case 6:
7452 gen_helper_mtc0_taglo(cpu_env, arg);
7453 rn = "TagLo";
7454 break;
7455 case 1:
7456 case 3:
7457 case 5:
7458 case 7:
7459 gen_helper_mtc0_datalo(cpu_env, arg);
7460 rn = "DataLo";
7461 break;
7462 default:
7463 goto cp0_unimplemented;
7465 break;
7466 case 29:
7467 switch (sel) {
7468 case 0:
7469 case 2:
7470 case 4:
7471 case 6:
7472 gen_helper_mtc0_taghi(cpu_env, arg);
7473 rn = "TagHi";
7474 break;
7475 case 1:
7476 case 3:
7477 case 5:
7478 case 7:
7479 gen_helper_mtc0_datahi(cpu_env, arg);
7480 rn = "DataHi";
7481 break;
7482 default:
7483 rn = "invalid sel";
7484 goto cp0_unimplemented;
7486 break;
7487 case 30:
7488 switch (sel) {
7489 case 0:
7490 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7491 rn = "ErrorEPC";
7492 break;
7493 default:
7494 goto cp0_unimplemented;
7496 break;
7497 case 31:
7498 switch (sel) {
7499 case 0:
7500 /* EJTAG support */
7501 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7502 rn = "DESAVE";
7503 break;
7504 case 2 ... 7:
7505 CP0_CHECK(ctx->kscrexist & (1 << sel));
7506 tcg_gen_st_tl(arg, cpu_env,
7507 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7508 rn = "KScratch";
7509 break;
7510 default:
7511 goto cp0_unimplemented;
7513 /* Stop translation as we may have switched the execution mode */
7514 ctx->bstate = BS_STOP;
7515 break;
7516 default:
7517 goto cp0_unimplemented;
7519 (void)rn; /* avoid a compiler warning */
7520 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7521 /* For simplicity assume that all writes can cause interrupts. */
7522 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7523 gen_io_end();
7524 ctx->bstate = BS_STOP;
7526 return;
7528 cp0_unimplemented:
7529 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7531 #endif /* TARGET_MIPS64 */
7533 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7534 int u, int sel, int h)
7536 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7537 TCGv t0 = tcg_temp_local_new();
7539 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7540 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7541 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7542 tcg_gen_movi_tl(t0, -1);
7543 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7544 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7545 tcg_gen_movi_tl(t0, -1);
7546 else if (u == 0) {
7547 switch (rt) {
7548 case 1:
7549 switch (sel) {
7550 case 1:
7551 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7552 break;
7553 case 2:
7554 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7555 break;
7556 default:
7557 goto die;
7558 break;
7560 break;
7561 case 2:
7562 switch (sel) {
7563 case 1:
7564 gen_helper_mftc0_tcstatus(t0, cpu_env);
7565 break;
7566 case 2:
7567 gen_helper_mftc0_tcbind(t0, cpu_env);
7568 break;
7569 case 3:
7570 gen_helper_mftc0_tcrestart(t0, cpu_env);
7571 break;
7572 case 4:
7573 gen_helper_mftc0_tchalt(t0, cpu_env);
7574 break;
7575 case 5:
7576 gen_helper_mftc0_tccontext(t0, cpu_env);
7577 break;
7578 case 6:
7579 gen_helper_mftc0_tcschedule(t0, cpu_env);
7580 break;
7581 case 7:
7582 gen_helper_mftc0_tcschefback(t0, cpu_env);
7583 break;
7584 default:
7585 gen_mfc0(ctx, t0, rt, sel);
7586 break;
7588 break;
7589 case 10:
7590 switch (sel) {
7591 case 0:
7592 gen_helper_mftc0_entryhi(t0, cpu_env);
7593 break;
7594 default:
7595 gen_mfc0(ctx, t0, rt, sel);
7596 break;
7598 case 12:
7599 switch (sel) {
7600 case 0:
7601 gen_helper_mftc0_status(t0, cpu_env);
7602 break;
7603 default:
7604 gen_mfc0(ctx, t0, rt, sel);
7605 break;
7607 case 13:
7608 switch (sel) {
7609 case 0:
7610 gen_helper_mftc0_cause(t0, cpu_env);
7611 break;
7612 default:
7613 goto die;
7614 break;
7616 break;
7617 case 14:
7618 switch (sel) {
7619 case 0:
7620 gen_helper_mftc0_epc(t0, cpu_env);
7621 break;
7622 default:
7623 goto die;
7624 break;
7626 break;
7627 case 15:
7628 switch (sel) {
7629 case 1:
7630 gen_helper_mftc0_ebase(t0, cpu_env);
7631 break;
7632 default:
7633 goto die;
7634 break;
7636 break;
7637 case 16:
7638 switch (sel) {
7639 case 0 ... 7:
7640 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7641 break;
7642 default:
7643 goto die;
7644 break;
7646 break;
7647 case 23:
7648 switch (sel) {
7649 case 0:
7650 gen_helper_mftc0_debug(t0, cpu_env);
7651 break;
7652 default:
7653 gen_mfc0(ctx, t0, rt, sel);
7654 break;
7656 break;
7657 default:
7658 gen_mfc0(ctx, t0, rt, sel);
7660 } else switch (sel) {
7661 /* GPR registers. */
7662 case 0:
7663 gen_helper_1e0i(mftgpr, t0, rt);
7664 break;
7665 /* Auxiliary CPU registers */
7666 case 1:
7667 switch (rt) {
7668 case 0:
7669 gen_helper_1e0i(mftlo, t0, 0);
7670 break;
7671 case 1:
7672 gen_helper_1e0i(mfthi, t0, 0);
7673 break;
7674 case 2:
7675 gen_helper_1e0i(mftacx, t0, 0);
7676 break;
7677 case 4:
7678 gen_helper_1e0i(mftlo, t0, 1);
7679 break;
7680 case 5:
7681 gen_helper_1e0i(mfthi, t0, 1);
7682 break;
7683 case 6:
7684 gen_helper_1e0i(mftacx, t0, 1);
7685 break;
7686 case 8:
7687 gen_helper_1e0i(mftlo, t0, 2);
7688 break;
7689 case 9:
7690 gen_helper_1e0i(mfthi, t0, 2);
7691 break;
7692 case 10:
7693 gen_helper_1e0i(mftacx, t0, 2);
7694 break;
7695 case 12:
7696 gen_helper_1e0i(mftlo, t0, 3);
7697 break;
7698 case 13:
7699 gen_helper_1e0i(mfthi, t0, 3);
7700 break;
7701 case 14:
7702 gen_helper_1e0i(mftacx, t0, 3);
7703 break;
7704 case 16:
7705 gen_helper_mftdsp(t0, cpu_env);
7706 break;
7707 default:
7708 goto die;
7710 break;
7711 /* Floating point (COP1). */
7712 case 2:
7713 /* XXX: For now we support only a single FPU context. */
7714 if (h == 0) {
7715 TCGv_i32 fp0 = tcg_temp_new_i32();
7717 gen_load_fpr32(ctx, fp0, rt);
7718 tcg_gen_ext_i32_tl(t0, fp0);
7719 tcg_temp_free_i32(fp0);
7720 } else {
7721 TCGv_i32 fp0 = tcg_temp_new_i32();
7723 gen_load_fpr32h(ctx, fp0, rt);
7724 tcg_gen_ext_i32_tl(t0, fp0);
7725 tcg_temp_free_i32(fp0);
7727 break;
7728 case 3:
7729 /* XXX: For now we support only a single FPU context. */
7730 gen_helper_1e0i(cfc1, t0, rt);
7731 break;
7732 /* COP2: Not implemented. */
7733 case 4:
7734 case 5:
7735 /* fall through */
7736 default:
7737 goto die;
7739 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7740 gen_store_gpr(t0, rd);
7741 tcg_temp_free(t0);
7742 return;
7744 die:
7745 tcg_temp_free(t0);
7746 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7747 generate_exception_end(ctx, EXCP_RI);
7750 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7751 int u, int sel, int h)
7753 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7754 TCGv t0 = tcg_temp_local_new();
7756 gen_load_gpr(t0, rt);
7757 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7758 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7759 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7760 /* NOP */ ;
7761 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7762 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7763 /* NOP */ ;
7764 else if (u == 0) {
7765 switch (rd) {
7766 case 1:
7767 switch (sel) {
7768 case 1:
7769 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7770 break;
7771 case 2:
7772 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7773 break;
7774 default:
7775 goto die;
7776 break;
7778 break;
7779 case 2:
7780 switch (sel) {
7781 case 1:
7782 gen_helper_mttc0_tcstatus(cpu_env, t0);
7783 break;
7784 case 2:
7785 gen_helper_mttc0_tcbind(cpu_env, t0);
7786 break;
7787 case 3:
7788 gen_helper_mttc0_tcrestart(cpu_env, t0);
7789 break;
7790 case 4:
7791 gen_helper_mttc0_tchalt(cpu_env, t0);
7792 break;
7793 case 5:
7794 gen_helper_mttc0_tccontext(cpu_env, t0);
7795 break;
7796 case 6:
7797 gen_helper_mttc0_tcschedule(cpu_env, t0);
7798 break;
7799 case 7:
7800 gen_helper_mttc0_tcschefback(cpu_env, t0);
7801 break;
7802 default:
7803 gen_mtc0(ctx, t0, rd, sel);
7804 break;
7806 break;
7807 case 10:
7808 switch (sel) {
7809 case 0:
7810 gen_helper_mttc0_entryhi(cpu_env, t0);
7811 break;
7812 default:
7813 gen_mtc0(ctx, t0, rd, sel);
7814 break;
7816 case 12:
7817 switch (sel) {
7818 case 0:
7819 gen_helper_mttc0_status(cpu_env, t0);
7820 break;
7821 default:
7822 gen_mtc0(ctx, t0, rd, sel);
7823 break;
7825 case 13:
7826 switch (sel) {
7827 case 0:
7828 gen_helper_mttc0_cause(cpu_env, t0);
7829 break;
7830 default:
7831 goto die;
7832 break;
7834 break;
7835 case 15:
7836 switch (sel) {
7837 case 1:
7838 gen_helper_mttc0_ebase(cpu_env, t0);
7839 break;
7840 default:
7841 goto die;
7842 break;
7844 break;
7845 case 23:
7846 switch (sel) {
7847 case 0:
7848 gen_helper_mttc0_debug(cpu_env, t0);
7849 break;
7850 default:
7851 gen_mtc0(ctx, t0, rd, sel);
7852 break;
7854 break;
7855 default:
7856 gen_mtc0(ctx, t0, rd, sel);
7858 } else switch (sel) {
7859 /* GPR registers. */
7860 case 0:
7861 gen_helper_0e1i(mttgpr, t0, rd);
7862 break;
7863 /* Auxiliary CPU registers */
7864 case 1:
7865 switch (rd) {
7866 case 0:
7867 gen_helper_0e1i(mttlo, t0, 0);
7868 break;
7869 case 1:
7870 gen_helper_0e1i(mtthi, t0, 0);
7871 break;
7872 case 2:
7873 gen_helper_0e1i(mttacx, t0, 0);
7874 break;
7875 case 4:
7876 gen_helper_0e1i(mttlo, t0, 1);
7877 break;
7878 case 5:
7879 gen_helper_0e1i(mtthi, t0, 1);
7880 break;
7881 case 6:
7882 gen_helper_0e1i(mttacx, t0, 1);
7883 break;
7884 case 8:
7885 gen_helper_0e1i(mttlo, t0, 2);
7886 break;
7887 case 9:
7888 gen_helper_0e1i(mtthi, t0, 2);
7889 break;
7890 case 10:
7891 gen_helper_0e1i(mttacx, t0, 2);
7892 break;
7893 case 12:
7894 gen_helper_0e1i(mttlo, t0, 3);
7895 break;
7896 case 13:
7897 gen_helper_0e1i(mtthi, t0, 3);
7898 break;
7899 case 14:
7900 gen_helper_0e1i(mttacx, t0, 3);
7901 break;
7902 case 16:
7903 gen_helper_mttdsp(cpu_env, t0);
7904 break;
7905 default:
7906 goto die;
7908 break;
7909 /* Floating point (COP1). */
7910 case 2:
7911 /* XXX: For now we support only a single FPU context. */
7912 if (h == 0) {
7913 TCGv_i32 fp0 = tcg_temp_new_i32();
7915 tcg_gen_trunc_tl_i32(fp0, t0);
7916 gen_store_fpr32(ctx, fp0, rd);
7917 tcg_temp_free_i32(fp0);
7918 } else {
7919 TCGv_i32 fp0 = tcg_temp_new_i32();
7921 tcg_gen_trunc_tl_i32(fp0, t0);
7922 gen_store_fpr32h(ctx, fp0, rd);
7923 tcg_temp_free_i32(fp0);
7925 break;
7926 case 3:
7927 /* XXX: For now we support only a single FPU context. */
7929 TCGv_i32 fs_tmp = tcg_const_i32(rd);
7931 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7932 tcg_temp_free_i32(fs_tmp);
7934 /* Stop translation as we may have changed hflags */
7935 ctx->bstate = BS_STOP;
7936 break;
7937 /* COP2: Not implemented. */
7938 case 4:
7939 case 5:
7940 /* fall through */
7941 default:
7942 goto die;
7944 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7945 tcg_temp_free(t0);
7946 return;
7948 die:
7949 tcg_temp_free(t0);
7950 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7951 generate_exception_end(ctx, EXCP_RI);
7954 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
7956 const char *opn = "ldst";
7958 check_cp0_enabled(ctx);
7959 switch (opc) {
7960 case OPC_MFC0:
7961 if (rt == 0) {
7962 /* Treat as NOP. */
7963 return;
7965 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7966 opn = "mfc0";
7967 break;
7968 case OPC_MTC0:
7970 TCGv t0 = tcg_temp_new();
7972 gen_load_gpr(t0, rt);
7973 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
7974 tcg_temp_free(t0);
7976 opn = "mtc0";
7977 break;
7978 #if defined(TARGET_MIPS64)
7979 case OPC_DMFC0:
7980 check_insn(ctx, ISA_MIPS3);
7981 if (rt == 0) {
7982 /* Treat as NOP. */
7983 return;
7985 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7986 opn = "dmfc0";
7987 break;
7988 case OPC_DMTC0:
7989 check_insn(ctx, ISA_MIPS3);
7991 TCGv t0 = tcg_temp_new();
7993 gen_load_gpr(t0, rt);
7994 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
7995 tcg_temp_free(t0);
7997 opn = "dmtc0";
7998 break;
7999 #endif
8000 case OPC_MFHC0:
8001 check_mvh(ctx);
8002 if (rt == 0) {
8003 /* Treat as NOP. */
8004 return;
8006 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8007 opn = "mfhc0";
8008 break;
8009 case OPC_MTHC0:
8010 check_mvh(ctx);
8012 TCGv t0 = tcg_temp_new();
8013 gen_load_gpr(t0, rt);
8014 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8015 tcg_temp_free(t0);
8017 opn = "mthc0";
8018 break;
8019 case OPC_MFTR:
8020 check_insn(ctx, ASE_MT);
8021 if (rd == 0) {
8022 /* Treat as NOP. */
8023 return;
8025 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8026 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8027 opn = "mftr";
8028 break;
8029 case OPC_MTTR:
8030 check_insn(ctx, ASE_MT);
8031 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8032 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8033 opn = "mttr";
8034 break;
8035 case OPC_TLBWI:
8036 opn = "tlbwi";
8037 if (!env->tlb->helper_tlbwi)
8038 goto die;
8039 gen_helper_tlbwi(cpu_env);
8040 break;
8041 case OPC_TLBINV:
8042 opn = "tlbinv";
8043 if (ctx->ie >= 2) {
8044 if (!env->tlb->helper_tlbinv) {
8045 goto die;
8047 gen_helper_tlbinv(cpu_env);
8048 } /* treat as nop if TLBINV not supported */
8049 break;
8050 case OPC_TLBINVF:
8051 opn = "tlbinvf";
8052 if (ctx->ie >= 2) {
8053 if (!env->tlb->helper_tlbinvf) {
8054 goto die;
8056 gen_helper_tlbinvf(cpu_env);
8057 } /* treat as nop if TLBINV not supported */
8058 break;
8059 case OPC_TLBWR:
8060 opn = "tlbwr";
8061 if (!env->tlb->helper_tlbwr)
8062 goto die;
8063 gen_helper_tlbwr(cpu_env);
8064 break;
8065 case OPC_TLBP:
8066 opn = "tlbp";
8067 if (!env->tlb->helper_tlbp)
8068 goto die;
8069 gen_helper_tlbp(cpu_env);
8070 break;
8071 case OPC_TLBR:
8072 opn = "tlbr";
8073 if (!env->tlb->helper_tlbr)
8074 goto die;
8075 gen_helper_tlbr(cpu_env);
8076 break;
8077 case OPC_ERET: /* OPC_ERETNC */
8078 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8079 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8080 goto die;
8081 } else {
8082 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8083 if (ctx->opcode & (1 << bit_shift)) {
8084 /* OPC_ERETNC */
8085 opn = "eretnc";
8086 check_insn(ctx, ISA_MIPS32R5);
8087 gen_helper_eretnc(cpu_env);
8088 } else {
8089 /* OPC_ERET */
8090 opn = "eret";
8091 check_insn(ctx, ISA_MIPS2);
8092 gen_helper_eret(cpu_env);
8094 ctx->bstate = BS_EXCP;
8096 break;
8097 case OPC_DERET:
8098 opn = "deret";
8099 check_insn(ctx, ISA_MIPS32);
8100 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8101 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8102 goto die;
8104 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8105 MIPS_INVAL(opn);
8106 generate_exception_end(ctx, EXCP_RI);
8107 } else {
8108 gen_helper_deret(cpu_env);
8109 ctx->bstate = BS_EXCP;
8111 break;
8112 case OPC_WAIT:
8113 opn = "wait";
8114 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8115 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8116 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8117 goto die;
8119 /* If we get an exception, we want to restart at next instruction */
8120 ctx->pc += 4;
8121 save_cpu_state(ctx, 1);
8122 ctx->pc -= 4;
8123 gen_helper_wait(cpu_env);
8124 ctx->bstate = BS_EXCP;
8125 break;
8126 default:
8127 die:
8128 MIPS_INVAL(opn);
8129 generate_exception_end(ctx, EXCP_RI);
8130 return;
8132 (void)opn; /* avoid a compiler warning */
8134 #endif /* !CONFIG_USER_ONLY */
8136 /* CP1 Branches (before delay slot) */
8137 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8138 int32_t cc, int32_t offset)
8140 target_ulong btarget;
8141 TCGv_i32 t0 = tcg_temp_new_i32();
8143 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8144 generate_exception_end(ctx, EXCP_RI);
8145 goto out;
8148 if (cc != 0)
8149 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8151 btarget = ctx->pc + 4 + offset;
8153 switch (op) {
8154 case OPC_BC1F:
8155 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8156 tcg_gen_not_i32(t0, t0);
8157 tcg_gen_andi_i32(t0, t0, 1);
8158 tcg_gen_extu_i32_tl(bcond, t0);
8159 goto not_likely;
8160 case OPC_BC1FL:
8161 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8162 tcg_gen_not_i32(t0, t0);
8163 tcg_gen_andi_i32(t0, t0, 1);
8164 tcg_gen_extu_i32_tl(bcond, t0);
8165 goto likely;
8166 case OPC_BC1T:
8167 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8168 tcg_gen_andi_i32(t0, t0, 1);
8169 tcg_gen_extu_i32_tl(bcond, t0);
8170 goto not_likely;
8171 case OPC_BC1TL:
8172 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8173 tcg_gen_andi_i32(t0, t0, 1);
8174 tcg_gen_extu_i32_tl(bcond, t0);
8175 likely:
8176 ctx->hflags |= MIPS_HFLAG_BL;
8177 break;
8178 case OPC_BC1FANY2:
8180 TCGv_i32 t1 = tcg_temp_new_i32();
8181 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8182 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8183 tcg_gen_nand_i32(t0, t0, t1);
8184 tcg_temp_free_i32(t1);
8185 tcg_gen_andi_i32(t0, t0, 1);
8186 tcg_gen_extu_i32_tl(bcond, t0);
8188 goto not_likely;
8189 case OPC_BC1TANY2:
8191 TCGv_i32 t1 = tcg_temp_new_i32();
8192 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8193 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8194 tcg_gen_or_i32(t0, t0, t1);
8195 tcg_temp_free_i32(t1);
8196 tcg_gen_andi_i32(t0, t0, 1);
8197 tcg_gen_extu_i32_tl(bcond, t0);
8199 goto not_likely;
8200 case OPC_BC1FANY4:
8202 TCGv_i32 t1 = tcg_temp_new_i32();
8203 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8204 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8205 tcg_gen_and_i32(t0, t0, t1);
8206 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8207 tcg_gen_and_i32(t0, t0, t1);
8208 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8209 tcg_gen_nand_i32(t0, t0, t1);
8210 tcg_temp_free_i32(t1);
8211 tcg_gen_andi_i32(t0, t0, 1);
8212 tcg_gen_extu_i32_tl(bcond, t0);
8214 goto not_likely;
8215 case OPC_BC1TANY4:
8217 TCGv_i32 t1 = tcg_temp_new_i32();
8218 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8219 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8220 tcg_gen_or_i32(t0, t0, t1);
8221 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8222 tcg_gen_or_i32(t0, t0, t1);
8223 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8224 tcg_gen_or_i32(t0, t0, t1);
8225 tcg_temp_free_i32(t1);
8226 tcg_gen_andi_i32(t0, t0, 1);
8227 tcg_gen_extu_i32_tl(bcond, t0);
8229 not_likely:
8230 ctx->hflags |= MIPS_HFLAG_BC;
8231 break;
8232 default:
8233 MIPS_INVAL("cp1 cond branch");
8234 generate_exception_end(ctx, EXCP_RI);
8235 goto out;
8237 ctx->btarget = btarget;
8238 ctx->hflags |= MIPS_HFLAG_BDS32;
8239 out:
8240 tcg_temp_free_i32(t0);
8243 /* R6 CP1 Branches */
8244 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8245 int32_t ft, int32_t offset,
8246 int delayslot_size)
8248 target_ulong btarget;
8249 TCGv_i64 t0 = tcg_temp_new_i64();
8251 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8252 #ifdef MIPS_DEBUG_DISAS
8253 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8254 "\n", ctx->pc);
8255 #endif
8256 generate_exception_end(ctx, EXCP_RI);
8257 goto out;
8260 gen_load_fpr64(ctx, t0, ft);
8261 tcg_gen_andi_i64(t0, t0, 1);
8263 btarget = addr_add(ctx, ctx->pc + 4, offset);
8265 switch (op) {
8266 case OPC_BC1EQZ:
8267 tcg_gen_xori_i64(t0, t0, 1);
8268 ctx->hflags |= MIPS_HFLAG_BC;
8269 break;
8270 case OPC_BC1NEZ:
8271 /* t0 already set */
8272 ctx->hflags |= MIPS_HFLAG_BC;
8273 break;
8274 default:
8275 MIPS_INVAL("cp1 cond branch");
8276 generate_exception_end(ctx, EXCP_RI);
8277 goto out;
8280 tcg_gen_trunc_i64_tl(bcond, t0);
8282 ctx->btarget = btarget;
8284 switch (delayslot_size) {
8285 case 2:
8286 ctx->hflags |= MIPS_HFLAG_BDS16;
8287 break;
8288 case 4:
8289 ctx->hflags |= MIPS_HFLAG_BDS32;
8290 break;
8293 out:
8294 tcg_temp_free_i64(t0);
8297 /* Coprocessor 1 (FPU) */
8299 #define FOP(func, fmt) (((fmt) << 21) | (func))
8301 enum fopcode {
8302 OPC_ADD_S = FOP(0, FMT_S),
8303 OPC_SUB_S = FOP(1, FMT_S),
8304 OPC_MUL_S = FOP(2, FMT_S),
8305 OPC_DIV_S = FOP(3, FMT_S),
8306 OPC_SQRT_S = FOP(4, FMT_S),
8307 OPC_ABS_S = FOP(5, FMT_S),
8308 OPC_MOV_S = FOP(6, FMT_S),
8309 OPC_NEG_S = FOP(7, FMT_S),
8310 OPC_ROUND_L_S = FOP(8, FMT_S),
8311 OPC_TRUNC_L_S = FOP(9, FMT_S),
8312 OPC_CEIL_L_S = FOP(10, FMT_S),
8313 OPC_FLOOR_L_S = FOP(11, FMT_S),
8314 OPC_ROUND_W_S = FOP(12, FMT_S),
8315 OPC_TRUNC_W_S = FOP(13, FMT_S),
8316 OPC_CEIL_W_S = FOP(14, FMT_S),
8317 OPC_FLOOR_W_S = FOP(15, FMT_S),
8318 OPC_SEL_S = FOP(16, FMT_S),
8319 OPC_MOVCF_S = FOP(17, FMT_S),
8320 OPC_MOVZ_S = FOP(18, FMT_S),
8321 OPC_MOVN_S = FOP(19, FMT_S),
8322 OPC_SELEQZ_S = FOP(20, FMT_S),
8323 OPC_RECIP_S = FOP(21, FMT_S),
8324 OPC_RSQRT_S = FOP(22, FMT_S),
8325 OPC_SELNEZ_S = FOP(23, FMT_S),
8326 OPC_MADDF_S = FOP(24, FMT_S),
8327 OPC_MSUBF_S = FOP(25, FMT_S),
8328 OPC_RINT_S = FOP(26, FMT_S),
8329 OPC_CLASS_S = FOP(27, FMT_S),
8330 OPC_MIN_S = FOP(28, FMT_S),
8331 OPC_RECIP2_S = FOP(28, FMT_S),
8332 OPC_MINA_S = FOP(29, FMT_S),
8333 OPC_RECIP1_S = FOP(29, FMT_S),
8334 OPC_MAX_S = FOP(30, FMT_S),
8335 OPC_RSQRT1_S = FOP(30, FMT_S),
8336 OPC_MAXA_S = FOP(31, FMT_S),
8337 OPC_RSQRT2_S = FOP(31, FMT_S),
8338 OPC_CVT_D_S = FOP(33, FMT_S),
8339 OPC_CVT_W_S = FOP(36, FMT_S),
8340 OPC_CVT_L_S = FOP(37, FMT_S),
8341 OPC_CVT_PS_S = FOP(38, FMT_S),
8342 OPC_CMP_F_S = FOP (48, FMT_S),
8343 OPC_CMP_UN_S = FOP (49, FMT_S),
8344 OPC_CMP_EQ_S = FOP (50, FMT_S),
8345 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8346 OPC_CMP_OLT_S = FOP (52, FMT_S),
8347 OPC_CMP_ULT_S = FOP (53, FMT_S),
8348 OPC_CMP_OLE_S = FOP (54, FMT_S),
8349 OPC_CMP_ULE_S = FOP (55, FMT_S),
8350 OPC_CMP_SF_S = FOP (56, FMT_S),
8351 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8352 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8353 OPC_CMP_NGL_S = FOP (59, FMT_S),
8354 OPC_CMP_LT_S = FOP (60, FMT_S),
8355 OPC_CMP_NGE_S = FOP (61, FMT_S),
8356 OPC_CMP_LE_S = FOP (62, FMT_S),
8357 OPC_CMP_NGT_S = FOP (63, FMT_S),
8359 OPC_ADD_D = FOP(0, FMT_D),
8360 OPC_SUB_D = FOP(1, FMT_D),
8361 OPC_MUL_D = FOP(2, FMT_D),
8362 OPC_DIV_D = FOP(3, FMT_D),
8363 OPC_SQRT_D = FOP(4, FMT_D),
8364 OPC_ABS_D = FOP(5, FMT_D),
8365 OPC_MOV_D = FOP(6, FMT_D),
8366 OPC_NEG_D = FOP(7, FMT_D),
8367 OPC_ROUND_L_D = FOP(8, FMT_D),
8368 OPC_TRUNC_L_D = FOP(9, FMT_D),
8369 OPC_CEIL_L_D = FOP(10, FMT_D),
8370 OPC_FLOOR_L_D = FOP(11, FMT_D),
8371 OPC_ROUND_W_D = FOP(12, FMT_D),
8372 OPC_TRUNC_W_D = FOP(13, FMT_D),
8373 OPC_CEIL_W_D = FOP(14, FMT_D),
8374 OPC_FLOOR_W_D = FOP(15, FMT_D),
8375 OPC_SEL_D = FOP(16, FMT_D),
8376 OPC_MOVCF_D = FOP(17, FMT_D),
8377 OPC_MOVZ_D = FOP(18, FMT_D),
8378 OPC_MOVN_D = FOP(19, FMT_D),
8379 OPC_SELEQZ_D = FOP(20, FMT_D),
8380 OPC_RECIP_D = FOP(21, FMT_D),
8381 OPC_RSQRT_D = FOP(22, FMT_D),
8382 OPC_SELNEZ_D = FOP(23, FMT_D),
8383 OPC_MADDF_D = FOP(24, FMT_D),
8384 OPC_MSUBF_D = FOP(25, FMT_D),
8385 OPC_RINT_D = FOP(26, FMT_D),
8386 OPC_CLASS_D = FOP(27, FMT_D),
8387 OPC_MIN_D = FOP(28, FMT_D),
8388 OPC_RECIP2_D = FOP(28, FMT_D),
8389 OPC_MINA_D = FOP(29, FMT_D),
8390 OPC_RECIP1_D = FOP(29, FMT_D),
8391 OPC_MAX_D = FOP(30, FMT_D),
8392 OPC_RSQRT1_D = FOP(30, FMT_D),
8393 OPC_MAXA_D = FOP(31, FMT_D),
8394 OPC_RSQRT2_D = FOP(31, FMT_D),
8395 OPC_CVT_S_D = FOP(32, FMT_D),
8396 OPC_CVT_W_D = FOP(36, FMT_D),
8397 OPC_CVT_L_D = FOP(37, FMT_D),
8398 OPC_CMP_F_D = FOP (48, FMT_D),
8399 OPC_CMP_UN_D = FOP (49, FMT_D),
8400 OPC_CMP_EQ_D = FOP (50, FMT_D),
8401 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8402 OPC_CMP_OLT_D = FOP (52, FMT_D),
8403 OPC_CMP_ULT_D = FOP (53, FMT_D),
8404 OPC_CMP_OLE_D = FOP (54, FMT_D),
8405 OPC_CMP_ULE_D = FOP (55, FMT_D),
8406 OPC_CMP_SF_D = FOP (56, FMT_D),
8407 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8408 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8409 OPC_CMP_NGL_D = FOP (59, FMT_D),
8410 OPC_CMP_LT_D = FOP (60, FMT_D),
8411 OPC_CMP_NGE_D = FOP (61, FMT_D),
8412 OPC_CMP_LE_D = FOP (62, FMT_D),
8413 OPC_CMP_NGT_D = FOP (63, FMT_D),
8415 OPC_CVT_S_W = FOP(32, FMT_W),
8416 OPC_CVT_D_W = FOP(33, FMT_W),
8417 OPC_CVT_S_L = FOP(32, FMT_L),
8418 OPC_CVT_D_L = FOP(33, FMT_L),
8419 OPC_CVT_PS_PW = FOP(38, FMT_W),
8421 OPC_ADD_PS = FOP(0, FMT_PS),
8422 OPC_SUB_PS = FOP(1, FMT_PS),
8423 OPC_MUL_PS = FOP(2, FMT_PS),
8424 OPC_DIV_PS = FOP(3, FMT_PS),
8425 OPC_ABS_PS = FOP(5, FMT_PS),
8426 OPC_MOV_PS = FOP(6, FMT_PS),
8427 OPC_NEG_PS = FOP(7, FMT_PS),
8428 OPC_MOVCF_PS = FOP(17, FMT_PS),
8429 OPC_MOVZ_PS = FOP(18, FMT_PS),
8430 OPC_MOVN_PS = FOP(19, FMT_PS),
8431 OPC_ADDR_PS = FOP(24, FMT_PS),
8432 OPC_MULR_PS = FOP(26, FMT_PS),
8433 OPC_RECIP2_PS = FOP(28, FMT_PS),
8434 OPC_RECIP1_PS = FOP(29, FMT_PS),
8435 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8436 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8438 OPC_CVT_S_PU = FOP(32, FMT_PS),
8439 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8440 OPC_CVT_S_PL = FOP(40, FMT_PS),
8441 OPC_PLL_PS = FOP(44, FMT_PS),
8442 OPC_PLU_PS = FOP(45, FMT_PS),
8443 OPC_PUL_PS = FOP(46, FMT_PS),
8444 OPC_PUU_PS = FOP(47, FMT_PS),
8445 OPC_CMP_F_PS = FOP (48, FMT_PS),
8446 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8447 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8448 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8449 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8450 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8451 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8452 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8453 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8454 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8455 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8456 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8457 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8458 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8459 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8460 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8463 enum r6_f_cmp_op {
8464 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8465 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8466 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8467 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8468 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8469 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8470 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8471 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8472 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8473 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8474 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8475 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8476 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8477 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8478 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8479 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8480 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8481 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8482 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8483 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8484 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8485 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8487 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8488 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8489 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8490 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8491 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8492 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8493 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8494 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8495 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8496 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8497 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8498 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8499 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8500 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8501 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8502 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8503 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8504 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8505 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8506 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8507 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8508 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8510 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8512 TCGv t0 = tcg_temp_new();
8514 switch (opc) {
8515 case OPC_MFC1:
8517 TCGv_i32 fp0 = tcg_temp_new_i32();
8519 gen_load_fpr32(ctx, fp0, fs);
8520 tcg_gen_ext_i32_tl(t0, fp0);
8521 tcg_temp_free_i32(fp0);
8523 gen_store_gpr(t0, rt);
8524 break;
8525 case OPC_MTC1:
8526 gen_load_gpr(t0, rt);
8528 TCGv_i32 fp0 = tcg_temp_new_i32();
8530 tcg_gen_trunc_tl_i32(fp0, t0);
8531 gen_store_fpr32(ctx, fp0, fs);
8532 tcg_temp_free_i32(fp0);
8534 break;
8535 case OPC_CFC1:
8536 gen_helper_1e0i(cfc1, t0, fs);
8537 gen_store_gpr(t0, rt);
8538 break;
8539 case OPC_CTC1:
8540 gen_load_gpr(t0, rt);
8541 save_cpu_state(ctx, 0);
8543 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8545 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8546 tcg_temp_free_i32(fs_tmp);
8548 /* Stop translation as we may have changed hflags */
8549 ctx->bstate = BS_STOP;
8550 break;
8551 #if defined(TARGET_MIPS64)
8552 case OPC_DMFC1:
8553 gen_load_fpr64(ctx, t0, fs);
8554 gen_store_gpr(t0, rt);
8555 break;
8556 case OPC_DMTC1:
8557 gen_load_gpr(t0, rt);
8558 gen_store_fpr64(ctx, t0, fs);
8559 break;
8560 #endif
8561 case OPC_MFHC1:
8563 TCGv_i32 fp0 = tcg_temp_new_i32();
8565 gen_load_fpr32h(ctx, fp0, fs);
8566 tcg_gen_ext_i32_tl(t0, fp0);
8567 tcg_temp_free_i32(fp0);
8569 gen_store_gpr(t0, rt);
8570 break;
8571 case OPC_MTHC1:
8572 gen_load_gpr(t0, rt);
8574 TCGv_i32 fp0 = tcg_temp_new_i32();
8576 tcg_gen_trunc_tl_i32(fp0, t0);
8577 gen_store_fpr32h(ctx, fp0, fs);
8578 tcg_temp_free_i32(fp0);
8580 break;
8581 default:
8582 MIPS_INVAL("cp1 move");
8583 generate_exception_end(ctx, EXCP_RI);
8584 goto out;
8587 out:
8588 tcg_temp_free(t0);
8591 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8593 TCGLabel *l1;
8594 TCGCond cond;
8595 TCGv_i32 t0;
8597 if (rd == 0) {
8598 /* Treat as NOP. */
8599 return;
8602 if (tf)
8603 cond = TCG_COND_EQ;
8604 else
8605 cond = TCG_COND_NE;
8607 l1 = gen_new_label();
8608 t0 = tcg_temp_new_i32();
8609 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8610 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8611 tcg_temp_free_i32(t0);
8612 if (rs == 0) {
8613 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8614 } else {
8615 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8617 gen_set_label(l1);
8620 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
8621 int tf)
8623 int cond;
8624 TCGv_i32 t0 = tcg_temp_new_i32();
8625 TCGLabel *l1 = gen_new_label();
8627 if (tf)
8628 cond = TCG_COND_EQ;
8629 else
8630 cond = TCG_COND_NE;
8632 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8633 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8634 gen_load_fpr32(ctx, t0, fs);
8635 gen_store_fpr32(ctx, t0, fd);
8636 gen_set_label(l1);
8637 tcg_temp_free_i32(t0);
8640 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8642 int cond;
8643 TCGv_i32 t0 = tcg_temp_new_i32();
8644 TCGv_i64 fp0;
8645 TCGLabel *l1 = gen_new_label();
8647 if (tf)
8648 cond = TCG_COND_EQ;
8649 else
8650 cond = TCG_COND_NE;
8652 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8653 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8654 tcg_temp_free_i32(t0);
8655 fp0 = tcg_temp_new_i64();
8656 gen_load_fpr64(ctx, fp0, fs);
8657 gen_store_fpr64(ctx, fp0, fd);
8658 tcg_temp_free_i64(fp0);
8659 gen_set_label(l1);
8662 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8663 int cc, int tf)
8665 int cond;
8666 TCGv_i32 t0 = tcg_temp_new_i32();
8667 TCGLabel *l1 = gen_new_label();
8668 TCGLabel *l2 = gen_new_label();
8670 if (tf)
8671 cond = TCG_COND_EQ;
8672 else
8673 cond = TCG_COND_NE;
8675 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8676 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8677 gen_load_fpr32(ctx, t0, fs);
8678 gen_store_fpr32(ctx, t0, fd);
8679 gen_set_label(l1);
8681 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8682 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8683 gen_load_fpr32h(ctx, t0, fs);
8684 gen_store_fpr32h(ctx, t0, fd);
8685 tcg_temp_free_i32(t0);
8686 gen_set_label(l2);
8689 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8690 int fs)
8692 TCGv_i32 t1 = tcg_const_i32(0);
8693 TCGv_i32 fp0 = tcg_temp_new_i32();
8694 TCGv_i32 fp1 = tcg_temp_new_i32();
8695 TCGv_i32 fp2 = tcg_temp_new_i32();
8696 gen_load_fpr32(ctx, fp0, fd);
8697 gen_load_fpr32(ctx, fp1, ft);
8698 gen_load_fpr32(ctx, fp2, fs);
8700 switch (op1) {
8701 case OPC_SEL_S:
8702 tcg_gen_andi_i32(fp0, fp0, 1);
8703 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8704 break;
8705 case OPC_SELEQZ_S:
8706 tcg_gen_andi_i32(fp1, fp1, 1);
8707 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8708 break;
8709 case OPC_SELNEZ_S:
8710 tcg_gen_andi_i32(fp1, fp1, 1);
8711 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8712 break;
8713 default:
8714 MIPS_INVAL("gen_sel_s");
8715 generate_exception_end(ctx, EXCP_RI);
8716 break;
8719 gen_store_fpr32(ctx, fp0, fd);
8720 tcg_temp_free_i32(fp2);
8721 tcg_temp_free_i32(fp1);
8722 tcg_temp_free_i32(fp0);
8723 tcg_temp_free_i32(t1);
8726 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8727 int fs)
8729 TCGv_i64 t1 = tcg_const_i64(0);
8730 TCGv_i64 fp0 = tcg_temp_new_i64();
8731 TCGv_i64 fp1 = tcg_temp_new_i64();
8732 TCGv_i64 fp2 = tcg_temp_new_i64();
8733 gen_load_fpr64(ctx, fp0, fd);
8734 gen_load_fpr64(ctx, fp1, ft);
8735 gen_load_fpr64(ctx, fp2, fs);
8737 switch (op1) {
8738 case OPC_SEL_D:
8739 tcg_gen_andi_i64(fp0, fp0, 1);
8740 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8741 break;
8742 case OPC_SELEQZ_D:
8743 tcg_gen_andi_i64(fp1, fp1, 1);
8744 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8745 break;
8746 case OPC_SELNEZ_D:
8747 tcg_gen_andi_i64(fp1, fp1, 1);
8748 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8749 break;
8750 default:
8751 MIPS_INVAL("gen_sel_d");
8752 generate_exception_end(ctx, EXCP_RI);
8753 break;
8756 gen_store_fpr64(ctx, fp0, fd);
8757 tcg_temp_free_i64(fp2);
8758 tcg_temp_free_i64(fp1);
8759 tcg_temp_free_i64(fp0);
8760 tcg_temp_free_i64(t1);
8763 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8764 int ft, int fs, int fd, int cc)
8766 uint32_t func = ctx->opcode & 0x3f;
8767 switch (op1) {
8768 case OPC_ADD_S:
8770 TCGv_i32 fp0 = tcg_temp_new_i32();
8771 TCGv_i32 fp1 = tcg_temp_new_i32();
8773 gen_load_fpr32(ctx, fp0, fs);
8774 gen_load_fpr32(ctx, fp1, ft);
8775 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
8776 tcg_temp_free_i32(fp1);
8777 gen_store_fpr32(ctx, fp0, fd);
8778 tcg_temp_free_i32(fp0);
8780 break;
8781 case OPC_SUB_S:
8783 TCGv_i32 fp0 = tcg_temp_new_i32();
8784 TCGv_i32 fp1 = tcg_temp_new_i32();
8786 gen_load_fpr32(ctx, fp0, fs);
8787 gen_load_fpr32(ctx, fp1, ft);
8788 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
8789 tcg_temp_free_i32(fp1);
8790 gen_store_fpr32(ctx, fp0, fd);
8791 tcg_temp_free_i32(fp0);
8793 break;
8794 case OPC_MUL_S:
8796 TCGv_i32 fp0 = tcg_temp_new_i32();
8797 TCGv_i32 fp1 = tcg_temp_new_i32();
8799 gen_load_fpr32(ctx, fp0, fs);
8800 gen_load_fpr32(ctx, fp1, ft);
8801 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
8802 tcg_temp_free_i32(fp1);
8803 gen_store_fpr32(ctx, fp0, fd);
8804 tcg_temp_free_i32(fp0);
8806 break;
8807 case OPC_DIV_S:
8809 TCGv_i32 fp0 = tcg_temp_new_i32();
8810 TCGv_i32 fp1 = tcg_temp_new_i32();
8812 gen_load_fpr32(ctx, fp0, fs);
8813 gen_load_fpr32(ctx, fp1, ft);
8814 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
8815 tcg_temp_free_i32(fp1);
8816 gen_store_fpr32(ctx, fp0, fd);
8817 tcg_temp_free_i32(fp0);
8819 break;
8820 case OPC_SQRT_S:
8822 TCGv_i32 fp0 = tcg_temp_new_i32();
8824 gen_load_fpr32(ctx, fp0, fs);
8825 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
8826 gen_store_fpr32(ctx, fp0, fd);
8827 tcg_temp_free_i32(fp0);
8829 break;
8830 case OPC_ABS_S:
8832 TCGv_i32 fp0 = tcg_temp_new_i32();
8834 gen_load_fpr32(ctx, fp0, fs);
8835 gen_helper_float_abs_s(fp0, fp0);
8836 gen_store_fpr32(ctx, fp0, fd);
8837 tcg_temp_free_i32(fp0);
8839 break;
8840 case OPC_MOV_S:
8842 TCGv_i32 fp0 = tcg_temp_new_i32();
8844 gen_load_fpr32(ctx, fp0, fs);
8845 gen_store_fpr32(ctx, fp0, fd);
8846 tcg_temp_free_i32(fp0);
8848 break;
8849 case OPC_NEG_S:
8851 TCGv_i32 fp0 = tcg_temp_new_i32();
8853 gen_load_fpr32(ctx, fp0, fs);
8854 gen_helper_float_chs_s(fp0, fp0);
8855 gen_store_fpr32(ctx, fp0, fd);
8856 tcg_temp_free_i32(fp0);
8858 break;
8859 case OPC_ROUND_L_S:
8860 check_cp1_64bitmode(ctx);
8862 TCGv_i32 fp32 = tcg_temp_new_i32();
8863 TCGv_i64 fp64 = tcg_temp_new_i64();
8865 gen_load_fpr32(ctx, fp32, fs);
8866 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
8867 tcg_temp_free_i32(fp32);
8868 gen_store_fpr64(ctx, fp64, fd);
8869 tcg_temp_free_i64(fp64);
8871 break;
8872 case OPC_TRUNC_L_S:
8873 check_cp1_64bitmode(ctx);
8875 TCGv_i32 fp32 = tcg_temp_new_i32();
8876 TCGv_i64 fp64 = tcg_temp_new_i64();
8878 gen_load_fpr32(ctx, fp32, fs);
8879 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
8880 tcg_temp_free_i32(fp32);
8881 gen_store_fpr64(ctx, fp64, fd);
8882 tcg_temp_free_i64(fp64);
8884 break;
8885 case OPC_CEIL_L_S:
8886 check_cp1_64bitmode(ctx);
8888 TCGv_i32 fp32 = tcg_temp_new_i32();
8889 TCGv_i64 fp64 = tcg_temp_new_i64();
8891 gen_load_fpr32(ctx, fp32, fs);
8892 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
8893 tcg_temp_free_i32(fp32);
8894 gen_store_fpr64(ctx, fp64, fd);
8895 tcg_temp_free_i64(fp64);
8897 break;
8898 case OPC_FLOOR_L_S:
8899 check_cp1_64bitmode(ctx);
8901 TCGv_i32 fp32 = tcg_temp_new_i32();
8902 TCGv_i64 fp64 = tcg_temp_new_i64();
8904 gen_load_fpr32(ctx, fp32, fs);
8905 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
8906 tcg_temp_free_i32(fp32);
8907 gen_store_fpr64(ctx, fp64, fd);
8908 tcg_temp_free_i64(fp64);
8910 break;
8911 case OPC_ROUND_W_S:
8913 TCGv_i32 fp0 = tcg_temp_new_i32();
8915 gen_load_fpr32(ctx, fp0, fs);
8916 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
8917 gen_store_fpr32(ctx, fp0, fd);
8918 tcg_temp_free_i32(fp0);
8920 break;
8921 case OPC_TRUNC_W_S:
8923 TCGv_i32 fp0 = tcg_temp_new_i32();
8925 gen_load_fpr32(ctx, fp0, fs);
8926 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
8927 gen_store_fpr32(ctx, fp0, fd);
8928 tcg_temp_free_i32(fp0);
8930 break;
8931 case OPC_CEIL_W_S:
8933 TCGv_i32 fp0 = tcg_temp_new_i32();
8935 gen_load_fpr32(ctx, fp0, fs);
8936 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
8937 gen_store_fpr32(ctx, fp0, fd);
8938 tcg_temp_free_i32(fp0);
8940 break;
8941 case OPC_FLOOR_W_S:
8943 TCGv_i32 fp0 = tcg_temp_new_i32();
8945 gen_load_fpr32(ctx, fp0, fs);
8946 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
8947 gen_store_fpr32(ctx, fp0, fd);
8948 tcg_temp_free_i32(fp0);
8950 break;
8951 case OPC_SEL_S:
8952 check_insn(ctx, ISA_MIPS32R6);
8953 gen_sel_s(ctx, op1, fd, ft, fs);
8954 break;
8955 case OPC_SELEQZ_S:
8956 check_insn(ctx, ISA_MIPS32R6);
8957 gen_sel_s(ctx, op1, fd, ft, fs);
8958 break;
8959 case OPC_SELNEZ_S:
8960 check_insn(ctx, ISA_MIPS32R6);
8961 gen_sel_s(ctx, op1, fd, ft, fs);
8962 break;
8963 case OPC_MOVCF_S:
8964 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8965 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
8966 break;
8967 case OPC_MOVZ_S:
8968 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8970 TCGLabel *l1 = gen_new_label();
8971 TCGv_i32 fp0;
8973 if (ft != 0) {
8974 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8976 fp0 = tcg_temp_new_i32();
8977 gen_load_fpr32(ctx, fp0, fs);
8978 gen_store_fpr32(ctx, fp0, fd);
8979 tcg_temp_free_i32(fp0);
8980 gen_set_label(l1);
8982 break;
8983 case OPC_MOVN_S:
8984 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8986 TCGLabel *l1 = gen_new_label();
8987 TCGv_i32 fp0;
8989 if (ft != 0) {
8990 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8991 fp0 = tcg_temp_new_i32();
8992 gen_load_fpr32(ctx, fp0, fs);
8993 gen_store_fpr32(ctx, fp0, fd);
8994 tcg_temp_free_i32(fp0);
8995 gen_set_label(l1);
8998 break;
8999 case OPC_RECIP_S:
9001 TCGv_i32 fp0 = tcg_temp_new_i32();
9003 gen_load_fpr32(ctx, fp0, fs);
9004 gen_helper_float_recip_s(fp0, cpu_env, fp0);
9005 gen_store_fpr32(ctx, fp0, fd);
9006 tcg_temp_free_i32(fp0);
9008 break;
9009 case OPC_RSQRT_S:
9011 TCGv_i32 fp0 = tcg_temp_new_i32();
9013 gen_load_fpr32(ctx, fp0, fs);
9014 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
9015 gen_store_fpr32(ctx, fp0, fd);
9016 tcg_temp_free_i32(fp0);
9018 break;
9019 case OPC_MADDF_S:
9020 check_insn(ctx, ISA_MIPS32R6);
9022 TCGv_i32 fp0 = tcg_temp_new_i32();
9023 TCGv_i32 fp1 = tcg_temp_new_i32();
9024 TCGv_i32 fp2 = tcg_temp_new_i32();
9025 gen_load_fpr32(ctx, fp0, fs);
9026 gen_load_fpr32(ctx, fp1, ft);
9027 gen_load_fpr32(ctx, fp2, fd);
9028 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
9029 gen_store_fpr32(ctx, fp2, fd);
9030 tcg_temp_free_i32(fp2);
9031 tcg_temp_free_i32(fp1);
9032 tcg_temp_free_i32(fp0);
9034 break;
9035 case OPC_MSUBF_S:
9036 check_insn(ctx, ISA_MIPS32R6);
9038 TCGv_i32 fp0 = tcg_temp_new_i32();
9039 TCGv_i32 fp1 = tcg_temp_new_i32();
9040 TCGv_i32 fp2 = tcg_temp_new_i32();
9041 gen_load_fpr32(ctx, fp0, fs);
9042 gen_load_fpr32(ctx, fp1, ft);
9043 gen_load_fpr32(ctx, fp2, fd);
9044 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9045 gen_store_fpr32(ctx, fp2, fd);
9046 tcg_temp_free_i32(fp2);
9047 tcg_temp_free_i32(fp1);
9048 tcg_temp_free_i32(fp0);
9050 break;
9051 case OPC_RINT_S:
9052 check_insn(ctx, ISA_MIPS32R6);
9054 TCGv_i32 fp0 = tcg_temp_new_i32();
9055 gen_load_fpr32(ctx, fp0, fs);
9056 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9057 gen_store_fpr32(ctx, fp0, fd);
9058 tcg_temp_free_i32(fp0);
9060 break;
9061 case OPC_CLASS_S:
9062 check_insn(ctx, ISA_MIPS32R6);
9064 TCGv_i32 fp0 = tcg_temp_new_i32();
9065 gen_load_fpr32(ctx, fp0, fs);
9066 gen_helper_float_class_s(fp0, fp0);
9067 gen_store_fpr32(ctx, fp0, fd);
9068 tcg_temp_free_i32(fp0);
9070 break;
9071 case OPC_MIN_S: /* OPC_RECIP2_S */
9072 if (ctx->insn_flags & ISA_MIPS32R6) {
9073 /* OPC_MIN_S */
9074 TCGv_i32 fp0 = tcg_temp_new_i32();
9075 TCGv_i32 fp1 = tcg_temp_new_i32();
9076 TCGv_i32 fp2 = tcg_temp_new_i32();
9077 gen_load_fpr32(ctx, fp0, fs);
9078 gen_load_fpr32(ctx, fp1, ft);
9079 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9080 gen_store_fpr32(ctx, fp2, fd);
9081 tcg_temp_free_i32(fp2);
9082 tcg_temp_free_i32(fp1);
9083 tcg_temp_free_i32(fp0);
9084 } else {
9085 /* OPC_RECIP2_S */
9086 check_cp1_64bitmode(ctx);
9088 TCGv_i32 fp0 = tcg_temp_new_i32();
9089 TCGv_i32 fp1 = tcg_temp_new_i32();
9091 gen_load_fpr32(ctx, fp0, fs);
9092 gen_load_fpr32(ctx, fp1, ft);
9093 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9094 tcg_temp_free_i32(fp1);
9095 gen_store_fpr32(ctx, fp0, fd);
9096 tcg_temp_free_i32(fp0);
9099 break;
9100 case OPC_MINA_S: /* OPC_RECIP1_S */
9101 if (ctx->insn_flags & ISA_MIPS32R6) {
9102 /* OPC_MINA_S */
9103 TCGv_i32 fp0 = tcg_temp_new_i32();
9104 TCGv_i32 fp1 = tcg_temp_new_i32();
9105 TCGv_i32 fp2 = tcg_temp_new_i32();
9106 gen_load_fpr32(ctx, fp0, fs);
9107 gen_load_fpr32(ctx, fp1, ft);
9108 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9109 gen_store_fpr32(ctx, fp2, fd);
9110 tcg_temp_free_i32(fp2);
9111 tcg_temp_free_i32(fp1);
9112 tcg_temp_free_i32(fp0);
9113 } else {
9114 /* OPC_RECIP1_S */
9115 check_cp1_64bitmode(ctx);
9117 TCGv_i32 fp0 = tcg_temp_new_i32();
9119 gen_load_fpr32(ctx, fp0, fs);
9120 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9121 gen_store_fpr32(ctx, fp0, fd);
9122 tcg_temp_free_i32(fp0);
9125 break;
9126 case OPC_MAX_S: /* OPC_RSQRT1_S */
9127 if (ctx->insn_flags & ISA_MIPS32R6) {
9128 /* OPC_MAX_S */
9129 TCGv_i32 fp0 = tcg_temp_new_i32();
9130 TCGv_i32 fp1 = tcg_temp_new_i32();
9131 gen_load_fpr32(ctx, fp0, fs);
9132 gen_load_fpr32(ctx, fp1, ft);
9133 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9134 gen_store_fpr32(ctx, fp1, fd);
9135 tcg_temp_free_i32(fp1);
9136 tcg_temp_free_i32(fp0);
9137 } else {
9138 /* OPC_RSQRT1_S */
9139 check_cp1_64bitmode(ctx);
9141 TCGv_i32 fp0 = tcg_temp_new_i32();
9143 gen_load_fpr32(ctx, fp0, fs);
9144 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9145 gen_store_fpr32(ctx, fp0, fd);
9146 tcg_temp_free_i32(fp0);
9149 break;
9150 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9151 if (ctx->insn_flags & ISA_MIPS32R6) {
9152 /* OPC_MAXA_S */
9153 TCGv_i32 fp0 = tcg_temp_new_i32();
9154 TCGv_i32 fp1 = tcg_temp_new_i32();
9155 gen_load_fpr32(ctx, fp0, fs);
9156 gen_load_fpr32(ctx, fp1, ft);
9157 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9158 gen_store_fpr32(ctx, fp1, fd);
9159 tcg_temp_free_i32(fp1);
9160 tcg_temp_free_i32(fp0);
9161 } else {
9162 /* OPC_RSQRT2_S */
9163 check_cp1_64bitmode(ctx);
9165 TCGv_i32 fp0 = tcg_temp_new_i32();
9166 TCGv_i32 fp1 = tcg_temp_new_i32();
9168 gen_load_fpr32(ctx, fp0, fs);
9169 gen_load_fpr32(ctx, fp1, ft);
9170 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9171 tcg_temp_free_i32(fp1);
9172 gen_store_fpr32(ctx, fp0, fd);
9173 tcg_temp_free_i32(fp0);
9176 break;
9177 case OPC_CVT_D_S:
9178 check_cp1_registers(ctx, fd);
9180 TCGv_i32 fp32 = tcg_temp_new_i32();
9181 TCGv_i64 fp64 = tcg_temp_new_i64();
9183 gen_load_fpr32(ctx, fp32, fs);
9184 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9185 tcg_temp_free_i32(fp32);
9186 gen_store_fpr64(ctx, fp64, fd);
9187 tcg_temp_free_i64(fp64);
9189 break;
9190 case OPC_CVT_W_S:
9192 TCGv_i32 fp0 = tcg_temp_new_i32();
9194 gen_load_fpr32(ctx, fp0, fs);
9195 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
9196 gen_store_fpr32(ctx, fp0, fd);
9197 tcg_temp_free_i32(fp0);
9199 break;
9200 case OPC_CVT_L_S:
9201 check_cp1_64bitmode(ctx);
9203 TCGv_i32 fp32 = tcg_temp_new_i32();
9204 TCGv_i64 fp64 = tcg_temp_new_i64();
9206 gen_load_fpr32(ctx, fp32, fs);
9207 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
9208 tcg_temp_free_i32(fp32);
9209 gen_store_fpr64(ctx, fp64, fd);
9210 tcg_temp_free_i64(fp64);
9212 break;
9213 case OPC_CVT_PS_S:
9214 check_ps(ctx);
9216 TCGv_i64 fp64 = tcg_temp_new_i64();
9217 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9218 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9220 gen_load_fpr32(ctx, fp32_0, fs);
9221 gen_load_fpr32(ctx, fp32_1, ft);
9222 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9223 tcg_temp_free_i32(fp32_1);
9224 tcg_temp_free_i32(fp32_0);
9225 gen_store_fpr64(ctx, fp64, fd);
9226 tcg_temp_free_i64(fp64);
9228 break;
9229 case OPC_CMP_F_S:
9230 case OPC_CMP_UN_S:
9231 case OPC_CMP_EQ_S:
9232 case OPC_CMP_UEQ_S:
9233 case OPC_CMP_OLT_S:
9234 case OPC_CMP_ULT_S:
9235 case OPC_CMP_OLE_S:
9236 case OPC_CMP_ULE_S:
9237 case OPC_CMP_SF_S:
9238 case OPC_CMP_NGLE_S:
9239 case OPC_CMP_SEQ_S:
9240 case OPC_CMP_NGL_S:
9241 case OPC_CMP_LT_S:
9242 case OPC_CMP_NGE_S:
9243 case OPC_CMP_LE_S:
9244 case OPC_CMP_NGT_S:
9245 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9246 if (ctx->opcode & (1 << 6)) {
9247 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9248 } else {
9249 gen_cmp_s(ctx, func-48, ft, fs, cc);
9251 break;
9252 case OPC_ADD_D:
9253 check_cp1_registers(ctx, fs | ft | fd);
9255 TCGv_i64 fp0 = tcg_temp_new_i64();
9256 TCGv_i64 fp1 = tcg_temp_new_i64();
9258 gen_load_fpr64(ctx, fp0, fs);
9259 gen_load_fpr64(ctx, fp1, ft);
9260 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9261 tcg_temp_free_i64(fp1);
9262 gen_store_fpr64(ctx, fp0, fd);
9263 tcg_temp_free_i64(fp0);
9265 break;
9266 case OPC_SUB_D:
9267 check_cp1_registers(ctx, fs | ft | fd);
9269 TCGv_i64 fp0 = tcg_temp_new_i64();
9270 TCGv_i64 fp1 = tcg_temp_new_i64();
9272 gen_load_fpr64(ctx, fp0, fs);
9273 gen_load_fpr64(ctx, fp1, ft);
9274 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9275 tcg_temp_free_i64(fp1);
9276 gen_store_fpr64(ctx, fp0, fd);
9277 tcg_temp_free_i64(fp0);
9279 break;
9280 case OPC_MUL_D:
9281 check_cp1_registers(ctx, fs | ft | fd);
9283 TCGv_i64 fp0 = tcg_temp_new_i64();
9284 TCGv_i64 fp1 = tcg_temp_new_i64();
9286 gen_load_fpr64(ctx, fp0, fs);
9287 gen_load_fpr64(ctx, fp1, ft);
9288 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9289 tcg_temp_free_i64(fp1);
9290 gen_store_fpr64(ctx, fp0, fd);
9291 tcg_temp_free_i64(fp0);
9293 break;
9294 case OPC_DIV_D:
9295 check_cp1_registers(ctx, fs | ft | fd);
9297 TCGv_i64 fp0 = tcg_temp_new_i64();
9298 TCGv_i64 fp1 = tcg_temp_new_i64();
9300 gen_load_fpr64(ctx, fp0, fs);
9301 gen_load_fpr64(ctx, fp1, ft);
9302 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9303 tcg_temp_free_i64(fp1);
9304 gen_store_fpr64(ctx, fp0, fd);
9305 tcg_temp_free_i64(fp0);
9307 break;
9308 case OPC_SQRT_D:
9309 check_cp1_registers(ctx, fs | fd);
9311 TCGv_i64 fp0 = tcg_temp_new_i64();
9313 gen_load_fpr64(ctx, fp0, fs);
9314 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9315 gen_store_fpr64(ctx, fp0, fd);
9316 tcg_temp_free_i64(fp0);
9318 break;
9319 case OPC_ABS_D:
9320 check_cp1_registers(ctx, fs | fd);
9322 TCGv_i64 fp0 = tcg_temp_new_i64();
9324 gen_load_fpr64(ctx, fp0, fs);
9325 gen_helper_float_abs_d(fp0, fp0);
9326 gen_store_fpr64(ctx, fp0, fd);
9327 tcg_temp_free_i64(fp0);
9329 break;
9330 case OPC_MOV_D:
9331 check_cp1_registers(ctx, fs | fd);
9333 TCGv_i64 fp0 = tcg_temp_new_i64();
9335 gen_load_fpr64(ctx, fp0, fs);
9336 gen_store_fpr64(ctx, fp0, fd);
9337 tcg_temp_free_i64(fp0);
9339 break;
9340 case OPC_NEG_D:
9341 check_cp1_registers(ctx, fs | fd);
9343 TCGv_i64 fp0 = tcg_temp_new_i64();
9345 gen_load_fpr64(ctx, fp0, fs);
9346 gen_helper_float_chs_d(fp0, fp0);
9347 gen_store_fpr64(ctx, fp0, fd);
9348 tcg_temp_free_i64(fp0);
9350 break;
9351 case OPC_ROUND_L_D:
9352 check_cp1_64bitmode(ctx);
9354 TCGv_i64 fp0 = tcg_temp_new_i64();
9356 gen_load_fpr64(ctx, fp0, fs);
9357 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
9358 gen_store_fpr64(ctx, fp0, fd);
9359 tcg_temp_free_i64(fp0);
9361 break;
9362 case OPC_TRUNC_L_D:
9363 check_cp1_64bitmode(ctx);
9365 TCGv_i64 fp0 = tcg_temp_new_i64();
9367 gen_load_fpr64(ctx, fp0, fs);
9368 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
9369 gen_store_fpr64(ctx, fp0, fd);
9370 tcg_temp_free_i64(fp0);
9372 break;
9373 case OPC_CEIL_L_D:
9374 check_cp1_64bitmode(ctx);
9376 TCGv_i64 fp0 = tcg_temp_new_i64();
9378 gen_load_fpr64(ctx, fp0, fs);
9379 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
9380 gen_store_fpr64(ctx, fp0, fd);
9381 tcg_temp_free_i64(fp0);
9383 break;
9384 case OPC_FLOOR_L_D:
9385 check_cp1_64bitmode(ctx);
9387 TCGv_i64 fp0 = tcg_temp_new_i64();
9389 gen_load_fpr64(ctx, fp0, fs);
9390 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
9391 gen_store_fpr64(ctx, fp0, fd);
9392 tcg_temp_free_i64(fp0);
9394 break;
9395 case OPC_ROUND_W_D:
9396 check_cp1_registers(ctx, fs);
9398 TCGv_i32 fp32 = tcg_temp_new_i32();
9399 TCGv_i64 fp64 = tcg_temp_new_i64();
9401 gen_load_fpr64(ctx, fp64, fs);
9402 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
9403 tcg_temp_free_i64(fp64);
9404 gen_store_fpr32(ctx, fp32, fd);
9405 tcg_temp_free_i32(fp32);
9407 break;
9408 case OPC_TRUNC_W_D:
9409 check_cp1_registers(ctx, fs);
9411 TCGv_i32 fp32 = tcg_temp_new_i32();
9412 TCGv_i64 fp64 = tcg_temp_new_i64();
9414 gen_load_fpr64(ctx, fp64, fs);
9415 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
9416 tcg_temp_free_i64(fp64);
9417 gen_store_fpr32(ctx, fp32, fd);
9418 tcg_temp_free_i32(fp32);
9420 break;
9421 case OPC_CEIL_W_D:
9422 check_cp1_registers(ctx, fs);
9424 TCGv_i32 fp32 = tcg_temp_new_i32();
9425 TCGv_i64 fp64 = tcg_temp_new_i64();
9427 gen_load_fpr64(ctx, fp64, fs);
9428 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
9429 tcg_temp_free_i64(fp64);
9430 gen_store_fpr32(ctx, fp32, fd);
9431 tcg_temp_free_i32(fp32);
9433 break;
9434 case OPC_FLOOR_W_D:
9435 check_cp1_registers(ctx, fs);
9437 TCGv_i32 fp32 = tcg_temp_new_i32();
9438 TCGv_i64 fp64 = tcg_temp_new_i64();
9440 gen_load_fpr64(ctx, fp64, fs);
9441 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
9442 tcg_temp_free_i64(fp64);
9443 gen_store_fpr32(ctx, fp32, fd);
9444 tcg_temp_free_i32(fp32);
9446 break;
9447 case OPC_SEL_D:
9448 check_insn(ctx, ISA_MIPS32R6);
9449 gen_sel_d(ctx, op1, fd, ft, fs);
9450 break;
9451 case OPC_SELEQZ_D:
9452 check_insn(ctx, ISA_MIPS32R6);
9453 gen_sel_d(ctx, op1, fd, ft, fs);
9454 break;
9455 case OPC_SELNEZ_D:
9456 check_insn(ctx, ISA_MIPS32R6);
9457 gen_sel_d(ctx, op1, fd, ft, fs);
9458 break;
9459 case OPC_MOVCF_D:
9460 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9461 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9462 break;
9463 case OPC_MOVZ_D:
9464 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9466 TCGLabel *l1 = gen_new_label();
9467 TCGv_i64 fp0;
9469 if (ft != 0) {
9470 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9472 fp0 = tcg_temp_new_i64();
9473 gen_load_fpr64(ctx, fp0, fs);
9474 gen_store_fpr64(ctx, fp0, fd);
9475 tcg_temp_free_i64(fp0);
9476 gen_set_label(l1);
9478 break;
9479 case OPC_MOVN_D:
9480 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9482 TCGLabel *l1 = gen_new_label();
9483 TCGv_i64 fp0;
9485 if (ft != 0) {
9486 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9487 fp0 = tcg_temp_new_i64();
9488 gen_load_fpr64(ctx, fp0, fs);
9489 gen_store_fpr64(ctx, fp0, fd);
9490 tcg_temp_free_i64(fp0);
9491 gen_set_label(l1);
9494 break;
9495 case OPC_RECIP_D:
9496 check_cp1_registers(ctx, fs | fd);
9498 TCGv_i64 fp0 = tcg_temp_new_i64();
9500 gen_load_fpr64(ctx, fp0, fs);
9501 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9502 gen_store_fpr64(ctx, fp0, fd);
9503 tcg_temp_free_i64(fp0);
9505 break;
9506 case OPC_RSQRT_D:
9507 check_cp1_registers(ctx, fs | fd);
9509 TCGv_i64 fp0 = tcg_temp_new_i64();
9511 gen_load_fpr64(ctx, fp0, fs);
9512 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9513 gen_store_fpr64(ctx, fp0, fd);
9514 tcg_temp_free_i64(fp0);
9516 break;
9517 case OPC_MADDF_D:
9518 check_insn(ctx, ISA_MIPS32R6);
9520 TCGv_i64 fp0 = tcg_temp_new_i64();
9521 TCGv_i64 fp1 = tcg_temp_new_i64();
9522 TCGv_i64 fp2 = tcg_temp_new_i64();
9523 gen_load_fpr64(ctx, fp0, fs);
9524 gen_load_fpr64(ctx, fp1, ft);
9525 gen_load_fpr64(ctx, fp2, fd);
9526 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9527 gen_store_fpr64(ctx, fp2, fd);
9528 tcg_temp_free_i64(fp2);
9529 tcg_temp_free_i64(fp1);
9530 tcg_temp_free_i64(fp0);
9532 break;
9533 case OPC_MSUBF_D:
9534 check_insn(ctx, ISA_MIPS32R6);
9536 TCGv_i64 fp0 = tcg_temp_new_i64();
9537 TCGv_i64 fp1 = tcg_temp_new_i64();
9538 TCGv_i64 fp2 = tcg_temp_new_i64();
9539 gen_load_fpr64(ctx, fp0, fs);
9540 gen_load_fpr64(ctx, fp1, ft);
9541 gen_load_fpr64(ctx, fp2, fd);
9542 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9543 gen_store_fpr64(ctx, fp2, fd);
9544 tcg_temp_free_i64(fp2);
9545 tcg_temp_free_i64(fp1);
9546 tcg_temp_free_i64(fp0);
9548 break;
9549 case OPC_RINT_D:
9550 check_insn(ctx, ISA_MIPS32R6);
9552 TCGv_i64 fp0 = tcg_temp_new_i64();
9553 gen_load_fpr64(ctx, fp0, fs);
9554 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9555 gen_store_fpr64(ctx, fp0, fd);
9556 tcg_temp_free_i64(fp0);
9558 break;
9559 case OPC_CLASS_D:
9560 check_insn(ctx, ISA_MIPS32R6);
9562 TCGv_i64 fp0 = tcg_temp_new_i64();
9563 gen_load_fpr64(ctx, fp0, fs);
9564 gen_helper_float_class_d(fp0, fp0);
9565 gen_store_fpr64(ctx, fp0, fd);
9566 tcg_temp_free_i64(fp0);
9568 break;
9569 case OPC_MIN_D: /* OPC_RECIP2_D */
9570 if (ctx->insn_flags & ISA_MIPS32R6) {
9571 /* OPC_MIN_D */
9572 TCGv_i64 fp0 = tcg_temp_new_i64();
9573 TCGv_i64 fp1 = tcg_temp_new_i64();
9574 gen_load_fpr64(ctx, fp0, fs);
9575 gen_load_fpr64(ctx, fp1, ft);
9576 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9577 gen_store_fpr64(ctx, fp1, fd);
9578 tcg_temp_free_i64(fp1);
9579 tcg_temp_free_i64(fp0);
9580 } else {
9581 /* OPC_RECIP2_D */
9582 check_cp1_64bitmode(ctx);
9584 TCGv_i64 fp0 = tcg_temp_new_i64();
9585 TCGv_i64 fp1 = tcg_temp_new_i64();
9587 gen_load_fpr64(ctx, fp0, fs);
9588 gen_load_fpr64(ctx, fp1, ft);
9589 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9590 tcg_temp_free_i64(fp1);
9591 gen_store_fpr64(ctx, fp0, fd);
9592 tcg_temp_free_i64(fp0);
9595 break;
9596 case OPC_MINA_D: /* OPC_RECIP1_D */
9597 if (ctx->insn_flags & ISA_MIPS32R6) {
9598 /* OPC_MINA_D */
9599 TCGv_i64 fp0 = tcg_temp_new_i64();
9600 TCGv_i64 fp1 = tcg_temp_new_i64();
9601 gen_load_fpr64(ctx, fp0, fs);
9602 gen_load_fpr64(ctx, fp1, ft);
9603 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9604 gen_store_fpr64(ctx, fp1, fd);
9605 tcg_temp_free_i64(fp1);
9606 tcg_temp_free_i64(fp0);
9607 } else {
9608 /* OPC_RECIP1_D */
9609 check_cp1_64bitmode(ctx);
9611 TCGv_i64 fp0 = tcg_temp_new_i64();
9613 gen_load_fpr64(ctx, fp0, fs);
9614 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9615 gen_store_fpr64(ctx, fp0, fd);
9616 tcg_temp_free_i64(fp0);
9619 break;
9620 case OPC_MAX_D: /* OPC_RSQRT1_D */
9621 if (ctx->insn_flags & ISA_MIPS32R6) {
9622 /* OPC_MAX_D */
9623 TCGv_i64 fp0 = tcg_temp_new_i64();
9624 TCGv_i64 fp1 = tcg_temp_new_i64();
9625 gen_load_fpr64(ctx, fp0, fs);
9626 gen_load_fpr64(ctx, fp1, ft);
9627 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9628 gen_store_fpr64(ctx, fp1, fd);
9629 tcg_temp_free_i64(fp1);
9630 tcg_temp_free_i64(fp0);
9631 } else {
9632 /* OPC_RSQRT1_D */
9633 check_cp1_64bitmode(ctx);
9635 TCGv_i64 fp0 = tcg_temp_new_i64();
9637 gen_load_fpr64(ctx, fp0, fs);
9638 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9639 gen_store_fpr64(ctx, fp0, fd);
9640 tcg_temp_free_i64(fp0);
9643 break;
9644 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9645 if (ctx->insn_flags & ISA_MIPS32R6) {
9646 /* OPC_MAXA_D */
9647 TCGv_i64 fp0 = tcg_temp_new_i64();
9648 TCGv_i64 fp1 = tcg_temp_new_i64();
9649 gen_load_fpr64(ctx, fp0, fs);
9650 gen_load_fpr64(ctx, fp1, ft);
9651 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9652 gen_store_fpr64(ctx, fp1, fd);
9653 tcg_temp_free_i64(fp1);
9654 tcg_temp_free_i64(fp0);
9655 } else {
9656 /* OPC_RSQRT2_D */
9657 check_cp1_64bitmode(ctx);
9659 TCGv_i64 fp0 = tcg_temp_new_i64();
9660 TCGv_i64 fp1 = tcg_temp_new_i64();
9662 gen_load_fpr64(ctx, fp0, fs);
9663 gen_load_fpr64(ctx, fp1, ft);
9664 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9665 tcg_temp_free_i64(fp1);
9666 gen_store_fpr64(ctx, fp0, fd);
9667 tcg_temp_free_i64(fp0);
9670 break;
9671 case OPC_CMP_F_D:
9672 case OPC_CMP_UN_D:
9673 case OPC_CMP_EQ_D:
9674 case OPC_CMP_UEQ_D:
9675 case OPC_CMP_OLT_D:
9676 case OPC_CMP_ULT_D:
9677 case OPC_CMP_OLE_D:
9678 case OPC_CMP_ULE_D:
9679 case OPC_CMP_SF_D:
9680 case OPC_CMP_NGLE_D:
9681 case OPC_CMP_SEQ_D:
9682 case OPC_CMP_NGL_D:
9683 case OPC_CMP_LT_D:
9684 case OPC_CMP_NGE_D:
9685 case OPC_CMP_LE_D:
9686 case OPC_CMP_NGT_D:
9687 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9688 if (ctx->opcode & (1 << 6)) {
9689 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9690 } else {
9691 gen_cmp_d(ctx, func-48, ft, fs, cc);
9693 break;
9694 case OPC_CVT_S_D:
9695 check_cp1_registers(ctx, fs);
9697 TCGv_i32 fp32 = tcg_temp_new_i32();
9698 TCGv_i64 fp64 = tcg_temp_new_i64();
9700 gen_load_fpr64(ctx, fp64, fs);
9701 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
9702 tcg_temp_free_i64(fp64);
9703 gen_store_fpr32(ctx, fp32, fd);
9704 tcg_temp_free_i32(fp32);
9706 break;
9707 case OPC_CVT_W_D:
9708 check_cp1_registers(ctx, fs);
9710 TCGv_i32 fp32 = tcg_temp_new_i32();
9711 TCGv_i64 fp64 = tcg_temp_new_i64();
9713 gen_load_fpr64(ctx, fp64, fs);
9714 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
9715 tcg_temp_free_i64(fp64);
9716 gen_store_fpr32(ctx, fp32, fd);
9717 tcg_temp_free_i32(fp32);
9719 break;
9720 case OPC_CVT_L_D:
9721 check_cp1_64bitmode(ctx);
9723 TCGv_i64 fp0 = tcg_temp_new_i64();
9725 gen_load_fpr64(ctx, fp0, fs);
9726 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
9727 gen_store_fpr64(ctx, fp0, fd);
9728 tcg_temp_free_i64(fp0);
9730 break;
9731 case OPC_CVT_S_W:
9733 TCGv_i32 fp0 = tcg_temp_new_i32();
9735 gen_load_fpr32(ctx, fp0, fs);
9736 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
9737 gen_store_fpr32(ctx, fp0, fd);
9738 tcg_temp_free_i32(fp0);
9740 break;
9741 case OPC_CVT_D_W:
9742 check_cp1_registers(ctx, fd);
9744 TCGv_i32 fp32 = tcg_temp_new_i32();
9745 TCGv_i64 fp64 = tcg_temp_new_i64();
9747 gen_load_fpr32(ctx, fp32, fs);
9748 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
9749 tcg_temp_free_i32(fp32);
9750 gen_store_fpr64(ctx, fp64, fd);
9751 tcg_temp_free_i64(fp64);
9753 break;
9754 case OPC_CVT_S_L:
9755 check_cp1_64bitmode(ctx);
9757 TCGv_i32 fp32 = tcg_temp_new_i32();
9758 TCGv_i64 fp64 = tcg_temp_new_i64();
9760 gen_load_fpr64(ctx, fp64, fs);
9761 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
9762 tcg_temp_free_i64(fp64);
9763 gen_store_fpr32(ctx, fp32, fd);
9764 tcg_temp_free_i32(fp32);
9766 break;
9767 case OPC_CVT_D_L:
9768 check_cp1_64bitmode(ctx);
9770 TCGv_i64 fp0 = tcg_temp_new_i64();
9772 gen_load_fpr64(ctx, fp0, fs);
9773 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
9774 gen_store_fpr64(ctx, fp0, fd);
9775 tcg_temp_free_i64(fp0);
9777 break;
9778 case OPC_CVT_PS_PW:
9779 check_ps(ctx);
9781 TCGv_i64 fp0 = tcg_temp_new_i64();
9783 gen_load_fpr64(ctx, fp0, fs);
9784 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
9785 gen_store_fpr64(ctx, fp0, fd);
9786 tcg_temp_free_i64(fp0);
9788 break;
9789 case OPC_ADD_PS:
9790 check_ps(ctx);
9792 TCGv_i64 fp0 = tcg_temp_new_i64();
9793 TCGv_i64 fp1 = tcg_temp_new_i64();
9795 gen_load_fpr64(ctx, fp0, fs);
9796 gen_load_fpr64(ctx, fp1, ft);
9797 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
9798 tcg_temp_free_i64(fp1);
9799 gen_store_fpr64(ctx, fp0, fd);
9800 tcg_temp_free_i64(fp0);
9802 break;
9803 case OPC_SUB_PS:
9804 check_ps(ctx);
9806 TCGv_i64 fp0 = tcg_temp_new_i64();
9807 TCGv_i64 fp1 = tcg_temp_new_i64();
9809 gen_load_fpr64(ctx, fp0, fs);
9810 gen_load_fpr64(ctx, fp1, ft);
9811 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
9812 tcg_temp_free_i64(fp1);
9813 gen_store_fpr64(ctx, fp0, fd);
9814 tcg_temp_free_i64(fp0);
9816 break;
9817 case OPC_MUL_PS:
9818 check_ps(ctx);
9820 TCGv_i64 fp0 = tcg_temp_new_i64();
9821 TCGv_i64 fp1 = tcg_temp_new_i64();
9823 gen_load_fpr64(ctx, fp0, fs);
9824 gen_load_fpr64(ctx, fp1, ft);
9825 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
9826 tcg_temp_free_i64(fp1);
9827 gen_store_fpr64(ctx, fp0, fd);
9828 tcg_temp_free_i64(fp0);
9830 break;
9831 case OPC_ABS_PS:
9832 check_ps(ctx);
9834 TCGv_i64 fp0 = tcg_temp_new_i64();
9836 gen_load_fpr64(ctx, fp0, fs);
9837 gen_helper_float_abs_ps(fp0, fp0);
9838 gen_store_fpr64(ctx, fp0, fd);
9839 tcg_temp_free_i64(fp0);
9841 break;
9842 case OPC_MOV_PS:
9843 check_ps(ctx);
9845 TCGv_i64 fp0 = tcg_temp_new_i64();
9847 gen_load_fpr64(ctx, fp0, fs);
9848 gen_store_fpr64(ctx, fp0, fd);
9849 tcg_temp_free_i64(fp0);
9851 break;
9852 case OPC_NEG_PS:
9853 check_ps(ctx);
9855 TCGv_i64 fp0 = tcg_temp_new_i64();
9857 gen_load_fpr64(ctx, fp0, fs);
9858 gen_helper_float_chs_ps(fp0, fp0);
9859 gen_store_fpr64(ctx, fp0, fd);
9860 tcg_temp_free_i64(fp0);
9862 break;
9863 case OPC_MOVCF_PS:
9864 check_ps(ctx);
9865 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9866 break;
9867 case OPC_MOVZ_PS:
9868 check_ps(ctx);
9870 TCGLabel *l1 = gen_new_label();
9871 TCGv_i64 fp0;
9873 if (ft != 0)
9874 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9875 fp0 = tcg_temp_new_i64();
9876 gen_load_fpr64(ctx, fp0, fs);
9877 gen_store_fpr64(ctx, fp0, fd);
9878 tcg_temp_free_i64(fp0);
9879 gen_set_label(l1);
9881 break;
9882 case OPC_MOVN_PS:
9883 check_ps(ctx);
9885 TCGLabel *l1 = gen_new_label();
9886 TCGv_i64 fp0;
9888 if (ft != 0) {
9889 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9890 fp0 = tcg_temp_new_i64();
9891 gen_load_fpr64(ctx, fp0, fs);
9892 gen_store_fpr64(ctx, fp0, fd);
9893 tcg_temp_free_i64(fp0);
9894 gen_set_label(l1);
9897 break;
9898 case OPC_ADDR_PS:
9899 check_ps(ctx);
9901 TCGv_i64 fp0 = tcg_temp_new_i64();
9902 TCGv_i64 fp1 = tcg_temp_new_i64();
9904 gen_load_fpr64(ctx, fp0, ft);
9905 gen_load_fpr64(ctx, fp1, fs);
9906 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
9907 tcg_temp_free_i64(fp1);
9908 gen_store_fpr64(ctx, fp0, fd);
9909 tcg_temp_free_i64(fp0);
9911 break;
9912 case OPC_MULR_PS:
9913 check_ps(ctx);
9915 TCGv_i64 fp0 = tcg_temp_new_i64();
9916 TCGv_i64 fp1 = tcg_temp_new_i64();
9918 gen_load_fpr64(ctx, fp0, ft);
9919 gen_load_fpr64(ctx, fp1, fs);
9920 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
9921 tcg_temp_free_i64(fp1);
9922 gen_store_fpr64(ctx, fp0, fd);
9923 tcg_temp_free_i64(fp0);
9925 break;
9926 case OPC_RECIP2_PS:
9927 check_ps(ctx);
9929 TCGv_i64 fp0 = tcg_temp_new_i64();
9930 TCGv_i64 fp1 = tcg_temp_new_i64();
9932 gen_load_fpr64(ctx, fp0, fs);
9933 gen_load_fpr64(ctx, fp1, ft);
9934 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
9935 tcg_temp_free_i64(fp1);
9936 gen_store_fpr64(ctx, fp0, fd);
9937 tcg_temp_free_i64(fp0);
9939 break;
9940 case OPC_RECIP1_PS:
9941 check_ps(ctx);
9943 TCGv_i64 fp0 = tcg_temp_new_i64();
9945 gen_load_fpr64(ctx, fp0, fs);
9946 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
9947 gen_store_fpr64(ctx, fp0, fd);
9948 tcg_temp_free_i64(fp0);
9950 break;
9951 case OPC_RSQRT1_PS:
9952 check_ps(ctx);
9954 TCGv_i64 fp0 = tcg_temp_new_i64();
9956 gen_load_fpr64(ctx, fp0, fs);
9957 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
9958 gen_store_fpr64(ctx, fp0, fd);
9959 tcg_temp_free_i64(fp0);
9961 break;
9962 case OPC_RSQRT2_PS:
9963 check_ps(ctx);
9965 TCGv_i64 fp0 = tcg_temp_new_i64();
9966 TCGv_i64 fp1 = tcg_temp_new_i64();
9968 gen_load_fpr64(ctx, fp0, fs);
9969 gen_load_fpr64(ctx, fp1, ft);
9970 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
9971 tcg_temp_free_i64(fp1);
9972 gen_store_fpr64(ctx, fp0, fd);
9973 tcg_temp_free_i64(fp0);
9975 break;
9976 case OPC_CVT_S_PU:
9977 check_cp1_64bitmode(ctx);
9979 TCGv_i32 fp0 = tcg_temp_new_i32();
9981 gen_load_fpr32h(ctx, fp0, fs);
9982 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
9983 gen_store_fpr32(ctx, fp0, fd);
9984 tcg_temp_free_i32(fp0);
9986 break;
9987 case OPC_CVT_PW_PS:
9988 check_ps(ctx);
9990 TCGv_i64 fp0 = tcg_temp_new_i64();
9992 gen_load_fpr64(ctx, fp0, fs);
9993 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
9994 gen_store_fpr64(ctx, fp0, fd);
9995 tcg_temp_free_i64(fp0);
9997 break;
9998 case OPC_CVT_S_PL:
9999 check_cp1_64bitmode(ctx);
10001 TCGv_i32 fp0 = tcg_temp_new_i32();
10003 gen_load_fpr32(ctx, fp0, fs);
10004 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10005 gen_store_fpr32(ctx, fp0, fd);
10006 tcg_temp_free_i32(fp0);
10008 break;
10009 case OPC_PLL_PS:
10010 check_ps(ctx);
10012 TCGv_i32 fp0 = tcg_temp_new_i32();
10013 TCGv_i32 fp1 = tcg_temp_new_i32();
10015 gen_load_fpr32(ctx, fp0, fs);
10016 gen_load_fpr32(ctx, fp1, ft);
10017 gen_store_fpr32h(ctx, fp0, fd);
10018 gen_store_fpr32(ctx, fp1, fd);
10019 tcg_temp_free_i32(fp0);
10020 tcg_temp_free_i32(fp1);
10022 break;
10023 case OPC_PLU_PS:
10024 check_ps(ctx);
10026 TCGv_i32 fp0 = tcg_temp_new_i32();
10027 TCGv_i32 fp1 = tcg_temp_new_i32();
10029 gen_load_fpr32(ctx, fp0, fs);
10030 gen_load_fpr32h(ctx, fp1, ft);
10031 gen_store_fpr32(ctx, fp1, fd);
10032 gen_store_fpr32h(ctx, fp0, fd);
10033 tcg_temp_free_i32(fp0);
10034 tcg_temp_free_i32(fp1);
10036 break;
10037 case OPC_PUL_PS:
10038 check_ps(ctx);
10040 TCGv_i32 fp0 = tcg_temp_new_i32();
10041 TCGv_i32 fp1 = tcg_temp_new_i32();
10043 gen_load_fpr32h(ctx, fp0, fs);
10044 gen_load_fpr32(ctx, fp1, ft);
10045 gen_store_fpr32(ctx, fp1, fd);
10046 gen_store_fpr32h(ctx, fp0, fd);
10047 tcg_temp_free_i32(fp0);
10048 tcg_temp_free_i32(fp1);
10050 break;
10051 case OPC_PUU_PS:
10052 check_ps(ctx);
10054 TCGv_i32 fp0 = tcg_temp_new_i32();
10055 TCGv_i32 fp1 = tcg_temp_new_i32();
10057 gen_load_fpr32h(ctx, fp0, fs);
10058 gen_load_fpr32h(ctx, fp1, ft);
10059 gen_store_fpr32(ctx, fp1, fd);
10060 gen_store_fpr32h(ctx, fp0, fd);
10061 tcg_temp_free_i32(fp0);
10062 tcg_temp_free_i32(fp1);
10064 break;
10065 case OPC_CMP_F_PS:
10066 case OPC_CMP_UN_PS:
10067 case OPC_CMP_EQ_PS:
10068 case OPC_CMP_UEQ_PS:
10069 case OPC_CMP_OLT_PS:
10070 case OPC_CMP_ULT_PS:
10071 case OPC_CMP_OLE_PS:
10072 case OPC_CMP_ULE_PS:
10073 case OPC_CMP_SF_PS:
10074 case OPC_CMP_NGLE_PS:
10075 case OPC_CMP_SEQ_PS:
10076 case OPC_CMP_NGL_PS:
10077 case OPC_CMP_LT_PS:
10078 case OPC_CMP_NGE_PS:
10079 case OPC_CMP_LE_PS:
10080 case OPC_CMP_NGT_PS:
10081 if (ctx->opcode & (1 << 6)) {
10082 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10083 } else {
10084 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10086 break;
10087 default:
10088 MIPS_INVAL("farith");
10089 generate_exception_end(ctx, EXCP_RI);
10090 return;
10094 /* Coprocessor 3 (FPU) */
10095 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10096 int fd, int fs, int base, int index)
10098 TCGv t0 = tcg_temp_new();
10100 if (base == 0) {
10101 gen_load_gpr(t0, index);
10102 } else if (index == 0) {
10103 gen_load_gpr(t0, base);
10104 } else {
10105 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10107 /* Don't do NOP if destination is zero: we must perform the actual
10108 memory access. */
10109 switch (opc) {
10110 case OPC_LWXC1:
10111 check_cop1x(ctx);
10113 TCGv_i32 fp0 = tcg_temp_new_i32();
10115 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10116 tcg_gen_trunc_tl_i32(fp0, t0);
10117 gen_store_fpr32(ctx, fp0, fd);
10118 tcg_temp_free_i32(fp0);
10120 break;
10121 case OPC_LDXC1:
10122 check_cop1x(ctx);
10123 check_cp1_registers(ctx, fd);
10125 TCGv_i64 fp0 = tcg_temp_new_i64();
10126 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10127 gen_store_fpr64(ctx, fp0, fd);
10128 tcg_temp_free_i64(fp0);
10130 break;
10131 case OPC_LUXC1:
10132 check_cp1_64bitmode(ctx);
10133 tcg_gen_andi_tl(t0, t0, ~0x7);
10135 TCGv_i64 fp0 = tcg_temp_new_i64();
10137 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10138 gen_store_fpr64(ctx, fp0, fd);
10139 tcg_temp_free_i64(fp0);
10141 break;
10142 case OPC_SWXC1:
10143 check_cop1x(ctx);
10145 TCGv_i32 fp0 = tcg_temp_new_i32();
10146 gen_load_fpr32(ctx, fp0, fs);
10147 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10148 tcg_temp_free_i32(fp0);
10150 break;
10151 case OPC_SDXC1:
10152 check_cop1x(ctx);
10153 check_cp1_registers(ctx, fs);
10155 TCGv_i64 fp0 = tcg_temp_new_i64();
10156 gen_load_fpr64(ctx, fp0, fs);
10157 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10158 tcg_temp_free_i64(fp0);
10160 break;
10161 case OPC_SUXC1:
10162 check_cp1_64bitmode(ctx);
10163 tcg_gen_andi_tl(t0, t0, ~0x7);
10165 TCGv_i64 fp0 = tcg_temp_new_i64();
10166 gen_load_fpr64(ctx, fp0, fs);
10167 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10168 tcg_temp_free_i64(fp0);
10170 break;
10172 tcg_temp_free(t0);
10175 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10176 int fd, int fr, int fs, int ft)
10178 switch (opc) {
10179 case OPC_ALNV_PS:
10180 check_ps(ctx);
10182 TCGv t0 = tcg_temp_local_new();
10183 TCGv_i32 fp = tcg_temp_new_i32();
10184 TCGv_i32 fph = tcg_temp_new_i32();
10185 TCGLabel *l1 = gen_new_label();
10186 TCGLabel *l2 = gen_new_label();
10188 gen_load_gpr(t0, fr);
10189 tcg_gen_andi_tl(t0, t0, 0x7);
10191 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10192 gen_load_fpr32(ctx, fp, fs);
10193 gen_load_fpr32h(ctx, fph, fs);
10194 gen_store_fpr32(ctx, fp, fd);
10195 gen_store_fpr32h(ctx, fph, fd);
10196 tcg_gen_br(l2);
10197 gen_set_label(l1);
10198 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10199 tcg_temp_free(t0);
10200 #ifdef TARGET_WORDS_BIGENDIAN
10201 gen_load_fpr32(ctx, fp, fs);
10202 gen_load_fpr32h(ctx, fph, ft);
10203 gen_store_fpr32h(ctx, fp, fd);
10204 gen_store_fpr32(ctx, fph, fd);
10205 #else
10206 gen_load_fpr32h(ctx, fph, fs);
10207 gen_load_fpr32(ctx, fp, ft);
10208 gen_store_fpr32(ctx, fph, fd);
10209 gen_store_fpr32h(ctx, fp, fd);
10210 #endif
10211 gen_set_label(l2);
10212 tcg_temp_free_i32(fp);
10213 tcg_temp_free_i32(fph);
10215 break;
10216 case OPC_MADD_S:
10217 check_cop1x(ctx);
10219 TCGv_i32 fp0 = tcg_temp_new_i32();
10220 TCGv_i32 fp1 = tcg_temp_new_i32();
10221 TCGv_i32 fp2 = tcg_temp_new_i32();
10223 gen_load_fpr32(ctx, fp0, fs);
10224 gen_load_fpr32(ctx, fp1, ft);
10225 gen_load_fpr32(ctx, fp2, fr);
10226 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10227 tcg_temp_free_i32(fp0);
10228 tcg_temp_free_i32(fp1);
10229 gen_store_fpr32(ctx, fp2, fd);
10230 tcg_temp_free_i32(fp2);
10232 break;
10233 case OPC_MADD_D:
10234 check_cop1x(ctx);
10235 check_cp1_registers(ctx, fd | fs | ft | fr);
10237 TCGv_i64 fp0 = tcg_temp_new_i64();
10238 TCGv_i64 fp1 = tcg_temp_new_i64();
10239 TCGv_i64 fp2 = tcg_temp_new_i64();
10241 gen_load_fpr64(ctx, fp0, fs);
10242 gen_load_fpr64(ctx, fp1, ft);
10243 gen_load_fpr64(ctx, fp2, fr);
10244 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10245 tcg_temp_free_i64(fp0);
10246 tcg_temp_free_i64(fp1);
10247 gen_store_fpr64(ctx, fp2, fd);
10248 tcg_temp_free_i64(fp2);
10250 break;
10251 case OPC_MADD_PS:
10252 check_ps(ctx);
10254 TCGv_i64 fp0 = tcg_temp_new_i64();
10255 TCGv_i64 fp1 = tcg_temp_new_i64();
10256 TCGv_i64 fp2 = tcg_temp_new_i64();
10258 gen_load_fpr64(ctx, fp0, fs);
10259 gen_load_fpr64(ctx, fp1, ft);
10260 gen_load_fpr64(ctx, fp2, fr);
10261 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10262 tcg_temp_free_i64(fp0);
10263 tcg_temp_free_i64(fp1);
10264 gen_store_fpr64(ctx, fp2, fd);
10265 tcg_temp_free_i64(fp2);
10267 break;
10268 case OPC_MSUB_S:
10269 check_cop1x(ctx);
10271 TCGv_i32 fp0 = tcg_temp_new_i32();
10272 TCGv_i32 fp1 = tcg_temp_new_i32();
10273 TCGv_i32 fp2 = tcg_temp_new_i32();
10275 gen_load_fpr32(ctx, fp0, fs);
10276 gen_load_fpr32(ctx, fp1, ft);
10277 gen_load_fpr32(ctx, fp2, fr);
10278 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10279 tcg_temp_free_i32(fp0);
10280 tcg_temp_free_i32(fp1);
10281 gen_store_fpr32(ctx, fp2, fd);
10282 tcg_temp_free_i32(fp2);
10284 break;
10285 case OPC_MSUB_D:
10286 check_cop1x(ctx);
10287 check_cp1_registers(ctx, fd | fs | ft | fr);
10289 TCGv_i64 fp0 = tcg_temp_new_i64();
10290 TCGv_i64 fp1 = tcg_temp_new_i64();
10291 TCGv_i64 fp2 = tcg_temp_new_i64();
10293 gen_load_fpr64(ctx, fp0, fs);
10294 gen_load_fpr64(ctx, fp1, ft);
10295 gen_load_fpr64(ctx, fp2, fr);
10296 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10297 tcg_temp_free_i64(fp0);
10298 tcg_temp_free_i64(fp1);
10299 gen_store_fpr64(ctx, fp2, fd);
10300 tcg_temp_free_i64(fp2);
10302 break;
10303 case OPC_MSUB_PS:
10304 check_ps(ctx);
10306 TCGv_i64 fp0 = tcg_temp_new_i64();
10307 TCGv_i64 fp1 = tcg_temp_new_i64();
10308 TCGv_i64 fp2 = tcg_temp_new_i64();
10310 gen_load_fpr64(ctx, fp0, fs);
10311 gen_load_fpr64(ctx, fp1, ft);
10312 gen_load_fpr64(ctx, fp2, fr);
10313 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10314 tcg_temp_free_i64(fp0);
10315 tcg_temp_free_i64(fp1);
10316 gen_store_fpr64(ctx, fp2, fd);
10317 tcg_temp_free_i64(fp2);
10319 break;
10320 case OPC_NMADD_S:
10321 check_cop1x(ctx);
10323 TCGv_i32 fp0 = tcg_temp_new_i32();
10324 TCGv_i32 fp1 = tcg_temp_new_i32();
10325 TCGv_i32 fp2 = tcg_temp_new_i32();
10327 gen_load_fpr32(ctx, fp0, fs);
10328 gen_load_fpr32(ctx, fp1, ft);
10329 gen_load_fpr32(ctx, fp2, fr);
10330 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10331 tcg_temp_free_i32(fp0);
10332 tcg_temp_free_i32(fp1);
10333 gen_store_fpr32(ctx, fp2, fd);
10334 tcg_temp_free_i32(fp2);
10336 break;
10337 case OPC_NMADD_D:
10338 check_cop1x(ctx);
10339 check_cp1_registers(ctx, fd | fs | ft | fr);
10341 TCGv_i64 fp0 = tcg_temp_new_i64();
10342 TCGv_i64 fp1 = tcg_temp_new_i64();
10343 TCGv_i64 fp2 = tcg_temp_new_i64();
10345 gen_load_fpr64(ctx, fp0, fs);
10346 gen_load_fpr64(ctx, fp1, ft);
10347 gen_load_fpr64(ctx, fp2, fr);
10348 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10349 tcg_temp_free_i64(fp0);
10350 tcg_temp_free_i64(fp1);
10351 gen_store_fpr64(ctx, fp2, fd);
10352 tcg_temp_free_i64(fp2);
10354 break;
10355 case OPC_NMADD_PS:
10356 check_ps(ctx);
10358 TCGv_i64 fp0 = tcg_temp_new_i64();
10359 TCGv_i64 fp1 = tcg_temp_new_i64();
10360 TCGv_i64 fp2 = tcg_temp_new_i64();
10362 gen_load_fpr64(ctx, fp0, fs);
10363 gen_load_fpr64(ctx, fp1, ft);
10364 gen_load_fpr64(ctx, fp2, fr);
10365 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10366 tcg_temp_free_i64(fp0);
10367 tcg_temp_free_i64(fp1);
10368 gen_store_fpr64(ctx, fp2, fd);
10369 tcg_temp_free_i64(fp2);
10371 break;
10372 case OPC_NMSUB_S:
10373 check_cop1x(ctx);
10375 TCGv_i32 fp0 = tcg_temp_new_i32();
10376 TCGv_i32 fp1 = tcg_temp_new_i32();
10377 TCGv_i32 fp2 = tcg_temp_new_i32();
10379 gen_load_fpr32(ctx, fp0, fs);
10380 gen_load_fpr32(ctx, fp1, ft);
10381 gen_load_fpr32(ctx, fp2, fr);
10382 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10383 tcg_temp_free_i32(fp0);
10384 tcg_temp_free_i32(fp1);
10385 gen_store_fpr32(ctx, fp2, fd);
10386 tcg_temp_free_i32(fp2);
10388 break;
10389 case OPC_NMSUB_D:
10390 check_cop1x(ctx);
10391 check_cp1_registers(ctx, fd | fs | ft | fr);
10393 TCGv_i64 fp0 = tcg_temp_new_i64();
10394 TCGv_i64 fp1 = tcg_temp_new_i64();
10395 TCGv_i64 fp2 = tcg_temp_new_i64();
10397 gen_load_fpr64(ctx, fp0, fs);
10398 gen_load_fpr64(ctx, fp1, ft);
10399 gen_load_fpr64(ctx, fp2, fr);
10400 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10401 tcg_temp_free_i64(fp0);
10402 tcg_temp_free_i64(fp1);
10403 gen_store_fpr64(ctx, fp2, fd);
10404 tcg_temp_free_i64(fp2);
10406 break;
10407 case OPC_NMSUB_PS:
10408 check_ps(ctx);
10410 TCGv_i64 fp0 = tcg_temp_new_i64();
10411 TCGv_i64 fp1 = tcg_temp_new_i64();
10412 TCGv_i64 fp2 = tcg_temp_new_i64();
10414 gen_load_fpr64(ctx, fp0, fs);
10415 gen_load_fpr64(ctx, fp1, ft);
10416 gen_load_fpr64(ctx, fp2, fr);
10417 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10418 tcg_temp_free_i64(fp0);
10419 tcg_temp_free_i64(fp1);
10420 gen_store_fpr64(ctx, fp2, fd);
10421 tcg_temp_free_i64(fp2);
10423 break;
10424 default:
10425 MIPS_INVAL("flt3_arith");
10426 generate_exception_end(ctx, EXCP_RI);
10427 return;
10431 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
10433 TCGv t0;
10435 #if !defined(CONFIG_USER_ONLY)
10436 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10437 Therefore only check the ISA in system mode. */
10438 check_insn(ctx, ISA_MIPS32R2);
10439 #endif
10440 t0 = tcg_temp_new();
10442 switch (rd) {
10443 case 0:
10444 gen_helper_rdhwr_cpunum(t0, cpu_env);
10445 gen_store_gpr(t0, rt);
10446 break;
10447 case 1:
10448 gen_helper_rdhwr_synci_step(t0, cpu_env);
10449 gen_store_gpr(t0, rt);
10450 break;
10451 case 2:
10452 gen_helper_rdhwr_cc(t0, cpu_env);
10453 gen_store_gpr(t0, rt);
10454 break;
10455 case 3:
10456 gen_helper_rdhwr_ccres(t0, cpu_env);
10457 gen_store_gpr(t0, rt);
10458 break;
10459 case 4:
10460 check_insn(ctx, ISA_MIPS32R6);
10461 if (sel != 0) {
10462 /* Performance counter registers are not implemented other than
10463 * control register 0.
10465 generate_exception(ctx, EXCP_RI);
10467 gen_helper_rdhwr_performance(t0, cpu_env);
10468 gen_store_gpr(t0, rt);
10469 break;
10470 case 5:
10471 check_insn(ctx, ISA_MIPS32R6);
10472 gen_helper_rdhwr_xnp(t0, cpu_env);
10473 gen_store_gpr(t0, rt);
10474 break;
10475 case 29:
10476 #if defined(CONFIG_USER_ONLY)
10477 tcg_gen_ld_tl(t0, cpu_env,
10478 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10479 gen_store_gpr(t0, rt);
10480 break;
10481 #else
10482 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10483 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10484 tcg_gen_ld_tl(t0, cpu_env,
10485 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10486 gen_store_gpr(t0, rt);
10487 } else {
10488 generate_exception_end(ctx, EXCP_RI);
10490 break;
10491 #endif
10492 default: /* Invalid */
10493 MIPS_INVAL("rdhwr");
10494 generate_exception_end(ctx, EXCP_RI);
10495 break;
10497 tcg_temp_free(t0);
10500 static inline void clear_branch_hflags(DisasContext *ctx)
10502 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10503 if (ctx->bstate == BS_NONE) {
10504 save_cpu_state(ctx, 0);
10505 } else {
10506 /* it is not safe to save ctx->hflags as hflags may be changed
10507 in execution time by the instruction in delay / forbidden slot. */
10508 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10512 static void gen_branch(DisasContext *ctx, int insn_bytes)
10514 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10515 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10516 /* Branches completion */
10517 clear_branch_hflags(ctx);
10518 ctx->bstate = BS_BRANCH;
10519 /* FIXME: Need to clear can_do_io. */
10520 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10521 case MIPS_HFLAG_FBNSLOT:
10522 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10523 break;
10524 case MIPS_HFLAG_B:
10525 /* unconditional branch */
10526 if (proc_hflags & MIPS_HFLAG_BX) {
10527 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10529 gen_goto_tb(ctx, 0, ctx->btarget);
10530 break;
10531 case MIPS_HFLAG_BL:
10532 /* blikely taken case */
10533 gen_goto_tb(ctx, 0, ctx->btarget);
10534 break;
10535 case MIPS_HFLAG_BC:
10536 /* Conditional branch */
10538 TCGLabel *l1 = gen_new_label();
10540 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10541 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10542 gen_set_label(l1);
10543 gen_goto_tb(ctx, 0, ctx->btarget);
10545 break;
10546 case MIPS_HFLAG_BR:
10547 /* unconditional branch to register */
10548 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10549 TCGv t0 = tcg_temp_new();
10550 TCGv_i32 t1 = tcg_temp_new_i32();
10552 tcg_gen_andi_tl(t0, btarget, 0x1);
10553 tcg_gen_trunc_tl_i32(t1, t0);
10554 tcg_temp_free(t0);
10555 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10556 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10557 tcg_gen_or_i32(hflags, hflags, t1);
10558 tcg_temp_free_i32(t1);
10560 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10561 } else {
10562 tcg_gen_mov_tl(cpu_PC, btarget);
10564 if (ctx->singlestep_enabled) {
10565 save_cpu_state(ctx, 0);
10566 gen_helper_raise_exception_debug(cpu_env);
10568 tcg_gen_exit_tb(0);
10569 break;
10570 default:
10571 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
10572 abort();
10577 /* Compact Branches */
10578 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
10579 int rs, int rt, int32_t offset)
10581 int bcond_compute = 0;
10582 TCGv t0 = tcg_temp_new();
10583 TCGv t1 = tcg_temp_new();
10584 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
10586 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10587 #ifdef MIPS_DEBUG_DISAS
10588 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10589 "\n", ctx->pc);
10590 #endif
10591 generate_exception_end(ctx, EXCP_RI);
10592 goto out;
10595 /* Load needed operands and calculate btarget */
10596 switch (opc) {
10597 /* compact branch */
10598 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10599 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10600 gen_load_gpr(t0, rs);
10601 gen_load_gpr(t1, rt);
10602 bcond_compute = 1;
10603 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10604 if (rs <= rt && rs == 0) {
10605 /* OPC_BEQZALC, OPC_BNEZALC */
10606 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10608 break;
10609 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10610 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10611 gen_load_gpr(t0, rs);
10612 gen_load_gpr(t1, rt);
10613 bcond_compute = 1;
10614 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10615 break;
10616 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10617 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10618 if (rs == 0 || rs == rt) {
10619 /* OPC_BLEZALC, OPC_BGEZALC */
10620 /* OPC_BGTZALC, OPC_BLTZALC */
10621 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10623 gen_load_gpr(t0, rs);
10624 gen_load_gpr(t1, rt);
10625 bcond_compute = 1;
10626 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10627 break;
10628 case OPC_BC:
10629 case OPC_BALC:
10630 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10631 break;
10632 case OPC_BEQZC:
10633 case OPC_BNEZC:
10634 if (rs != 0) {
10635 /* OPC_BEQZC, OPC_BNEZC */
10636 gen_load_gpr(t0, rs);
10637 bcond_compute = 1;
10638 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10639 } else {
10640 /* OPC_JIC, OPC_JIALC */
10641 TCGv tbase = tcg_temp_new();
10642 TCGv toffset = tcg_temp_new();
10644 gen_load_gpr(tbase, rt);
10645 tcg_gen_movi_tl(toffset, offset);
10646 gen_op_addr_add(ctx, btarget, tbase, toffset);
10647 tcg_temp_free(tbase);
10648 tcg_temp_free(toffset);
10650 break;
10651 default:
10652 MIPS_INVAL("Compact branch/jump");
10653 generate_exception_end(ctx, EXCP_RI);
10654 goto out;
10657 if (bcond_compute == 0) {
10658 /* Uncoditional compact branch */
10659 switch (opc) {
10660 case OPC_JIALC:
10661 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10662 /* Fallthrough */
10663 case OPC_JIC:
10664 ctx->hflags |= MIPS_HFLAG_BR;
10665 break;
10666 case OPC_BALC:
10667 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10668 /* Fallthrough */
10669 case OPC_BC:
10670 ctx->hflags |= MIPS_HFLAG_B;
10671 break;
10672 default:
10673 MIPS_INVAL("Compact branch/jump");
10674 generate_exception_end(ctx, EXCP_RI);
10675 goto out;
10678 /* Generating branch here as compact branches don't have delay slot */
10679 gen_branch(ctx, 4);
10680 } else {
10681 /* Conditional compact branch */
10682 TCGLabel *fs = gen_new_label();
10683 save_cpu_state(ctx, 0);
10685 switch (opc) {
10686 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10687 if (rs == 0 && rt != 0) {
10688 /* OPC_BLEZALC */
10689 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10690 } else if (rs != 0 && rt != 0 && rs == rt) {
10691 /* OPC_BGEZALC */
10692 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10693 } else {
10694 /* OPC_BGEUC */
10695 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
10697 break;
10698 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10699 if (rs == 0 && rt != 0) {
10700 /* OPC_BGTZALC */
10701 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10702 } else if (rs != 0 && rt != 0 && rs == rt) {
10703 /* OPC_BLTZALC */
10704 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10705 } else {
10706 /* OPC_BLTUC */
10707 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
10709 break;
10710 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10711 if (rs == 0 && rt != 0) {
10712 /* OPC_BLEZC */
10713 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10714 } else if (rs != 0 && rt != 0 && rs == rt) {
10715 /* OPC_BGEZC */
10716 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10717 } else {
10718 /* OPC_BGEC */
10719 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
10721 break;
10722 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10723 if (rs == 0 && rt != 0) {
10724 /* OPC_BGTZC */
10725 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10726 } else if (rs != 0 && rt != 0 && rs == rt) {
10727 /* OPC_BLTZC */
10728 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10729 } else {
10730 /* OPC_BLTC */
10731 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
10733 break;
10734 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10735 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10736 if (rs >= rt) {
10737 /* OPC_BOVC, OPC_BNVC */
10738 TCGv t2 = tcg_temp_new();
10739 TCGv t3 = tcg_temp_new();
10740 TCGv t4 = tcg_temp_new();
10741 TCGv input_overflow = tcg_temp_new();
10743 gen_load_gpr(t0, rs);
10744 gen_load_gpr(t1, rt);
10745 tcg_gen_ext32s_tl(t2, t0);
10746 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
10747 tcg_gen_ext32s_tl(t3, t1);
10748 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
10749 tcg_gen_or_tl(input_overflow, input_overflow, t4);
10751 tcg_gen_add_tl(t4, t2, t3);
10752 tcg_gen_ext32s_tl(t4, t4);
10753 tcg_gen_xor_tl(t2, t2, t3);
10754 tcg_gen_xor_tl(t3, t4, t3);
10755 tcg_gen_andc_tl(t2, t3, t2);
10756 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
10757 tcg_gen_or_tl(t4, t4, input_overflow);
10758 if (opc == OPC_BOVC) {
10759 /* OPC_BOVC */
10760 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
10761 } else {
10762 /* OPC_BNVC */
10763 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
10765 tcg_temp_free(input_overflow);
10766 tcg_temp_free(t4);
10767 tcg_temp_free(t3);
10768 tcg_temp_free(t2);
10769 } else if (rs < rt && rs == 0) {
10770 /* OPC_BEQZALC, OPC_BNEZALC */
10771 if (opc == OPC_BEQZALC) {
10772 /* OPC_BEQZALC */
10773 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
10774 } else {
10775 /* OPC_BNEZALC */
10776 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
10778 } else {
10779 /* OPC_BEQC, OPC_BNEC */
10780 if (opc == OPC_BEQC) {
10781 /* OPC_BEQC */
10782 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
10783 } else {
10784 /* OPC_BNEC */
10785 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
10788 break;
10789 case OPC_BEQZC:
10790 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
10791 break;
10792 case OPC_BNEZC:
10793 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
10794 break;
10795 default:
10796 MIPS_INVAL("Compact conditional branch/jump");
10797 generate_exception_end(ctx, EXCP_RI);
10798 goto out;
10801 /* Generating branch here as compact branches don't have delay slot */
10802 gen_goto_tb(ctx, 1, ctx->btarget);
10803 gen_set_label(fs);
10805 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
10808 out:
10809 tcg_temp_free(t0);
10810 tcg_temp_free(t1);
10813 /* ISA extensions (ASEs) */
10814 /* MIPS16 extension to MIPS32 */
10816 /* MIPS16 major opcodes */
10817 enum {
10818 M16_OPC_ADDIUSP = 0x00,
10819 M16_OPC_ADDIUPC = 0x01,
10820 M16_OPC_B = 0x02,
10821 M16_OPC_JAL = 0x03,
10822 M16_OPC_BEQZ = 0x04,
10823 M16_OPC_BNEQZ = 0x05,
10824 M16_OPC_SHIFT = 0x06,
10825 M16_OPC_LD = 0x07,
10826 M16_OPC_RRIA = 0x08,
10827 M16_OPC_ADDIU8 = 0x09,
10828 M16_OPC_SLTI = 0x0a,
10829 M16_OPC_SLTIU = 0x0b,
10830 M16_OPC_I8 = 0x0c,
10831 M16_OPC_LI = 0x0d,
10832 M16_OPC_CMPI = 0x0e,
10833 M16_OPC_SD = 0x0f,
10834 M16_OPC_LB = 0x10,
10835 M16_OPC_LH = 0x11,
10836 M16_OPC_LWSP = 0x12,
10837 M16_OPC_LW = 0x13,
10838 M16_OPC_LBU = 0x14,
10839 M16_OPC_LHU = 0x15,
10840 M16_OPC_LWPC = 0x16,
10841 M16_OPC_LWU = 0x17,
10842 M16_OPC_SB = 0x18,
10843 M16_OPC_SH = 0x19,
10844 M16_OPC_SWSP = 0x1a,
10845 M16_OPC_SW = 0x1b,
10846 M16_OPC_RRR = 0x1c,
10847 M16_OPC_RR = 0x1d,
10848 M16_OPC_EXTEND = 0x1e,
10849 M16_OPC_I64 = 0x1f
10852 /* I8 funct field */
10853 enum {
10854 I8_BTEQZ = 0x0,
10855 I8_BTNEZ = 0x1,
10856 I8_SWRASP = 0x2,
10857 I8_ADJSP = 0x3,
10858 I8_SVRS = 0x4,
10859 I8_MOV32R = 0x5,
10860 I8_MOVR32 = 0x7
10863 /* RRR f field */
10864 enum {
10865 RRR_DADDU = 0x0,
10866 RRR_ADDU = 0x1,
10867 RRR_DSUBU = 0x2,
10868 RRR_SUBU = 0x3
10871 /* RR funct field */
10872 enum {
10873 RR_JR = 0x00,
10874 RR_SDBBP = 0x01,
10875 RR_SLT = 0x02,
10876 RR_SLTU = 0x03,
10877 RR_SLLV = 0x04,
10878 RR_BREAK = 0x05,
10879 RR_SRLV = 0x06,
10880 RR_SRAV = 0x07,
10881 RR_DSRL = 0x08,
10882 RR_CMP = 0x0a,
10883 RR_NEG = 0x0b,
10884 RR_AND = 0x0c,
10885 RR_OR = 0x0d,
10886 RR_XOR = 0x0e,
10887 RR_NOT = 0x0f,
10888 RR_MFHI = 0x10,
10889 RR_CNVT = 0x11,
10890 RR_MFLO = 0x12,
10891 RR_DSRA = 0x13,
10892 RR_DSLLV = 0x14,
10893 RR_DSRLV = 0x16,
10894 RR_DSRAV = 0x17,
10895 RR_MULT = 0x18,
10896 RR_MULTU = 0x19,
10897 RR_DIV = 0x1a,
10898 RR_DIVU = 0x1b,
10899 RR_DMULT = 0x1c,
10900 RR_DMULTU = 0x1d,
10901 RR_DDIV = 0x1e,
10902 RR_DDIVU = 0x1f
10905 /* I64 funct field */
10906 enum {
10907 I64_LDSP = 0x0,
10908 I64_SDSP = 0x1,
10909 I64_SDRASP = 0x2,
10910 I64_DADJSP = 0x3,
10911 I64_LDPC = 0x4,
10912 I64_DADDIU5 = 0x5,
10913 I64_DADDIUPC = 0x6,
10914 I64_DADDIUSP = 0x7
10917 /* RR ry field for CNVT */
10918 enum {
10919 RR_RY_CNVT_ZEB = 0x0,
10920 RR_RY_CNVT_ZEH = 0x1,
10921 RR_RY_CNVT_ZEW = 0x2,
10922 RR_RY_CNVT_SEB = 0x4,
10923 RR_RY_CNVT_SEH = 0x5,
10924 RR_RY_CNVT_SEW = 0x6,
10927 static int xlat (int r)
10929 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10931 return map[r];
10934 static void gen_mips16_save (DisasContext *ctx,
10935 int xsregs, int aregs,
10936 int do_ra, int do_s0, int do_s1,
10937 int framesize)
10939 TCGv t0 = tcg_temp_new();
10940 TCGv t1 = tcg_temp_new();
10941 TCGv t2 = tcg_temp_new();
10942 int args, astatic;
10944 switch (aregs) {
10945 case 0:
10946 case 1:
10947 case 2:
10948 case 3:
10949 case 11:
10950 args = 0;
10951 break;
10952 case 4:
10953 case 5:
10954 case 6:
10955 case 7:
10956 args = 1;
10957 break;
10958 case 8:
10959 case 9:
10960 case 10:
10961 args = 2;
10962 break;
10963 case 12:
10964 case 13:
10965 args = 3;
10966 break;
10967 case 14:
10968 args = 4;
10969 break;
10970 default:
10971 generate_exception_end(ctx, EXCP_RI);
10972 return;
10975 switch (args) {
10976 case 4:
10977 gen_base_offset_addr(ctx, t0, 29, 12);
10978 gen_load_gpr(t1, 7);
10979 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10980 /* Fall through */
10981 case 3:
10982 gen_base_offset_addr(ctx, t0, 29, 8);
10983 gen_load_gpr(t1, 6);
10984 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10985 /* Fall through */
10986 case 2:
10987 gen_base_offset_addr(ctx, t0, 29, 4);
10988 gen_load_gpr(t1, 5);
10989 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10990 /* Fall through */
10991 case 1:
10992 gen_base_offset_addr(ctx, t0, 29, 0);
10993 gen_load_gpr(t1, 4);
10994 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10997 gen_load_gpr(t0, 29);
10999 #define DECR_AND_STORE(reg) do { \
11000 tcg_gen_movi_tl(t2, -4); \
11001 gen_op_addr_add(ctx, t0, t0, t2); \
11002 gen_load_gpr(t1, reg); \
11003 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
11004 } while (0)
11006 if (do_ra) {
11007 DECR_AND_STORE(31);
11010 switch (xsregs) {
11011 case 7:
11012 DECR_AND_STORE(30);
11013 /* Fall through */
11014 case 6:
11015 DECR_AND_STORE(23);
11016 /* Fall through */
11017 case 5:
11018 DECR_AND_STORE(22);
11019 /* Fall through */
11020 case 4:
11021 DECR_AND_STORE(21);
11022 /* Fall through */
11023 case 3:
11024 DECR_AND_STORE(20);
11025 /* Fall through */
11026 case 2:
11027 DECR_AND_STORE(19);
11028 /* Fall through */
11029 case 1:
11030 DECR_AND_STORE(18);
11033 if (do_s1) {
11034 DECR_AND_STORE(17);
11036 if (do_s0) {
11037 DECR_AND_STORE(16);
11040 switch (aregs) {
11041 case 0:
11042 case 4:
11043 case 8:
11044 case 12:
11045 case 14:
11046 astatic = 0;
11047 break;
11048 case 1:
11049 case 5:
11050 case 9:
11051 case 13:
11052 astatic = 1;
11053 break;
11054 case 2:
11055 case 6:
11056 case 10:
11057 astatic = 2;
11058 break;
11059 case 3:
11060 case 7:
11061 astatic = 3;
11062 break;
11063 case 11:
11064 astatic = 4;
11065 break;
11066 default:
11067 generate_exception_end(ctx, EXCP_RI);
11068 return;
11071 if (astatic > 0) {
11072 DECR_AND_STORE(7);
11073 if (astatic > 1) {
11074 DECR_AND_STORE(6);
11075 if (astatic > 2) {
11076 DECR_AND_STORE(5);
11077 if (astatic > 3) {
11078 DECR_AND_STORE(4);
11083 #undef DECR_AND_STORE
11085 tcg_gen_movi_tl(t2, -framesize);
11086 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11087 tcg_temp_free(t0);
11088 tcg_temp_free(t1);
11089 tcg_temp_free(t2);
11092 static void gen_mips16_restore (DisasContext *ctx,
11093 int xsregs, int aregs,
11094 int do_ra, int do_s0, int do_s1,
11095 int framesize)
11097 int astatic;
11098 TCGv t0 = tcg_temp_new();
11099 TCGv t1 = tcg_temp_new();
11100 TCGv t2 = tcg_temp_new();
11102 tcg_gen_movi_tl(t2, framesize);
11103 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11105 #define DECR_AND_LOAD(reg) do { \
11106 tcg_gen_movi_tl(t2, -4); \
11107 gen_op_addr_add(ctx, t0, t0, t2); \
11108 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11109 gen_store_gpr(t1, reg); \
11110 } while (0)
11112 if (do_ra) {
11113 DECR_AND_LOAD(31);
11116 switch (xsregs) {
11117 case 7:
11118 DECR_AND_LOAD(30);
11119 /* Fall through */
11120 case 6:
11121 DECR_AND_LOAD(23);
11122 /* Fall through */
11123 case 5:
11124 DECR_AND_LOAD(22);
11125 /* Fall through */
11126 case 4:
11127 DECR_AND_LOAD(21);
11128 /* Fall through */
11129 case 3:
11130 DECR_AND_LOAD(20);
11131 /* Fall through */
11132 case 2:
11133 DECR_AND_LOAD(19);
11134 /* Fall through */
11135 case 1:
11136 DECR_AND_LOAD(18);
11139 if (do_s1) {
11140 DECR_AND_LOAD(17);
11142 if (do_s0) {
11143 DECR_AND_LOAD(16);
11146 switch (aregs) {
11147 case 0:
11148 case 4:
11149 case 8:
11150 case 12:
11151 case 14:
11152 astatic = 0;
11153 break;
11154 case 1:
11155 case 5:
11156 case 9:
11157 case 13:
11158 astatic = 1;
11159 break;
11160 case 2:
11161 case 6:
11162 case 10:
11163 astatic = 2;
11164 break;
11165 case 3:
11166 case 7:
11167 astatic = 3;
11168 break;
11169 case 11:
11170 astatic = 4;
11171 break;
11172 default:
11173 generate_exception_end(ctx, EXCP_RI);
11174 return;
11177 if (astatic > 0) {
11178 DECR_AND_LOAD(7);
11179 if (astatic > 1) {
11180 DECR_AND_LOAD(6);
11181 if (astatic > 2) {
11182 DECR_AND_LOAD(5);
11183 if (astatic > 3) {
11184 DECR_AND_LOAD(4);
11189 #undef DECR_AND_LOAD
11191 tcg_gen_movi_tl(t2, framesize);
11192 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11193 tcg_temp_free(t0);
11194 tcg_temp_free(t1);
11195 tcg_temp_free(t2);
11198 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11199 int is_64_bit, int extended)
11201 TCGv t0;
11203 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11204 generate_exception_end(ctx, EXCP_RI);
11205 return;
11208 t0 = tcg_temp_new();
11210 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11211 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11212 if (!is_64_bit) {
11213 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11216 tcg_temp_free(t0);
11219 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
11220 int16_t offset)
11222 TCGv_i32 t0 = tcg_const_i32(op);
11223 TCGv t1 = tcg_temp_new();
11224 gen_base_offset_addr(ctx, t1, base, offset);
11225 gen_helper_cache(cpu_env, t1, t0);
11228 #if defined(TARGET_MIPS64)
11229 static void decode_i64_mips16 (DisasContext *ctx,
11230 int ry, int funct, int16_t offset,
11231 int extended)
11233 switch (funct) {
11234 case I64_LDSP:
11235 check_insn(ctx, ISA_MIPS3);
11236 check_mips_64(ctx);
11237 offset = extended ? offset : offset << 3;
11238 gen_ld(ctx, OPC_LD, ry, 29, offset);
11239 break;
11240 case I64_SDSP:
11241 check_insn(ctx, ISA_MIPS3);
11242 check_mips_64(ctx);
11243 offset = extended ? offset : offset << 3;
11244 gen_st(ctx, OPC_SD, ry, 29, offset);
11245 break;
11246 case I64_SDRASP:
11247 check_insn(ctx, ISA_MIPS3);
11248 check_mips_64(ctx);
11249 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11250 gen_st(ctx, OPC_SD, 31, 29, offset);
11251 break;
11252 case I64_DADJSP:
11253 check_insn(ctx, ISA_MIPS3);
11254 check_mips_64(ctx);
11255 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11256 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11257 break;
11258 case I64_LDPC:
11259 check_insn(ctx, ISA_MIPS3);
11260 check_mips_64(ctx);
11261 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11262 generate_exception_end(ctx, EXCP_RI);
11263 } else {
11264 offset = extended ? offset : offset << 3;
11265 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11267 break;
11268 case I64_DADDIU5:
11269 check_insn(ctx, ISA_MIPS3);
11270 check_mips_64(ctx);
11271 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11272 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11273 break;
11274 case I64_DADDIUPC:
11275 check_insn(ctx, ISA_MIPS3);
11276 check_mips_64(ctx);
11277 offset = extended ? offset : offset << 2;
11278 gen_addiupc(ctx, ry, offset, 1, extended);
11279 break;
11280 case I64_DADDIUSP:
11281 check_insn(ctx, ISA_MIPS3);
11282 check_mips_64(ctx);
11283 offset = extended ? offset : offset << 2;
11284 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11285 break;
11288 #endif
11290 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11292 int extend = cpu_lduw_code(env, ctx->pc + 2);
11293 int op, rx, ry, funct, sa;
11294 int16_t imm, offset;
11296 ctx->opcode = (ctx->opcode << 16) | extend;
11297 op = (ctx->opcode >> 11) & 0x1f;
11298 sa = (ctx->opcode >> 22) & 0x1f;
11299 funct = (ctx->opcode >> 8) & 0x7;
11300 rx = xlat((ctx->opcode >> 8) & 0x7);
11301 ry = xlat((ctx->opcode >> 5) & 0x7);
11302 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11303 | ((ctx->opcode >> 21) & 0x3f) << 5
11304 | (ctx->opcode & 0x1f));
11306 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11307 counterparts. */
11308 switch (op) {
11309 case M16_OPC_ADDIUSP:
11310 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11311 break;
11312 case M16_OPC_ADDIUPC:
11313 gen_addiupc(ctx, rx, imm, 0, 1);
11314 break;
11315 case M16_OPC_B:
11316 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11317 /* No delay slot, so just process as a normal instruction */
11318 break;
11319 case M16_OPC_BEQZ:
11320 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11321 /* No delay slot, so just process as a normal instruction */
11322 break;
11323 case M16_OPC_BNEQZ:
11324 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11325 /* No delay slot, so just process as a normal instruction */
11326 break;
11327 case M16_OPC_SHIFT:
11328 switch (ctx->opcode & 0x3) {
11329 case 0x0:
11330 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11331 break;
11332 case 0x1:
11333 #if defined(TARGET_MIPS64)
11334 check_mips_64(ctx);
11335 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11336 #else
11337 generate_exception_end(ctx, EXCP_RI);
11338 #endif
11339 break;
11340 case 0x2:
11341 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11342 break;
11343 case 0x3:
11344 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11345 break;
11347 break;
11348 #if defined(TARGET_MIPS64)
11349 case M16_OPC_LD:
11350 check_insn(ctx, ISA_MIPS3);
11351 check_mips_64(ctx);
11352 gen_ld(ctx, OPC_LD, ry, rx, offset);
11353 break;
11354 #endif
11355 case M16_OPC_RRIA:
11356 imm = ctx->opcode & 0xf;
11357 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11358 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11359 imm = (int16_t) (imm << 1) >> 1;
11360 if ((ctx->opcode >> 4) & 0x1) {
11361 #if defined(TARGET_MIPS64)
11362 check_mips_64(ctx);
11363 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11364 #else
11365 generate_exception_end(ctx, EXCP_RI);
11366 #endif
11367 } else {
11368 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11370 break;
11371 case M16_OPC_ADDIU8:
11372 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11373 break;
11374 case M16_OPC_SLTI:
11375 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11376 break;
11377 case M16_OPC_SLTIU:
11378 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11379 break;
11380 case M16_OPC_I8:
11381 switch (funct) {
11382 case I8_BTEQZ:
11383 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11384 break;
11385 case I8_BTNEZ:
11386 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11387 break;
11388 case I8_SWRASP:
11389 gen_st(ctx, OPC_SW, 31, 29, imm);
11390 break;
11391 case I8_ADJSP:
11392 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11393 break;
11394 case I8_SVRS:
11395 check_insn(ctx, ISA_MIPS32);
11397 int xsregs = (ctx->opcode >> 24) & 0x7;
11398 int aregs = (ctx->opcode >> 16) & 0xf;
11399 int do_ra = (ctx->opcode >> 6) & 0x1;
11400 int do_s0 = (ctx->opcode >> 5) & 0x1;
11401 int do_s1 = (ctx->opcode >> 4) & 0x1;
11402 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11403 | (ctx->opcode & 0xf)) << 3;
11405 if (ctx->opcode & (1 << 7)) {
11406 gen_mips16_save(ctx, xsregs, aregs,
11407 do_ra, do_s0, do_s1,
11408 framesize);
11409 } else {
11410 gen_mips16_restore(ctx, xsregs, aregs,
11411 do_ra, do_s0, do_s1,
11412 framesize);
11415 break;
11416 default:
11417 generate_exception_end(ctx, EXCP_RI);
11418 break;
11420 break;
11421 case M16_OPC_LI:
11422 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11423 break;
11424 case M16_OPC_CMPI:
11425 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11426 break;
11427 #if defined(TARGET_MIPS64)
11428 case M16_OPC_SD:
11429 check_insn(ctx, ISA_MIPS3);
11430 check_mips_64(ctx);
11431 gen_st(ctx, OPC_SD, ry, rx, offset);
11432 break;
11433 #endif
11434 case M16_OPC_LB:
11435 gen_ld(ctx, OPC_LB, ry, rx, offset);
11436 break;
11437 case M16_OPC_LH:
11438 gen_ld(ctx, OPC_LH, ry, rx, offset);
11439 break;
11440 case M16_OPC_LWSP:
11441 gen_ld(ctx, OPC_LW, rx, 29, offset);
11442 break;
11443 case M16_OPC_LW:
11444 gen_ld(ctx, OPC_LW, ry, rx, offset);
11445 break;
11446 case M16_OPC_LBU:
11447 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11448 break;
11449 case M16_OPC_LHU:
11450 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11451 break;
11452 case M16_OPC_LWPC:
11453 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11454 break;
11455 #if defined(TARGET_MIPS64)
11456 case M16_OPC_LWU:
11457 check_insn(ctx, ISA_MIPS3);
11458 check_mips_64(ctx);
11459 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11460 break;
11461 #endif
11462 case M16_OPC_SB:
11463 gen_st(ctx, OPC_SB, ry, rx, offset);
11464 break;
11465 case M16_OPC_SH:
11466 gen_st(ctx, OPC_SH, ry, rx, offset);
11467 break;
11468 case M16_OPC_SWSP:
11469 gen_st(ctx, OPC_SW, rx, 29, offset);
11470 break;
11471 case M16_OPC_SW:
11472 gen_st(ctx, OPC_SW, ry, rx, offset);
11473 break;
11474 #if defined(TARGET_MIPS64)
11475 case M16_OPC_I64:
11476 decode_i64_mips16(ctx, ry, funct, offset, 1);
11477 break;
11478 #endif
11479 default:
11480 generate_exception_end(ctx, EXCP_RI);
11481 break;
11484 return 4;
11487 static inline bool is_uhi(int sdbbp_code)
11489 #ifdef CONFIG_USER_ONLY
11490 return false;
11491 #else
11492 return semihosting_enabled() && sdbbp_code == 1;
11493 #endif
11496 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11498 int rx, ry;
11499 int sa;
11500 int op, cnvt_op, op1, offset;
11501 int funct;
11502 int n_bytes;
11504 op = (ctx->opcode >> 11) & 0x1f;
11505 sa = (ctx->opcode >> 2) & 0x7;
11506 sa = sa == 0 ? 8 : sa;
11507 rx = xlat((ctx->opcode >> 8) & 0x7);
11508 cnvt_op = (ctx->opcode >> 5) & 0x7;
11509 ry = xlat((ctx->opcode >> 5) & 0x7);
11510 op1 = offset = ctx->opcode & 0x1f;
11512 n_bytes = 2;
11514 switch (op) {
11515 case M16_OPC_ADDIUSP:
11517 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11519 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11521 break;
11522 case M16_OPC_ADDIUPC:
11523 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11524 break;
11525 case M16_OPC_B:
11526 offset = (ctx->opcode & 0x7ff) << 1;
11527 offset = (int16_t)(offset << 4) >> 4;
11528 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11529 /* No delay slot, so just process as a normal instruction */
11530 break;
11531 case M16_OPC_JAL:
11532 offset = cpu_lduw_code(env, ctx->pc + 2);
11533 offset = (((ctx->opcode & 0x1f) << 21)
11534 | ((ctx->opcode >> 5) & 0x1f) << 16
11535 | offset) << 2;
11536 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11537 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11538 n_bytes = 4;
11539 break;
11540 case M16_OPC_BEQZ:
11541 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11542 ((int8_t)ctx->opcode) << 1, 0);
11543 /* No delay slot, so just process as a normal instruction */
11544 break;
11545 case M16_OPC_BNEQZ:
11546 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11547 ((int8_t)ctx->opcode) << 1, 0);
11548 /* No delay slot, so just process as a normal instruction */
11549 break;
11550 case M16_OPC_SHIFT:
11551 switch (ctx->opcode & 0x3) {
11552 case 0x0:
11553 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11554 break;
11555 case 0x1:
11556 #if defined(TARGET_MIPS64)
11557 check_insn(ctx, ISA_MIPS3);
11558 check_mips_64(ctx);
11559 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11560 #else
11561 generate_exception_end(ctx, EXCP_RI);
11562 #endif
11563 break;
11564 case 0x2:
11565 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11566 break;
11567 case 0x3:
11568 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11569 break;
11571 break;
11572 #if defined(TARGET_MIPS64)
11573 case M16_OPC_LD:
11574 check_insn(ctx, ISA_MIPS3);
11575 check_mips_64(ctx);
11576 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
11577 break;
11578 #endif
11579 case M16_OPC_RRIA:
11581 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
11583 if ((ctx->opcode >> 4) & 1) {
11584 #if defined(TARGET_MIPS64)
11585 check_insn(ctx, ISA_MIPS3);
11586 check_mips_64(ctx);
11587 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11588 #else
11589 generate_exception_end(ctx, EXCP_RI);
11590 #endif
11591 } else {
11592 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11595 break;
11596 case M16_OPC_ADDIU8:
11598 int16_t imm = (int8_t) ctx->opcode;
11600 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11602 break;
11603 case M16_OPC_SLTI:
11605 int16_t imm = (uint8_t) ctx->opcode;
11606 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11608 break;
11609 case M16_OPC_SLTIU:
11611 int16_t imm = (uint8_t) ctx->opcode;
11612 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11614 break;
11615 case M16_OPC_I8:
11617 int reg32;
11619 funct = (ctx->opcode >> 8) & 0x7;
11620 switch (funct) {
11621 case I8_BTEQZ:
11622 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
11623 ((int8_t)ctx->opcode) << 1, 0);
11624 break;
11625 case I8_BTNEZ:
11626 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
11627 ((int8_t)ctx->opcode) << 1, 0);
11628 break;
11629 case I8_SWRASP:
11630 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
11631 break;
11632 case I8_ADJSP:
11633 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
11634 ((int8_t)ctx->opcode) << 3);
11635 break;
11636 case I8_SVRS:
11637 check_insn(ctx, ISA_MIPS32);
11639 int do_ra = ctx->opcode & (1 << 6);
11640 int do_s0 = ctx->opcode & (1 << 5);
11641 int do_s1 = ctx->opcode & (1 << 4);
11642 int framesize = ctx->opcode & 0xf;
11644 if (framesize == 0) {
11645 framesize = 128;
11646 } else {
11647 framesize = framesize << 3;
11650 if (ctx->opcode & (1 << 7)) {
11651 gen_mips16_save(ctx, 0, 0,
11652 do_ra, do_s0, do_s1, framesize);
11653 } else {
11654 gen_mips16_restore(ctx, 0, 0,
11655 do_ra, do_s0, do_s1, framesize);
11658 break;
11659 case I8_MOV32R:
11661 int rz = xlat(ctx->opcode & 0x7);
11663 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
11664 ((ctx->opcode >> 5) & 0x7);
11665 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
11667 break;
11668 case I8_MOVR32:
11669 reg32 = ctx->opcode & 0x1f;
11670 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
11671 break;
11672 default:
11673 generate_exception_end(ctx, EXCP_RI);
11674 break;
11677 break;
11678 case M16_OPC_LI:
11680 int16_t imm = (uint8_t) ctx->opcode;
11682 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
11684 break;
11685 case M16_OPC_CMPI:
11687 int16_t imm = (uint8_t) ctx->opcode;
11688 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
11690 break;
11691 #if defined(TARGET_MIPS64)
11692 case M16_OPC_SD:
11693 check_insn(ctx, ISA_MIPS3);
11694 check_mips_64(ctx);
11695 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
11696 break;
11697 #endif
11698 case M16_OPC_LB:
11699 gen_ld(ctx, OPC_LB, ry, rx, offset);
11700 break;
11701 case M16_OPC_LH:
11702 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
11703 break;
11704 case M16_OPC_LWSP:
11705 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11706 break;
11707 case M16_OPC_LW:
11708 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
11709 break;
11710 case M16_OPC_LBU:
11711 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11712 break;
11713 case M16_OPC_LHU:
11714 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
11715 break;
11716 case M16_OPC_LWPC:
11717 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
11718 break;
11719 #if defined (TARGET_MIPS64)
11720 case M16_OPC_LWU:
11721 check_insn(ctx, ISA_MIPS3);
11722 check_mips_64(ctx);
11723 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
11724 break;
11725 #endif
11726 case M16_OPC_SB:
11727 gen_st(ctx, OPC_SB, ry, rx, offset);
11728 break;
11729 case M16_OPC_SH:
11730 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
11731 break;
11732 case M16_OPC_SWSP:
11733 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11734 break;
11735 case M16_OPC_SW:
11736 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
11737 break;
11738 case M16_OPC_RRR:
11740 int rz = xlat((ctx->opcode >> 2) & 0x7);
11741 int mips32_op;
11743 switch (ctx->opcode & 0x3) {
11744 case RRR_ADDU:
11745 mips32_op = OPC_ADDU;
11746 break;
11747 case RRR_SUBU:
11748 mips32_op = OPC_SUBU;
11749 break;
11750 #if defined(TARGET_MIPS64)
11751 case RRR_DADDU:
11752 mips32_op = OPC_DADDU;
11753 check_insn(ctx, ISA_MIPS3);
11754 check_mips_64(ctx);
11755 break;
11756 case RRR_DSUBU:
11757 mips32_op = OPC_DSUBU;
11758 check_insn(ctx, ISA_MIPS3);
11759 check_mips_64(ctx);
11760 break;
11761 #endif
11762 default:
11763 generate_exception_end(ctx, EXCP_RI);
11764 goto done;
11767 gen_arith(ctx, mips32_op, rz, rx, ry);
11768 done:
11771 break;
11772 case M16_OPC_RR:
11773 switch (op1) {
11774 case RR_JR:
11776 int nd = (ctx->opcode >> 7) & 0x1;
11777 int link = (ctx->opcode >> 6) & 0x1;
11778 int ra = (ctx->opcode >> 5) & 0x1;
11780 if (nd) {
11781 check_insn(ctx, ISA_MIPS32);
11784 if (link) {
11785 op = OPC_JALR;
11786 } else {
11787 op = OPC_JR;
11790 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
11791 (nd ? 0 : 2));
11793 break;
11794 case RR_SDBBP:
11795 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
11796 gen_helper_do_semihosting(cpu_env);
11797 } else {
11798 /* XXX: not clear which exception should be raised
11799 * when in debug mode...
11801 check_insn(ctx, ISA_MIPS32);
11802 generate_exception_end(ctx, EXCP_DBp);
11804 break;
11805 case RR_SLT:
11806 gen_slt(ctx, OPC_SLT, 24, rx, ry);
11807 break;
11808 case RR_SLTU:
11809 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
11810 break;
11811 case RR_BREAK:
11812 generate_exception_end(ctx, EXCP_BREAK);
11813 break;
11814 case RR_SLLV:
11815 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
11816 break;
11817 case RR_SRLV:
11818 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
11819 break;
11820 case RR_SRAV:
11821 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
11822 break;
11823 #if defined (TARGET_MIPS64)
11824 case RR_DSRL:
11825 check_insn(ctx, ISA_MIPS3);
11826 check_mips_64(ctx);
11827 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
11828 break;
11829 #endif
11830 case RR_CMP:
11831 gen_logic(ctx, OPC_XOR, 24, rx, ry);
11832 break;
11833 case RR_NEG:
11834 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
11835 break;
11836 case RR_AND:
11837 gen_logic(ctx, OPC_AND, rx, rx, ry);
11838 break;
11839 case RR_OR:
11840 gen_logic(ctx, OPC_OR, rx, rx, ry);
11841 break;
11842 case RR_XOR:
11843 gen_logic(ctx, OPC_XOR, rx, rx, ry);
11844 break;
11845 case RR_NOT:
11846 gen_logic(ctx, OPC_NOR, rx, ry, 0);
11847 break;
11848 case RR_MFHI:
11849 gen_HILO(ctx, OPC_MFHI, 0, rx);
11850 break;
11851 case RR_CNVT:
11852 check_insn(ctx, ISA_MIPS32);
11853 switch (cnvt_op) {
11854 case RR_RY_CNVT_ZEB:
11855 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11856 break;
11857 case RR_RY_CNVT_ZEH:
11858 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11859 break;
11860 case RR_RY_CNVT_SEB:
11861 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11862 break;
11863 case RR_RY_CNVT_SEH:
11864 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11865 break;
11866 #if defined (TARGET_MIPS64)
11867 case RR_RY_CNVT_ZEW:
11868 check_insn(ctx, ISA_MIPS64);
11869 check_mips_64(ctx);
11870 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11871 break;
11872 case RR_RY_CNVT_SEW:
11873 check_insn(ctx, ISA_MIPS64);
11874 check_mips_64(ctx);
11875 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11876 break;
11877 #endif
11878 default:
11879 generate_exception_end(ctx, EXCP_RI);
11880 break;
11882 break;
11883 case RR_MFLO:
11884 gen_HILO(ctx, OPC_MFLO, 0, rx);
11885 break;
11886 #if defined (TARGET_MIPS64)
11887 case RR_DSRA:
11888 check_insn(ctx, ISA_MIPS3);
11889 check_mips_64(ctx);
11890 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
11891 break;
11892 case RR_DSLLV:
11893 check_insn(ctx, ISA_MIPS3);
11894 check_mips_64(ctx);
11895 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
11896 break;
11897 case RR_DSRLV:
11898 check_insn(ctx, ISA_MIPS3);
11899 check_mips_64(ctx);
11900 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
11901 break;
11902 case RR_DSRAV:
11903 check_insn(ctx, ISA_MIPS3);
11904 check_mips_64(ctx);
11905 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
11906 break;
11907 #endif
11908 case RR_MULT:
11909 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
11910 break;
11911 case RR_MULTU:
11912 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
11913 break;
11914 case RR_DIV:
11915 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
11916 break;
11917 case RR_DIVU:
11918 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
11919 break;
11920 #if defined (TARGET_MIPS64)
11921 case RR_DMULT:
11922 check_insn(ctx, ISA_MIPS3);
11923 check_mips_64(ctx);
11924 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
11925 break;
11926 case RR_DMULTU:
11927 check_insn(ctx, ISA_MIPS3);
11928 check_mips_64(ctx);
11929 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
11930 break;
11931 case RR_DDIV:
11932 check_insn(ctx, ISA_MIPS3);
11933 check_mips_64(ctx);
11934 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
11935 break;
11936 case RR_DDIVU:
11937 check_insn(ctx, ISA_MIPS3);
11938 check_mips_64(ctx);
11939 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
11940 break;
11941 #endif
11942 default:
11943 generate_exception_end(ctx, EXCP_RI);
11944 break;
11946 break;
11947 case M16_OPC_EXTEND:
11948 decode_extended_mips16_opc(env, ctx);
11949 n_bytes = 4;
11950 break;
11951 #if defined(TARGET_MIPS64)
11952 case M16_OPC_I64:
11953 funct = (ctx->opcode >> 8) & 0x7;
11954 decode_i64_mips16(ctx, ry, funct, offset, 0);
11955 break;
11956 #endif
11957 default:
11958 generate_exception_end(ctx, EXCP_RI);
11959 break;
11962 return n_bytes;
11965 /* microMIPS extension to MIPS32/MIPS64 */
11968 * microMIPS32/microMIPS64 major opcodes
11970 * 1. MIPS Architecture for Programmers Volume II-B:
11971 * The microMIPS32 Instruction Set (Revision 3.05)
11973 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
11975 * 2. MIPS Architecture For Programmers Volume II-A:
11976 * The MIPS64 Instruction Set (Revision 3.51)
11979 enum {
11980 POOL32A = 0x00,
11981 POOL16A = 0x01,
11982 LBU16 = 0x02,
11983 MOVE16 = 0x03,
11984 ADDI32 = 0x04,
11985 R6_LUI = 0x04,
11986 AUI = 0x04,
11987 LBU32 = 0x05,
11988 SB32 = 0x06,
11989 LB32 = 0x07,
11991 POOL32B = 0x08,
11992 POOL16B = 0x09,
11993 LHU16 = 0x0a,
11994 ANDI16 = 0x0b,
11995 ADDIU32 = 0x0c,
11996 LHU32 = 0x0d,
11997 SH32 = 0x0e,
11998 LH32 = 0x0f,
12000 POOL32I = 0x10,
12001 POOL16C = 0x11,
12002 LWSP16 = 0x12,
12003 POOL16D = 0x13,
12004 ORI32 = 0x14,
12005 POOL32F = 0x15,
12006 POOL32S = 0x16, /* MIPS64 */
12007 DADDIU32 = 0x17, /* MIPS64 */
12009 POOL32C = 0x18,
12010 LWGP16 = 0x19,
12011 LW16 = 0x1a,
12012 POOL16E = 0x1b,
12013 XORI32 = 0x1c,
12014 JALS32 = 0x1d,
12015 BOVC = 0x1d,
12016 BEQC = 0x1d,
12017 BEQZALC = 0x1d,
12018 ADDIUPC = 0x1e,
12019 PCREL = 0x1e,
12020 BNVC = 0x1f,
12021 BNEC = 0x1f,
12022 BNEZALC = 0x1f,
12024 R6_BEQZC = 0x20,
12025 JIC = 0x20,
12026 POOL16F = 0x21,
12027 SB16 = 0x22,
12028 BEQZ16 = 0x23,
12029 BEQZC16 = 0x23,
12030 SLTI32 = 0x24,
12031 BEQ32 = 0x25,
12032 BC = 0x25,
12033 SWC132 = 0x26,
12034 LWC132 = 0x27,
12036 /* 0x29 is reserved */
12037 RES_29 = 0x29,
12038 R6_BNEZC = 0x28,
12039 JIALC = 0x28,
12040 SH16 = 0x2a,
12041 BNEZ16 = 0x2b,
12042 BNEZC16 = 0x2b,
12043 SLTIU32 = 0x2c,
12044 BNE32 = 0x2d,
12045 BALC = 0x2d,
12046 SDC132 = 0x2e,
12047 LDC132 = 0x2f,
12049 /* 0x31 is reserved */
12050 RES_31 = 0x31,
12051 BLEZALC = 0x30,
12052 BGEZALC = 0x30,
12053 BGEUC = 0x30,
12054 SWSP16 = 0x32,
12055 B16 = 0x33,
12056 BC16 = 0x33,
12057 ANDI32 = 0x34,
12058 J32 = 0x35,
12059 BGTZC = 0x35,
12060 BLTZC = 0x35,
12061 BLTC = 0x35,
12062 SD32 = 0x36, /* MIPS64 */
12063 LD32 = 0x37, /* MIPS64 */
12065 /* 0x39 is reserved */
12066 RES_39 = 0x39,
12067 BGTZALC = 0x38,
12068 BLTZALC = 0x38,
12069 BLTUC = 0x38,
12070 SW16 = 0x3a,
12071 LI16 = 0x3b,
12072 JALX32 = 0x3c,
12073 JAL32 = 0x3d,
12074 BLEZC = 0x3d,
12075 BGEZC = 0x3d,
12076 BGEC = 0x3d,
12077 SW32 = 0x3e,
12078 LW32 = 0x3f
12081 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12082 enum {
12083 ADDIUPC_00 = 0x00,
12084 ADDIUPC_07 = 0x07,
12085 AUIPC = 0x1e,
12086 ALUIPC = 0x1f,
12087 LWPC_08 = 0x08,
12088 LWPC_0F = 0x0F,
12091 /* POOL32A encoding of minor opcode field */
12093 enum {
12094 /* These opcodes are distinguished only by bits 9..6; those bits are
12095 * what are recorded below. */
12096 SLL32 = 0x0,
12097 SRL32 = 0x1,
12098 SRA = 0x2,
12099 ROTR = 0x3,
12100 SELEQZ = 0x5,
12101 SELNEZ = 0x6,
12102 R6_RDHWR = 0x7,
12104 SLLV = 0x0,
12105 SRLV = 0x1,
12106 SRAV = 0x2,
12107 ROTRV = 0x3,
12108 ADD = 0x4,
12109 ADDU32 = 0x5,
12110 SUB = 0x6,
12111 SUBU32 = 0x7,
12112 MUL = 0x8,
12113 AND = 0x9,
12114 OR32 = 0xa,
12115 NOR = 0xb,
12116 XOR32 = 0xc,
12117 SLT = 0xd,
12118 SLTU = 0xe,
12120 MOVN = 0x0,
12121 R6_MUL = 0x0,
12122 MOVZ = 0x1,
12123 MUH = 0x1,
12124 MULU = 0x2,
12125 MUHU = 0x3,
12126 LWXS = 0x4,
12127 R6_DIV = 0x4,
12128 MOD = 0x5,
12129 R6_DIVU = 0x6,
12130 MODU = 0x7,
12132 /* The following can be distinguished by their lower 6 bits. */
12133 BREAK32 = 0x07,
12134 INS = 0x0c,
12135 LSA = 0x0f,
12136 ALIGN = 0x1f,
12137 EXT = 0x2c,
12138 POOL32AXF = 0x3c,
12139 SIGRIE = 0x3f
12142 /* POOL32AXF encoding of minor opcode field extension */
12145 * 1. MIPS Architecture for Programmers Volume II-B:
12146 * The microMIPS32 Instruction Set (Revision 3.05)
12148 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12150 * 2. MIPS Architecture for Programmers VolumeIV-e:
12151 * The MIPS DSP Application-Specific Extension
12152 * to the microMIPS32 Architecture (Revision 2.34)
12154 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12157 enum {
12158 /* bits 11..6 */
12159 TEQ = 0x00,
12160 TGE = 0x08,
12161 TGEU = 0x10,
12162 TLT = 0x20,
12163 TLTU = 0x28,
12164 TNE = 0x30,
12166 MFC0 = 0x03,
12167 MTC0 = 0x0b,
12169 /* begin of microMIPS32 DSP */
12171 /* bits 13..12 for 0x01 */
12172 MFHI_ACC = 0x0,
12173 MFLO_ACC = 0x1,
12174 MTHI_ACC = 0x2,
12175 MTLO_ACC = 0x3,
12177 /* bits 13..12 for 0x2a */
12178 MADD_ACC = 0x0,
12179 MADDU_ACC = 0x1,
12180 MSUB_ACC = 0x2,
12181 MSUBU_ACC = 0x3,
12183 /* bits 13..12 for 0x32 */
12184 MULT_ACC = 0x0,
12185 MULTU_ACC = 0x1,
12187 /* end of microMIPS32 DSP */
12189 /* bits 15..12 for 0x2c */
12190 BITSWAP = 0x0,
12191 SEB = 0x2,
12192 SEH = 0x3,
12193 CLO = 0x4,
12194 CLZ = 0x5,
12195 RDHWR = 0x6,
12196 WSBH = 0x7,
12197 MULT = 0x8,
12198 MULTU = 0x9,
12199 DIV = 0xa,
12200 DIVU = 0xb,
12201 MADD = 0xc,
12202 MADDU = 0xd,
12203 MSUB = 0xe,
12204 MSUBU = 0xf,
12206 /* bits 15..12 for 0x34 */
12207 MFC2 = 0x4,
12208 MTC2 = 0x5,
12209 MFHC2 = 0x8,
12210 MTHC2 = 0x9,
12211 CFC2 = 0xc,
12212 CTC2 = 0xd,
12214 /* bits 15..12 for 0x3c */
12215 JALR = 0x0,
12216 JR = 0x0, /* alias */
12217 JALRC = 0x0,
12218 JRC = 0x0,
12219 JALR_HB = 0x1,
12220 JALRC_HB = 0x1,
12221 JALRS = 0x4,
12222 JALRS_HB = 0x5,
12224 /* bits 15..12 for 0x05 */
12225 RDPGPR = 0xe,
12226 WRPGPR = 0xf,
12228 /* bits 15..12 for 0x0d */
12229 TLBP = 0x0,
12230 TLBR = 0x1,
12231 TLBWI = 0x2,
12232 TLBWR = 0x3,
12233 TLBINV = 0x4,
12234 TLBINVF = 0x5,
12235 WAIT = 0x9,
12236 IRET = 0xd,
12237 DERET = 0xe,
12238 ERET = 0xf,
12240 /* bits 15..12 for 0x15 */
12241 DMT = 0x0,
12242 DVPE = 0x1,
12243 EMT = 0x2,
12244 EVPE = 0x3,
12246 /* bits 15..12 for 0x1d */
12247 DI = 0x4,
12248 EI = 0x5,
12250 /* bits 15..12 for 0x2d */
12251 SYNC = 0x6,
12252 SYSCALL = 0x8,
12253 SDBBP = 0xd,
12255 /* bits 15..12 for 0x35 */
12256 MFHI32 = 0x0,
12257 MFLO32 = 0x1,
12258 MTHI32 = 0x2,
12259 MTLO32 = 0x3,
12262 /* POOL32B encoding of minor opcode field (bits 15..12) */
12264 enum {
12265 LWC2 = 0x0,
12266 LWP = 0x1,
12267 LDP = 0x4,
12268 LWM32 = 0x5,
12269 CACHE = 0x6,
12270 LDM = 0x7,
12271 SWC2 = 0x8,
12272 SWP = 0x9,
12273 SDP = 0xc,
12274 SWM32 = 0xd,
12275 SDM = 0xf
12278 /* POOL32C encoding of minor opcode field (bits 15..12) */
12280 enum {
12281 LWL = 0x0,
12282 SWL = 0x8,
12283 LWR = 0x1,
12284 SWR = 0x9,
12285 PREF = 0x2,
12286 /* 0xa is reserved */
12287 LL = 0x3,
12288 SC = 0xb,
12289 LDL = 0x4,
12290 SDL = 0xc,
12291 LDR = 0x5,
12292 SDR = 0xd,
12293 /* 0x6 is reserved */
12294 LWU = 0xe,
12295 LLD = 0x7,
12296 SCD = 0xf
12299 /* POOL32F encoding of minor opcode field (bits 5..0) */
12301 enum {
12302 /* These are the bit 7..6 values */
12303 ADD_FMT = 0x0,
12305 SUB_FMT = 0x1,
12307 MUL_FMT = 0x2,
12309 DIV_FMT = 0x3,
12311 /* These are the bit 8..6 values */
12312 MOVN_FMT = 0x0,
12313 RSQRT2_FMT = 0x0,
12314 MOVF_FMT = 0x0,
12315 RINT_FMT = 0x0,
12316 SELNEZ_FMT = 0x0,
12318 MOVZ_FMT = 0x1,
12319 LWXC1 = 0x1,
12320 MOVT_FMT = 0x1,
12321 CLASS_FMT = 0x1,
12322 SELEQZ_FMT = 0x1,
12324 PLL_PS = 0x2,
12325 SWXC1 = 0x2,
12326 SEL_FMT = 0x2,
12328 PLU_PS = 0x3,
12329 LDXC1 = 0x3,
12331 MOVN_FMT_04 = 0x4,
12332 PUL_PS = 0x4,
12333 SDXC1 = 0x4,
12334 RECIP2_FMT = 0x4,
12336 MOVZ_FMT_05 = 0x05,
12337 PUU_PS = 0x5,
12338 LUXC1 = 0x5,
12340 CVT_PS_S = 0x6,
12341 SUXC1 = 0x6,
12342 ADDR_PS = 0x6,
12343 PREFX = 0x6,
12344 MADDF_FMT = 0x6,
12346 MULR_PS = 0x7,
12347 MSUBF_FMT = 0x7,
12349 MADD_S = 0x01,
12350 MADD_D = 0x09,
12351 MADD_PS = 0x11,
12352 ALNV_PS = 0x19,
12353 MSUB_S = 0x21,
12354 MSUB_D = 0x29,
12355 MSUB_PS = 0x31,
12357 NMADD_S = 0x02,
12358 NMADD_D = 0x0a,
12359 NMADD_PS = 0x12,
12360 NMSUB_S = 0x22,
12361 NMSUB_D = 0x2a,
12362 NMSUB_PS = 0x32,
12364 MIN_FMT = 0x3,
12365 MAX_FMT = 0xb,
12366 MINA_FMT = 0x23,
12367 MAXA_FMT = 0x2b,
12368 POOL32FXF = 0x3b,
12370 CABS_COND_FMT = 0x1c, /* MIPS3D */
12371 C_COND_FMT = 0x3c,
12373 CMP_CONDN_S = 0x5,
12374 CMP_CONDN_D = 0x15
12377 /* POOL32Fxf encoding of minor opcode extension field */
12379 enum {
12380 CVT_L = 0x04,
12381 RSQRT_FMT = 0x08,
12382 FLOOR_L = 0x0c,
12383 CVT_PW_PS = 0x1c,
12384 CVT_W = 0x24,
12385 SQRT_FMT = 0x28,
12386 FLOOR_W = 0x2c,
12387 CVT_PS_PW = 0x3c,
12388 CFC1 = 0x40,
12389 RECIP_FMT = 0x48,
12390 CEIL_L = 0x4c,
12391 CTC1 = 0x60,
12392 CEIL_W = 0x6c,
12393 MFC1 = 0x80,
12394 CVT_S_PL = 0x84,
12395 TRUNC_L = 0x8c,
12396 MTC1 = 0xa0,
12397 CVT_S_PU = 0xa4,
12398 TRUNC_W = 0xac,
12399 MFHC1 = 0xc0,
12400 ROUND_L = 0xcc,
12401 MTHC1 = 0xe0,
12402 ROUND_W = 0xec,
12404 MOV_FMT = 0x01,
12405 MOVF = 0x05,
12406 ABS_FMT = 0x0d,
12407 RSQRT1_FMT = 0x1d,
12408 MOVT = 0x25,
12409 NEG_FMT = 0x2d,
12410 CVT_D = 0x4d,
12411 RECIP1_FMT = 0x5d,
12412 CVT_S = 0x6d
12415 /* POOL32I encoding of minor opcode field (bits 25..21) */
12417 enum {
12418 BLTZ = 0x00,
12419 BLTZAL = 0x01,
12420 BGEZ = 0x02,
12421 BGEZAL = 0x03,
12422 BLEZ = 0x04,
12423 BNEZC = 0x05,
12424 BGTZ = 0x06,
12425 BEQZC = 0x07,
12426 TLTI = 0x08,
12427 BC1EQZC = 0x08,
12428 TGEI = 0x09,
12429 BC1NEZC = 0x09,
12430 TLTIU = 0x0a,
12431 BC2EQZC = 0x0a,
12432 TGEIU = 0x0b,
12433 BC2NEZC = 0x0a,
12434 TNEI = 0x0c,
12435 R6_SYNCI = 0x0c,
12436 LUI = 0x0d,
12437 TEQI = 0x0e,
12438 SYNCI = 0x10,
12439 BLTZALS = 0x11,
12440 BGEZALS = 0x13,
12441 BC2F = 0x14,
12442 BC2T = 0x15,
12443 BPOSGE64 = 0x1a,
12444 BPOSGE32 = 0x1b,
12445 /* These overlap and are distinguished by bit16 of the instruction */
12446 BC1F = 0x1c,
12447 BC1T = 0x1d,
12448 BC1ANY2F = 0x1c,
12449 BC1ANY2T = 0x1d,
12450 BC1ANY4F = 0x1e,
12451 BC1ANY4T = 0x1f
12454 /* POOL16A encoding of minor opcode field */
12456 enum {
12457 ADDU16 = 0x0,
12458 SUBU16 = 0x1
12461 /* POOL16B encoding of minor opcode field */
12463 enum {
12464 SLL16 = 0x0,
12465 SRL16 = 0x1
12468 /* POOL16C encoding of minor opcode field */
12470 enum {
12471 NOT16 = 0x00,
12472 XOR16 = 0x04,
12473 AND16 = 0x08,
12474 OR16 = 0x0c,
12475 LWM16 = 0x10,
12476 SWM16 = 0x14,
12477 JR16 = 0x18,
12478 JRC16 = 0x1a,
12479 JALR16 = 0x1c,
12480 JALR16S = 0x1e,
12481 MFHI16 = 0x20,
12482 MFLO16 = 0x24,
12483 BREAK16 = 0x28,
12484 SDBBP16 = 0x2c,
12485 JRADDIUSP = 0x30
12488 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
12490 enum {
12491 R6_NOT16 = 0x00,
12492 R6_AND16 = 0x01,
12493 R6_LWM16 = 0x02,
12494 R6_JRC16 = 0x03,
12495 MOVEP = 0x04,
12496 MOVEP_07 = 0x07,
12497 R6_XOR16 = 0x08,
12498 R6_OR16 = 0x09,
12499 R6_SWM16 = 0x0a,
12500 JALRC16 = 0x0b,
12501 MOVEP_0C = 0x0c,
12502 MOVEP_0F = 0x0f,
12503 JRCADDIUSP = 0x13,
12504 R6_BREAK16 = 0x1b,
12505 R6_SDBBP16 = 0x3b
12508 /* POOL16D encoding of minor opcode field */
12510 enum {
12511 ADDIUS5 = 0x0,
12512 ADDIUSP = 0x1
12515 /* POOL16E encoding of minor opcode field */
12517 enum {
12518 ADDIUR2 = 0x0,
12519 ADDIUR1SP = 0x1
12522 static int mmreg (int r)
12524 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12526 return map[r];
12529 /* Used for 16-bit store instructions. */
12530 static int mmreg2 (int r)
12532 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12534 return map[r];
12537 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12538 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12539 #define uMIPS_RS2(op) uMIPS_RS(op)
12540 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12541 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12542 #define uMIPS_RS5(op) (op & 0x1f)
12544 /* Signed immediate */
12545 #define SIMM(op, start, width) \
12546 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12547 << (32-width)) \
12548 >> (32-width))
12549 /* Zero-extended immediate */
12550 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12552 static void gen_addiur1sp(DisasContext *ctx)
12554 int rd = mmreg(uMIPS_RD(ctx->opcode));
12556 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12559 static void gen_addiur2(DisasContext *ctx)
12561 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12562 int rd = mmreg(uMIPS_RD(ctx->opcode));
12563 int rs = mmreg(uMIPS_RS(ctx->opcode));
12565 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12568 static void gen_addiusp(DisasContext *ctx)
12570 int encoded = ZIMM(ctx->opcode, 1, 9);
12571 int decoded;
12573 if (encoded <= 1) {
12574 decoded = 256 + encoded;
12575 } else if (encoded <= 255) {
12576 decoded = encoded;
12577 } else if (encoded <= 509) {
12578 decoded = encoded - 512;
12579 } else {
12580 decoded = encoded - 768;
12583 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
12586 static void gen_addius5(DisasContext *ctx)
12588 int imm = SIMM(ctx->opcode, 1, 4);
12589 int rd = (ctx->opcode >> 5) & 0x1f;
12591 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
12594 static void gen_andi16(DisasContext *ctx)
12596 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
12597 31, 32, 63, 64, 255, 32768, 65535 };
12598 int rd = mmreg(uMIPS_RD(ctx->opcode));
12599 int rs = mmreg(uMIPS_RS(ctx->opcode));
12600 int encoded = ZIMM(ctx->opcode, 0, 4);
12602 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
12605 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
12606 int base, int16_t offset)
12608 TCGv t0, t1;
12609 TCGv_i32 t2;
12611 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12612 generate_exception_end(ctx, EXCP_RI);
12613 return;
12616 t0 = tcg_temp_new();
12618 gen_base_offset_addr(ctx, t0, base, offset);
12620 t1 = tcg_const_tl(reglist);
12621 t2 = tcg_const_i32(ctx->mem_idx);
12623 save_cpu_state(ctx, 1);
12624 switch (opc) {
12625 case LWM32:
12626 gen_helper_lwm(cpu_env, t0, t1, t2);
12627 break;
12628 case SWM32:
12629 gen_helper_swm(cpu_env, t0, t1, t2);
12630 break;
12631 #ifdef TARGET_MIPS64
12632 case LDM:
12633 gen_helper_ldm(cpu_env, t0, t1, t2);
12634 break;
12635 case SDM:
12636 gen_helper_sdm(cpu_env, t0, t1, t2);
12637 break;
12638 #endif
12640 tcg_temp_free(t0);
12641 tcg_temp_free(t1);
12642 tcg_temp_free_i32(t2);
12646 static void gen_pool16c_insn(DisasContext *ctx)
12648 int rd = mmreg((ctx->opcode >> 3) & 0x7);
12649 int rs = mmreg(ctx->opcode & 0x7);
12651 switch (((ctx->opcode) >> 4) & 0x3f) {
12652 case NOT16 + 0:
12653 case NOT16 + 1:
12654 case NOT16 + 2:
12655 case NOT16 + 3:
12656 gen_logic(ctx, OPC_NOR, rd, rs, 0);
12657 break;
12658 case XOR16 + 0:
12659 case XOR16 + 1:
12660 case XOR16 + 2:
12661 case XOR16 + 3:
12662 gen_logic(ctx, OPC_XOR, rd, rd, rs);
12663 break;
12664 case AND16 + 0:
12665 case AND16 + 1:
12666 case AND16 + 2:
12667 case AND16 + 3:
12668 gen_logic(ctx, OPC_AND, rd, rd, rs);
12669 break;
12670 case OR16 + 0:
12671 case OR16 + 1:
12672 case OR16 + 2:
12673 case OR16 + 3:
12674 gen_logic(ctx, OPC_OR, rd, rd, rs);
12675 break;
12676 case LWM16 + 0:
12677 case LWM16 + 1:
12678 case LWM16 + 2:
12679 case LWM16 + 3:
12681 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12682 int offset = ZIMM(ctx->opcode, 0, 4);
12684 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
12685 29, offset << 2);
12687 break;
12688 case SWM16 + 0:
12689 case SWM16 + 1:
12690 case SWM16 + 2:
12691 case SWM16 + 3:
12693 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12694 int offset = ZIMM(ctx->opcode, 0, 4);
12696 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
12697 29, offset << 2);
12699 break;
12700 case JR16 + 0:
12701 case JR16 + 1:
12703 int reg = ctx->opcode & 0x1f;
12705 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
12707 break;
12708 case JRC16 + 0:
12709 case JRC16 + 1:
12711 int reg = ctx->opcode & 0x1f;
12712 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
12713 /* Let normal delay slot handling in our caller take us
12714 to the branch target. */
12716 break;
12717 case JALR16 + 0:
12718 case JALR16 + 1:
12719 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
12720 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12721 break;
12722 case JALR16S + 0:
12723 case JALR16S + 1:
12724 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
12725 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12726 break;
12727 case MFHI16 + 0:
12728 case MFHI16 + 1:
12729 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
12730 break;
12731 case MFLO16 + 0:
12732 case MFLO16 + 1:
12733 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
12734 break;
12735 case BREAK16:
12736 generate_exception_end(ctx, EXCP_BREAK);
12737 break;
12738 case SDBBP16:
12739 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
12740 gen_helper_do_semihosting(cpu_env);
12741 } else {
12742 /* XXX: not clear which exception should be raised
12743 * when in debug mode...
12745 check_insn(ctx, ISA_MIPS32);
12746 generate_exception_end(ctx, EXCP_DBp);
12748 break;
12749 case JRADDIUSP + 0:
12750 case JRADDIUSP + 1:
12752 int imm = ZIMM(ctx->opcode, 0, 5);
12753 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12754 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12755 /* Let normal delay slot handling in our caller take us
12756 to the branch target. */
12758 break;
12759 default:
12760 generate_exception_end(ctx, EXCP_RI);
12761 break;
12765 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
12766 int enc_rs)
12768 int rd, rs, re, rt;
12769 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
12770 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
12771 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
12772 rd = rd_enc[enc_dest];
12773 re = re_enc[enc_dest];
12774 rs = rs_rt_enc[enc_rs];
12775 rt = rs_rt_enc[enc_rt];
12776 if (rs) {
12777 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
12778 } else {
12779 tcg_gen_movi_tl(cpu_gpr[rd], 0);
12781 if (rt) {
12782 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
12783 } else {
12784 tcg_gen_movi_tl(cpu_gpr[re], 0);
12788 static void gen_pool16c_r6_insn(DisasContext *ctx)
12790 int rt = mmreg((ctx->opcode >> 7) & 0x7);
12791 int rs = mmreg((ctx->opcode >> 4) & 0x7);
12793 switch (ctx->opcode & 0xf) {
12794 case R6_NOT16:
12795 gen_logic(ctx, OPC_NOR, rt, rs, 0);
12796 break;
12797 case R6_AND16:
12798 gen_logic(ctx, OPC_AND, rt, rt, rs);
12799 break;
12800 case R6_LWM16:
12802 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
12803 int offset = extract32(ctx->opcode, 4, 4);
12804 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
12806 break;
12807 case R6_JRC16: /* JRCADDIUSP */
12808 if ((ctx->opcode >> 4) & 1) {
12809 /* JRCADDIUSP */
12810 int imm = extract32(ctx->opcode, 5, 5);
12811 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12812 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12813 } else {
12814 /* JRC16 */
12815 int rs = extract32(ctx->opcode, 5, 5);
12816 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
12818 break;
12819 case MOVEP ... MOVEP_07:
12820 case MOVEP_0C ... MOVEP_0F:
12822 int enc_dest = uMIPS_RD(ctx->opcode);
12823 int enc_rt = uMIPS_RS2(ctx->opcode);
12824 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
12825 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
12827 break;
12828 case R6_XOR16:
12829 gen_logic(ctx, OPC_XOR, rt, rt, rs);
12830 break;
12831 case R6_OR16:
12832 gen_logic(ctx, OPC_OR, rt, rt, rs);
12833 break;
12834 case R6_SWM16:
12836 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
12837 int offset = extract32(ctx->opcode, 4, 4);
12838 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
12840 break;
12841 case JALRC16: /* BREAK16, SDBBP16 */
12842 switch (ctx->opcode & 0x3f) {
12843 case JALRC16:
12844 case JALRC16 + 0x20:
12845 /* JALRC16 */
12846 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
12847 31, 0, 0);
12848 break;
12849 case R6_BREAK16:
12850 /* BREAK16 */
12851 generate_exception(ctx, EXCP_BREAK);
12852 break;
12853 case R6_SDBBP16:
12854 /* SDBBP16 */
12855 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
12856 gen_helper_do_semihosting(cpu_env);
12857 } else {
12858 if (ctx->hflags & MIPS_HFLAG_SBRI) {
12859 generate_exception(ctx, EXCP_RI);
12860 } else {
12861 generate_exception(ctx, EXCP_DBp);
12864 break;
12866 break;
12867 default:
12868 generate_exception(ctx, EXCP_RI);
12869 break;
12873 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
12875 TCGv t0 = tcg_temp_new();
12876 TCGv t1 = tcg_temp_new();
12878 gen_load_gpr(t0, base);
12880 if (index != 0) {
12881 gen_load_gpr(t1, index);
12882 tcg_gen_shli_tl(t1, t1, 2);
12883 gen_op_addr_add(ctx, t0, t1, t0);
12886 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12887 gen_store_gpr(t1, rd);
12889 tcg_temp_free(t0);
12890 tcg_temp_free(t1);
12893 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
12894 int base, int16_t offset)
12896 TCGv t0, t1;
12898 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
12899 generate_exception_end(ctx, EXCP_RI);
12900 return;
12903 t0 = tcg_temp_new();
12904 t1 = tcg_temp_new();
12906 gen_base_offset_addr(ctx, t0, base, offset);
12908 switch (opc) {
12909 case LWP:
12910 if (rd == base) {
12911 generate_exception_end(ctx, EXCP_RI);
12912 return;
12914 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12915 gen_store_gpr(t1, rd);
12916 tcg_gen_movi_tl(t1, 4);
12917 gen_op_addr_add(ctx, t0, t0, t1);
12918 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12919 gen_store_gpr(t1, rd+1);
12920 break;
12921 case SWP:
12922 gen_load_gpr(t1, rd);
12923 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12924 tcg_gen_movi_tl(t1, 4);
12925 gen_op_addr_add(ctx, t0, t0, t1);
12926 gen_load_gpr(t1, rd+1);
12927 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12928 break;
12929 #ifdef TARGET_MIPS64
12930 case LDP:
12931 if (rd == base) {
12932 generate_exception_end(ctx, EXCP_RI);
12933 return;
12935 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12936 gen_store_gpr(t1, rd);
12937 tcg_gen_movi_tl(t1, 8);
12938 gen_op_addr_add(ctx, t0, t0, t1);
12939 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12940 gen_store_gpr(t1, rd+1);
12941 break;
12942 case SDP:
12943 gen_load_gpr(t1, rd);
12944 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12945 tcg_gen_movi_tl(t1, 8);
12946 gen_op_addr_add(ctx, t0, t0, t1);
12947 gen_load_gpr(t1, rd+1);
12948 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12949 break;
12950 #endif
12952 tcg_temp_free(t0);
12953 tcg_temp_free(t1);
12956 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
12958 int extension = (ctx->opcode >> 6) & 0x3f;
12959 int minor = (ctx->opcode >> 12) & 0xf;
12960 uint32_t mips32_op;
12962 switch (extension) {
12963 case TEQ:
12964 mips32_op = OPC_TEQ;
12965 goto do_trap;
12966 case TGE:
12967 mips32_op = OPC_TGE;
12968 goto do_trap;
12969 case TGEU:
12970 mips32_op = OPC_TGEU;
12971 goto do_trap;
12972 case TLT:
12973 mips32_op = OPC_TLT;
12974 goto do_trap;
12975 case TLTU:
12976 mips32_op = OPC_TLTU;
12977 goto do_trap;
12978 case TNE:
12979 mips32_op = OPC_TNE;
12980 do_trap:
12981 gen_trap(ctx, mips32_op, rs, rt, -1);
12982 break;
12983 #ifndef CONFIG_USER_ONLY
12984 case MFC0:
12985 case MFC0 + 32:
12986 check_cp0_enabled(ctx);
12987 if (rt == 0) {
12988 /* Treat as NOP. */
12989 break;
12991 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
12992 break;
12993 case MTC0:
12994 case MTC0 + 32:
12995 check_cp0_enabled(ctx);
12997 TCGv t0 = tcg_temp_new();
12999 gen_load_gpr(t0, rt);
13000 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
13001 tcg_temp_free(t0);
13003 break;
13004 #endif
13005 case 0x2a:
13006 switch (minor & 3) {
13007 case MADD_ACC:
13008 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
13009 break;
13010 case MADDU_ACC:
13011 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
13012 break;
13013 case MSUB_ACC:
13014 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
13015 break;
13016 case MSUBU_ACC:
13017 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
13018 break;
13019 default:
13020 goto pool32axf_invalid;
13022 break;
13023 case 0x32:
13024 switch (minor & 3) {
13025 case MULT_ACC:
13026 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
13027 break;
13028 case MULTU_ACC:
13029 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
13030 break;
13031 default:
13032 goto pool32axf_invalid;
13034 break;
13035 case 0x2c:
13036 switch (minor) {
13037 case BITSWAP:
13038 check_insn(ctx, ISA_MIPS32R6);
13039 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
13040 break;
13041 case SEB:
13042 gen_bshfl(ctx, OPC_SEB, rs, rt);
13043 break;
13044 case SEH:
13045 gen_bshfl(ctx, OPC_SEH, rs, rt);
13046 break;
13047 case CLO:
13048 mips32_op = OPC_CLO;
13049 goto do_cl;
13050 case CLZ:
13051 mips32_op = OPC_CLZ;
13052 do_cl:
13053 check_insn(ctx, ISA_MIPS32);
13054 gen_cl(ctx, mips32_op, rt, rs);
13055 break;
13056 case RDHWR:
13057 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13058 gen_rdhwr(ctx, rt, rs, 0);
13059 break;
13060 case WSBH:
13061 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13062 break;
13063 case MULT:
13064 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13065 mips32_op = OPC_MULT;
13066 goto do_mul;
13067 case MULTU:
13068 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13069 mips32_op = OPC_MULTU;
13070 goto do_mul;
13071 case DIV:
13072 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13073 mips32_op = OPC_DIV;
13074 goto do_div;
13075 case DIVU:
13076 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13077 mips32_op = OPC_DIVU;
13078 goto do_div;
13079 do_div:
13080 check_insn(ctx, ISA_MIPS32);
13081 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13082 break;
13083 case MADD:
13084 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13085 mips32_op = OPC_MADD;
13086 goto do_mul;
13087 case MADDU:
13088 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13089 mips32_op = OPC_MADDU;
13090 goto do_mul;
13091 case MSUB:
13092 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13093 mips32_op = OPC_MSUB;
13094 goto do_mul;
13095 case MSUBU:
13096 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13097 mips32_op = OPC_MSUBU;
13098 do_mul:
13099 check_insn(ctx, ISA_MIPS32);
13100 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13101 break;
13102 default:
13103 goto pool32axf_invalid;
13105 break;
13106 case 0x34:
13107 switch (minor) {
13108 case MFC2:
13109 case MTC2:
13110 case MFHC2:
13111 case MTHC2:
13112 case CFC2:
13113 case CTC2:
13114 generate_exception_err(ctx, EXCP_CpU, 2);
13115 break;
13116 default:
13117 goto pool32axf_invalid;
13119 break;
13120 case 0x3c:
13121 switch (minor) {
13122 case JALR: /* JALRC */
13123 case JALR_HB: /* JALRC_HB */
13124 if (ctx->insn_flags & ISA_MIPS32R6) {
13125 /* JALRC, JALRC_HB */
13126 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13127 } else {
13128 /* JALR, JALR_HB */
13129 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13130 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13132 break;
13133 case JALRS:
13134 case JALRS_HB:
13135 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13136 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13137 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13138 break;
13139 default:
13140 goto pool32axf_invalid;
13142 break;
13143 case 0x05:
13144 switch (minor) {
13145 case RDPGPR:
13146 check_cp0_enabled(ctx);
13147 check_insn(ctx, ISA_MIPS32R2);
13148 gen_load_srsgpr(rs, rt);
13149 break;
13150 case WRPGPR:
13151 check_cp0_enabled(ctx);
13152 check_insn(ctx, ISA_MIPS32R2);
13153 gen_store_srsgpr(rs, rt);
13154 break;
13155 default:
13156 goto pool32axf_invalid;
13158 break;
13159 #ifndef CONFIG_USER_ONLY
13160 case 0x0d:
13161 switch (minor) {
13162 case TLBP:
13163 mips32_op = OPC_TLBP;
13164 goto do_cp0;
13165 case TLBR:
13166 mips32_op = OPC_TLBR;
13167 goto do_cp0;
13168 case TLBWI:
13169 mips32_op = OPC_TLBWI;
13170 goto do_cp0;
13171 case TLBWR:
13172 mips32_op = OPC_TLBWR;
13173 goto do_cp0;
13174 case TLBINV:
13175 mips32_op = OPC_TLBINV;
13176 goto do_cp0;
13177 case TLBINVF:
13178 mips32_op = OPC_TLBINVF;
13179 goto do_cp0;
13180 case WAIT:
13181 mips32_op = OPC_WAIT;
13182 goto do_cp0;
13183 case DERET:
13184 mips32_op = OPC_DERET;
13185 goto do_cp0;
13186 case ERET:
13187 mips32_op = OPC_ERET;
13188 do_cp0:
13189 gen_cp0(env, ctx, mips32_op, rt, rs);
13190 break;
13191 default:
13192 goto pool32axf_invalid;
13194 break;
13195 case 0x1d:
13196 switch (minor) {
13197 case DI:
13198 check_cp0_enabled(ctx);
13200 TCGv t0 = tcg_temp_new();
13202 save_cpu_state(ctx, 1);
13203 gen_helper_di(t0, cpu_env);
13204 gen_store_gpr(t0, rs);
13205 /* Stop translation as we may have switched the execution mode */
13206 ctx->bstate = BS_STOP;
13207 tcg_temp_free(t0);
13209 break;
13210 case EI:
13211 check_cp0_enabled(ctx);
13213 TCGv t0 = tcg_temp_new();
13215 save_cpu_state(ctx, 1);
13216 gen_helper_ei(t0, cpu_env);
13217 gen_store_gpr(t0, rs);
13218 /* Stop translation as we may have switched the execution mode */
13219 ctx->bstate = BS_STOP;
13220 tcg_temp_free(t0);
13222 break;
13223 default:
13224 goto pool32axf_invalid;
13226 break;
13227 #endif
13228 case 0x2d:
13229 switch (minor) {
13230 case SYNC:
13231 /* NOP */
13232 break;
13233 case SYSCALL:
13234 generate_exception_end(ctx, EXCP_SYSCALL);
13235 break;
13236 case SDBBP:
13237 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
13238 gen_helper_do_semihosting(cpu_env);
13239 } else {
13240 check_insn(ctx, ISA_MIPS32);
13241 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13242 generate_exception_end(ctx, EXCP_RI);
13243 } else {
13244 generate_exception_end(ctx, EXCP_DBp);
13247 break;
13248 default:
13249 goto pool32axf_invalid;
13251 break;
13252 case 0x01:
13253 switch (minor & 3) {
13254 case MFHI_ACC:
13255 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
13256 break;
13257 case MFLO_ACC:
13258 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
13259 break;
13260 case MTHI_ACC:
13261 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
13262 break;
13263 case MTLO_ACC:
13264 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
13265 break;
13266 default:
13267 goto pool32axf_invalid;
13269 break;
13270 case 0x35:
13271 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13272 switch (minor) {
13273 case MFHI32:
13274 gen_HILO(ctx, OPC_MFHI, 0, rs);
13275 break;
13276 case MFLO32:
13277 gen_HILO(ctx, OPC_MFLO, 0, rs);
13278 break;
13279 case MTHI32:
13280 gen_HILO(ctx, OPC_MTHI, 0, rs);
13281 break;
13282 case MTLO32:
13283 gen_HILO(ctx, OPC_MTLO, 0, rs);
13284 break;
13285 default:
13286 goto pool32axf_invalid;
13288 break;
13289 default:
13290 pool32axf_invalid:
13291 MIPS_INVAL("pool32axf");
13292 generate_exception_end(ctx, EXCP_RI);
13293 break;
13297 /* Values for microMIPS fmt field. Variable-width, depending on which
13298 formats the instruction supports. */
13300 enum {
13301 FMT_SD_S = 0,
13302 FMT_SD_D = 1,
13304 FMT_SDPS_S = 0,
13305 FMT_SDPS_D = 1,
13306 FMT_SDPS_PS = 2,
13308 FMT_SWL_S = 0,
13309 FMT_SWL_W = 1,
13310 FMT_SWL_L = 2,
13312 FMT_DWL_D = 0,
13313 FMT_DWL_W = 1,
13314 FMT_DWL_L = 2
13317 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
13319 int extension = (ctx->opcode >> 6) & 0x3ff;
13320 uint32_t mips32_op;
13322 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
13323 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
13324 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
13326 switch (extension) {
13327 case FLOAT_1BIT_FMT(CFC1, 0):
13328 mips32_op = OPC_CFC1;
13329 goto do_cp1;
13330 case FLOAT_1BIT_FMT(CTC1, 0):
13331 mips32_op = OPC_CTC1;
13332 goto do_cp1;
13333 case FLOAT_1BIT_FMT(MFC1, 0):
13334 mips32_op = OPC_MFC1;
13335 goto do_cp1;
13336 case FLOAT_1BIT_FMT(MTC1, 0):
13337 mips32_op = OPC_MTC1;
13338 goto do_cp1;
13339 case FLOAT_1BIT_FMT(MFHC1, 0):
13340 mips32_op = OPC_MFHC1;
13341 goto do_cp1;
13342 case FLOAT_1BIT_FMT(MTHC1, 0):
13343 mips32_op = OPC_MTHC1;
13344 do_cp1:
13345 gen_cp1(ctx, mips32_op, rt, rs);
13346 break;
13348 /* Reciprocal square root */
13349 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
13350 mips32_op = OPC_RSQRT_S;
13351 goto do_unaryfp;
13352 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
13353 mips32_op = OPC_RSQRT_D;
13354 goto do_unaryfp;
13356 /* Square root */
13357 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
13358 mips32_op = OPC_SQRT_S;
13359 goto do_unaryfp;
13360 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
13361 mips32_op = OPC_SQRT_D;
13362 goto do_unaryfp;
13364 /* Reciprocal */
13365 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
13366 mips32_op = OPC_RECIP_S;
13367 goto do_unaryfp;
13368 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
13369 mips32_op = OPC_RECIP_D;
13370 goto do_unaryfp;
13372 /* Floor */
13373 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
13374 mips32_op = OPC_FLOOR_L_S;
13375 goto do_unaryfp;
13376 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
13377 mips32_op = OPC_FLOOR_L_D;
13378 goto do_unaryfp;
13379 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
13380 mips32_op = OPC_FLOOR_W_S;
13381 goto do_unaryfp;
13382 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
13383 mips32_op = OPC_FLOOR_W_D;
13384 goto do_unaryfp;
13386 /* Ceiling */
13387 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
13388 mips32_op = OPC_CEIL_L_S;
13389 goto do_unaryfp;
13390 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
13391 mips32_op = OPC_CEIL_L_D;
13392 goto do_unaryfp;
13393 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
13394 mips32_op = OPC_CEIL_W_S;
13395 goto do_unaryfp;
13396 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
13397 mips32_op = OPC_CEIL_W_D;
13398 goto do_unaryfp;
13400 /* Truncation */
13401 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
13402 mips32_op = OPC_TRUNC_L_S;
13403 goto do_unaryfp;
13404 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
13405 mips32_op = OPC_TRUNC_L_D;
13406 goto do_unaryfp;
13407 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
13408 mips32_op = OPC_TRUNC_W_S;
13409 goto do_unaryfp;
13410 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
13411 mips32_op = OPC_TRUNC_W_D;
13412 goto do_unaryfp;
13414 /* Round */
13415 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
13416 mips32_op = OPC_ROUND_L_S;
13417 goto do_unaryfp;
13418 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
13419 mips32_op = OPC_ROUND_L_D;
13420 goto do_unaryfp;
13421 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
13422 mips32_op = OPC_ROUND_W_S;
13423 goto do_unaryfp;
13424 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
13425 mips32_op = OPC_ROUND_W_D;
13426 goto do_unaryfp;
13428 /* Integer to floating-point conversion */
13429 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
13430 mips32_op = OPC_CVT_L_S;
13431 goto do_unaryfp;
13432 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
13433 mips32_op = OPC_CVT_L_D;
13434 goto do_unaryfp;
13435 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
13436 mips32_op = OPC_CVT_W_S;
13437 goto do_unaryfp;
13438 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
13439 mips32_op = OPC_CVT_W_D;
13440 goto do_unaryfp;
13442 /* Paired-foo conversions */
13443 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
13444 mips32_op = OPC_CVT_S_PL;
13445 goto do_unaryfp;
13446 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13447 mips32_op = OPC_CVT_S_PU;
13448 goto do_unaryfp;
13449 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13450 mips32_op = OPC_CVT_PW_PS;
13451 goto do_unaryfp;
13452 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13453 mips32_op = OPC_CVT_PS_PW;
13454 goto do_unaryfp;
13456 /* Floating-point moves */
13457 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13458 mips32_op = OPC_MOV_S;
13459 goto do_unaryfp;
13460 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13461 mips32_op = OPC_MOV_D;
13462 goto do_unaryfp;
13463 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13464 mips32_op = OPC_MOV_PS;
13465 goto do_unaryfp;
13467 /* Absolute value */
13468 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13469 mips32_op = OPC_ABS_S;
13470 goto do_unaryfp;
13471 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13472 mips32_op = OPC_ABS_D;
13473 goto do_unaryfp;
13474 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13475 mips32_op = OPC_ABS_PS;
13476 goto do_unaryfp;
13478 /* Negation */
13479 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13480 mips32_op = OPC_NEG_S;
13481 goto do_unaryfp;
13482 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13483 mips32_op = OPC_NEG_D;
13484 goto do_unaryfp;
13485 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13486 mips32_op = OPC_NEG_PS;
13487 goto do_unaryfp;
13489 /* Reciprocal square root step */
13490 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13491 mips32_op = OPC_RSQRT1_S;
13492 goto do_unaryfp;
13493 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13494 mips32_op = OPC_RSQRT1_D;
13495 goto do_unaryfp;
13496 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13497 mips32_op = OPC_RSQRT1_PS;
13498 goto do_unaryfp;
13500 /* Reciprocal step */
13501 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13502 mips32_op = OPC_RECIP1_S;
13503 goto do_unaryfp;
13504 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13505 mips32_op = OPC_RECIP1_S;
13506 goto do_unaryfp;
13507 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13508 mips32_op = OPC_RECIP1_PS;
13509 goto do_unaryfp;
13511 /* Conversions from double */
13512 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13513 mips32_op = OPC_CVT_D_S;
13514 goto do_unaryfp;
13515 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13516 mips32_op = OPC_CVT_D_W;
13517 goto do_unaryfp;
13518 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13519 mips32_op = OPC_CVT_D_L;
13520 goto do_unaryfp;
13522 /* Conversions from single */
13523 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13524 mips32_op = OPC_CVT_S_D;
13525 goto do_unaryfp;
13526 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13527 mips32_op = OPC_CVT_S_W;
13528 goto do_unaryfp;
13529 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13530 mips32_op = OPC_CVT_S_L;
13531 do_unaryfp:
13532 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13533 break;
13535 /* Conditional moves on floating-point codes */
13536 case COND_FLOAT_MOV(MOVT, 0):
13537 case COND_FLOAT_MOV(MOVT, 1):
13538 case COND_FLOAT_MOV(MOVT, 2):
13539 case COND_FLOAT_MOV(MOVT, 3):
13540 case COND_FLOAT_MOV(MOVT, 4):
13541 case COND_FLOAT_MOV(MOVT, 5):
13542 case COND_FLOAT_MOV(MOVT, 6):
13543 case COND_FLOAT_MOV(MOVT, 7):
13544 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13545 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13546 break;
13547 case COND_FLOAT_MOV(MOVF, 0):
13548 case COND_FLOAT_MOV(MOVF, 1):
13549 case COND_FLOAT_MOV(MOVF, 2):
13550 case COND_FLOAT_MOV(MOVF, 3):
13551 case COND_FLOAT_MOV(MOVF, 4):
13552 case COND_FLOAT_MOV(MOVF, 5):
13553 case COND_FLOAT_MOV(MOVF, 6):
13554 case COND_FLOAT_MOV(MOVF, 7):
13555 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13556 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13557 break;
13558 default:
13559 MIPS_INVAL("pool32fxf");
13560 generate_exception_end(ctx, EXCP_RI);
13561 break;
13565 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
13567 int32_t offset;
13568 uint16_t insn;
13569 int rt, rs, rd, rr;
13570 int16_t imm;
13571 uint32_t op, minor, mips32_op;
13572 uint32_t cond, fmt, cc;
13574 insn = cpu_lduw_code(env, ctx->pc + 2);
13575 ctx->opcode = (ctx->opcode << 16) | insn;
13577 rt = (ctx->opcode >> 21) & 0x1f;
13578 rs = (ctx->opcode >> 16) & 0x1f;
13579 rd = (ctx->opcode >> 11) & 0x1f;
13580 rr = (ctx->opcode >> 6) & 0x1f;
13581 imm = (int16_t) ctx->opcode;
13583 op = (ctx->opcode >> 26) & 0x3f;
13584 switch (op) {
13585 case POOL32A:
13586 minor = ctx->opcode & 0x3f;
13587 switch (minor) {
13588 case 0x00:
13589 minor = (ctx->opcode >> 6) & 0xf;
13590 switch (minor) {
13591 case SLL32:
13592 mips32_op = OPC_SLL;
13593 goto do_shifti;
13594 case SRA:
13595 mips32_op = OPC_SRA;
13596 goto do_shifti;
13597 case SRL32:
13598 mips32_op = OPC_SRL;
13599 goto do_shifti;
13600 case ROTR:
13601 mips32_op = OPC_ROTR;
13602 do_shifti:
13603 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
13604 break;
13605 case SELEQZ:
13606 check_insn(ctx, ISA_MIPS32R6);
13607 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
13608 break;
13609 case SELNEZ:
13610 check_insn(ctx, ISA_MIPS32R6);
13611 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
13612 break;
13613 case R6_RDHWR:
13614 check_insn(ctx, ISA_MIPS32R6);
13615 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
13616 break;
13617 default:
13618 goto pool32a_invalid;
13620 break;
13621 case 0x10:
13622 minor = (ctx->opcode >> 6) & 0xf;
13623 switch (minor) {
13624 /* Arithmetic */
13625 case ADD:
13626 mips32_op = OPC_ADD;
13627 goto do_arith;
13628 case ADDU32:
13629 mips32_op = OPC_ADDU;
13630 goto do_arith;
13631 case SUB:
13632 mips32_op = OPC_SUB;
13633 goto do_arith;
13634 case SUBU32:
13635 mips32_op = OPC_SUBU;
13636 goto do_arith;
13637 case MUL:
13638 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13639 mips32_op = OPC_MUL;
13640 do_arith:
13641 gen_arith(ctx, mips32_op, rd, rs, rt);
13642 break;
13643 /* Shifts */
13644 case SLLV:
13645 mips32_op = OPC_SLLV;
13646 goto do_shift;
13647 case SRLV:
13648 mips32_op = OPC_SRLV;
13649 goto do_shift;
13650 case SRAV:
13651 mips32_op = OPC_SRAV;
13652 goto do_shift;
13653 case ROTRV:
13654 mips32_op = OPC_ROTRV;
13655 do_shift:
13656 gen_shift(ctx, mips32_op, rd, rs, rt);
13657 break;
13658 /* Logical operations */
13659 case AND:
13660 mips32_op = OPC_AND;
13661 goto do_logic;
13662 case OR32:
13663 mips32_op = OPC_OR;
13664 goto do_logic;
13665 case NOR:
13666 mips32_op = OPC_NOR;
13667 goto do_logic;
13668 case XOR32:
13669 mips32_op = OPC_XOR;
13670 do_logic:
13671 gen_logic(ctx, mips32_op, rd, rs, rt);
13672 break;
13673 /* Set less than */
13674 case SLT:
13675 mips32_op = OPC_SLT;
13676 goto do_slt;
13677 case SLTU:
13678 mips32_op = OPC_SLTU;
13679 do_slt:
13680 gen_slt(ctx, mips32_op, rd, rs, rt);
13681 break;
13682 default:
13683 goto pool32a_invalid;
13685 break;
13686 case 0x18:
13687 minor = (ctx->opcode >> 6) & 0xf;
13688 switch (minor) {
13689 /* Conditional moves */
13690 case MOVN: /* MUL */
13691 if (ctx->insn_flags & ISA_MIPS32R6) {
13692 /* MUL */
13693 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
13694 } else {
13695 /* MOVN */
13696 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
13698 break;
13699 case MOVZ: /* MUH */
13700 if (ctx->insn_flags & ISA_MIPS32R6) {
13701 /* MUH */
13702 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
13703 } else {
13704 /* MOVZ */
13705 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
13707 break;
13708 case MULU:
13709 check_insn(ctx, ISA_MIPS32R6);
13710 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
13711 break;
13712 case MUHU:
13713 check_insn(ctx, ISA_MIPS32R6);
13714 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
13715 break;
13716 case LWXS: /* DIV */
13717 if (ctx->insn_flags & ISA_MIPS32R6) {
13718 /* DIV */
13719 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
13720 } else {
13721 /* LWXS */
13722 gen_ldxs(ctx, rs, rt, rd);
13724 break;
13725 case MOD:
13726 check_insn(ctx, ISA_MIPS32R6);
13727 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
13728 break;
13729 case R6_DIVU:
13730 check_insn(ctx, ISA_MIPS32R6);
13731 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
13732 break;
13733 case MODU:
13734 check_insn(ctx, ISA_MIPS32R6);
13735 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
13736 break;
13737 default:
13738 goto pool32a_invalid;
13740 break;
13741 case INS:
13742 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
13743 return;
13744 case LSA:
13745 check_insn(ctx, ISA_MIPS32R6);
13746 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
13747 extract32(ctx->opcode, 9, 2));
13748 break;
13749 case ALIGN:
13750 check_insn(ctx, ISA_MIPS32R6);
13751 gen_align(ctx, OPC_ALIGN, rd, rs, rt,
13752 extract32(ctx->opcode, 9, 2));
13753 break;
13754 case EXT:
13755 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
13756 return;
13757 case POOL32AXF:
13758 gen_pool32axf(env, ctx, rt, rs);
13759 break;
13760 case BREAK32:
13761 generate_exception_end(ctx, EXCP_BREAK);
13762 break;
13763 case SIGRIE:
13764 check_insn(ctx, ISA_MIPS32R6);
13765 generate_exception_end(ctx, EXCP_RI);
13766 break;
13767 default:
13768 pool32a_invalid:
13769 MIPS_INVAL("pool32a");
13770 generate_exception_end(ctx, EXCP_RI);
13771 break;
13773 break;
13774 case POOL32B:
13775 minor = (ctx->opcode >> 12) & 0xf;
13776 switch (minor) {
13777 case CACHE:
13778 check_cp0_enabled(ctx);
13779 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
13780 gen_cache_operation(ctx, rt, rs, imm);
13782 break;
13783 case LWC2:
13784 case SWC2:
13785 /* COP2: Not implemented. */
13786 generate_exception_err(ctx, EXCP_CpU, 2);
13787 break;
13788 #ifdef TARGET_MIPS64
13789 case LDP:
13790 case SDP:
13791 check_insn(ctx, ISA_MIPS3);
13792 check_mips_64(ctx);
13793 /* Fallthrough */
13794 #endif
13795 case LWP:
13796 case SWP:
13797 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13798 break;
13799 #ifdef TARGET_MIPS64
13800 case LDM:
13801 case SDM:
13802 check_insn(ctx, ISA_MIPS3);
13803 check_mips_64(ctx);
13804 /* Fallthrough */
13805 #endif
13806 case LWM32:
13807 case SWM32:
13808 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13809 break;
13810 default:
13811 MIPS_INVAL("pool32b");
13812 generate_exception_end(ctx, EXCP_RI);
13813 break;
13815 break;
13816 case POOL32F:
13817 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
13818 minor = ctx->opcode & 0x3f;
13819 check_cp1_enabled(ctx);
13820 switch (minor) {
13821 case ALNV_PS:
13822 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13823 mips32_op = OPC_ALNV_PS;
13824 goto do_madd;
13825 case MADD_S:
13826 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13827 mips32_op = OPC_MADD_S;
13828 goto do_madd;
13829 case MADD_D:
13830 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13831 mips32_op = OPC_MADD_D;
13832 goto do_madd;
13833 case MADD_PS:
13834 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13835 mips32_op = OPC_MADD_PS;
13836 goto do_madd;
13837 case MSUB_S:
13838 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13839 mips32_op = OPC_MSUB_S;
13840 goto do_madd;
13841 case MSUB_D:
13842 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13843 mips32_op = OPC_MSUB_D;
13844 goto do_madd;
13845 case MSUB_PS:
13846 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13847 mips32_op = OPC_MSUB_PS;
13848 goto do_madd;
13849 case NMADD_S:
13850 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13851 mips32_op = OPC_NMADD_S;
13852 goto do_madd;
13853 case NMADD_D:
13854 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13855 mips32_op = OPC_NMADD_D;
13856 goto do_madd;
13857 case NMADD_PS:
13858 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13859 mips32_op = OPC_NMADD_PS;
13860 goto do_madd;
13861 case NMSUB_S:
13862 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13863 mips32_op = OPC_NMSUB_S;
13864 goto do_madd;
13865 case NMSUB_D:
13866 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13867 mips32_op = OPC_NMSUB_D;
13868 goto do_madd;
13869 case NMSUB_PS:
13870 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13871 mips32_op = OPC_NMSUB_PS;
13872 do_madd:
13873 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
13874 break;
13875 case CABS_COND_FMT:
13876 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13877 cond = (ctx->opcode >> 6) & 0xf;
13878 cc = (ctx->opcode >> 13) & 0x7;
13879 fmt = (ctx->opcode >> 10) & 0x3;
13880 switch (fmt) {
13881 case 0x0:
13882 gen_cmpabs_s(ctx, cond, rt, rs, cc);
13883 break;
13884 case 0x1:
13885 gen_cmpabs_d(ctx, cond, rt, rs, cc);
13886 break;
13887 case 0x2:
13888 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
13889 break;
13890 default:
13891 goto pool32f_invalid;
13893 break;
13894 case C_COND_FMT:
13895 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13896 cond = (ctx->opcode >> 6) & 0xf;
13897 cc = (ctx->opcode >> 13) & 0x7;
13898 fmt = (ctx->opcode >> 10) & 0x3;
13899 switch (fmt) {
13900 case 0x0:
13901 gen_cmp_s(ctx, cond, rt, rs, cc);
13902 break;
13903 case 0x1:
13904 gen_cmp_d(ctx, cond, rt, rs, cc);
13905 break;
13906 case 0x2:
13907 gen_cmp_ps(ctx, cond, rt, rs, cc);
13908 break;
13909 default:
13910 goto pool32f_invalid;
13912 break;
13913 case CMP_CONDN_S:
13914 check_insn(ctx, ISA_MIPS32R6);
13915 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
13916 break;
13917 case CMP_CONDN_D:
13918 check_insn(ctx, ISA_MIPS32R6);
13919 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
13920 break;
13921 case POOL32FXF:
13922 gen_pool32fxf(ctx, rt, rs);
13923 break;
13924 case 0x00:
13925 /* PLL foo */
13926 switch ((ctx->opcode >> 6) & 0x7) {
13927 case PLL_PS:
13928 mips32_op = OPC_PLL_PS;
13929 goto do_ps;
13930 case PLU_PS:
13931 mips32_op = OPC_PLU_PS;
13932 goto do_ps;
13933 case PUL_PS:
13934 mips32_op = OPC_PUL_PS;
13935 goto do_ps;
13936 case PUU_PS:
13937 mips32_op = OPC_PUU_PS;
13938 goto do_ps;
13939 case CVT_PS_S:
13940 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13941 mips32_op = OPC_CVT_PS_S;
13942 do_ps:
13943 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13944 break;
13945 default:
13946 goto pool32f_invalid;
13948 break;
13949 case MIN_FMT:
13950 check_insn(ctx, ISA_MIPS32R6);
13951 switch ((ctx->opcode >> 9) & 0x3) {
13952 case FMT_SDPS_S:
13953 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
13954 break;
13955 case FMT_SDPS_D:
13956 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
13957 break;
13958 default:
13959 goto pool32f_invalid;
13961 break;
13962 case 0x08:
13963 /* [LS][WDU]XC1 */
13964 switch ((ctx->opcode >> 6) & 0x7) {
13965 case LWXC1:
13966 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13967 mips32_op = OPC_LWXC1;
13968 goto do_ldst_cp1;
13969 case SWXC1:
13970 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13971 mips32_op = OPC_SWXC1;
13972 goto do_ldst_cp1;
13973 case LDXC1:
13974 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13975 mips32_op = OPC_LDXC1;
13976 goto do_ldst_cp1;
13977 case SDXC1:
13978 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13979 mips32_op = OPC_SDXC1;
13980 goto do_ldst_cp1;
13981 case LUXC1:
13982 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13983 mips32_op = OPC_LUXC1;
13984 goto do_ldst_cp1;
13985 case SUXC1:
13986 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13987 mips32_op = OPC_SUXC1;
13988 do_ldst_cp1:
13989 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
13990 break;
13991 default:
13992 goto pool32f_invalid;
13994 break;
13995 case MAX_FMT:
13996 check_insn(ctx, ISA_MIPS32R6);
13997 switch ((ctx->opcode >> 9) & 0x3) {
13998 case FMT_SDPS_S:
13999 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
14000 break;
14001 case FMT_SDPS_D:
14002 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
14003 break;
14004 default:
14005 goto pool32f_invalid;
14007 break;
14008 case 0x18:
14009 /* 3D insns */
14010 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14011 fmt = (ctx->opcode >> 9) & 0x3;
14012 switch ((ctx->opcode >> 6) & 0x7) {
14013 case RSQRT2_FMT:
14014 switch (fmt) {
14015 case FMT_SDPS_S:
14016 mips32_op = OPC_RSQRT2_S;
14017 goto do_3d;
14018 case FMT_SDPS_D:
14019 mips32_op = OPC_RSQRT2_D;
14020 goto do_3d;
14021 case FMT_SDPS_PS:
14022 mips32_op = OPC_RSQRT2_PS;
14023 goto do_3d;
14024 default:
14025 goto pool32f_invalid;
14027 break;
14028 case RECIP2_FMT:
14029 switch (fmt) {
14030 case FMT_SDPS_S:
14031 mips32_op = OPC_RECIP2_S;
14032 goto do_3d;
14033 case FMT_SDPS_D:
14034 mips32_op = OPC_RECIP2_D;
14035 goto do_3d;
14036 case FMT_SDPS_PS:
14037 mips32_op = OPC_RECIP2_PS;
14038 goto do_3d;
14039 default:
14040 goto pool32f_invalid;
14042 break;
14043 case ADDR_PS:
14044 mips32_op = OPC_ADDR_PS;
14045 goto do_3d;
14046 case MULR_PS:
14047 mips32_op = OPC_MULR_PS;
14048 do_3d:
14049 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14050 break;
14051 default:
14052 goto pool32f_invalid;
14054 break;
14055 case 0x20:
14056 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
14057 cc = (ctx->opcode >> 13) & 0x7;
14058 fmt = (ctx->opcode >> 9) & 0x3;
14059 switch ((ctx->opcode >> 6) & 0x7) {
14060 case MOVF_FMT: /* RINT_FMT */
14061 if (ctx->insn_flags & ISA_MIPS32R6) {
14062 /* RINT_FMT */
14063 switch (fmt) {
14064 case FMT_SDPS_S:
14065 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14066 break;
14067 case FMT_SDPS_D:
14068 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14069 break;
14070 default:
14071 goto pool32f_invalid;
14073 } else {
14074 /* MOVF_FMT */
14075 switch (fmt) {
14076 case FMT_SDPS_S:
14077 gen_movcf_s(ctx, rs, rt, cc, 0);
14078 break;
14079 case FMT_SDPS_D:
14080 gen_movcf_d(ctx, rs, rt, cc, 0);
14081 break;
14082 case FMT_SDPS_PS:
14083 check_ps(ctx);
14084 gen_movcf_ps(ctx, rs, rt, cc, 0);
14085 break;
14086 default:
14087 goto pool32f_invalid;
14090 break;
14091 case MOVT_FMT: /* CLASS_FMT */
14092 if (ctx->insn_flags & ISA_MIPS32R6) {
14093 /* CLASS_FMT */
14094 switch (fmt) {
14095 case FMT_SDPS_S:
14096 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14097 break;
14098 case FMT_SDPS_D:
14099 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14100 break;
14101 default:
14102 goto pool32f_invalid;
14104 } else {
14105 /* MOVT_FMT */
14106 switch (fmt) {
14107 case FMT_SDPS_S:
14108 gen_movcf_s(ctx, rs, rt, cc, 1);
14109 break;
14110 case FMT_SDPS_D:
14111 gen_movcf_d(ctx, rs, rt, cc, 1);
14112 break;
14113 case FMT_SDPS_PS:
14114 check_ps(ctx);
14115 gen_movcf_ps(ctx, rs, rt, cc, 1);
14116 break;
14117 default:
14118 goto pool32f_invalid;
14121 break;
14122 case PREFX:
14123 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14124 break;
14125 default:
14126 goto pool32f_invalid;
14128 break;
14129 #define FINSN_3ARG_SDPS(prfx) \
14130 switch ((ctx->opcode >> 8) & 0x3) { \
14131 case FMT_SDPS_S: \
14132 mips32_op = OPC_##prfx##_S; \
14133 goto do_fpop; \
14134 case FMT_SDPS_D: \
14135 mips32_op = OPC_##prfx##_D; \
14136 goto do_fpop; \
14137 case FMT_SDPS_PS: \
14138 check_ps(ctx); \
14139 mips32_op = OPC_##prfx##_PS; \
14140 goto do_fpop; \
14141 default: \
14142 goto pool32f_invalid; \
14144 case MINA_FMT:
14145 check_insn(ctx, ISA_MIPS32R6);
14146 switch ((ctx->opcode >> 9) & 0x3) {
14147 case FMT_SDPS_S:
14148 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14149 break;
14150 case FMT_SDPS_D:
14151 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14152 break;
14153 default:
14154 goto pool32f_invalid;
14156 break;
14157 case MAXA_FMT:
14158 check_insn(ctx, ISA_MIPS32R6);
14159 switch ((ctx->opcode >> 9) & 0x3) {
14160 case FMT_SDPS_S:
14161 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14162 break;
14163 case FMT_SDPS_D:
14164 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14165 break;
14166 default:
14167 goto pool32f_invalid;
14169 break;
14170 case 0x30:
14171 /* regular FP ops */
14172 switch ((ctx->opcode >> 6) & 0x3) {
14173 case ADD_FMT:
14174 FINSN_3ARG_SDPS(ADD);
14175 break;
14176 case SUB_FMT:
14177 FINSN_3ARG_SDPS(SUB);
14178 break;
14179 case MUL_FMT:
14180 FINSN_3ARG_SDPS(MUL);
14181 break;
14182 case DIV_FMT:
14183 fmt = (ctx->opcode >> 8) & 0x3;
14184 if (fmt == 1) {
14185 mips32_op = OPC_DIV_D;
14186 } else if (fmt == 0) {
14187 mips32_op = OPC_DIV_S;
14188 } else {
14189 goto pool32f_invalid;
14191 goto do_fpop;
14192 default:
14193 goto pool32f_invalid;
14195 break;
14196 case 0x38:
14197 /* cmovs */
14198 switch ((ctx->opcode >> 6) & 0x7) {
14199 case MOVN_FMT: /* SELNEZ_FMT */
14200 if (ctx->insn_flags & ISA_MIPS32R6) {
14201 /* SELNEZ_FMT */
14202 switch ((ctx->opcode >> 9) & 0x3) {
14203 case FMT_SDPS_S:
14204 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14205 break;
14206 case FMT_SDPS_D:
14207 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
14208 break;
14209 default:
14210 goto pool32f_invalid;
14212 } else {
14213 /* MOVN_FMT */
14214 FINSN_3ARG_SDPS(MOVN);
14216 break;
14217 case MOVN_FMT_04:
14218 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14219 FINSN_3ARG_SDPS(MOVN);
14220 break;
14221 case MOVZ_FMT: /* SELEQZ_FMT */
14222 if (ctx->insn_flags & ISA_MIPS32R6) {
14223 /* SELEQZ_FMT */
14224 switch ((ctx->opcode >> 9) & 0x3) {
14225 case FMT_SDPS_S:
14226 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
14227 break;
14228 case FMT_SDPS_D:
14229 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
14230 break;
14231 default:
14232 goto pool32f_invalid;
14234 } else {
14235 /* MOVZ_FMT */
14236 FINSN_3ARG_SDPS(MOVZ);
14238 break;
14239 case MOVZ_FMT_05:
14240 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14241 FINSN_3ARG_SDPS(MOVZ);
14242 break;
14243 case SEL_FMT:
14244 check_insn(ctx, ISA_MIPS32R6);
14245 switch ((ctx->opcode >> 9) & 0x3) {
14246 case FMT_SDPS_S:
14247 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
14248 break;
14249 case FMT_SDPS_D:
14250 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
14251 break;
14252 default:
14253 goto pool32f_invalid;
14255 break;
14256 case MADDF_FMT:
14257 check_insn(ctx, ISA_MIPS32R6);
14258 switch ((ctx->opcode >> 9) & 0x3) {
14259 case FMT_SDPS_S:
14260 mips32_op = OPC_MADDF_S;
14261 goto do_fpop;
14262 case FMT_SDPS_D:
14263 mips32_op = OPC_MADDF_D;
14264 goto do_fpop;
14265 default:
14266 goto pool32f_invalid;
14268 break;
14269 case MSUBF_FMT:
14270 check_insn(ctx, ISA_MIPS32R6);
14271 switch ((ctx->opcode >> 9) & 0x3) {
14272 case FMT_SDPS_S:
14273 mips32_op = OPC_MSUBF_S;
14274 goto do_fpop;
14275 case FMT_SDPS_D:
14276 mips32_op = OPC_MSUBF_D;
14277 goto do_fpop;
14278 default:
14279 goto pool32f_invalid;
14281 break;
14282 default:
14283 goto pool32f_invalid;
14285 break;
14286 do_fpop:
14287 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14288 break;
14289 default:
14290 pool32f_invalid:
14291 MIPS_INVAL("pool32f");
14292 generate_exception_end(ctx, EXCP_RI);
14293 break;
14295 } else {
14296 generate_exception_err(ctx, EXCP_CpU, 1);
14298 break;
14299 case POOL32I:
14300 minor = (ctx->opcode >> 21) & 0x1f;
14301 switch (minor) {
14302 case BLTZ:
14303 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14304 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
14305 break;
14306 case BLTZAL:
14307 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14308 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
14309 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14310 break;
14311 case BLTZALS:
14312 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14313 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
14314 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14315 break;
14316 case BGEZ:
14317 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14318 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
14319 break;
14320 case BGEZAL:
14321 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14322 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
14323 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14324 break;
14325 case BGEZALS:
14326 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14327 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
14328 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14329 break;
14330 case BLEZ:
14331 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14332 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
14333 break;
14334 case BGTZ:
14335 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14336 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
14337 break;
14339 /* Traps */
14340 case TLTI: /* BC1EQZC */
14341 if (ctx->insn_flags & ISA_MIPS32R6) {
14342 /* BC1EQZC */
14343 check_cp1_enabled(ctx);
14344 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
14345 } else {
14346 /* TLTI */
14347 mips32_op = OPC_TLTI;
14348 goto do_trapi;
14350 break;
14351 case TGEI: /* BC1NEZC */
14352 if (ctx->insn_flags & ISA_MIPS32R6) {
14353 /* BC1NEZC */
14354 check_cp1_enabled(ctx);
14355 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
14356 } else {
14357 /* TGEI */
14358 mips32_op = OPC_TGEI;
14359 goto do_trapi;
14361 break;
14362 case TLTIU:
14363 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14364 mips32_op = OPC_TLTIU;
14365 goto do_trapi;
14366 case TGEIU:
14367 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14368 mips32_op = OPC_TGEIU;
14369 goto do_trapi;
14370 case TNEI: /* SYNCI */
14371 if (ctx->insn_flags & ISA_MIPS32R6) {
14372 /* SYNCI */
14373 /* Break the TB to be able to sync copied instructions
14374 immediately */
14375 ctx->bstate = BS_STOP;
14376 } else {
14377 /* TNEI */
14378 mips32_op = OPC_TNEI;
14379 goto do_trapi;
14381 break;
14382 case TEQI:
14383 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14384 mips32_op = OPC_TEQI;
14385 do_trapi:
14386 gen_trap(ctx, mips32_op, rs, -1, imm);
14387 break;
14389 case BNEZC:
14390 case BEQZC:
14391 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14392 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
14393 4, rs, 0, imm << 1, 0);
14394 /* Compact branches don't have a delay slot, so just let
14395 the normal delay slot handling take us to the branch
14396 target. */
14397 break;
14398 case LUI:
14399 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14400 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
14401 break;
14402 case SYNCI:
14403 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14404 /* Break the TB to be able to sync copied instructions
14405 immediately */
14406 ctx->bstate = BS_STOP;
14407 break;
14408 case BC2F:
14409 case BC2T:
14410 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14411 /* COP2: Not implemented. */
14412 generate_exception_err(ctx, EXCP_CpU, 2);
14413 break;
14414 case BC1F:
14415 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14416 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
14417 goto do_cp1branch;
14418 case BC1T:
14419 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14420 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
14421 goto do_cp1branch;
14422 case BC1ANY4F:
14423 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14424 mips32_op = OPC_BC1FANY4;
14425 goto do_cp1mips3d;
14426 case BC1ANY4T:
14427 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14428 mips32_op = OPC_BC1TANY4;
14429 do_cp1mips3d:
14430 check_cop1x(ctx);
14431 check_insn(ctx, ASE_MIPS3D);
14432 /* Fall through */
14433 do_cp1branch:
14434 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14435 check_cp1_enabled(ctx);
14436 gen_compute_branch1(ctx, mips32_op,
14437 (ctx->opcode >> 18) & 0x7, imm << 1);
14438 } else {
14439 generate_exception_err(ctx, EXCP_CpU, 1);
14441 break;
14442 case BPOSGE64:
14443 case BPOSGE32:
14444 /* MIPS DSP: not implemented */
14445 /* Fall through */
14446 default:
14447 MIPS_INVAL("pool32i");
14448 generate_exception_end(ctx, EXCP_RI);
14449 break;
14451 break;
14452 case POOL32C:
14453 minor = (ctx->opcode >> 12) & 0xf;
14454 offset = sextract32(ctx->opcode, 0,
14455 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
14456 switch (minor) {
14457 case LWL:
14458 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14459 mips32_op = OPC_LWL;
14460 goto do_ld_lr;
14461 case SWL:
14462 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14463 mips32_op = OPC_SWL;
14464 goto do_st_lr;
14465 case LWR:
14466 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14467 mips32_op = OPC_LWR;
14468 goto do_ld_lr;
14469 case SWR:
14470 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14471 mips32_op = OPC_SWR;
14472 goto do_st_lr;
14473 #if defined(TARGET_MIPS64)
14474 case LDL:
14475 check_insn(ctx, ISA_MIPS3);
14476 check_mips_64(ctx);
14477 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14478 mips32_op = OPC_LDL;
14479 goto do_ld_lr;
14480 case SDL:
14481 check_insn(ctx, ISA_MIPS3);
14482 check_mips_64(ctx);
14483 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14484 mips32_op = OPC_SDL;
14485 goto do_st_lr;
14486 case LDR:
14487 check_insn(ctx, ISA_MIPS3);
14488 check_mips_64(ctx);
14489 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14490 mips32_op = OPC_LDR;
14491 goto do_ld_lr;
14492 case SDR:
14493 check_insn(ctx, ISA_MIPS3);
14494 check_mips_64(ctx);
14495 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14496 mips32_op = OPC_SDR;
14497 goto do_st_lr;
14498 case LWU:
14499 check_insn(ctx, ISA_MIPS3);
14500 check_mips_64(ctx);
14501 mips32_op = OPC_LWU;
14502 goto do_ld_lr;
14503 case LLD:
14504 check_insn(ctx, ISA_MIPS3);
14505 check_mips_64(ctx);
14506 mips32_op = OPC_LLD;
14507 goto do_ld_lr;
14508 #endif
14509 case LL:
14510 mips32_op = OPC_LL;
14511 goto do_ld_lr;
14512 do_ld_lr:
14513 gen_ld(ctx, mips32_op, rt, rs, offset);
14514 break;
14515 do_st_lr:
14516 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
14517 break;
14518 case SC:
14519 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
14520 break;
14521 #if defined(TARGET_MIPS64)
14522 case SCD:
14523 check_insn(ctx, ISA_MIPS3);
14524 check_mips_64(ctx);
14525 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
14526 break;
14527 #endif
14528 case PREF:
14529 /* Treat as no-op */
14530 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
14531 /* hint codes 24-31 are reserved and signal RI */
14532 generate_exception(ctx, EXCP_RI);
14534 break;
14535 default:
14536 MIPS_INVAL("pool32c");
14537 generate_exception_end(ctx, EXCP_RI);
14538 break;
14540 break;
14541 case ADDI32: /* AUI, LUI */
14542 if (ctx->insn_flags & ISA_MIPS32R6) {
14543 /* AUI, LUI */
14544 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
14545 } else {
14546 /* ADDI32 */
14547 mips32_op = OPC_ADDI;
14548 goto do_addi;
14550 break;
14551 case ADDIU32:
14552 mips32_op = OPC_ADDIU;
14553 do_addi:
14554 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
14555 break;
14557 /* Logical operations */
14558 case ORI32:
14559 mips32_op = OPC_ORI;
14560 goto do_logici;
14561 case XORI32:
14562 mips32_op = OPC_XORI;
14563 goto do_logici;
14564 case ANDI32:
14565 mips32_op = OPC_ANDI;
14566 do_logici:
14567 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
14568 break;
14570 /* Set less than immediate */
14571 case SLTI32:
14572 mips32_op = OPC_SLTI;
14573 goto do_slti;
14574 case SLTIU32:
14575 mips32_op = OPC_SLTIU;
14576 do_slti:
14577 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
14578 break;
14579 case JALX32:
14580 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14581 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14582 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
14583 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14584 break;
14585 case JALS32: /* BOVC, BEQC, BEQZALC */
14586 if (ctx->insn_flags & ISA_MIPS32R6) {
14587 if (rs >= rt) {
14588 /* BOVC */
14589 mips32_op = OPC_BOVC;
14590 } else if (rs < rt && rs == 0) {
14591 /* BEQZALC */
14592 mips32_op = OPC_BEQZALC;
14593 } else {
14594 /* BEQC */
14595 mips32_op = OPC_BEQC;
14597 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14598 } else {
14599 /* JALS32 */
14600 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
14601 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
14602 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14604 break;
14605 case BEQ32: /* BC */
14606 if (ctx->insn_flags & ISA_MIPS32R6) {
14607 /* BC */
14608 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
14609 sextract32(ctx->opcode << 1, 0, 27));
14610 } else {
14611 /* BEQ32 */
14612 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
14614 break;
14615 case BNE32: /* BALC */
14616 if (ctx->insn_flags & ISA_MIPS32R6) {
14617 /* BALC */
14618 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
14619 sextract32(ctx->opcode << 1, 0, 27));
14620 } else {
14621 /* BNE32 */
14622 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
14624 break;
14625 case J32: /* BGTZC, BLTZC, BLTC */
14626 if (ctx->insn_flags & ISA_MIPS32R6) {
14627 if (rs == 0 && rt != 0) {
14628 /* BGTZC */
14629 mips32_op = OPC_BGTZC;
14630 } else if (rs != 0 && rt != 0 && rs == rt) {
14631 /* BLTZC */
14632 mips32_op = OPC_BLTZC;
14633 } else {
14634 /* BLTC */
14635 mips32_op = OPC_BLTC;
14637 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14638 } else {
14639 /* J32 */
14640 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
14641 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14643 break;
14644 case JAL32: /* BLEZC, BGEZC, BGEC */
14645 if (ctx->insn_flags & ISA_MIPS32R6) {
14646 if (rs == 0 && rt != 0) {
14647 /* BLEZC */
14648 mips32_op = OPC_BLEZC;
14649 } else if (rs != 0 && rt != 0 && rs == rt) {
14650 /* BGEZC */
14651 mips32_op = OPC_BGEZC;
14652 } else {
14653 /* BGEC */
14654 mips32_op = OPC_BGEC;
14656 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14657 } else {
14658 /* JAL32 */
14659 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
14660 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14661 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14663 break;
14664 /* Floating point (COP1) */
14665 case LWC132:
14666 mips32_op = OPC_LWC1;
14667 goto do_cop1;
14668 case LDC132:
14669 mips32_op = OPC_LDC1;
14670 goto do_cop1;
14671 case SWC132:
14672 mips32_op = OPC_SWC1;
14673 goto do_cop1;
14674 case SDC132:
14675 mips32_op = OPC_SDC1;
14676 do_cop1:
14677 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
14678 break;
14679 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14680 if (ctx->insn_flags & ISA_MIPS32R6) {
14681 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14682 switch ((ctx->opcode >> 16) & 0x1f) {
14683 case ADDIUPC_00 ... ADDIUPC_07:
14684 gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
14685 break;
14686 case AUIPC:
14687 gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
14688 break;
14689 case ALUIPC:
14690 gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
14691 break;
14692 case LWPC_08 ... LWPC_0F:
14693 gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
14694 break;
14695 default:
14696 generate_exception(ctx, EXCP_RI);
14697 break;
14699 } else {
14700 /* ADDIUPC */
14701 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
14702 int offset = SIMM(ctx->opcode, 0, 23) << 2;
14704 gen_addiupc(ctx, reg, offset, 0, 0);
14706 break;
14707 case BNVC: /* BNEC, BNEZALC */
14708 check_insn(ctx, ISA_MIPS32R6);
14709 if (rs >= rt) {
14710 /* BNVC */
14711 mips32_op = OPC_BNVC;
14712 } else if (rs < rt && rs == 0) {
14713 /* BNEZALC */
14714 mips32_op = OPC_BNEZALC;
14715 } else {
14716 /* BNEC */
14717 mips32_op = OPC_BNEC;
14719 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14720 break;
14721 case R6_BNEZC: /* JIALC */
14722 check_insn(ctx, ISA_MIPS32R6);
14723 if (rt != 0) {
14724 /* BNEZC */
14725 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
14726 sextract32(ctx->opcode << 1, 0, 22));
14727 } else {
14728 /* JIALC */
14729 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
14731 break;
14732 case R6_BEQZC: /* JIC */
14733 check_insn(ctx, ISA_MIPS32R6);
14734 if (rt != 0) {
14735 /* BEQZC */
14736 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
14737 sextract32(ctx->opcode << 1, 0, 22));
14738 } else {
14739 /* JIC */
14740 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
14742 break;
14743 case BLEZALC: /* BGEZALC, BGEUC */
14744 check_insn(ctx, ISA_MIPS32R6);
14745 if (rs == 0 && rt != 0) {
14746 /* BLEZALC */
14747 mips32_op = OPC_BLEZALC;
14748 } else if (rs != 0 && rt != 0 && rs == rt) {
14749 /* BGEZALC */
14750 mips32_op = OPC_BGEZALC;
14751 } else {
14752 /* BGEUC */
14753 mips32_op = OPC_BGEUC;
14755 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14756 break;
14757 case BGTZALC: /* BLTZALC, BLTUC */
14758 check_insn(ctx, ISA_MIPS32R6);
14759 if (rs == 0 && rt != 0) {
14760 /* BGTZALC */
14761 mips32_op = OPC_BGTZALC;
14762 } else if (rs != 0 && rt != 0 && rs == rt) {
14763 /* BLTZALC */
14764 mips32_op = OPC_BLTZALC;
14765 } else {
14766 /* BLTUC */
14767 mips32_op = OPC_BLTUC;
14769 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14770 break;
14771 /* Loads and stores */
14772 case LB32:
14773 mips32_op = OPC_LB;
14774 goto do_ld;
14775 case LBU32:
14776 mips32_op = OPC_LBU;
14777 goto do_ld;
14778 case LH32:
14779 mips32_op = OPC_LH;
14780 goto do_ld;
14781 case LHU32:
14782 mips32_op = OPC_LHU;
14783 goto do_ld;
14784 case LW32:
14785 mips32_op = OPC_LW;
14786 goto do_ld;
14787 #ifdef TARGET_MIPS64
14788 case LD32:
14789 check_insn(ctx, ISA_MIPS3);
14790 check_mips_64(ctx);
14791 mips32_op = OPC_LD;
14792 goto do_ld;
14793 case SD32:
14794 check_insn(ctx, ISA_MIPS3);
14795 check_mips_64(ctx);
14796 mips32_op = OPC_SD;
14797 goto do_st;
14798 #endif
14799 case SB32:
14800 mips32_op = OPC_SB;
14801 goto do_st;
14802 case SH32:
14803 mips32_op = OPC_SH;
14804 goto do_st;
14805 case SW32:
14806 mips32_op = OPC_SW;
14807 goto do_st;
14808 do_ld:
14809 gen_ld(ctx, mips32_op, rt, rs, imm);
14810 break;
14811 do_st:
14812 gen_st(ctx, mips32_op, rt, rs, imm);
14813 break;
14814 default:
14815 generate_exception_end(ctx, EXCP_RI);
14816 break;
14820 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
14822 uint32_t op;
14824 /* make sure instructions are on a halfword boundary */
14825 if (ctx->pc & 0x1) {
14826 env->CP0_BadVAddr = ctx->pc;
14827 generate_exception_end(ctx, EXCP_AdEL);
14828 return 2;
14831 op = (ctx->opcode >> 10) & 0x3f;
14832 /* Enforce properly-sized instructions in a delay slot */
14833 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
14834 switch (op & 0x7) { /* MSB-3..MSB-5 */
14835 case 0:
14836 /* POOL32A, POOL32B, POOL32I, POOL32C */
14837 case 4:
14838 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
14839 case 5:
14840 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
14841 case 6:
14842 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
14843 case 7:
14844 /* LB32, LH32, LWC132, LDC132, LW32 */
14845 if (ctx->hflags & MIPS_HFLAG_BDS16) {
14846 generate_exception_end(ctx, EXCP_RI);
14847 return 2;
14849 break;
14850 case 1:
14851 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
14852 case 2:
14853 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
14854 case 3:
14855 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
14856 if (ctx->hflags & MIPS_HFLAG_BDS32) {
14857 generate_exception_end(ctx, EXCP_RI);
14858 return 2;
14860 break;
14864 switch (op) {
14865 case POOL16A:
14867 int rd = mmreg(uMIPS_RD(ctx->opcode));
14868 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
14869 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
14870 uint32_t opc = 0;
14872 switch (ctx->opcode & 0x1) {
14873 case ADDU16:
14874 opc = OPC_ADDU;
14875 break;
14876 case SUBU16:
14877 opc = OPC_SUBU;
14878 break;
14880 if (ctx->insn_flags & ISA_MIPS32R6) {
14881 /* In the Release 6 the register number location in
14882 * the instruction encoding has changed.
14884 gen_arith(ctx, opc, rs1, rd, rs2);
14885 } else {
14886 gen_arith(ctx, opc, rd, rs1, rs2);
14889 break;
14890 case POOL16B:
14892 int rd = mmreg(uMIPS_RD(ctx->opcode));
14893 int rs = mmreg(uMIPS_RS(ctx->opcode));
14894 int amount = (ctx->opcode >> 1) & 0x7;
14895 uint32_t opc = 0;
14896 amount = amount == 0 ? 8 : amount;
14898 switch (ctx->opcode & 0x1) {
14899 case SLL16:
14900 opc = OPC_SLL;
14901 break;
14902 case SRL16:
14903 opc = OPC_SRL;
14904 break;
14907 gen_shift_imm(ctx, opc, rd, rs, amount);
14909 break;
14910 case POOL16C:
14911 if (ctx->insn_flags & ISA_MIPS32R6) {
14912 gen_pool16c_r6_insn(ctx);
14913 } else {
14914 gen_pool16c_insn(ctx);
14916 break;
14917 case LWGP16:
14919 int rd = mmreg(uMIPS_RD(ctx->opcode));
14920 int rb = 28; /* GP */
14921 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
14923 gen_ld(ctx, OPC_LW, rd, rb, offset);
14925 break;
14926 case POOL16F:
14927 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14928 if (ctx->opcode & 1) {
14929 generate_exception_end(ctx, EXCP_RI);
14930 } else {
14931 /* MOVEP */
14932 int enc_dest = uMIPS_RD(ctx->opcode);
14933 int enc_rt = uMIPS_RS2(ctx->opcode);
14934 int enc_rs = uMIPS_RS1(ctx->opcode);
14935 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14937 break;
14938 case LBU16:
14940 int rd = mmreg(uMIPS_RD(ctx->opcode));
14941 int rb = mmreg(uMIPS_RS(ctx->opcode));
14942 int16_t offset = ZIMM(ctx->opcode, 0, 4);
14943 offset = (offset == 0xf ? -1 : offset);
14945 gen_ld(ctx, OPC_LBU, rd, rb, offset);
14947 break;
14948 case LHU16:
14950 int rd = mmreg(uMIPS_RD(ctx->opcode));
14951 int rb = mmreg(uMIPS_RS(ctx->opcode));
14952 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
14954 gen_ld(ctx, OPC_LHU, rd, rb, offset);
14956 break;
14957 case LWSP16:
14959 int rd = (ctx->opcode >> 5) & 0x1f;
14960 int rb = 29; /* SP */
14961 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
14963 gen_ld(ctx, OPC_LW, rd, rb, offset);
14965 break;
14966 case LW16:
14968 int rd = mmreg(uMIPS_RD(ctx->opcode));
14969 int rb = mmreg(uMIPS_RS(ctx->opcode));
14970 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
14972 gen_ld(ctx, OPC_LW, rd, rb, offset);
14974 break;
14975 case SB16:
14977 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14978 int rb = mmreg(uMIPS_RS(ctx->opcode));
14979 int16_t offset = ZIMM(ctx->opcode, 0, 4);
14981 gen_st(ctx, OPC_SB, rd, rb, offset);
14983 break;
14984 case SH16:
14986 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14987 int rb = mmreg(uMIPS_RS(ctx->opcode));
14988 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
14990 gen_st(ctx, OPC_SH, rd, rb, offset);
14992 break;
14993 case SWSP16:
14995 int rd = (ctx->opcode >> 5) & 0x1f;
14996 int rb = 29; /* SP */
14997 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
14999 gen_st(ctx, OPC_SW, rd, rb, offset);
15001 break;
15002 case SW16:
15004 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15005 int rb = mmreg(uMIPS_RS(ctx->opcode));
15006 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15008 gen_st(ctx, OPC_SW, rd, rb, offset);
15010 break;
15011 case MOVE16:
15013 int rd = uMIPS_RD5(ctx->opcode);
15014 int rs = uMIPS_RS5(ctx->opcode);
15016 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
15018 break;
15019 case ANDI16:
15020 gen_andi16(ctx);
15021 break;
15022 case POOL16D:
15023 switch (ctx->opcode & 0x1) {
15024 case ADDIUS5:
15025 gen_addius5(ctx);
15026 break;
15027 case ADDIUSP:
15028 gen_addiusp(ctx);
15029 break;
15031 break;
15032 case POOL16E:
15033 switch (ctx->opcode & 0x1) {
15034 case ADDIUR2:
15035 gen_addiur2(ctx);
15036 break;
15037 case ADDIUR1SP:
15038 gen_addiur1sp(ctx);
15039 break;
15041 break;
15042 case B16: /* BC16 */
15043 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
15044 sextract32(ctx->opcode, 0, 10) << 1,
15045 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15046 break;
15047 case BNEZ16: /* BNEZC16 */
15048 case BEQZ16: /* BEQZC16 */
15049 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
15050 mmreg(uMIPS_RD(ctx->opcode)),
15051 0, sextract32(ctx->opcode, 0, 7) << 1,
15052 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15054 break;
15055 case LI16:
15057 int reg = mmreg(uMIPS_RD(ctx->opcode));
15058 int imm = ZIMM(ctx->opcode, 0, 7);
15060 imm = (imm == 0x7f ? -1 : imm);
15061 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15063 break;
15064 case RES_29:
15065 case RES_31:
15066 case RES_39:
15067 generate_exception_end(ctx, EXCP_RI);
15068 break;
15069 default:
15070 decode_micromips32_opc(env, ctx);
15071 return 4;
15074 return 2;
15077 /* SmartMIPS extension to MIPS32 */
15079 #if defined(TARGET_MIPS64)
15081 /* MDMX extension to MIPS64 */
15083 #endif
15085 /* MIPSDSP functions. */
15086 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
15087 int rd, int base, int offset)
15089 TCGv t0;
15091 check_dsp(ctx);
15092 t0 = tcg_temp_new();
15094 if (base == 0) {
15095 gen_load_gpr(t0, offset);
15096 } else if (offset == 0) {
15097 gen_load_gpr(t0, base);
15098 } else {
15099 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
15102 switch (opc) {
15103 case OPC_LBUX:
15104 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
15105 gen_store_gpr(t0, rd);
15106 break;
15107 case OPC_LHX:
15108 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
15109 gen_store_gpr(t0, rd);
15110 break;
15111 case OPC_LWX:
15112 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
15113 gen_store_gpr(t0, rd);
15114 break;
15115 #if defined(TARGET_MIPS64)
15116 case OPC_LDX:
15117 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
15118 gen_store_gpr(t0, rd);
15119 break;
15120 #endif
15122 tcg_temp_free(t0);
15125 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
15126 int ret, int v1, int v2)
15128 TCGv v1_t;
15129 TCGv v2_t;
15131 if (ret == 0) {
15132 /* Treat as NOP. */
15133 return;
15136 v1_t = tcg_temp_new();
15137 v2_t = tcg_temp_new();
15139 gen_load_gpr(v1_t, v1);
15140 gen_load_gpr(v2_t, v2);
15142 switch (op1) {
15143 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
15144 case OPC_MULT_G_2E:
15145 check_dspr2(ctx);
15146 switch (op2) {
15147 case OPC_ADDUH_QB:
15148 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
15149 break;
15150 case OPC_ADDUH_R_QB:
15151 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15152 break;
15153 case OPC_ADDQH_PH:
15154 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
15155 break;
15156 case OPC_ADDQH_R_PH:
15157 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15158 break;
15159 case OPC_ADDQH_W:
15160 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
15161 break;
15162 case OPC_ADDQH_R_W:
15163 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15164 break;
15165 case OPC_SUBUH_QB:
15166 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
15167 break;
15168 case OPC_SUBUH_R_QB:
15169 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15170 break;
15171 case OPC_SUBQH_PH:
15172 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
15173 break;
15174 case OPC_SUBQH_R_PH:
15175 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15176 break;
15177 case OPC_SUBQH_W:
15178 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
15179 break;
15180 case OPC_SUBQH_R_W:
15181 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15182 break;
15184 break;
15185 case OPC_ABSQ_S_PH_DSP:
15186 switch (op2) {
15187 case OPC_ABSQ_S_QB:
15188 check_dspr2(ctx);
15189 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
15190 break;
15191 case OPC_ABSQ_S_PH:
15192 check_dsp(ctx);
15193 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
15194 break;
15195 case OPC_ABSQ_S_W:
15196 check_dsp(ctx);
15197 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
15198 break;
15199 case OPC_PRECEQ_W_PHL:
15200 check_dsp(ctx);
15201 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
15202 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15203 break;
15204 case OPC_PRECEQ_W_PHR:
15205 check_dsp(ctx);
15206 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
15207 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
15208 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15209 break;
15210 case OPC_PRECEQU_PH_QBL:
15211 check_dsp(ctx);
15212 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
15213 break;
15214 case OPC_PRECEQU_PH_QBR:
15215 check_dsp(ctx);
15216 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
15217 break;
15218 case OPC_PRECEQU_PH_QBLA:
15219 check_dsp(ctx);
15220 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
15221 break;
15222 case OPC_PRECEQU_PH_QBRA:
15223 check_dsp(ctx);
15224 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
15225 break;
15226 case OPC_PRECEU_PH_QBL:
15227 check_dsp(ctx);
15228 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
15229 break;
15230 case OPC_PRECEU_PH_QBR:
15231 check_dsp(ctx);
15232 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
15233 break;
15234 case OPC_PRECEU_PH_QBLA:
15235 check_dsp(ctx);
15236 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
15237 break;
15238 case OPC_PRECEU_PH_QBRA:
15239 check_dsp(ctx);
15240 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
15241 break;
15243 break;
15244 case OPC_ADDU_QB_DSP:
15245 switch (op2) {
15246 case OPC_ADDQ_PH:
15247 check_dsp(ctx);
15248 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15249 break;
15250 case OPC_ADDQ_S_PH:
15251 check_dsp(ctx);
15252 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15253 break;
15254 case OPC_ADDQ_S_W:
15255 check_dsp(ctx);
15256 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15257 break;
15258 case OPC_ADDU_QB:
15259 check_dsp(ctx);
15260 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15261 break;
15262 case OPC_ADDU_S_QB:
15263 check_dsp(ctx);
15264 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15265 break;
15266 case OPC_ADDU_PH:
15267 check_dspr2(ctx);
15268 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15269 break;
15270 case OPC_ADDU_S_PH:
15271 check_dspr2(ctx);
15272 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15273 break;
15274 case OPC_SUBQ_PH:
15275 check_dsp(ctx);
15276 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15277 break;
15278 case OPC_SUBQ_S_PH:
15279 check_dsp(ctx);
15280 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15281 break;
15282 case OPC_SUBQ_S_W:
15283 check_dsp(ctx);
15284 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15285 break;
15286 case OPC_SUBU_QB:
15287 check_dsp(ctx);
15288 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15289 break;
15290 case OPC_SUBU_S_QB:
15291 check_dsp(ctx);
15292 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15293 break;
15294 case OPC_SUBU_PH:
15295 check_dspr2(ctx);
15296 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15297 break;
15298 case OPC_SUBU_S_PH:
15299 check_dspr2(ctx);
15300 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15301 break;
15302 case OPC_ADDSC:
15303 check_dsp(ctx);
15304 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15305 break;
15306 case OPC_ADDWC:
15307 check_dsp(ctx);
15308 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15309 break;
15310 case OPC_MODSUB:
15311 check_dsp(ctx);
15312 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
15313 break;
15314 case OPC_RADDU_W_QB:
15315 check_dsp(ctx);
15316 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
15317 break;
15319 break;
15320 case OPC_CMPU_EQ_QB_DSP:
15321 switch (op2) {
15322 case OPC_PRECR_QB_PH:
15323 check_dspr2(ctx);
15324 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15325 break;
15326 case OPC_PRECRQ_QB_PH:
15327 check_dsp(ctx);
15328 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15329 break;
15330 case OPC_PRECR_SRA_PH_W:
15331 check_dspr2(ctx);
15333 TCGv_i32 sa_t = tcg_const_i32(v2);
15334 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
15335 cpu_gpr[ret]);
15336 tcg_temp_free_i32(sa_t);
15337 break;
15339 case OPC_PRECR_SRA_R_PH_W:
15340 check_dspr2(ctx);
15342 TCGv_i32 sa_t = tcg_const_i32(v2);
15343 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
15344 cpu_gpr[ret]);
15345 tcg_temp_free_i32(sa_t);
15346 break;
15348 case OPC_PRECRQ_PH_W:
15349 check_dsp(ctx);
15350 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
15351 break;
15352 case OPC_PRECRQ_RS_PH_W:
15353 check_dsp(ctx);
15354 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15355 break;
15356 case OPC_PRECRQU_S_QB_PH:
15357 check_dsp(ctx);
15358 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15359 break;
15361 break;
15362 #ifdef TARGET_MIPS64
15363 case OPC_ABSQ_S_QH_DSP:
15364 switch (op2) {
15365 case OPC_PRECEQ_L_PWL:
15366 check_dsp(ctx);
15367 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
15368 break;
15369 case OPC_PRECEQ_L_PWR:
15370 check_dsp(ctx);
15371 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
15372 break;
15373 case OPC_PRECEQ_PW_QHL:
15374 check_dsp(ctx);
15375 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
15376 break;
15377 case OPC_PRECEQ_PW_QHR:
15378 check_dsp(ctx);
15379 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
15380 break;
15381 case OPC_PRECEQ_PW_QHLA:
15382 check_dsp(ctx);
15383 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
15384 break;
15385 case OPC_PRECEQ_PW_QHRA:
15386 check_dsp(ctx);
15387 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
15388 break;
15389 case OPC_PRECEQU_QH_OBL:
15390 check_dsp(ctx);
15391 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
15392 break;
15393 case OPC_PRECEQU_QH_OBR:
15394 check_dsp(ctx);
15395 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
15396 break;
15397 case OPC_PRECEQU_QH_OBLA:
15398 check_dsp(ctx);
15399 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
15400 break;
15401 case OPC_PRECEQU_QH_OBRA:
15402 check_dsp(ctx);
15403 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
15404 break;
15405 case OPC_PRECEU_QH_OBL:
15406 check_dsp(ctx);
15407 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
15408 break;
15409 case OPC_PRECEU_QH_OBR:
15410 check_dsp(ctx);
15411 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
15412 break;
15413 case OPC_PRECEU_QH_OBLA:
15414 check_dsp(ctx);
15415 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
15416 break;
15417 case OPC_PRECEU_QH_OBRA:
15418 check_dsp(ctx);
15419 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
15420 break;
15421 case OPC_ABSQ_S_OB:
15422 check_dspr2(ctx);
15423 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
15424 break;
15425 case OPC_ABSQ_S_PW:
15426 check_dsp(ctx);
15427 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
15428 break;
15429 case OPC_ABSQ_S_QH:
15430 check_dsp(ctx);
15431 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
15432 break;
15434 break;
15435 case OPC_ADDU_OB_DSP:
15436 switch (op2) {
15437 case OPC_RADDU_L_OB:
15438 check_dsp(ctx);
15439 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
15440 break;
15441 case OPC_SUBQ_PW:
15442 check_dsp(ctx);
15443 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15444 break;
15445 case OPC_SUBQ_S_PW:
15446 check_dsp(ctx);
15447 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15448 break;
15449 case OPC_SUBQ_QH:
15450 check_dsp(ctx);
15451 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15452 break;
15453 case OPC_SUBQ_S_QH:
15454 check_dsp(ctx);
15455 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15456 break;
15457 case OPC_SUBU_OB:
15458 check_dsp(ctx);
15459 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15460 break;
15461 case OPC_SUBU_S_OB:
15462 check_dsp(ctx);
15463 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15464 break;
15465 case OPC_SUBU_QH:
15466 check_dspr2(ctx);
15467 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15468 break;
15469 case OPC_SUBU_S_QH:
15470 check_dspr2(ctx);
15471 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15472 break;
15473 case OPC_SUBUH_OB:
15474 check_dspr2(ctx);
15475 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
15476 break;
15477 case OPC_SUBUH_R_OB:
15478 check_dspr2(ctx);
15479 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15480 break;
15481 case OPC_ADDQ_PW:
15482 check_dsp(ctx);
15483 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15484 break;
15485 case OPC_ADDQ_S_PW:
15486 check_dsp(ctx);
15487 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15488 break;
15489 case OPC_ADDQ_QH:
15490 check_dsp(ctx);
15491 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15492 break;
15493 case OPC_ADDQ_S_QH:
15494 check_dsp(ctx);
15495 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15496 break;
15497 case OPC_ADDU_OB:
15498 check_dsp(ctx);
15499 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15500 break;
15501 case OPC_ADDU_S_OB:
15502 check_dsp(ctx);
15503 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15504 break;
15505 case OPC_ADDU_QH:
15506 check_dspr2(ctx);
15507 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15508 break;
15509 case OPC_ADDU_S_QH:
15510 check_dspr2(ctx);
15511 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15512 break;
15513 case OPC_ADDUH_OB:
15514 check_dspr2(ctx);
15515 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
15516 break;
15517 case OPC_ADDUH_R_OB:
15518 check_dspr2(ctx);
15519 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15520 break;
15522 break;
15523 case OPC_CMPU_EQ_OB_DSP:
15524 switch (op2) {
15525 case OPC_PRECR_OB_QH:
15526 check_dspr2(ctx);
15527 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15528 break;
15529 case OPC_PRECR_SRA_QH_PW:
15530 check_dspr2(ctx);
15532 TCGv_i32 ret_t = tcg_const_i32(ret);
15533 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
15534 tcg_temp_free_i32(ret_t);
15535 break;
15537 case OPC_PRECR_SRA_R_QH_PW:
15538 check_dspr2(ctx);
15540 TCGv_i32 sa_v = tcg_const_i32(ret);
15541 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
15542 tcg_temp_free_i32(sa_v);
15543 break;
15545 case OPC_PRECRQ_OB_QH:
15546 check_dsp(ctx);
15547 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15548 break;
15549 case OPC_PRECRQ_PW_L:
15550 check_dsp(ctx);
15551 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
15552 break;
15553 case OPC_PRECRQ_QH_PW:
15554 check_dsp(ctx);
15555 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
15556 break;
15557 case OPC_PRECRQ_RS_QH_PW:
15558 check_dsp(ctx);
15559 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15560 break;
15561 case OPC_PRECRQU_S_OB_QH:
15562 check_dsp(ctx);
15563 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15564 break;
15566 break;
15567 #endif
15570 tcg_temp_free(v1_t);
15571 tcg_temp_free(v2_t);
15574 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
15575 int ret, int v1, int v2)
15577 uint32_t op2;
15578 TCGv t0;
15579 TCGv v1_t;
15580 TCGv v2_t;
15582 if (ret == 0) {
15583 /* Treat as NOP. */
15584 return;
15587 t0 = tcg_temp_new();
15588 v1_t = tcg_temp_new();
15589 v2_t = tcg_temp_new();
15591 tcg_gen_movi_tl(t0, v1);
15592 gen_load_gpr(v1_t, v1);
15593 gen_load_gpr(v2_t, v2);
15595 switch (opc) {
15596 case OPC_SHLL_QB_DSP:
15598 op2 = MASK_SHLL_QB(ctx->opcode);
15599 switch (op2) {
15600 case OPC_SHLL_QB:
15601 check_dsp(ctx);
15602 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
15603 break;
15604 case OPC_SHLLV_QB:
15605 check_dsp(ctx);
15606 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15607 break;
15608 case OPC_SHLL_PH:
15609 check_dsp(ctx);
15610 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15611 break;
15612 case OPC_SHLLV_PH:
15613 check_dsp(ctx);
15614 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15615 break;
15616 case OPC_SHLL_S_PH:
15617 check_dsp(ctx);
15618 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15619 break;
15620 case OPC_SHLLV_S_PH:
15621 check_dsp(ctx);
15622 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15623 break;
15624 case OPC_SHLL_S_W:
15625 check_dsp(ctx);
15626 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
15627 break;
15628 case OPC_SHLLV_S_W:
15629 check_dsp(ctx);
15630 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15631 break;
15632 case OPC_SHRL_QB:
15633 check_dsp(ctx);
15634 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
15635 break;
15636 case OPC_SHRLV_QB:
15637 check_dsp(ctx);
15638 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
15639 break;
15640 case OPC_SHRL_PH:
15641 check_dspr2(ctx);
15642 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
15643 break;
15644 case OPC_SHRLV_PH:
15645 check_dspr2(ctx);
15646 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
15647 break;
15648 case OPC_SHRA_QB:
15649 check_dspr2(ctx);
15650 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
15651 break;
15652 case OPC_SHRA_R_QB:
15653 check_dspr2(ctx);
15654 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
15655 break;
15656 case OPC_SHRAV_QB:
15657 check_dspr2(ctx);
15658 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
15659 break;
15660 case OPC_SHRAV_R_QB:
15661 check_dspr2(ctx);
15662 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
15663 break;
15664 case OPC_SHRA_PH:
15665 check_dsp(ctx);
15666 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
15667 break;
15668 case OPC_SHRA_R_PH:
15669 check_dsp(ctx);
15670 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
15671 break;
15672 case OPC_SHRAV_PH:
15673 check_dsp(ctx);
15674 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
15675 break;
15676 case OPC_SHRAV_R_PH:
15677 check_dsp(ctx);
15678 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
15679 break;
15680 case OPC_SHRA_R_W:
15681 check_dsp(ctx);
15682 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
15683 break;
15684 case OPC_SHRAV_R_W:
15685 check_dsp(ctx);
15686 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
15687 break;
15688 default: /* Invalid */
15689 MIPS_INVAL("MASK SHLL.QB");
15690 generate_exception_end(ctx, EXCP_RI);
15691 break;
15693 break;
15695 #ifdef TARGET_MIPS64
15696 case OPC_SHLL_OB_DSP:
15697 op2 = MASK_SHLL_OB(ctx->opcode);
15698 switch (op2) {
15699 case OPC_SHLL_PW:
15700 check_dsp(ctx);
15701 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15702 break;
15703 case OPC_SHLLV_PW:
15704 check_dsp(ctx);
15705 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15706 break;
15707 case OPC_SHLL_S_PW:
15708 check_dsp(ctx);
15709 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15710 break;
15711 case OPC_SHLLV_S_PW:
15712 check_dsp(ctx);
15713 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15714 break;
15715 case OPC_SHLL_OB:
15716 check_dsp(ctx);
15717 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
15718 break;
15719 case OPC_SHLLV_OB:
15720 check_dsp(ctx);
15721 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15722 break;
15723 case OPC_SHLL_QH:
15724 check_dsp(ctx);
15725 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15726 break;
15727 case OPC_SHLLV_QH:
15728 check_dsp(ctx);
15729 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15730 break;
15731 case OPC_SHLL_S_QH:
15732 check_dsp(ctx);
15733 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15734 break;
15735 case OPC_SHLLV_S_QH:
15736 check_dsp(ctx);
15737 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15738 break;
15739 case OPC_SHRA_OB:
15740 check_dspr2(ctx);
15741 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
15742 break;
15743 case OPC_SHRAV_OB:
15744 check_dspr2(ctx);
15745 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
15746 break;
15747 case OPC_SHRA_R_OB:
15748 check_dspr2(ctx);
15749 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
15750 break;
15751 case OPC_SHRAV_R_OB:
15752 check_dspr2(ctx);
15753 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
15754 break;
15755 case OPC_SHRA_PW:
15756 check_dsp(ctx);
15757 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
15758 break;
15759 case OPC_SHRAV_PW:
15760 check_dsp(ctx);
15761 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
15762 break;
15763 case OPC_SHRA_R_PW:
15764 check_dsp(ctx);
15765 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
15766 break;
15767 case OPC_SHRAV_R_PW:
15768 check_dsp(ctx);
15769 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
15770 break;
15771 case OPC_SHRA_QH:
15772 check_dsp(ctx);
15773 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
15774 break;
15775 case OPC_SHRAV_QH:
15776 check_dsp(ctx);
15777 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
15778 break;
15779 case OPC_SHRA_R_QH:
15780 check_dsp(ctx);
15781 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
15782 break;
15783 case OPC_SHRAV_R_QH:
15784 check_dsp(ctx);
15785 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
15786 break;
15787 case OPC_SHRL_OB:
15788 check_dsp(ctx);
15789 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
15790 break;
15791 case OPC_SHRLV_OB:
15792 check_dsp(ctx);
15793 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
15794 break;
15795 case OPC_SHRL_QH:
15796 check_dspr2(ctx);
15797 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
15798 break;
15799 case OPC_SHRLV_QH:
15800 check_dspr2(ctx);
15801 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
15802 break;
15803 default: /* Invalid */
15804 MIPS_INVAL("MASK SHLL.OB");
15805 generate_exception_end(ctx, EXCP_RI);
15806 break;
15808 break;
15809 #endif
15812 tcg_temp_free(t0);
15813 tcg_temp_free(v1_t);
15814 tcg_temp_free(v2_t);
15817 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
15818 int ret, int v1, int v2, int check_ret)
15820 TCGv_i32 t0;
15821 TCGv v1_t;
15822 TCGv v2_t;
15824 if ((ret == 0) && (check_ret == 1)) {
15825 /* Treat as NOP. */
15826 return;
15829 t0 = tcg_temp_new_i32();
15830 v1_t = tcg_temp_new();
15831 v2_t = tcg_temp_new();
15833 tcg_gen_movi_i32(t0, ret);
15834 gen_load_gpr(v1_t, v1);
15835 gen_load_gpr(v2_t, v2);
15837 switch (op1) {
15838 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
15839 * the same mask and op1. */
15840 case OPC_MULT_G_2E:
15841 check_dspr2(ctx);
15842 switch (op2) {
15843 case OPC_MUL_PH:
15844 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15845 break;
15846 case OPC_MUL_S_PH:
15847 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15848 break;
15849 case OPC_MULQ_S_W:
15850 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15851 break;
15852 case OPC_MULQ_RS_W:
15853 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15854 break;
15856 break;
15857 case OPC_DPA_W_PH_DSP:
15858 switch (op2) {
15859 case OPC_DPAU_H_QBL:
15860 check_dsp(ctx);
15861 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
15862 break;
15863 case OPC_DPAU_H_QBR:
15864 check_dsp(ctx);
15865 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
15866 break;
15867 case OPC_DPSU_H_QBL:
15868 check_dsp(ctx);
15869 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
15870 break;
15871 case OPC_DPSU_H_QBR:
15872 check_dsp(ctx);
15873 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
15874 break;
15875 case OPC_DPA_W_PH:
15876 check_dspr2(ctx);
15877 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
15878 break;
15879 case OPC_DPAX_W_PH:
15880 check_dspr2(ctx);
15881 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
15882 break;
15883 case OPC_DPAQ_S_W_PH:
15884 check_dsp(ctx);
15885 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15886 break;
15887 case OPC_DPAQX_S_W_PH:
15888 check_dspr2(ctx);
15889 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
15890 break;
15891 case OPC_DPAQX_SA_W_PH:
15892 check_dspr2(ctx);
15893 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
15894 break;
15895 case OPC_DPS_W_PH:
15896 check_dspr2(ctx);
15897 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
15898 break;
15899 case OPC_DPSX_W_PH:
15900 check_dspr2(ctx);
15901 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
15902 break;
15903 case OPC_DPSQ_S_W_PH:
15904 check_dsp(ctx);
15905 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15906 break;
15907 case OPC_DPSQX_S_W_PH:
15908 check_dspr2(ctx);
15909 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
15910 break;
15911 case OPC_DPSQX_SA_W_PH:
15912 check_dspr2(ctx);
15913 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
15914 break;
15915 case OPC_MULSAQ_S_W_PH:
15916 check_dsp(ctx);
15917 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15918 break;
15919 case OPC_DPAQ_SA_L_W:
15920 check_dsp(ctx);
15921 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
15922 break;
15923 case OPC_DPSQ_SA_L_W:
15924 check_dsp(ctx);
15925 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
15926 break;
15927 case OPC_MAQ_S_W_PHL:
15928 check_dsp(ctx);
15929 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
15930 break;
15931 case OPC_MAQ_S_W_PHR:
15932 check_dsp(ctx);
15933 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
15934 break;
15935 case OPC_MAQ_SA_W_PHL:
15936 check_dsp(ctx);
15937 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
15938 break;
15939 case OPC_MAQ_SA_W_PHR:
15940 check_dsp(ctx);
15941 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
15942 break;
15943 case OPC_MULSA_W_PH:
15944 check_dspr2(ctx);
15945 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
15946 break;
15948 break;
15949 #ifdef TARGET_MIPS64
15950 case OPC_DPAQ_W_QH_DSP:
15952 int ac = ret & 0x03;
15953 tcg_gen_movi_i32(t0, ac);
15955 switch (op2) {
15956 case OPC_DMADD:
15957 check_dsp(ctx);
15958 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
15959 break;
15960 case OPC_DMADDU:
15961 check_dsp(ctx);
15962 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
15963 break;
15964 case OPC_DMSUB:
15965 check_dsp(ctx);
15966 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
15967 break;
15968 case OPC_DMSUBU:
15969 check_dsp(ctx);
15970 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
15971 break;
15972 case OPC_DPA_W_QH:
15973 check_dspr2(ctx);
15974 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
15975 break;
15976 case OPC_DPAQ_S_W_QH:
15977 check_dsp(ctx);
15978 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15979 break;
15980 case OPC_DPAQ_SA_L_PW:
15981 check_dsp(ctx);
15982 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
15983 break;
15984 case OPC_DPAU_H_OBL:
15985 check_dsp(ctx);
15986 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
15987 break;
15988 case OPC_DPAU_H_OBR:
15989 check_dsp(ctx);
15990 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
15991 break;
15992 case OPC_DPS_W_QH:
15993 check_dspr2(ctx);
15994 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
15995 break;
15996 case OPC_DPSQ_S_W_QH:
15997 check_dsp(ctx);
15998 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15999 break;
16000 case OPC_DPSQ_SA_L_PW:
16001 check_dsp(ctx);
16002 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16003 break;
16004 case OPC_DPSU_H_OBL:
16005 check_dsp(ctx);
16006 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
16007 break;
16008 case OPC_DPSU_H_OBR:
16009 check_dsp(ctx);
16010 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
16011 break;
16012 case OPC_MAQ_S_L_PWL:
16013 check_dsp(ctx);
16014 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
16015 break;
16016 case OPC_MAQ_S_L_PWR:
16017 check_dsp(ctx);
16018 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
16019 break;
16020 case OPC_MAQ_S_W_QHLL:
16021 check_dsp(ctx);
16022 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
16023 break;
16024 case OPC_MAQ_SA_W_QHLL:
16025 check_dsp(ctx);
16026 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
16027 break;
16028 case OPC_MAQ_S_W_QHLR:
16029 check_dsp(ctx);
16030 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
16031 break;
16032 case OPC_MAQ_SA_W_QHLR:
16033 check_dsp(ctx);
16034 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
16035 break;
16036 case OPC_MAQ_S_W_QHRL:
16037 check_dsp(ctx);
16038 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
16039 break;
16040 case OPC_MAQ_SA_W_QHRL:
16041 check_dsp(ctx);
16042 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
16043 break;
16044 case OPC_MAQ_S_W_QHRR:
16045 check_dsp(ctx);
16046 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
16047 break;
16048 case OPC_MAQ_SA_W_QHRR:
16049 check_dsp(ctx);
16050 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
16051 break;
16052 case OPC_MULSAQ_S_L_PW:
16053 check_dsp(ctx);
16054 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
16055 break;
16056 case OPC_MULSAQ_S_W_QH:
16057 check_dsp(ctx);
16058 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16059 break;
16062 break;
16063 #endif
16064 case OPC_ADDU_QB_DSP:
16065 switch (op2) {
16066 case OPC_MULEU_S_PH_QBL:
16067 check_dsp(ctx);
16068 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16069 break;
16070 case OPC_MULEU_S_PH_QBR:
16071 check_dsp(ctx);
16072 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16073 break;
16074 case OPC_MULQ_RS_PH:
16075 check_dsp(ctx);
16076 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16077 break;
16078 case OPC_MULEQ_S_W_PHL:
16079 check_dsp(ctx);
16080 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16081 break;
16082 case OPC_MULEQ_S_W_PHR:
16083 check_dsp(ctx);
16084 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16085 break;
16086 case OPC_MULQ_S_PH:
16087 check_dspr2(ctx);
16088 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16089 break;
16091 break;
16092 #ifdef TARGET_MIPS64
16093 case OPC_ADDU_OB_DSP:
16094 switch (op2) {
16095 case OPC_MULEQ_S_PW_QHL:
16096 check_dsp(ctx);
16097 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16098 break;
16099 case OPC_MULEQ_S_PW_QHR:
16100 check_dsp(ctx);
16101 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16102 break;
16103 case OPC_MULEU_S_QH_OBL:
16104 check_dsp(ctx);
16105 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16106 break;
16107 case OPC_MULEU_S_QH_OBR:
16108 check_dsp(ctx);
16109 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16110 break;
16111 case OPC_MULQ_RS_QH:
16112 check_dsp(ctx);
16113 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16114 break;
16116 break;
16117 #endif
16120 tcg_temp_free_i32(t0);
16121 tcg_temp_free(v1_t);
16122 tcg_temp_free(v2_t);
16125 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16126 int ret, int val)
16128 int16_t imm;
16129 TCGv t0;
16130 TCGv val_t;
16132 if (ret == 0) {
16133 /* Treat as NOP. */
16134 return;
16137 t0 = tcg_temp_new();
16138 val_t = tcg_temp_new();
16139 gen_load_gpr(val_t, val);
16141 switch (op1) {
16142 case OPC_ABSQ_S_PH_DSP:
16143 switch (op2) {
16144 case OPC_BITREV:
16145 check_dsp(ctx);
16146 gen_helper_bitrev(cpu_gpr[ret], val_t);
16147 break;
16148 case OPC_REPL_QB:
16149 check_dsp(ctx);
16151 target_long result;
16152 imm = (ctx->opcode >> 16) & 0xFF;
16153 result = (uint32_t)imm << 24 |
16154 (uint32_t)imm << 16 |
16155 (uint32_t)imm << 8 |
16156 (uint32_t)imm;
16157 result = (int32_t)result;
16158 tcg_gen_movi_tl(cpu_gpr[ret], result);
16160 break;
16161 case OPC_REPLV_QB:
16162 check_dsp(ctx);
16163 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16164 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16165 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16166 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16167 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16168 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16169 break;
16170 case OPC_REPL_PH:
16171 check_dsp(ctx);
16173 imm = (ctx->opcode >> 16) & 0x03FF;
16174 imm = (int16_t)(imm << 6) >> 6;
16175 tcg_gen_movi_tl(cpu_gpr[ret], \
16176 (target_long)((int32_t)imm << 16 | \
16177 (uint16_t)imm));
16179 break;
16180 case OPC_REPLV_PH:
16181 check_dsp(ctx);
16182 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16183 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16184 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16185 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16186 break;
16188 break;
16189 #ifdef TARGET_MIPS64
16190 case OPC_ABSQ_S_QH_DSP:
16191 switch (op2) {
16192 case OPC_REPL_OB:
16193 check_dsp(ctx);
16195 target_long temp;
16197 imm = (ctx->opcode >> 16) & 0xFF;
16198 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
16199 temp = (temp << 16) | temp;
16200 temp = (temp << 32) | temp;
16201 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16202 break;
16204 case OPC_REPL_PW:
16205 check_dsp(ctx);
16207 target_long temp;
16209 imm = (ctx->opcode >> 16) & 0x03FF;
16210 imm = (int16_t)(imm << 6) >> 6;
16211 temp = ((target_long)imm << 32) \
16212 | ((target_long)imm & 0xFFFFFFFF);
16213 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16214 break;
16216 case OPC_REPL_QH:
16217 check_dsp(ctx);
16219 target_long temp;
16221 imm = (ctx->opcode >> 16) & 0x03FF;
16222 imm = (int16_t)(imm << 6) >> 6;
16224 temp = ((uint64_t)(uint16_t)imm << 48) |
16225 ((uint64_t)(uint16_t)imm << 32) |
16226 ((uint64_t)(uint16_t)imm << 16) |
16227 (uint64_t)(uint16_t)imm;
16228 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16229 break;
16231 case OPC_REPLV_OB:
16232 check_dsp(ctx);
16233 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16234 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16235 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16236 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16237 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16238 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16239 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16240 break;
16241 case OPC_REPLV_PW:
16242 check_dsp(ctx);
16243 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
16244 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16245 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16246 break;
16247 case OPC_REPLV_QH:
16248 check_dsp(ctx);
16249 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16250 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16251 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16252 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16253 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16254 break;
16256 break;
16257 #endif
16259 tcg_temp_free(t0);
16260 tcg_temp_free(val_t);
16263 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
16264 uint32_t op1, uint32_t op2,
16265 int ret, int v1, int v2, int check_ret)
16267 TCGv t1;
16268 TCGv v1_t;
16269 TCGv v2_t;
16271 if ((ret == 0) && (check_ret == 1)) {
16272 /* Treat as NOP. */
16273 return;
16276 t1 = tcg_temp_new();
16277 v1_t = tcg_temp_new();
16278 v2_t = tcg_temp_new();
16280 gen_load_gpr(v1_t, v1);
16281 gen_load_gpr(v2_t, v2);
16283 switch (op1) {
16284 case OPC_CMPU_EQ_QB_DSP:
16285 switch (op2) {
16286 case OPC_CMPU_EQ_QB:
16287 check_dsp(ctx);
16288 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
16289 break;
16290 case OPC_CMPU_LT_QB:
16291 check_dsp(ctx);
16292 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
16293 break;
16294 case OPC_CMPU_LE_QB:
16295 check_dsp(ctx);
16296 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
16297 break;
16298 case OPC_CMPGU_EQ_QB:
16299 check_dsp(ctx);
16300 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
16301 break;
16302 case OPC_CMPGU_LT_QB:
16303 check_dsp(ctx);
16304 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
16305 break;
16306 case OPC_CMPGU_LE_QB:
16307 check_dsp(ctx);
16308 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
16309 break;
16310 case OPC_CMPGDU_EQ_QB:
16311 check_dspr2(ctx);
16312 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
16313 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16314 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16315 tcg_gen_shli_tl(t1, t1, 24);
16316 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16317 break;
16318 case OPC_CMPGDU_LT_QB:
16319 check_dspr2(ctx);
16320 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
16321 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16322 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16323 tcg_gen_shli_tl(t1, t1, 24);
16324 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16325 break;
16326 case OPC_CMPGDU_LE_QB:
16327 check_dspr2(ctx);
16328 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
16329 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16330 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16331 tcg_gen_shli_tl(t1, t1, 24);
16332 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16333 break;
16334 case OPC_CMP_EQ_PH:
16335 check_dsp(ctx);
16336 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
16337 break;
16338 case OPC_CMP_LT_PH:
16339 check_dsp(ctx);
16340 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
16341 break;
16342 case OPC_CMP_LE_PH:
16343 check_dsp(ctx);
16344 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
16345 break;
16346 case OPC_PICK_QB:
16347 check_dsp(ctx);
16348 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16349 break;
16350 case OPC_PICK_PH:
16351 check_dsp(ctx);
16352 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16353 break;
16354 case OPC_PACKRL_PH:
16355 check_dsp(ctx);
16356 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
16357 break;
16359 break;
16360 #ifdef TARGET_MIPS64
16361 case OPC_CMPU_EQ_OB_DSP:
16362 switch (op2) {
16363 case OPC_CMP_EQ_PW:
16364 check_dsp(ctx);
16365 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
16366 break;
16367 case OPC_CMP_LT_PW:
16368 check_dsp(ctx);
16369 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
16370 break;
16371 case OPC_CMP_LE_PW:
16372 check_dsp(ctx);
16373 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
16374 break;
16375 case OPC_CMP_EQ_QH:
16376 check_dsp(ctx);
16377 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
16378 break;
16379 case OPC_CMP_LT_QH:
16380 check_dsp(ctx);
16381 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
16382 break;
16383 case OPC_CMP_LE_QH:
16384 check_dsp(ctx);
16385 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
16386 break;
16387 case OPC_CMPGDU_EQ_OB:
16388 check_dspr2(ctx);
16389 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16390 break;
16391 case OPC_CMPGDU_LT_OB:
16392 check_dspr2(ctx);
16393 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16394 break;
16395 case OPC_CMPGDU_LE_OB:
16396 check_dspr2(ctx);
16397 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16398 break;
16399 case OPC_CMPGU_EQ_OB:
16400 check_dsp(ctx);
16401 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
16402 break;
16403 case OPC_CMPGU_LT_OB:
16404 check_dsp(ctx);
16405 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
16406 break;
16407 case OPC_CMPGU_LE_OB:
16408 check_dsp(ctx);
16409 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
16410 break;
16411 case OPC_CMPU_EQ_OB:
16412 check_dsp(ctx);
16413 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
16414 break;
16415 case OPC_CMPU_LT_OB:
16416 check_dsp(ctx);
16417 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
16418 break;
16419 case OPC_CMPU_LE_OB:
16420 check_dsp(ctx);
16421 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
16422 break;
16423 case OPC_PACKRL_PW:
16424 check_dsp(ctx);
16425 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
16426 break;
16427 case OPC_PICK_OB:
16428 check_dsp(ctx);
16429 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16430 break;
16431 case OPC_PICK_PW:
16432 check_dsp(ctx);
16433 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16434 break;
16435 case OPC_PICK_QH:
16436 check_dsp(ctx);
16437 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16438 break;
16440 break;
16441 #endif
16444 tcg_temp_free(t1);
16445 tcg_temp_free(v1_t);
16446 tcg_temp_free(v2_t);
16449 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
16450 uint32_t op1, int rt, int rs, int sa)
16452 TCGv t0;
16454 check_dspr2(ctx);
16456 if (rt == 0) {
16457 /* Treat as NOP. */
16458 return;
16461 t0 = tcg_temp_new();
16462 gen_load_gpr(t0, rs);
16464 switch (op1) {
16465 case OPC_APPEND_DSP:
16466 switch (MASK_APPEND(ctx->opcode)) {
16467 case OPC_APPEND:
16468 if (sa != 0) {
16469 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
16471 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16472 break;
16473 case OPC_PREPEND:
16474 if (sa != 0) {
16475 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
16476 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16477 tcg_gen_shli_tl(t0, t0, 32 - sa);
16478 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16480 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16481 break;
16482 case OPC_BALIGN:
16483 sa &= 3;
16484 if (sa != 0 && sa != 2) {
16485 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16486 tcg_gen_ext32u_tl(t0, t0);
16487 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
16488 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16490 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16491 break;
16492 default: /* Invalid */
16493 MIPS_INVAL("MASK APPEND");
16494 generate_exception_end(ctx, EXCP_RI);
16495 break;
16497 break;
16498 #ifdef TARGET_MIPS64
16499 case OPC_DAPPEND_DSP:
16500 switch (MASK_DAPPEND(ctx->opcode)) {
16501 case OPC_DAPPEND:
16502 if (sa != 0) {
16503 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
16505 break;
16506 case OPC_PREPENDD:
16507 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
16508 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
16509 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
16510 break;
16511 case OPC_PREPENDW:
16512 if (sa != 0) {
16513 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16514 tcg_gen_shli_tl(t0, t0, 64 - sa);
16515 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16517 break;
16518 case OPC_DBALIGN:
16519 sa &= 7;
16520 if (sa != 0 && sa != 2 && sa != 4) {
16521 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16522 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
16523 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16525 break;
16526 default: /* Invalid */
16527 MIPS_INVAL("MASK DAPPEND");
16528 generate_exception_end(ctx, EXCP_RI);
16529 break;
16531 break;
16532 #endif
16534 tcg_temp_free(t0);
16537 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16538 int ret, int v1, int v2, int check_ret)
16541 TCGv t0;
16542 TCGv t1;
16543 TCGv v1_t;
16544 TCGv v2_t;
16545 int16_t imm;
16547 if ((ret == 0) && (check_ret == 1)) {
16548 /* Treat as NOP. */
16549 return;
16552 t0 = tcg_temp_new();
16553 t1 = tcg_temp_new();
16554 v1_t = tcg_temp_new();
16555 v2_t = tcg_temp_new();
16557 gen_load_gpr(v1_t, v1);
16558 gen_load_gpr(v2_t, v2);
16560 switch (op1) {
16561 case OPC_EXTR_W_DSP:
16562 check_dsp(ctx);
16563 switch (op2) {
16564 case OPC_EXTR_W:
16565 tcg_gen_movi_tl(t0, v2);
16566 tcg_gen_movi_tl(t1, v1);
16567 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
16568 break;
16569 case OPC_EXTR_R_W:
16570 tcg_gen_movi_tl(t0, v2);
16571 tcg_gen_movi_tl(t1, v1);
16572 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16573 break;
16574 case OPC_EXTR_RS_W:
16575 tcg_gen_movi_tl(t0, v2);
16576 tcg_gen_movi_tl(t1, v1);
16577 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16578 break;
16579 case OPC_EXTR_S_H:
16580 tcg_gen_movi_tl(t0, v2);
16581 tcg_gen_movi_tl(t1, v1);
16582 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16583 break;
16584 case OPC_EXTRV_S_H:
16585 tcg_gen_movi_tl(t0, v2);
16586 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
16587 break;
16588 case OPC_EXTRV_W:
16589 tcg_gen_movi_tl(t0, v2);
16590 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16591 break;
16592 case OPC_EXTRV_R_W:
16593 tcg_gen_movi_tl(t0, v2);
16594 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16595 break;
16596 case OPC_EXTRV_RS_W:
16597 tcg_gen_movi_tl(t0, v2);
16598 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16599 break;
16600 case OPC_EXTP:
16601 tcg_gen_movi_tl(t0, v2);
16602 tcg_gen_movi_tl(t1, v1);
16603 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
16604 break;
16605 case OPC_EXTPV:
16606 tcg_gen_movi_tl(t0, v2);
16607 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
16608 break;
16609 case OPC_EXTPDP:
16610 tcg_gen_movi_tl(t0, v2);
16611 tcg_gen_movi_tl(t1, v1);
16612 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
16613 break;
16614 case OPC_EXTPDPV:
16615 tcg_gen_movi_tl(t0, v2);
16616 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16617 break;
16618 case OPC_SHILO:
16619 imm = (ctx->opcode >> 20) & 0x3F;
16620 tcg_gen_movi_tl(t0, ret);
16621 tcg_gen_movi_tl(t1, imm);
16622 gen_helper_shilo(t0, t1, cpu_env);
16623 break;
16624 case OPC_SHILOV:
16625 tcg_gen_movi_tl(t0, ret);
16626 gen_helper_shilo(t0, v1_t, cpu_env);
16627 break;
16628 case OPC_MTHLIP:
16629 tcg_gen_movi_tl(t0, ret);
16630 gen_helper_mthlip(t0, v1_t, cpu_env);
16631 break;
16632 case OPC_WRDSP:
16633 imm = (ctx->opcode >> 11) & 0x3FF;
16634 tcg_gen_movi_tl(t0, imm);
16635 gen_helper_wrdsp(v1_t, t0, cpu_env);
16636 break;
16637 case OPC_RDDSP:
16638 imm = (ctx->opcode >> 16) & 0x03FF;
16639 tcg_gen_movi_tl(t0, imm);
16640 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
16641 break;
16643 break;
16644 #ifdef TARGET_MIPS64
16645 case OPC_DEXTR_W_DSP:
16646 check_dsp(ctx);
16647 switch (op2) {
16648 case OPC_DMTHLIP:
16649 tcg_gen_movi_tl(t0, ret);
16650 gen_helper_dmthlip(v1_t, t0, cpu_env);
16651 break;
16652 case OPC_DSHILO:
16654 int shift = (ctx->opcode >> 19) & 0x7F;
16655 int ac = (ctx->opcode >> 11) & 0x03;
16656 tcg_gen_movi_tl(t0, shift);
16657 tcg_gen_movi_tl(t1, ac);
16658 gen_helper_dshilo(t0, t1, cpu_env);
16659 break;
16661 case OPC_DSHILOV:
16663 int ac = (ctx->opcode >> 11) & 0x03;
16664 tcg_gen_movi_tl(t0, ac);
16665 gen_helper_dshilo(v1_t, t0, cpu_env);
16666 break;
16668 case OPC_DEXTP:
16669 tcg_gen_movi_tl(t0, v2);
16670 tcg_gen_movi_tl(t1, v1);
16672 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
16673 break;
16674 case OPC_DEXTPV:
16675 tcg_gen_movi_tl(t0, v2);
16676 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
16677 break;
16678 case OPC_DEXTPDP:
16679 tcg_gen_movi_tl(t0, v2);
16680 tcg_gen_movi_tl(t1, v1);
16681 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
16682 break;
16683 case OPC_DEXTPDPV:
16684 tcg_gen_movi_tl(t0, v2);
16685 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16686 break;
16687 case OPC_DEXTR_L:
16688 tcg_gen_movi_tl(t0, v2);
16689 tcg_gen_movi_tl(t1, v1);
16690 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
16691 break;
16692 case OPC_DEXTR_R_L:
16693 tcg_gen_movi_tl(t0, v2);
16694 tcg_gen_movi_tl(t1, v1);
16695 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
16696 break;
16697 case OPC_DEXTR_RS_L:
16698 tcg_gen_movi_tl(t0, v2);
16699 tcg_gen_movi_tl(t1, v1);
16700 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
16701 break;
16702 case OPC_DEXTR_W:
16703 tcg_gen_movi_tl(t0, v2);
16704 tcg_gen_movi_tl(t1, v1);
16705 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
16706 break;
16707 case OPC_DEXTR_R_W:
16708 tcg_gen_movi_tl(t0, v2);
16709 tcg_gen_movi_tl(t1, v1);
16710 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16711 break;
16712 case OPC_DEXTR_RS_W:
16713 tcg_gen_movi_tl(t0, v2);
16714 tcg_gen_movi_tl(t1, v1);
16715 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16716 break;
16717 case OPC_DEXTR_S_H:
16718 tcg_gen_movi_tl(t0, v2);
16719 tcg_gen_movi_tl(t1, v1);
16720 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16721 break;
16722 case OPC_DEXTRV_S_H:
16723 tcg_gen_movi_tl(t0, v2);
16724 tcg_gen_movi_tl(t1, v1);
16725 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16726 break;
16727 case OPC_DEXTRV_L:
16728 tcg_gen_movi_tl(t0, v2);
16729 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16730 break;
16731 case OPC_DEXTRV_R_L:
16732 tcg_gen_movi_tl(t0, v2);
16733 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16734 break;
16735 case OPC_DEXTRV_RS_L:
16736 tcg_gen_movi_tl(t0, v2);
16737 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16738 break;
16739 case OPC_DEXTRV_W:
16740 tcg_gen_movi_tl(t0, v2);
16741 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16742 break;
16743 case OPC_DEXTRV_R_W:
16744 tcg_gen_movi_tl(t0, v2);
16745 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16746 break;
16747 case OPC_DEXTRV_RS_W:
16748 tcg_gen_movi_tl(t0, v2);
16749 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16750 break;
16752 break;
16753 #endif
16756 tcg_temp_free(t0);
16757 tcg_temp_free(t1);
16758 tcg_temp_free(v1_t);
16759 tcg_temp_free(v2_t);
16762 /* End MIPSDSP functions. */
16764 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
16766 int rs, rt, rd, sa;
16767 uint32_t op1, op2;
16769 rs = (ctx->opcode >> 21) & 0x1f;
16770 rt = (ctx->opcode >> 16) & 0x1f;
16771 rd = (ctx->opcode >> 11) & 0x1f;
16772 sa = (ctx->opcode >> 6) & 0x1f;
16774 op1 = MASK_SPECIAL(ctx->opcode);
16775 switch (op1) {
16776 case OPC_LSA:
16777 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
16778 break;
16779 case OPC_MULT ... OPC_DIVU:
16780 op2 = MASK_R6_MULDIV(ctx->opcode);
16781 switch (op2) {
16782 case R6_OPC_MUL:
16783 case R6_OPC_MUH:
16784 case R6_OPC_MULU:
16785 case R6_OPC_MUHU:
16786 case R6_OPC_DIV:
16787 case R6_OPC_MOD:
16788 case R6_OPC_DIVU:
16789 case R6_OPC_MODU:
16790 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16791 break;
16792 default:
16793 MIPS_INVAL("special_r6 muldiv");
16794 generate_exception_end(ctx, EXCP_RI);
16795 break;
16797 break;
16798 case OPC_SELEQZ:
16799 case OPC_SELNEZ:
16800 gen_cond_move(ctx, op1, rd, rs, rt);
16801 break;
16802 case R6_OPC_CLO:
16803 case R6_OPC_CLZ:
16804 if (rt == 0 && sa == 1) {
16805 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16806 We need additionally to check other fields */
16807 gen_cl(ctx, op1, rd, rs);
16808 } else {
16809 generate_exception_end(ctx, EXCP_RI);
16811 break;
16812 case R6_OPC_SDBBP:
16813 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
16814 gen_helper_do_semihosting(cpu_env);
16815 } else {
16816 if (ctx->hflags & MIPS_HFLAG_SBRI) {
16817 generate_exception_end(ctx, EXCP_RI);
16818 } else {
16819 generate_exception_end(ctx, EXCP_DBp);
16822 break;
16823 #if defined(TARGET_MIPS64)
16824 case OPC_DLSA:
16825 check_mips_64(ctx);
16826 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
16827 break;
16828 case R6_OPC_DCLO:
16829 case R6_OPC_DCLZ:
16830 if (rt == 0 && sa == 1) {
16831 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16832 We need additionally to check other fields */
16833 check_mips_64(ctx);
16834 gen_cl(ctx, op1, rd, rs);
16835 } else {
16836 generate_exception_end(ctx, EXCP_RI);
16838 break;
16839 case OPC_DMULT ... OPC_DDIVU:
16840 op2 = MASK_R6_MULDIV(ctx->opcode);
16841 switch (op2) {
16842 case R6_OPC_DMUL:
16843 case R6_OPC_DMUH:
16844 case R6_OPC_DMULU:
16845 case R6_OPC_DMUHU:
16846 case R6_OPC_DDIV:
16847 case R6_OPC_DMOD:
16848 case R6_OPC_DDIVU:
16849 case R6_OPC_DMODU:
16850 check_mips_64(ctx);
16851 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16852 break;
16853 default:
16854 MIPS_INVAL("special_r6 muldiv");
16855 generate_exception_end(ctx, EXCP_RI);
16856 break;
16858 break;
16859 #endif
16860 default: /* Invalid */
16861 MIPS_INVAL("special_r6");
16862 generate_exception_end(ctx, EXCP_RI);
16863 break;
16867 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
16869 int rs, rt, rd, sa;
16870 uint32_t op1;
16872 rs = (ctx->opcode >> 21) & 0x1f;
16873 rt = (ctx->opcode >> 16) & 0x1f;
16874 rd = (ctx->opcode >> 11) & 0x1f;
16875 sa = (ctx->opcode >> 6) & 0x1f;
16877 op1 = MASK_SPECIAL(ctx->opcode);
16878 switch (op1) {
16879 case OPC_MOVN: /* Conditional move */
16880 case OPC_MOVZ:
16881 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
16882 INSN_LOONGSON2E | INSN_LOONGSON2F);
16883 gen_cond_move(ctx, op1, rd, rs, rt);
16884 break;
16885 case OPC_MFHI: /* Move from HI/LO */
16886 case OPC_MFLO:
16887 gen_HILO(ctx, op1, rs & 3, rd);
16888 break;
16889 case OPC_MTHI:
16890 case OPC_MTLO: /* Move to HI/LO */
16891 gen_HILO(ctx, op1, rd & 3, rs);
16892 break;
16893 case OPC_MOVCI:
16894 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
16895 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16896 check_cp1_enabled(ctx);
16897 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
16898 (ctx->opcode >> 16) & 1);
16899 } else {
16900 generate_exception_err(ctx, EXCP_CpU, 1);
16902 break;
16903 case OPC_MULT:
16904 case OPC_MULTU:
16905 if (sa) {
16906 check_insn(ctx, INSN_VR54XX);
16907 op1 = MASK_MUL_VR54XX(ctx->opcode);
16908 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
16909 } else {
16910 gen_muldiv(ctx, op1, rd & 3, rs, rt);
16912 break;
16913 case OPC_DIV:
16914 case OPC_DIVU:
16915 gen_muldiv(ctx, op1, 0, rs, rt);
16916 break;
16917 #if defined(TARGET_MIPS64)
16918 case OPC_DMULT ... OPC_DDIVU:
16919 check_insn(ctx, ISA_MIPS3);
16920 check_mips_64(ctx);
16921 gen_muldiv(ctx, op1, 0, rs, rt);
16922 break;
16923 #endif
16924 case OPC_JR:
16925 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
16926 break;
16927 case OPC_SPIM:
16928 #ifdef MIPS_STRICT_STANDARD
16929 MIPS_INVAL("SPIM");
16930 generate_exception_end(ctx, EXCP_RI);
16931 #else
16932 /* Implemented as RI exception for now. */
16933 MIPS_INVAL("spim (unofficial)");
16934 generate_exception_end(ctx, EXCP_RI);
16935 #endif
16936 break;
16937 default: /* Invalid */
16938 MIPS_INVAL("special_legacy");
16939 generate_exception_end(ctx, EXCP_RI);
16940 break;
16944 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
16946 int rs, rt, rd, sa;
16947 uint32_t op1;
16949 rs = (ctx->opcode >> 21) & 0x1f;
16950 rt = (ctx->opcode >> 16) & 0x1f;
16951 rd = (ctx->opcode >> 11) & 0x1f;
16952 sa = (ctx->opcode >> 6) & 0x1f;
16954 op1 = MASK_SPECIAL(ctx->opcode);
16955 switch (op1) {
16956 case OPC_SLL: /* Shift with immediate */
16957 if (sa == 5 && rd == 0 &&
16958 rs == 0 && rt == 0) { /* PAUSE */
16959 if ((ctx->insn_flags & ISA_MIPS32R6) &&
16960 (ctx->hflags & MIPS_HFLAG_BMASK)) {
16961 generate_exception_end(ctx, EXCP_RI);
16962 break;
16965 /* Fallthrough */
16966 case OPC_SRA:
16967 gen_shift_imm(ctx, op1, rd, rt, sa);
16968 break;
16969 case OPC_SRL:
16970 switch ((ctx->opcode >> 21) & 0x1f) {
16971 case 1:
16972 /* rotr is decoded as srl on non-R2 CPUs */
16973 if (ctx->insn_flags & ISA_MIPS32R2) {
16974 op1 = OPC_ROTR;
16976 /* Fallthrough */
16977 case 0:
16978 gen_shift_imm(ctx, op1, rd, rt, sa);
16979 break;
16980 default:
16981 generate_exception_end(ctx, EXCP_RI);
16982 break;
16984 break;
16985 case OPC_ADD ... OPC_SUBU:
16986 gen_arith(ctx, op1, rd, rs, rt);
16987 break;
16988 case OPC_SLLV: /* Shifts */
16989 case OPC_SRAV:
16990 gen_shift(ctx, op1, rd, rs, rt);
16991 break;
16992 case OPC_SRLV:
16993 switch ((ctx->opcode >> 6) & 0x1f) {
16994 case 1:
16995 /* rotrv is decoded as srlv on non-R2 CPUs */
16996 if (ctx->insn_flags & ISA_MIPS32R2) {
16997 op1 = OPC_ROTRV;
16999 /* Fallthrough */
17000 case 0:
17001 gen_shift(ctx, op1, rd, rs, rt);
17002 break;
17003 default:
17004 generate_exception_end(ctx, EXCP_RI);
17005 break;
17007 break;
17008 case OPC_SLT: /* Set on less than */
17009 case OPC_SLTU:
17010 gen_slt(ctx, op1, rd, rs, rt);
17011 break;
17012 case OPC_AND: /* Logic*/
17013 case OPC_OR:
17014 case OPC_NOR:
17015 case OPC_XOR:
17016 gen_logic(ctx, op1, rd, rs, rt);
17017 break;
17018 case OPC_JALR:
17019 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17020 break;
17021 case OPC_TGE ... OPC_TEQ: /* Traps */
17022 case OPC_TNE:
17023 check_insn(ctx, ISA_MIPS2);
17024 gen_trap(ctx, op1, rs, rt, -1);
17025 break;
17026 case OPC_LSA: /* OPC_PMON */
17027 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17028 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17029 decode_opc_special_r6(env, ctx);
17030 } else {
17031 /* Pmon entry point, also R4010 selsl */
17032 #ifdef MIPS_STRICT_STANDARD
17033 MIPS_INVAL("PMON / selsl");
17034 generate_exception_end(ctx, EXCP_RI);
17035 #else
17036 gen_helper_0e0i(pmon, sa);
17037 #endif
17039 break;
17040 case OPC_SYSCALL:
17041 generate_exception_end(ctx, EXCP_SYSCALL);
17042 break;
17043 case OPC_BREAK:
17044 generate_exception_end(ctx, EXCP_BREAK);
17045 break;
17046 case OPC_SYNC:
17047 check_insn(ctx, ISA_MIPS2);
17048 /* Treat as NOP. */
17049 break;
17051 #if defined(TARGET_MIPS64)
17052 /* MIPS64 specific opcodes */
17053 case OPC_DSLL:
17054 case OPC_DSRA:
17055 case OPC_DSLL32:
17056 case OPC_DSRA32:
17057 check_insn(ctx, ISA_MIPS3);
17058 check_mips_64(ctx);
17059 gen_shift_imm(ctx, op1, rd, rt, sa);
17060 break;
17061 case OPC_DSRL:
17062 switch ((ctx->opcode >> 21) & 0x1f) {
17063 case 1:
17064 /* drotr is decoded as dsrl on non-R2 CPUs */
17065 if (ctx->insn_flags & ISA_MIPS32R2) {
17066 op1 = OPC_DROTR;
17068 /* Fallthrough */
17069 case 0:
17070 check_insn(ctx, ISA_MIPS3);
17071 check_mips_64(ctx);
17072 gen_shift_imm(ctx, op1, rd, rt, sa);
17073 break;
17074 default:
17075 generate_exception_end(ctx, EXCP_RI);
17076 break;
17078 break;
17079 case OPC_DSRL32:
17080 switch ((ctx->opcode >> 21) & 0x1f) {
17081 case 1:
17082 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
17083 if (ctx->insn_flags & ISA_MIPS32R2) {
17084 op1 = OPC_DROTR32;
17086 /* Fallthrough */
17087 case 0:
17088 check_insn(ctx, ISA_MIPS3);
17089 check_mips_64(ctx);
17090 gen_shift_imm(ctx, op1, rd, rt, sa);
17091 break;
17092 default:
17093 generate_exception_end(ctx, EXCP_RI);
17094 break;
17096 break;
17097 case OPC_DADD ... OPC_DSUBU:
17098 check_insn(ctx, ISA_MIPS3);
17099 check_mips_64(ctx);
17100 gen_arith(ctx, op1, rd, rs, rt);
17101 break;
17102 case OPC_DSLLV:
17103 case OPC_DSRAV:
17104 check_insn(ctx, ISA_MIPS3);
17105 check_mips_64(ctx);
17106 gen_shift(ctx, op1, rd, rs, rt);
17107 break;
17108 case OPC_DSRLV:
17109 switch ((ctx->opcode >> 6) & 0x1f) {
17110 case 1:
17111 /* drotrv is decoded as dsrlv on non-R2 CPUs */
17112 if (ctx->insn_flags & ISA_MIPS32R2) {
17113 op1 = OPC_DROTRV;
17115 /* Fallthrough */
17116 case 0:
17117 check_insn(ctx, ISA_MIPS3);
17118 check_mips_64(ctx);
17119 gen_shift(ctx, op1, rd, rs, rt);
17120 break;
17121 default:
17122 generate_exception_end(ctx, EXCP_RI);
17123 break;
17125 break;
17126 case OPC_DLSA:
17127 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17128 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17129 decode_opc_special_r6(env, ctx);
17131 break;
17132 #endif
17133 default:
17134 if (ctx->insn_flags & ISA_MIPS32R6) {
17135 decode_opc_special_r6(env, ctx);
17136 } else {
17137 decode_opc_special_legacy(env, ctx);
17142 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
17144 int rs, rt, rd;
17145 uint32_t op1;
17147 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17149 rs = (ctx->opcode >> 21) & 0x1f;
17150 rt = (ctx->opcode >> 16) & 0x1f;
17151 rd = (ctx->opcode >> 11) & 0x1f;
17153 op1 = MASK_SPECIAL2(ctx->opcode);
17154 switch (op1) {
17155 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
17156 case OPC_MSUB ... OPC_MSUBU:
17157 check_insn(ctx, ISA_MIPS32);
17158 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17159 break;
17160 case OPC_MUL:
17161 gen_arith(ctx, op1, rd, rs, rt);
17162 break;
17163 case OPC_DIV_G_2F:
17164 case OPC_DIVU_G_2F:
17165 case OPC_MULT_G_2F:
17166 case OPC_MULTU_G_2F:
17167 case OPC_MOD_G_2F:
17168 case OPC_MODU_G_2F:
17169 check_insn(ctx, INSN_LOONGSON2F);
17170 gen_loongson_integer(ctx, op1, rd, rs, rt);
17171 break;
17172 case OPC_CLO:
17173 case OPC_CLZ:
17174 check_insn(ctx, ISA_MIPS32);
17175 gen_cl(ctx, op1, rd, rs);
17176 break;
17177 case OPC_SDBBP:
17178 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17179 gen_helper_do_semihosting(cpu_env);
17180 } else {
17181 /* XXX: not clear which exception should be raised
17182 * when in debug mode...
17184 check_insn(ctx, ISA_MIPS32);
17185 generate_exception_end(ctx, EXCP_DBp);
17187 break;
17188 #if defined(TARGET_MIPS64)
17189 case OPC_DCLO:
17190 case OPC_DCLZ:
17191 check_insn(ctx, ISA_MIPS64);
17192 check_mips_64(ctx);
17193 gen_cl(ctx, op1, rd, rs);
17194 break;
17195 case OPC_DMULT_G_2F:
17196 case OPC_DMULTU_G_2F:
17197 case OPC_DDIV_G_2F:
17198 case OPC_DDIVU_G_2F:
17199 case OPC_DMOD_G_2F:
17200 case OPC_DMODU_G_2F:
17201 check_insn(ctx, INSN_LOONGSON2F);
17202 gen_loongson_integer(ctx, op1, rd, rs, rt);
17203 break;
17204 #endif
17205 default: /* Invalid */
17206 MIPS_INVAL("special2_legacy");
17207 generate_exception_end(ctx, EXCP_RI);
17208 break;
17212 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
17214 int rs, rt, rd, sa;
17215 uint32_t op1, op2;
17216 int16_t imm;
17218 rs = (ctx->opcode >> 21) & 0x1f;
17219 rt = (ctx->opcode >> 16) & 0x1f;
17220 rd = (ctx->opcode >> 11) & 0x1f;
17221 sa = (ctx->opcode >> 6) & 0x1f;
17222 imm = (int16_t)ctx->opcode >> 7;
17224 op1 = MASK_SPECIAL3(ctx->opcode);
17225 switch (op1) {
17226 case R6_OPC_PREF:
17227 if (rt >= 24) {
17228 /* hint codes 24-31 are reserved and signal RI */
17229 generate_exception_end(ctx, EXCP_RI);
17231 /* Treat as NOP. */
17232 break;
17233 case R6_OPC_CACHE:
17234 check_cp0_enabled(ctx);
17235 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17236 gen_cache_operation(ctx, rt, rs, imm);
17238 break;
17239 case R6_OPC_SC:
17240 gen_st_cond(ctx, op1, rt, rs, imm);
17241 break;
17242 case R6_OPC_LL:
17243 gen_ld(ctx, op1, rt, rs, imm);
17244 break;
17245 case OPC_BSHFL:
17247 if (rd == 0) {
17248 /* Treat as NOP. */
17249 break;
17251 op2 = MASK_BSHFL(ctx->opcode);
17252 switch (op2) {
17253 case OPC_ALIGN ... OPC_ALIGN_END:
17254 gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3);
17255 break;
17256 case OPC_BITSWAP:
17257 gen_bitswap(ctx, op2, rd, rt);
17258 break;
17261 break;
17262 #if defined(TARGET_MIPS64)
17263 case R6_OPC_SCD:
17264 gen_st_cond(ctx, op1, rt, rs, imm);
17265 break;
17266 case R6_OPC_LLD:
17267 gen_ld(ctx, op1, rt, rs, imm);
17268 break;
17269 case OPC_DBSHFL:
17270 check_mips_64(ctx);
17272 if (rd == 0) {
17273 /* Treat as NOP. */
17274 break;
17276 op2 = MASK_DBSHFL(ctx->opcode);
17277 switch (op2) {
17278 case OPC_DALIGN ... OPC_DALIGN_END:
17279 gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7);
17280 break;
17281 case OPC_DBITSWAP:
17282 gen_bitswap(ctx, op2, rd, rt);
17283 break;
17287 break;
17288 #endif
17289 default: /* Invalid */
17290 MIPS_INVAL("special3_r6");
17291 generate_exception_end(ctx, EXCP_RI);
17292 break;
17296 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
17298 int rs, rt, rd;
17299 uint32_t op1, op2;
17301 rs = (ctx->opcode >> 21) & 0x1f;
17302 rt = (ctx->opcode >> 16) & 0x1f;
17303 rd = (ctx->opcode >> 11) & 0x1f;
17305 op1 = MASK_SPECIAL3(ctx->opcode);
17306 switch (op1) {
17307 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
17308 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
17309 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
17310 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
17311 * the same mask and op1. */
17312 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
17313 op2 = MASK_ADDUH_QB(ctx->opcode);
17314 switch (op2) {
17315 case OPC_ADDUH_QB:
17316 case OPC_ADDUH_R_QB:
17317 case OPC_ADDQH_PH:
17318 case OPC_ADDQH_R_PH:
17319 case OPC_ADDQH_W:
17320 case OPC_ADDQH_R_W:
17321 case OPC_SUBUH_QB:
17322 case OPC_SUBUH_R_QB:
17323 case OPC_SUBQH_PH:
17324 case OPC_SUBQH_R_PH:
17325 case OPC_SUBQH_W:
17326 case OPC_SUBQH_R_W:
17327 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17328 break;
17329 case OPC_MUL_PH:
17330 case OPC_MUL_S_PH:
17331 case OPC_MULQ_S_W:
17332 case OPC_MULQ_RS_W:
17333 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17334 break;
17335 default:
17336 MIPS_INVAL("MASK ADDUH.QB");
17337 generate_exception_end(ctx, EXCP_RI);
17338 break;
17340 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
17341 gen_loongson_integer(ctx, op1, rd, rs, rt);
17342 } else {
17343 generate_exception_end(ctx, EXCP_RI);
17345 break;
17346 case OPC_LX_DSP:
17347 op2 = MASK_LX(ctx->opcode);
17348 switch (op2) {
17349 #if defined(TARGET_MIPS64)
17350 case OPC_LDX:
17351 #endif
17352 case OPC_LBUX:
17353 case OPC_LHX:
17354 case OPC_LWX:
17355 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
17356 break;
17357 default: /* Invalid */
17358 MIPS_INVAL("MASK LX");
17359 generate_exception_end(ctx, EXCP_RI);
17360 break;
17362 break;
17363 case OPC_ABSQ_S_PH_DSP:
17364 op2 = MASK_ABSQ_S_PH(ctx->opcode);
17365 switch (op2) {
17366 case OPC_ABSQ_S_QB:
17367 case OPC_ABSQ_S_PH:
17368 case OPC_ABSQ_S_W:
17369 case OPC_PRECEQ_W_PHL:
17370 case OPC_PRECEQ_W_PHR:
17371 case OPC_PRECEQU_PH_QBL:
17372 case OPC_PRECEQU_PH_QBR:
17373 case OPC_PRECEQU_PH_QBLA:
17374 case OPC_PRECEQU_PH_QBRA:
17375 case OPC_PRECEU_PH_QBL:
17376 case OPC_PRECEU_PH_QBR:
17377 case OPC_PRECEU_PH_QBLA:
17378 case OPC_PRECEU_PH_QBRA:
17379 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17380 break;
17381 case OPC_BITREV:
17382 case OPC_REPL_QB:
17383 case OPC_REPLV_QB:
17384 case OPC_REPL_PH:
17385 case OPC_REPLV_PH:
17386 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17387 break;
17388 default:
17389 MIPS_INVAL("MASK ABSQ_S.PH");
17390 generate_exception_end(ctx, EXCP_RI);
17391 break;
17393 break;
17394 case OPC_ADDU_QB_DSP:
17395 op2 = MASK_ADDU_QB(ctx->opcode);
17396 switch (op2) {
17397 case OPC_ADDQ_PH:
17398 case OPC_ADDQ_S_PH:
17399 case OPC_ADDQ_S_W:
17400 case OPC_ADDU_QB:
17401 case OPC_ADDU_S_QB:
17402 case OPC_ADDU_PH:
17403 case OPC_ADDU_S_PH:
17404 case OPC_SUBQ_PH:
17405 case OPC_SUBQ_S_PH:
17406 case OPC_SUBQ_S_W:
17407 case OPC_SUBU_QB:
17408 case OPC_SUBU_S_QB:
17409 case OPC_SUBU_PH:
17410 case OPC_SUBU_S_PH:
17411 case OPC_ADDSC:
17412 case OPC_ADDWC:
17413 case OPC_MODSUB:
17414 case OPC_RADDU_W_QB:
17415 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17416 break;
17417 case OPC_MULEU_S_PH_QBL:
17418 case OPC_MULEU_S_PH_QBR:
17419 case OPC_MULQ_RS_PH:
17420 case OPC_MULEQ_S_W_PHL:
17421 case OPC_MULEQ_S_W_PHR:
17422 case OPC_MULQ_S_PH:
17423 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17424 break;
17425 default: /* Invalid */
17426 MIPS_INVAL("MASK ADDU.QB");
17427 generate_exception_end(ctx, EXCP_RI);
17428 break;
17431 break;
17432 case OPC_CMPU_EQ_QB_DSP:
17433 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
17434 switch (op2) {
17435 case OPC_PRECR_SRA_PH_W:
17436 case OPC_PRECR_SRA_R_PH_W:
17437 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17438 break;
17439 case OPC_PRECR_QB_PH:
17440 case OPC_PRECRQ_QB_PH:
17441 case OPC_PRECRQ_PH_W:
17442 case OPC_PRECRQ_RS_PH_W:
17443 case OPC_PRECRQU_S_QB_PH:
17444 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17445 break;
17446 case OPC_CMPU_EQ_QB:
17447 case OPC_CMPU_LT_QB:
17448 case OPC_CMPU_LE_QB:
17449 case OPC_CMP_EQ_PH:
17450 case OPC_CMP_LT_PH:
17451 case OPC_CMP_LE_PH:
17452 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17453 break;
17454 case OPC_CMPGU_EQ_QB:
17455 case OPC_CMPGU_LT_QB:
17456 case OPC_CMPGU_LE_QB:
17457 case OPC_CMPGDU_EQ_QB:
17458 case OPC_CMPGDU_LT_QB:
17459 case OPC_CMPGDU_LE_QB:
17460 case OPC_PICK_QB:
17461 case OPC_PICK_PH:
17462 case OPC_PACKRL_PH:
17463 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17464 break;
17465 default: /* Invalid */
17466 MIPS_INVAL("MASK CMPU.EQ.QB");
17467 generate_exception_end(ctx, EXCP_RI);
17468 break;
17470 break;
17471 case OPC_SHLL_QB_DSP:
17472 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17473 break;
17474 case OPC_DPA_W_PH_DSP:
17475 op2 = MASK_DPA_W_PH(ctx->opcode);
17476 switch (op2) {
17477 case OPC_DPAU_H_QBL:
17478 case OPC_DPAU_H_QBR:
17479 case OPC_DPSU_H_QBL:
17480 case OPC_DPSU_H_QBR:
17481 case OPC_DPA_W_PH:
17482 case OPC_DPAX_W_PH:
17483 case OPC_DPAQ_S_W_PH:
17484 case OPC_DPAQX_S_W_PH:
17485 case OPC_DPAQX_SA_W_PH:
17486 case OPC_DPS_W_PH:
17487 case OPC_DPSX_W_PH:
17488 case OPC_DPSQ_S_W_PH:
17489 case OPC_DPSQX_S_W_PH:
17490 case OPC_DPSQX_SA_W_PH:
17491 case OPC_MULSAQ_S_W_PH:
17492 case OPC_DPAQ_SA_L_W:
17493 case OPC_DPSQ_SA_L_W:
17494 case OPC_MAQ_S_W_PHL:
17495 case OPC_MAQ_S_W_PHR:
17496 case OPC_MAQ_SA_W_PHL:
17497 case OPC_MAQ_SA_W_PHR:
17498 case OPC_MULSA_W_PH:
17499 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17500 break;
17501 default: /* Invalid */
17502 MIPS_INVAL("MASK DPAW.PH");
17503 generate_exception_end(ctx, EXCP_RI);
17504 break;
17506 break;
17507 case OPC_INSV_DSP:
17508 op2 = MASK_INSV(ctx->opcode);
17509 switch (op2) {
17510 case OPC_INSV:
17511 check_dsp(ctx);
17513 TCGv t0, t1;
17515 if (rt == 0) {
17516 break;
17519 t0 = tcg_temp_new();
17520 t1 = tcg_temp_new();
17522 gen_load_gpr(t0, rt);
17523 gen_load_gpr(t1, rs);
17525 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
17527 tcg_temp_free(t0);
17528 tcg_temp_free(t1);
17529 break;
17531 default: /* Invalid */
17532 MIPS_INVAL("MASK INSV");
17533 generate_exception_end(ctx, EXCP_RI);
17534 break;
17536 break;
17537 case OPC_APPEND_DSP:
17538 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17539 break;
17540 case OPC_EXTR_W_DSP:
17541 op2 = MASK_EXTR_W(ctx->opcode);
17542 switch (op2) {
17543 case OPC_EXTR_W:
17544 case OPC_EXTR_R_W:
17545 case OPC_EXTR_RS_W:
17546 case OPC_EXTR_S_H:
17547 case OPC_EXTRV_S_H:
17548 case OPC_EXTRV_W:
17549 case OPC_EXTRV_R_W:
17550 case OPC_EXTRV_RS_W:
17551 case OPC_EXTP:
17552 case OPC_EXTPV:
17553 case OPC_EXTPDP:
17554 case OPC_EXTPDPV:
17555 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17556 break;
17557 case OPC_RDDSP:
17558 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
17559 break;
17560 case OPC_SHILO:
17561 case OPC_SHILOV:
17562 case OPC_MTHLIP:
17563 case OPC_WRDSP:
17564 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17565 break;
17566 default: /* Invalid */
17567 MIPS_INVAL("MASK EXTR.W");
17568 generate_exception_end(ctx, EXCP_RI);
17569 break;
17571 break;
17572 #if defined(TARGET_MIPS64)
17573 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
17574 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
17575 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
17576 check_insn(ctx, INSN_LOONGSON2E);
17577 gen_loongson_integer(ctx, op1, rd, rs, rt);
17578 break;
17579 case OPC_ABSQ_S_QH_DSP:
17580 op2 = MASK_ABSQ_S_QH(ctx->opcode);
17581 switch (op2) {
17582 case OPC_PRECEQ_L_PWL:
17583 case OPC_PRECEQ_L_PWR:
17584 case OPC_PRECEQ_PW_QHL:
17585 case OPC_PRECEQ_PW_QHR:
17586 case OPC_PRECEQ_PW_QHLA:
17587 case OPC_PRECEQ_PW_QHRA:
17588 case OPC_PRECEQU_QH_OBL:
17589 case OPC_PRECEQU_QH_OBR:
17590 case OPC_PRECEQU_QH_OBLA:
17591 case OPC_PRECEQU_QH_OBRA:
17592 case OPC_PRECEU_QH_OBL:
17593 case OPC_PRECEU_QH_OBR:
17594 case OPC_PRECEU_QH_OBLA:
17595 case OPC_PRECEU_QH_OBRA:
17596 case OPC_ABSQ_S_OB:
17597 case OPC_ABSQ_S_PW:
17598 case OPC_ABSQ_S_QH:
17599 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17600 break;
17601 case OPC_REPL_OB:
17602 case OPC_REPL_PW:
17603 case OPC_REPL_QH:
17604 case OPC_REPLV_OB:
17605 case OPC_REPLV_PW:
17606 case OPC_REPLV_QH:
17607 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17608 break;
17609 default: /* Invalid */
17610 MIPS_INVAL("MASK ABSQ_S.QH");
17611 generate_exception_end(ctx, EXCP_RI);
17612 break;
17614 break;
17615 case OPC_ADDU_OB_DSP:
17616 op2 = MASK_ADDU_OB(ctx->opcode);
17617 switch (op2) {
17618 case OPC_RADDU_L_OB:
17619 case OPC_SUBQ_PW:
17620 case OPC_SUBQ_S_PW:
17621 case OPC_SUBQ_QH:
17622 case OPC_SUBQ_S_QH:
17623 case OPC_SUBU_OB:
17624 case OPC_SUBU_S_OB:
17625 case OPC_SUBU_QH:
17626 case OPC_SUBU_S_QH:
17627 case OPC_SUBUH_OB:
17628 case OPC_SUBUH_R_OB:
17629 case OPC_ADDQ_PW:
17630 case OPC_ADDQ_S_PW:
17631 case OPC_ADDQ_QH:
17632 case OPC_ADDQ_S_QH:
17633 case OPC_ADDU_OB:
17634 case OPC_ADDU_S_OB:
17635 case OPC_ADDU_QH:
17636 case OPC_ADDU_S_QH:
17637 case OPC_ADDUH_OB:
17638 case OPC_ADDUH_R_OB:
17639 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17640 break;
17641 case OPC_MULEQ_S_PW_QHL:
17642 case OPC_MULEQ_S_PW_QHR:
17643 case OPC_MULEU_S_QH_OBL:
17644 case OPC_MULEU_S_QH_OBR:
17645 case OPC_MULQ_RS_QH:
17646 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17647 break;
17648 default: /* Invalid */
17649 MIPS_INVAL("MASK ADDU.OB");
17650 generate_exception_end(ctx, EXCP_RI);
17651 break;
17653 break;
17654 case OPC_CMPU_EQ_OB_DSP:
17655 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
17656 switch (op2) {
17657 case OPC_PRECR_SRA_QH_PW:
17658 case OPC_PRECR_SRA_R_QH_PW:
17659 /* Return value is rt. */
17660 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17661 break;
17662 case OPC_PRECR_OB_QH:
17663 case OPC_PRECRQ_OB_QH:
17664 case OPC_PRECRQ_PW_L:
17665 case OPC_PRECRQ_QH_PW:
17666 case OPC_PRECRQ_RS_QH_PW:
17667 case OPC_PRECRQU_S_OB_QH:
17668 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17669 break;
17670 case OPC_CMPU_EQ_OB:
17671 case OPC_CMPU_LT_OB:
17672 case OPC_CMPU_LE_OB:
17673 case OPC_CMP_EQ_QH:
17674 case OPC_CMP_LT_QH:
17675 case OPC_CMP_LE_QH:
17676 case OPC_CMP_EQ_PW:
17677 case OPC_CMP_LT_PW:
17678 case OPC_CMP_LE_PW:
17679 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17680 break;
17681 case OPC_CMPGDU_EQ_OB:
17682 case OPC_CMPGDU_LT_OB:
17683 case OPC_CMPGDU_LE_OB:
17684 case OPC_CMPGU_EQ_OB:
17685 case OPC_CMPGU_LT_OB:
17686 case OPC_CMPGU_LE_OB:
17687 case OPC_PACKRL_PW:
17688 case OPC_PICK_OB:
17689 case OPC_PICK_PW:
17690 case OPC_PICK_QH:
17691 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17692 break;
17693 default: /* Invalid */
17694 MIPS_INVAL("MASK CMPU_EQ.OB");
17695 generate_exception_end(ctx, EXCP_RI);
17696 break;
17698 break;
17699 case OPC_DAPPEND_DSP:
17700 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17701 break;
17702 case OPC_DEXTR_W_DSP:
17703 op2 = MASK_DEXTR_W(ctx->opcode);
17704 switch (op2) {
17705 case OPC_DEXTP:
17706 case OPC_DEXTPDP:
17707 case OPC_DEXTPDPV:
17708 case OPC_DEXTPV:
17709 case OPC_DEXTR_L:
17710 case OPC_DEXTR_R_L:
17711 case OPC_DEXTR_RS_L:
17712 case OPC_DEXTR_W:
17713 case OPC_DEXTR_R_W:
17714 case OPC_DEXTR_RS_W:
17715 case OPC_DEXTR_S_H:
17716 case OPC_DEXTRV_L:
17717 case OPC_DEXTRV_R_L:
17718 case OPC_DEXTRV_RS_L:
17719 case OPC_DEXTRV_S_H:
17720 case OPC_DEXTRV_W:
17721 case OPC_DEXTRV_R_W:
17722 case OPC_DEXTRV_RS_W:
17723 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17724 break;
17725 case OPC_DMTHLIP:
17726 case OPC_DSHILO:
17727 case OPC_DSHILOV:
17728 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17729 break;
17730 default: /* Invalid */
17731 MIPS_INVAL("MASK EXTR.W");
17732 generate_exception_end(ctx, EXCP_RI);
17733 break;
17735 break;
17736 case OPC_DPAQ_W_QH_DSP:
17737 op2 = MASK_DPAQ_W_QH(ctx->opcode);
17738 switch (op2) {
17739 case OPC_DPAU_H_OBL:
17740 case OPC_DPAU_H_OBR:
17741 case OPC_DPSU_H_OBL:
17742 case OPC_DPSU_H_OBR:
17743 case OPC_DPA_W_QH:
17744 case OPC_DPAQ_S_W_QH:
17745 case OPC_DPS_W_QH:
17746 case OPC_DPSQ_S_W_QH:
17747 case OPC_MULSAQ_S_W_QH:
17748 case OPC_DPAQ_SA_L_PW:
17749 case OPC_DPSQ_SA_L_PW:
17750 case OPC_MULSAQ_S_L_PW:
17751 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17752 break;
17753 case OPC_MAQ_S_W_QHLL:
17754 case OPC_MAQ_S_W_QHLR:
17755 case OPC_MAQ_S_W_QHRL:
17756 case OPC_MAQ_S_W_QHRR:
17757 case OPC_MAQ_SA_W_QHLL:
17758 case OPC_MAQ_SA_W_QHLR:
17759 case OPC_MAQ_SA_W_QHRL:
17760 case OPC_MAQ_SA_W_QHRR:
17761 case OPC_MAQ_S_L_PWL:
17762 case OPC_MAQ_S_L_PWR:
17763 case OPC_DMADD:
17764 case OPC_DMADDU:
17765 case OPC_DMSUB:
17766 case OPC_DMSUBU:
17767 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17768 break;
17769 default: /* Invalid */
17770 MIPS_INVAL("MASK DPAQ.W.QH");
17771 generate_exception_end(ctx, EXCP_RI);
17772 break;
17774 break;
17775 case OPC_DINSV_DSP:
17776 op2 = MASK_INSV(ctx->opcode);
17777 switch (op2) {
17778 case OPC_DINSV:
17780 TCGv t0, t1;
17782 if (rt == 0) {
17783 break;
17785 check_dsp(ctx);
17787 t0 = tcg_temp_new();
17788 t1 = tcg_temp_new();
17790 gen_load_gpr(t0, rt);
17791 gen_load_gpr(t1, rs);
17793 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
17795 tcg_temp_free(t0);
17796 tcg_temp_free(t1);
17797 break;
17799 default: /* Invalid */
17800 MIPS_INVAL("MASK DINSV");
17801 generate_exception_end(ctx, EXCP_RI);
17802 break;
17804 break;
17805 case OPC_SHLL_OB_DSP:
17806 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17807 break;
17808 #endif
17809 default: /* Invalid */
17810 MIPS_INVAL("special3_legacy");
17811 generate_exception_end(ctx, EXCP_RI);
17812 break;
17816 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
17818 int rs, rt, rd, sa;
17819 uint32_t op1, op2;
17821 rs = (ctx->opcode >> 21) & 0x1f;
17822 rt = (ctx->opcode >> 16) & 0x1f;
17823 rd = (ctx->opcode >> 11) & 0x1f;
17824 sa = (ctx->opcode >> 6) & 0x1f;
17826 op1 = MASK_SPECIAL3(ctx->opcode);
17827 switch (op1) {
17828 case OPC_EXT:
17829 case OPC_INS:
17830 check_insn(ctx, ISA_MIPS32R2);
17831 gen_bitops(ctx, op1, rt, rs, sa, rd);
17832 break;
17833 case OPC_BSHFL:
17834 op2 = MASK_BSHFL(ctx->opcode);
17835 switch (op2) {
17836 case OPC_ALIGN ... OPC_ALIGN_END:
17837 case OPC_BITSWAP:
17838 check_insn(ctx, ISA_MIPS32R6);
17839 decode_opc_special3_r6(env, ctx);
17840 break;
17841 default:
17842 check_insn(ctx, ISA_MIPS32R2);
17843 gen_bshfl(ctx, op2, rt, rd);
17844 break;
17846 break;
17847 #if defined(TARGET_MIPS64)
17848 case OPC_DEXTM ... OPC_DEXT:
17849 case OPC_DINSM ... OPC_DINS:
17850 check_insn(ctx, ISA_MIPS64R2);
17851 check_mips_64(ctx);
17852 gen_bitops(ctx, op1, rt, rs, sa, rd);
17853 break;
17854 case OPC_DBSHFL:
17855 op2 = MASK_DBSHFL(ctx->opcode);
17856 switch (op2) {
17857 case OPC_DALIGN ... OPC_DALIGN_END:
17858 case OPC_DBITSWAP:
17859 check_insn(ctx, ISA_MIPS32R6);
17860 decode_opc_special3_r6(env, ctx);
17861 break;
17862 default:
17863 check_insn(ctx, ISA_MIPS64R2);
17864 check_mips_64(ctx);
17865 op2 = MASK_DBSHFL(ctx->opcode);
17866 gen_bshfl(ctx, op2, rt, rd);
17867 break;
17869 break;
17870 #endif
17871 case OPC_RDHWR:
17872 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
17873 break;
17874 case OPC_FORK:
17875 check_insn(ctx, ASE_MT);
17877 TCGv t0 = tcg_temp_new();
17878 TCGv t1 = tcg_temp_new();
17880 gen_load_gpr(t0, rt);
17881 gen_load_gpr(t1, rs);
17882 gen_helper_fork(t0, t1);
17883 tcg_temp_free(t0);
17884 tcg_temp_free(t1);
17886 break;
17887 case OPC_YIELD:
17888 check_insn(ctx, ASE_MT);
17890 TCGv t0 = tcg_temp_new();
17892 gen_load_gpr(t0, rs);
17893 gen_helper_yield(t0, cpu_env, t0);
17894 gen_store_gpr(t0, rd);
17895 tcg_temp_free(t0);
17897 break;
17898 default:
17899 if (ctx->insn_flags & ISA_MIPS32R6) {
17900 decode_opc_special3_r6(env, ctx);
17901 } else {
17902 decode_opc_special3_legacy(env, ctx);
17907 /* MIPS SIMD Architecture (MSA) */
17908 static inline int check_msa_access(DisasContext *ctx)
17910 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
17911 !(ctx->hflags & MIPS_HFLAG_F64))) {
17912 generate_exception_end(ctx, EXCP_RI);
17913 return 0;
17916 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
17917 if (ctx->insn_flags & ASE_MSA) {
17918 generate_exception_end(ctx, EXCP_MSADIS);
17919 return 0;
17920 } else {
17921 generate_exception_end(ctx, EXCP_RI);
17922 return 0;
17925 return 1;
17928 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
17930 /* generates tcg ops to check if any element is 0 */
17931 /* Note this function only works with MSA_WRLEN = 128 */
17932 uint64_t eval_zero_or_big = 0;
17933 uint64_t eval_big = 0;
17934 TCGv_i64 t0 = tcg_temp_new_i64();
17935 TCGv_i64 t1 = tcg_temp_new_i64();
17936 switch (df) {
17937 case DF_BYTE:
17938 eval_zero_or_big = 0x0101010101010101ULL;
17939 eval_big = 0x8080808080808080ULL;
17940 break;
17941 case DF_HALF:
17942 eval_zero_or_big = 0x0001000100010001ULL;
17943 eval_big = 0x8000800080008000ULL;
17944 break;
17945 case DF_WORD:
17946 eval_zero_or_big = 0x0000000100000001ULL;
17947 eval_big = 0x8000000080000000ULL;
17948 break;
17949 case DF_DOUBLE:
17950 eval_zero_or_big = 0x0000000000000001ULL;
17951 eval_big = 0x8000000000000000ULL;
17952 break;
17954 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
17955 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
17956 tcg_gen_andi_i64(t0, t0, eval_big);
17957 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
17958 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
17959 tcg_gen_andi_i64(t1, t1, eval_big);
17960 tcg_gen_or_i64(t0, t0, t1);
17961 /* if all bits are zero then all elements are not zero */
17962 /* if some bit is non-zero then some element is zero */
17963 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
17964 tcg_gen_trunc_i64_tl(tresult, t0);
17965 tcg_temp_free_i64(t0);
17966 tcg_temp_free_i64(t1);
17969 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
17971 uint8_t df = (ctx->opcode >> 21) & 0x3;
17972 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
17973 int64_t s16 = (int16_t)ctx->opcode;
17975 check_msa_access(ctx);
17977 if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
17978 generate_exception_end(ctx, EXCP_RI);
17979 return;
17981 switch (op1) {
17982 case OPC_BZ_V:
17983 case OPC_BNZ_V:
17985 TCGv_i64 t0 = tcg_temp_new_i64();
17986 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
17987 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
17988 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
17989 tcg_gen_trunc_i64_tl(bcond, t0);
17990 tcg_temp_free_i64(t0);
17992 break;
17993 case OPC_BZ_B:
17994 case OPC_BZ_H:
17995 case OPC_BZ_W:
17996 case OPC_BZ_D:
17997 gen_check_zero_element(bcond, df, wt);
17998 break;
17999 case OPC_BNZ_B:
18000 case OPC_BNZ_H:
18001 case OPC_BNZ_W:
18002 case OPC_BNZ_D:
18003 gen_check_zero_element(bcond, df, wt);
18004 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
18005 break;
18008 ctx->btarget = ctx->pc + (s16 << 2) + 4;
18010 ctx->hflags |= MIPS_HFLAG_BC;
18011 ctx->hflags |= MIPS_HFLAG_BDS32;
18014 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
18016 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
18017 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
18018 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18019 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18021 TCGv_i32 twd = tcg_const_i32(wd);
18022 TCGv_i32 tws = tcg_const_i32(ws);
18023 TCGv_i32 ti8 = tcg_const_i32(i8);
18025 switch (MASK_MSA_I8(ctx->opcode)) {
18026 case OPC_ANDI_B:
18027 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
18028 break;
18029 case OPC_ORI_B:
18030 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
18031 break;
18032 case OPC_NORI_B:
18033 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
18034 break;
18035 case OPC_XORI_B:
18036 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
18037 break;
18038 case OPC_BMNZI_B:
18039 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
18040 break;
18041 case OPC_BMZI_B:
18042 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
18043 break;
18044 case OPC_BSELI_B:
18045 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
18046 break;
18047 case OPC_SHF_B:
18048 case OPC_SHF_H:
18049 case OPC_SHF_W:
18051 uint8_t df = (ctx->opcode >> 24) & 0x3;
18052 if (df == DF_DOUBLE) {
18053 generate_exception_end(ctx, EXCP_RI);
18054 } else {
18055 TCGv_i32 tdf = tcg_const_i32(df);
18056 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
18057 tcg_temp_free_i32(tdf);
18060 break;
18061 default:
18062 MIPS_INVAL("MSA instruction");
18063 generate_exception_end(ctx, EXCP_RI);
18064 break;
18067 tcg_temp_free_i32(twd);
18068 tcg_temp_free_i32(tws);
18069 tcg_temp_free_i32(ti8);
18072 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
18074 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18075 uint8_t df = (ctx->opcode >> 21) & 0x3;
18076 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
18077 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
18078 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18079 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18081 TCGv_i32 tdf = tcg_const_i32(df);
18082 TCGv_i32 twd = tcg_const_i32(wd);
18083 TCGv_i32 tws = tcg_const_i32(ws);
18084 TCGv_i32 timm = tcg_temp_new_i32();
18085 tcg_gen_movi_i32(timm, u5);
18087 switch (MASK_MSA_I5(ctx->opcode)) {
18088 case OPC_ADDVI_df:
18089 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
18090 break;
18091 case OPC_SUBVI_df:
18092 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
18093 break;
18094 case OPC_MAXI_S_df:
18095 tcg_gen_movi_i32(timm, s5);
18096 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
18097 break;
18098 case OPC_MAXI_U_df:
18099 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
18100 break;
18101 case OPC_MINI_S_df:
18102 tcg_gen_movi_i32(timm, s5);
18103 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
18104 break;
18105 case OPC_MINI_U_df:
18106 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
18107 break;
18108 case OPC_CEQI_df:
18109 tcg_gen_movi_i32(timm, s5);
18110 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
18111 break;
18112 case OPC_CLTI_S_df:
18113 tcg_gen_movi_i32(timm, s5);
18114 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
18115 break;
18116 case OPC_CLTI_U_df:
18117 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
18118 break;
18119 case OPC_CLEI_S_df:
18120 tcg_gen_movi_i32(timm, s5);
18121 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
18122 break;
18123 case OPC_CLEI_U_df:
18124 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
18125 break;
18126 case OPC_LDI_df:
18128 int32_t s10 = sextract32(ctx->opcode, 11, 10);
18129 tcg_gen_movi_i32(timm, s10);
18130 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
18132 break;
18133 default:
18134 MIPS_INVAL("MSA instruction");
18135 generate_exception_end(ctx, EXCP_RI);
18136 break;
18139 tcg_temp_free_i32(tdf);
18140 tcg_temp_free_i32(twd);
18141 tcg_temp_free_i32(tws);
18142 tcg_temp_free_i32(timm);
18145 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
18147 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18148 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
18149 uint32_t df = 0, m = 0;
18150 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18151 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18153 TCGv_i32 tdf;
18154 TCGv_i32 tm;
18155 TCGv_i32 twd;
18156 TCGv_i32 tws;
18158 if ((dfm & 0x40) == 0x00) {
18159 m = dfm & 0x3f;
18160 df = DF_DOUBLE;
18161 } else if ((dfm & 0x60) == 0x40) {
18162 m = dfm & 0x1f;
18163 df = DF_WORD;
18164 } else if ((dfm & 0x70) == 0x60) {
18165 m = dfm & 0x0f;
18166 df = DF_HALF;
18167 } else if ((dfm & 0x78) == 0x70) {
18168 m = dfm & 0x7;
18169 df = DF_BYTE;
18170 } else {
18171 generate_exception_end(ctx, EXCP_RI);
18172 return;
18175 tdf = tcg_const_i32(df);
18176 tm = tcg_const_i32(m);
18177 twd = tcg_const_i32(wd);
18178 tws = tcg_const_i32(ws);
18180 switch (MASK_MSA_BIT(ctx->opcode)) {
18181 case OPC_SLLI_df:
18182 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
18183 break;
18184 case OPC_SRAI_df:
18185 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
18186 break;
18187 case OPC_SRLI_df:
18188 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
18189 break;
18190 case OPC_BCLRI_df:
18191 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
18192 break;
18193 case OPC_BSETI_df:
18194 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
18195 break;
18196 case OPC_BNEGI_df:
18197 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
18198 break;
18199 case OPC_BINSLI_df:
18200 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
18201 break;
18202 case OPC_BINSRI_df:
18203 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
18204 break;
18205 case OPC_SAT_S_df:
18206 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
18207 break;
18208 case OPC_SAT_U_df:
18209 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
18210 break;
18211 case OPC_SRARI_df:
18212 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
18213 break;
18214 case OPC_SRLRI_df:
18215 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
18216 break;
18217 default:
18218 MIPS_INVAL("MSA instruction");
18219 generate_exception_end(ctx, EXCP_RI);
18220 break;
18223 tcg_temp_free_i32(tdf);
18224 tcg_temp_free_i32(tm);
18225 tcg_temp_free_i32(twd);
18226 tcg_temp_free_i32(tws);
18229 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
18231 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18232 uint8_t df = (ctx->opcode >> 21) & 0x3;
18233 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18234 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18235 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18237 TCGv_i32 tdf = tcg_const_i32(df);
18238 TCGv_i32 twd = tcg_const_i32(wd);
18239 TCGv_i32 tws = tcg_const_i32(ws);
18240 TCGv_i32 twt = tcg_const_i32(wt);
18242 switch (MASK_MSA_3R(ctx->opcode)) {
18243 case OPC_SLL_df:
18244 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
18245 break;
18246 case OPC_ADDV_df:
18247 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
18248 break;
18249 case OPC_CEQ_df:
18250 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
18251 break;
18252 case OPC_ADD_A_df:
18253 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
18254 break;
18255 case OPC_SUBS_S_df:
18256 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
18257 break;
18258 case OPC_MULV_df:
18259 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
18260 break;
18261 case OPC_SLD_df:
18262 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
18263 break;
18264 case OPC_VSHF_df:
18265 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
18266 break;
18267 case OPC_SRA_df:
18268 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
18269 break;
18270 case OPC_SUBV_df:
18271 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
18272 break;
18273 case OPC_ADDS_A_df:
18274 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
18275 break;
18276 case OPC_SUBS_U_df:
18277 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
18278 break;
18279 case OPC_MADDV_df:
18280 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
18281 break;
18282 case OPC_SPLAT_df:
18283 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
18284 break;
18285 case OPC_SRAR_df:
18286 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
18287 break;
18288 case OPC_SRL_df:
18289 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
18290 break;
18291 case OPC_MAX_S_df:
18292 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
18293 break;
18294 case OPC_CLT_S_df:
18295 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
18296 break;
18297 case OPC_ADDS_S_df:
18298 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
18299 break;
18300 case OPC_SUBSUS_U_df:
18301 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
18302 break;
18303 case OPC_MSUBV_df:
18304 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
18305 break;
18306 case OPC_PCKEV_df:
18307 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
18308 break;
18309 case OPC_SRLR_df:
18310 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
18311 break;
18312 case OPC_BCLR_df:
18313 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
18314 break;
18315 case OPC_MAX_U_df:
18316 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
18317 break;
18318 case OPC_CLT_U_df:
18319 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
18320 break;
18321 case OPC_ADDS_U_df:
18322 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
18323 break;
18324 case OPC_SUBSUU_S_df:
18325 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
18326 break;
18327 case OPC_PCKOD_df:
18328 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
18329 break;
18330 case OPC_BSET_df:
18331 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
18332 break;
18333 case OPC_MIN_S_df:
18334 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
18335 break;
18336 case OPC_CLE_S_df:
18337 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
18338 break;
18339 case OPC_AVE_S_df:
18340 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
18341 break;
18342 case OPC_ASUB_S_df:
18343 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
18344 break;
18345 case OPC_DIV_S_df:
18346 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
18347 break;
18348 case OPC_ILVL_df:
18349 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
18350 break;
18351 case OPC_BNEG_df:
18352 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
18353 break;
18354 case OPC_MIN_U_df:
18355 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
18356 break;
18357 case OPC_CLE_U_df:
18358 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
18359 break;
18360 case OPC_AVE_U_df:
18361 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
18362 break;
18363 case OPC_ASUB_U_df:
18364 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
18365 break;
18366 case OPC_DIV_U_df:
18367 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
18368 break;
18369 case OPC_ILVR_df:
18370 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
18371 break;
18372 case OPC_BINSL_df:
18373 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
18374 break;
18375 case OPC_MAX_A_df:
18376 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
18377 break;
18378 case OPC_AVER_S_df:
18379 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
18380 break;
18381 case OPC_MOD_S_df:
18382 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
18383 break;
18384 case OPC_ILVEV_df:
18385 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
18386 break;
18387 case OPC_BINSR_df:
18388 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
18389 break;
18390 case OPC_MIN_A_df:
18391 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
18392 break;
18393 case OPC_AVER_U_df:
18394 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
18395 break;
18396 case OPC_MOD_U_df:
18397 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
18398 break;
18399 case OPC_ILVOD_df:
18400 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
18401 break;
18403 case OPC_DOTP_S_df:
18404 case OPC_DOTP_U_df:
18405 case OPC_DPADD_S_df:
18406 case OPC_DPADD_U_df:
18407 case OPC_DPSUB_S_df:
18408 case OPC_HADD_S_df:
18409 case OPC_DPSUB_U_df:
18410 case OPC_HADD_U_df:
18411 case OPC_HSUB_S_df:
18412 case OPC_HSUB_U_df:
18413 if (df == DF_BYTE) {
18414 generate_exception_end(ctx, EXCP_RI);
18415 break;
18417 switch (MASK_MSA_3R(ctx->opcode)) {
18418 case OPC_DOTP_S_df:
18419 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
18420 break;
18421 case OPC_DOTP_U_df:
18422 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
18423 break;
18424 case OPC_DPADD_S_df:
18425 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
18426 break;
18427 case OPC_DPADD_U_df:
18428 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
18429 break;
18430 case OPC_DPSUB_S_df:
18431 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
18432 break;
18433 case OPC_HADD_S_df:
18434 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
18435 break;
18436 case OPC_DPSUB_U_df:
18437 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
18438 break;
18439 case OPC_HADD_U_df:
18440 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
18441 break;
18442 case OPC_HSUB_S_df:
18443 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
18444 break;
18445 case OPC_HSUB_U_df:
18446 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
18447 break;
18449 break;
18450 default:
18451 MIPS_INVAL("MSA instruction");
18452 generate_exception_end(ctx, EXCP_RI);
18453 break;
18455 tcg_temp_free_i32(twd);
18456 tcg_temp_free_i32(tws);
18457 tcg_temp_free_i32(twt);
18458 tcg_temp_free_i32(tdf);
18461 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
18463 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
18464 uint8_t source = (ctx->opcode >> 11) & 0x1f;
18465 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
18466 TCGv telm = tcg_temp_new();
18467 TCGv_i32 tsr = tcg_const_i32(source);
18468 TCGv_i32 tdt = tcg_const_i32(dest);
18470 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
18471 case OPC_CTCMSA:
18472 gen_load_gpr(telm, source);
18473 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
18474 break;
18475 case OPC_CFCMSA:
18476 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
18477 gen_store_gpr(telm, dest);
18478 break;
18479 case OPC_MOVE_V:
18480 gen_helper_msa_move_v(cpu_env, tdt, tsr);
18481 break;
18482 default:
18483 MIPS_INVAL("MSA instruction");
18484 generate_exception_end(ctx, EXCP_RI);
18485 break;
18488 tcg_temp_free(telm);
18489 tcg_temp_free_i32(tdt);
18490 tcg_temp_free_i32(tsr);
18493 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
18494 uint32_t n)
18496 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18497 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18498 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18500 TCGv_i32 tws = tcg_const_i32(ws);
18501 TCGv_i32 twd = tcg_const_i32(wd);
18502 TCGv_i32 tn = tcg_const_i32(n);
18503 TCGv_i32 tdf = tcg_const_i32(df);
18505 switch (MASK_MSA_ELM(ctx->opcode)) {
18506 case OPC_SLDI_df:
18507 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
18508 break;
18509 case OPC_SPLATI_df:
18510 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
18511 break;
18512 case OPC_INSVE_df:
18513 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
18514 break;
18515 case OPC_COPY_S_df:
18516 case OPC_COPY_U_df:
18517 case OPC_INSERT_df:
18518 #if !defined(TARGET_MIPS64)
18519 /* Double format valid only for MIPS64 */
18520 if (df == DF_DOUBLE) {
18521 generate_exception_end(ctx, EXCP_RI);
18522 break;
18524 #endif
18525 switch (MASK_MSA_ELM(ctx->opcode)) {
18526 case OPC_COPY_S_df:
18527 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
18528 break;
18529 case OPC_COPY_U_df:
18530 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
18531 break;
18532 case OPC_INSERT_df:
18533 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
18534 break;
18536 break;
18537 default:
18538 MIPS_INVAL("MSA instruction");
18539 generate_exception_end(ctx, EXCP_RI);
18541 tcg_temp_free_i32(twd);
18542 tcg_temp_free_i32(tws);
18543 tcg_temp_free_i32(tn);
18544 tcg_temp_free_i32(tdf);
18547 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
18549 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
18550 uint32_t df = 0, n = 0;
18552 if ((dfn & 0x30) == 0x00) {
18553 n = dfn & 0x0f;
18554 df = DF_BYTE;
18555 } else if ((dfn & 0x38) == 0x20) {
18556 n = dfn & 0x07;
18557 df = DF_HALF;
18558 } else if ((dfn & 0x3c) == 0x30) {
18559 n = dfn & 0x03;
18560 df = DF_WORD;
18561 } else if ((dfn & 0x3e) == 0x38) {
18562 n = dfn & 0x01;
18563 df = DF_DOUBLE;
18564 } else if (dfn == 0x3E) {
18565 /* CTCMSA, CFCMSA, MOVE.V */
18566 gen_msa_elm_3e(env, ctx);
18567 return;
18568 } else {
18569 generate_exception_end(ctx, EXCP_RI);
18570 return;
18573 gen_msa_elm_df(env, ctx, df, n);
18576 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
18578 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18579 uint8_t df = (ctx->opcode >> 21) & 0x1;
18580 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18581 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18582 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18584 TCGv_i32 twd = tcg_const_i32(wd);
18585 TCGv_i32 tws = tcg_const_i32(ws);
18586 TCGv_i32 twt = tcg_const_i32(wt);
18587 TCGv_i32 tdf = tcg_temp_new_i32();
18589 /* adjust df value for floating-point instruction */
18590 tcg_gen_movi_i32(tdf, df + 2);
18592 switch (MASK_MSA_3RF(ctx->opcode)) {
18593 case OPC_FCAF_df:
18594 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
18595 break;
18596 case OPC_FADD_df:
18597 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
18598 break;
18599 case OPC_FCUN_df:
18600 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
18601 break;
18602 case OPC_FSUB_df:
18603 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
18604 break;
18605 case OPC_FCOR_df:
18606 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
18607 break;
18608 case OPC_FCEQ_df:
18609 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
18610 break;
18611 case OPC_FMUL_df:
18612 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
18613 break;
18614 case OPC_FCUNE_df:
18615 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
18616 break;
18617 case OPC_FCUEQ_df:
18618 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
18619 break;
18620 case OPC_FDIV_df:
18621 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
18622 break;
18623 case OPC_FCNE_df:
18624 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
18625 break;
18626 case OPC_FCLT_df:
18627 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
18628 break;
18629 case OPC_FMADD_df:
18630 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
18631 break;
18632 case OPC_MUL_Q_df:
18633 tcg_gen_movi_i32(tdf, df + 1);
18634 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
18635 break;
18636 case OPC_FCULT_df:
18637 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
18638 break;
18639 case OPC_FMSUB_df:
18640 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
18641 break;
18642 case OPC_MADD_Q_df:
18643 tcg_gen_movi_i32(tdf, df + 1);
18644 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
18645 break;
18646 case OPC_FCLE_df:
18647 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
18648 break;
18649 case OPC_MSUB_Q_df:
18650 tcg_gen_movi_i32(tdf, df + 1);
18651 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
18652 break;
18653 case OPC_FCULE_df:
18654 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
18655 break;
18656 case OPC_FEXP2_df:
18657 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
18658 break;
18659 case OPC_FSAF_df:
18660 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
18661 break;
18662 case OPC_FEXDO_df:
18663 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
18664 break;
18665 case OPC_FSUN_df:
18666 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
18667 break;
18668 case OPC_FSOR_df:
18669 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
18670 break;
18671 case OPC_FSEQ_df:
18672 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
18673 break;
18674 case OPC_FTQ_df:
18675 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
18676 break;
18677 case OPC_FSUNE_df:
18678 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
18679 break;
18680 case OPC_FSUEQ_df:
18681 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
18682 break;
18683 case OPC_FSNE_df:
18684 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
18685 break;
18686 case OPC_FSLT_df:
18687 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
18688 break;
18689 case OPC_FMIN_df:
18690 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
18691 break;
18692 case OPC_MULR_Q_df:
18693 tcg_gen_movi_i32(tdf, df + 1);
18694 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
18695 break;
18696 case OPC_FSULT_df:
18697 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
18698 break;
18699 case OPC_FMIN_A_df:
18700 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
18701 break;
18702 case OPC_MADDR_Q_df:
18703 tcg_gen_movi_i32(tdf, df + 1);
18704 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
18705 break;
18706 case OPC_FSLE_df:
18707 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
18708 break;
18709 case OPC_FMAX_df:
18710 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
18711 break;
18712 case OPC_MSUBR_Q_df:
18713 tcg_gen_movi_i32(tdf, df + 1);
18714 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
18715 break;
18716 case OPC_FSULE_df:
18717 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
18718 break;
18719 case OPC_FMAX_A_df:
18720 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
18721 break;
18722 default:
18723 MIPS_INVAL("MSA instruction");
18724 generate_exception_end(ctx, EXCP_RI);
18725 break;
18728 tcg_temp_free_i32(twd);
18729 tcg_temp_free_i32(tws);
18730 tcg_temp_free_i32(twt);
18731 tcg_temp_free_i32(tdf);
18734 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
18736 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18737 (op & (0x7 << 18)))
18738 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18739 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18740 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18741 uint8_t df = (ctx->opcode >> 16) & 0x3;
18742 TCGv_i32 twd = tcg_const_i32(wd);
18743 TCGv_i32 tws = tcg_const_i32(ws);
18744 TCGv_i32 twt = tcg_const_i32(wt);
18745 TCGv_i32 tdf = tcg_const_i32(df);
18747 switch (MASK_MSA_2R(ctx->opcode)) {
18748 case OPC_FILL_df:
18749 #if !defined(TARGET_MIPS64)
18750 /* Double format valid only for MIPS64 */
18751 if (df == DF_DOUBLE) {
18752 generate_exception_end(ctx, EXCP_RI);
18753 break;
18755 #endif
18756 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
18757 break;
18758 case OPC_PCNT_df:
18759 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
18760 break;
18761 case OPC_NLOC_df:
18762 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
18763 break;
18764 case OPC_NLZC_df:
18765 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
18766 break;
18767 default:
18768 MIPS_INVAL("MSA instruction");
18769 generate_exception_end(ctx, EXCP_RI);
18770 break;
18773 tcg_temp_free_i32(twd);
18774 tcg_temp_free_i32(tws);
18775 tcg_temp_free_i32(twt);
18776 tcg_temp_free_i32(tdf);
18779 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
18781 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18782 (op & (0xf << 17)))
18783 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18784 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18785 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18786 uint8_t df = (ctx->opcode >> 16) & 0x1;
18787 TCGv_i32 twd = tcg_const_i32(wd);
18788 TCGv_i32 tws = tcg_const_i32(ws);
18789 TCGv_i32 twt = tcg_const_i32(wt);
18790 /* adjust df value for floating-point instruction */
18791 TCGv_i32 tdf = tcg_const_i32(df + 2);
18793 switch (MASK_MSA_2RF(ctx->opcode)) {
18794 case OPC_FCLASS_df:
18795 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
18796 break;
18797 case OPC_FTRUNC_S_df:
18798 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
18799 break;
18800 case OPC_FTRUNC_U_df:
18801 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
18802 break;
18803 case OPC_FSQRT_df:
18804 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
18805 break;
18806 case OPC_FRSQRT_df:
18807 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
18808 break;
18809 case OPC_FRCP_df:
18810 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
18811 break;
18812 case OPC_FRINT_df:
18813 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
18814 break;
18815 case OPC_FLOG2_df:
18816 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
18817 break;
18818 case OPC_FEXUPL_df:
18819 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
18820 break;
18821 case OPC_FEXUPR_df:
18822 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
18823 break;
18824 case OPC_FFQL_df:
18825 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
18826 break;
18827 case OPC_FFQR_df:
18828 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
18829 break;
18830 case OPC_FTINT_S_df:
18831 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
18832 break;
18833 case OPC_FTINT_U_df:
18834 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
18835 break;
18836 case OPC_FFINT_S_df:
18837 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
18838 break;
18839 case OPC_FFINT_U_df:
18840 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
18841 break;
18844 tcg_temp_free_i32(twd);
18845 tcg_temp_free_i32(tws);
18846 tcg_temp_free_i32(twt);
18847 tcg_temp_free_i32(tdf);
18850 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
18852 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
18853 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18854 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18855 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18856 TCGv_i32 twd = tcg_const_i32(wd);
18857 TCGv_i32 tws = tcg_const_i32(ws);
18858 TCGv_i32 twt = tcg_const_i32(wt);
18860 switch (MASK_MSA_VEC(ctx->opcode)) {
18861 case OPC_AND_V:
18862 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
18863 break;
18864 case OPC_OR_V:
18865 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
18866 break;
18867 case OPC_NOR_V:
18868 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
18869 break;
18870 case OPC_XOR_V:
18871 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
18872 break;
18873 case OPC_BMNZ_V:
18874 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
18875 break;
18876 case OPC_BMZ_V:
18877 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
18878 break;
18879 case OPC_BSEL_V:
18880 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
18881 break;
18882 default:
18883 MIPS_INVAL("MSA instruction");
18884 generate_exception_end(ctx, EXCP_RI);
18885 break;
18888 tcg_temp_free_i32(twd);
18889 tcg_temp_free_i32(tws);
18890 tcg_temp_free_i32(twt);
18893 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
18895 switch (MASK_MSA_VEC(ctx->opcode)) {
18896 case OPC_AND_V:
18897 case OPC_OR_V:
18898 case OPC_NOR_V:
18899 case OPC_XOR_V:
18900 case OPC_BMNZ_V:
18901 case OPC_BMZ_V:
18902 case OPC_BSEL_V:
18903 gen_msa_vec_v(env, ctx);
18904 break;
18905 case OPC_MSA_2R:
18906 gen_msa_2r(env, ctx);
18907 break;
18908 case OPC_MSA_2RF:
18909 gen_msa_2rf(env, ctx);
18910 break;
18911 default:
18912 MIPS_INVAL("MSA instruction");
18913 generate_exception_end(ctx, EXCP_RI);
18914 break;
18918 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
18920 uint32_t opcode = ctx->opcode;
18921 check_insn(ctx, ASE_MSA);
18922 check_msa_access(ctx);
18924 switch (MASK_MSA_MINOR(opcode)) {
18925 case OPC_MSA_I8_00:
18926 case OPC_MSA_I8_01:
18927 case OPC_MSA_I8_02:
18928 gen_msa_i8(env, ctx);
18929 break;
18930 case OPC_MSA_I5_06:
18931 case OPC_MSA_I5_07:
18932 gen_msa_i5(env, ctx);
18933 break;
18934 case OPC_MSA_BIT_09:
18935 case OPC_MSA_BIT_0A:
18936 gen_msa_bit(env, ctx);
18937 break;
18938 case OPC_MSA_3R_0D:
18939 case OPC_MSA_3R_0E:
18940 case OPC_MSA_3R_0F:
18941 case OPC_MSA_3R_10:
18942 case OPC_MSA_3R_11:
18943 case OPC_MSA_3R_12:
18944 case OPC_MSA_3R_13:
18945 case OPC_MSA_3R_14:
18946 case OPC_MSA_3R_15:
18947 gen_msa_3r(env, ctx);
18948 break;
18949 case OPC_MSA_ELM:
18950 gen_msa_elm(env, ctx);
18951 break;
18952 case OPC_MSA_3RF_1A:
18953 case OPC_MSA_3RF_1B:
18954 case OPC_MSA_3RF_1C:
18955 gen_msa_3rf(env, ctx);
18956 break;
18957 case OPC_MSA_VEC:
18958 gen_msa_vec(env, ctx);
18959 break;
18960 case OPC_LD_B:
18961 case OPC_LD_H:
18962 case OPC_LD_W:
18963 case OPC_LD_D:
18964 case OPC_ST_B:
18965 case OPC_ST_H:
18966 case OPC_ST_W:
18967 case OPC_ST_D:
18969 int32_t s10 = sextract32(ctx->opcode, 16, 10);
18970 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
18971 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18972 uint8_t df = (ctx->opcode >> 0) & 0x3;
18974 TCGv_i32 twd = tcg_const_i32(wd);
18975 TCGv taddr = tcg_temp_new();
18976 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
18978 switch (MASK_MSA_MINOR(opcode)) {
18979 case OPC_LD_B:
18980 gen_helper_msa_ld_b(cpu_env, twd, taddr);
18981 break;
18982 case OPC_LD_H:
18983 gen_helper_msa_ld_h(cpu_env, twd, taddr);
18984 break;
18985 case OPC_LD_W:
18986 gen_helper_msa_ld_w(cpu_env, twd, taddr);
18987 break;
18988 case OPC_LD_D:
18989 gen_helper_msa_ld_d(cpu_env, twd, taddr);
18990 break;
18991 case OPC_ST_B:
18992 gen_helper_msa_st_b(cpu_env, twd, taddr);
18993 break;
18994 case OPC_ST_H:
18995 gen_helper_msa_st_h(cpu_env, twd, taddr);
18996 break;
18997 case OPC_ST_W:
18998 gen_helper_msa_st_w(cpu_env, twd, taddr);
18999 break;
19000 case OPC_ST_D:
19001 gen_helper_msa_st_d(cpu_env, twd, taddr);
19002 break;
19005 tcg_temp_free_i32(twd);
19006 tcg_temp_free(taddr);
19008 break;
19009 default:
19010 MIPS_INVAL("MSA instruction");
19011 generate_exception_end(ctx, EXCP_RI);
19012 break;
19017 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
19019 int32_t offset;
19020 int rs, rt, rd, sa;
19021 uint32_t op, op1;
19022 int16_t imm;
19024 /* make sure instructions are on a word boundary */
19025 if (ctx->pc & 0x3) {
19026 env->CP0_BadVAddr = ctx->pc;
19027 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
19028 return;
19031 /* Handle blikely not taken case */
19032 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
19033 TCGLabel *l1 = gen_new_label();
19035 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
19036 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
19037 gen_goto_tb(ctx, 1, ctx->pc + 4);
19038 gen_set_label(l1);
19041 op = MASK_OP_MAJOR(ctx->opcode);
19042 rs = (ctx->opcode >> 21) & 0x1f;
19043 rt = (ctx->opcode >> 16) & 0x1f;
19044 rd = (ctx->opcode >> 11) & 0x1f;
19045 sa = (ctx->opcode >> 6) & 0x1f;
19046 imm = (int16_t)ctx->opcode;
19047 switch (op) {
19048 case OPC_SPECIAL:
19049 decode_opc_special(env, ctx);
19050 break;
19051 case OPC_SPECIAL2:
19052 decode_opc_special2_legacy(env, ctx);
19053 break;
19054 case OPC_SPECIAL3:
19055 decode_opc_special3(env, ctx);
19056 break;
19057 case OPC_REGIMM:
19058 op1 = MASK_REGIMM(ctx->opcode);
19059 switch (op1) {
19060 case OPC_BLTZL: /* REGIMM branches */
19061 case OPC_BGEZL:
19062 case OPC_BLTZALL:
19063 case OPC_BGEZALL:
19064 check_insn(ctx, ISA_MIPS2);
19065 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19066 /* Fallthrough */
19067 case OPC_BLTZ:
19068 case OPC_BGEZ:
19069 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19070 break;
19071 case OPC_BLTZAL:
19072 case OPC_BGEZAL:
19073 if (ctx->insn_flags & ISA_MIPS32R6) {
19074 if (rs == 0) {
19075 /* OPC_NAL, OPC_BAL */
19076 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
19077 } else {
19078 generate_exception_end(ctx, EXCP_RI);
19080 } else {
19081 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19083 break;
19084 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
19085 case OPC_TNEI:
19086 check_insn(ctx, ISA_MIPS2);
19087 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19088 gen_trap(ctx, op1, rs, -1, imm);
19089 break;
19090 case OPC_SIGRIE:
19091 check_insn(ctx, ISA_MIPS32R6);
19092 generate_exception_end(ctx, EXCP_RI);
19093 break;
19094 case OPC_SYNCI:
19095 check_insn(ctx, ISA_MIPS32R2);
19096 /* Break the TB to be able to sync copied instructions
19097 immediately */
19098 ctx->bstate = BS_STOP;
19099 break;
19100 case OPC_BPOSGE32: /* MIPS DSP branch */
19101 #if defined(TARGET_MIPS64)
19102 case OPC_BPOSGE64:
19103 #endif
19104 check_dsp(ctx);
19105 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
19106 break;
19107 #if defined(TARGET_MIPS64)
19108 case OPC_DAHI:
19109 check_insn(ctx, ISA_MIPS32R6);
19110 check_mips_64(ctx);
19111 if (rs != 0) {
19112 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
19114 break;
19115 case OPC_DATI:
19116 check_insn(ctx, ISA_MIPS32R6);
19117 check_mips_64(ctx);
19118 if (rs != 0) {
19119 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
19121 break;
19122 #endif
19123 default: /* Invalid */
19124 MIPS_INVAL("regimm");
19125 generate_exception_end(ctx, EXCP_RI);
19126 break;
19128 break;
19129 case OPC_CP0:
19130 check_cp0_enabled(ctx);
19131 op1 = MASK_CP0(ctx->opcode);
19132 switch (op1) {
19133 case OPC_MFC0:
19134 case OPC_MTC0:
19135 case OPC_MFTR:
19136 case OPC_MTTR:
19137 case OPC_MFHC0:
19138 case OPC_MTHC0:
19139 #if defined(TARGET_MIPS64)
19140 case OPC_DMFC0:
19141 case OPC_DMTC0:
19142 #endif
19143 #ifndef CONFIG_USER_ONLY
19144 gen_cp0(env, ctx, op1, rt, rd);
19145 #endif /* !CONFIG_USER_ONLY */
19146 break;
19147 case OPC_C0_FIRST ... OPC_C0_LAST:
19148 #ifndef CONFIG_USER_ONLY
19149 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
19150 #endif /* !CONFIG_USER_ONLY */
19151 break;
19152 case OPC_MFMC0:
19153 #ifndef CONFIG_USER_ONLY
19155 uint32_t op2;
19156 TCGv t0 = tcg_temp_new();
19158 op2 = MASK_MFMC0(ctx->opcode);
19159 switch (op2) {
19160 case OPC_DMT:
19161 check_insn(ctx, ASE_MT);
19162 gen_helper_dmt(t0);
19163 gen_store_gpr(t0, rt);
19164 break;
19165 case OPC_EMT:
19166 check_insn(ctx, ASE_MT);
19167 gen_helper_emt(t0);
19168 gen_store_gpr(t0, rt);
19169 break;
19170 case OPC_DVPE:
19171 check_insn(ctx, ASE_MT);
19172 gen_helper_dvpe(t0, cpu_env);
19173 gen_store_gpr(t0, rt);
19174 break;
19175 case OPC_EVPE:
19176 check_insn(ctx, ASE_MT);
19177 gen_helper_evpe(t0, cpu_env);
19178 gen_store_gpr(t0, rt);
19179 break;
19180 case OPC_DVP:
19181 check_insn(ctx, ISA_MIPS32R6);
19182 if (ctx->vp) {
19183 gen_helper_dvp(t0, cpu_env);
19184 gen_store_gpr(t0, rt);
19186 break;
19187 case OPC_EVP:
19188 check_insn(ctx, ISA_MIPS32R6);
19189 if (ctx->vp) {
19190 gen_helper_evp(t0, cpu_env);
19191 gen_store_gpr(t0, rt);
19193 break;
19194 case OPC_DI:
19195 check_insn(ctx, ISA_MIPS32R2);
19196 save_cpu_state(ctx, 1);
19197 gen_helper_di(t0, cpu_env);
19198 gen_store_gpr(t0, rt);
19199 /* Stop translation as we may have switched
19200 the execution mode. */
19201 ctx->bstate = BS_STOP;
19202 break;
19203 case OPC_EI:
19204 check_insn(ctx, ISA_MIPS32R2);
19205 save_cpu_state(ctx, 1);
19206 gen_helper_ei(t0, cpu_env);
19207 gen_store_gpr(t0, rt);
19208 /* Stop translation as we may have switched
19209 the execution mode. */
19210 ctx->bstate = BS_STOP;
19211 break;
19212 default: /* Invalid */
19213 MIPS_INVAL("mfmc0");
19214 generate_exception_end(ctx, EXCP_RI);
19215 break;
19217 tcg_temp_free(t0);
19219 #endif /* !CONFIG_USER_ONLY */
19220 break;
19221 case OPC_RDPGPR:
19222 check_insn(ctx, ISA_MIPS32R2);
19223 gen_load_srsgpr(rt, rd);
19224 break;
19225 case OPC_WRPGPR:
19226 check_insn(ctx, ISA_MIPS32R2);
19227 gen_store_srsgpr(rt, rd);
19228 break;
19229 default:
19230 MIPS_INVAL("cp0");
19231 generate_exception_end(ctx, EXCP_RI);
19232 break;
19234 break;
19235 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
19236 if (ctx->insn_flags & ISA_MIPS32R6) {
19237 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
19238 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19239 } else {
19240 /* OPC_ADDI */
19241 /* Arithmetic with immediate opcode */
19242 gen_arith_imm(ctx, op, rt, rs, imm);
19244 break;
19245 case OPC_ADDIU:
19246 gen_arith_imm(ctx, op, rt, rs, imm);
19247 break;
19248 case OPC_SLTI: /* Set on less than with immediate opcode */
19249 case OPC_SLTIU:
19250 gen_slt_imm(ctx, op, rt, rs, imm);
19251 break;
19252 case OPC_ANDI: /* Arithmetic with immediate opcode */
19253 case OPC_LUI: /* OPC_AUI */
19254 case OPC_ORI:
19255 case OPC_XORI:
19256 gen_logic_imm(ctx, op, rt, rs, imm);
19257 break;
19258 case OPC_J ... OPC_JAL: /* Jump */
19259 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19260 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19261 break;
19262 /* Branch */
19263 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
19264 if (ctx->insn_flags & ISA_MIPS32R6) {
19265 if (rt == 0) {
19266 generate_exception_end(ctx, EXCP_RI);
19267 break;
19269 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
19270 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19271 } else {
19272 /* OPC_BLEZL */
19273 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19275 break;
19276 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
19277 if (ctx->insn_flags & ISA_MIPS32R6) {
19278 if (rt == 0) {
19279 generate_exception_end(ctx, EXCP_RI);
19280 break;
19282 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
19283 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19284 } else {
19285 /* OPC_BGTZL */
19286 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19288 break;
19289 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
19290 if (rt == 0) {
19291 /* OPC_BLEZ */
19292 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19293 } else {
19294 check_insn(ctx, ISA_MIPS32R6);
19295 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
19296 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19298 break;
19299 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
19300 if (rt == 0) {
19301 /* OPC_BGTZ */
19302 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19303 } else {
19304 check_insn(ctx, ISA_MIPS32R6);
19305 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
19306 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19308 break;
19309 case OPC_BEQL:
19310 case OPC_BNEL:
19311 check_insn(ctx, ISA_MIPS2);
19312 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19313 /* Fallthrough */
19314 case OPC_BEQ:
19315 case OPC_BNE:
19316 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19317 break;
19318 case OPC_LL: /* Load and stores */
19319 check_insn(ctx, ISA_MIPS2);
19320 /* Fallthrough */
19321 case OPC_LWL:
19322 case OPC_LWR:
19323 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19324 /* Fallthrough */
19325 case OPC_LB ... OPC_LH:
19326 case OPC_LW ... OPC_LHU:
19327 gen_ld(ctx, op, rt, rs, imm);
19328 break;
19329 case OPC_SWL:
19330 case OPC_SWR:
19331 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19332 /* fall through */
19333 case OPC_SB ... OPC_SH:
19334 case OPC_SW:
19335 gen_st(ctx, op, rt, rs, imm);
19336 break;
19337 case OPC_SC:
19338 check_insn(ctx, ISA_MIPS2);
19339 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19340 gen_st_cond(ctx, op, rt, rs, imm);
19341 break;
19342 case OPC_CACHE:
19343 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19344 check_cp0_enabled(ctx);
19345 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
19346 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
19347 gen_cache_operation(ctx, rt, rs, imm);
19349 /* Treat as NOP. */
19350 break;
19351 case OPC_PREF:
19352 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19353 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
19354 /* Treat as NOP. */
19355 break;
19357 /* Floating point (COP1). */
19358 case OPC_LWC1:
19359 case OPC_LDC1:
19360 case OPC_SWC1:
19361 case OPC_SDC1:
19362 gen_cop1_ldst(ctx, op, rt, rs, imm);
19363 break;
19365 case OPC_CP1:
19366 op1 = MASK_CP1(ctx->opcode);
19368 switch (op1) {
19369 case OPC_MFHC1:
19370 case OPC_MTHC1:
19371 check_cp1_enabled(ctx);
19372 check_insn(ctx, ISA_MIPS32R2);
19373 case OPC_MFC1:
19374 case OPC_CFC1:
19375 case OPC_MTC1:
19376 case OPC_CTC1:
19377 check_cp1_enabled(ctx);
19378 gen_cp1(ctx, op1, rt, rd);
19379 break;
19380 #if defined(TARGET_MIPS64)
19381 case OPC_DMFC1:
19382 case OPC_DMTC1:
19383 check_cp1_enabled(ctx);
19384 check_insn(ctx, ISA_MIPS3);
19385 check_mips_64(ctx);
19386 gen_cp1(ctx, op1, rt, rd);
19387 break;
19388 #endif
19389 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
19390 check_cp1_enabled(ctx);
19391 if (ctx->insn_flags & ISA_MIPS32R6) {
19392 /* OPC_BC1EQZ */
19393 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19394 rt, imm << 2, 4);
19395 } else {
19396 /* OPC_BC1ANY2 */
19397 check_cop1x(ctx);
19398 check_insn(ctx, ASE_MIPS3D);
19399 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19400 (rt >> 2) & 0x7, imm << 2);
19402 break;
19403 case OPC_BC1NEZ:
19404 check_cp1_enabled(ctx);
19405 check_insn(ctx, ISA_MIPS32R6);
19406 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19407 rt, imm << 2, 4);
19408 break;
19409 case OPC_BC1ANY4:
19410 check_cp1_enabled(ctx);
19411 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19412 check_cop1x(ctx);
19413 check_insn(ctx, ASE_MIPS3D);
19414 /* fall through */
19415 case OPC_BC1:
19416 check_cp1_enabled(ctx);
19417 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19418 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19419 (rt >> 2) & 0x7, imm << 2);
19420 break;
19421 case OPC_PS_FMT:
19422 check_ps(ctx);
19423 /* fall through */
19424 case OPC_S_FMT:
19425 case OPC_D_FMT:
19426 check_cp1_enabled(ctx);
19427 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19428 (imm >> 8) & 0x7);
19429 break;
19430 case OPC_W_FMT:
19431 case OPC_L_FMT:
19433 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
19434 check_cp1_enabled(ctx);
19435 if (ctx->insn_flags & ISA_MIPS32R6) {
19436 switch (r6_op) {
19437 case R6_OPC_CMP_AF_S:
19438 case R6_OPC_CMP_UN_S:
19439 case R6_OPC_CMP_EQ_S:
19440 case R6_OPC_CMP_UEQ_S:
19441 case R6_OPC_CMP_LT_S:
19442 case R6_OPC_CMP_ULT_S:
19443 case R6_OPC_CMP_LE_S:
19444 case R6_OPC_CMP_ULE_S:
19445 case R6_OPC_CMP_SAF_S:
19446 case R6_OPC_CMP_SUN_S:
19447 case R6_OPC_CMP_SEQ_S:
19448 case R6_OPC_CMP_SEUQ_S:
19449 case R6_OPC_CMP_SLT_S:
19450 case R6_OPC_CMP_SULT_S:
19451 case R6_OPC_CMP_SLE_S:
19452 case R6_OPC_CMP_SULE_S:
19453 case R6_OPC_CMP_OR_S:
19454 case R6_OPC_CMP_UNE_S:
19455 case R6_OPC_CMP_NE_S:
19456 case R6_OPC_CMP_SOR_S:
19457 case R6_OPC_CMP_SUNE_S:
19458 case R6_OPC_CMP_SNE_S:
19459 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19460 break;
19461 case R6_OPC_CMP_AF_D:
19462 case R6_OPC_CMP_UN_D:
19463 case R6_OPC_CMP_EQ_D:
19464 case R6_OPC_CMP_UEQ_D:
19465 case R6_OPC_CMP_LT_D:
19466 case R6_OPC_CMP_ULT_D:
19467 case R6_OPC_CMP_LE_D:
19468 case R6_OPC_CMP_ULE_D:
19469 case R6_OPC_CMP_SAF_D:
19470 case R6_OPC_CMP_SUN_D:
19471 case R6_OPC_CMP_SEQ_D:
19472 case R6_OPC_CMP_SEUQ_D:
19473 case R6_OPC_CMP_SLT_D:
19474 case R6_OPC_CMP_SULT_D:
19475 case R6_OPC_CMP_SLE_D:
19476 case R6_OPC_CMP_SULE_D:
19477 case R6_OPC_CMP_OR_D:
19478 case R6_OPC_CMP_UNE_D:
19479 case R6_OPC_CMP_NE_D:
19480 case R6_OPC_CMP_SOR_D:
19481 case R6_OPC_CMP_SUNE_D:
19482 case R6_OPC_CMP_SNE_D:
19483 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19484 break;
19485 default:
19486 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
19487 rt, rd, sa, (imm >> 8) & 0x7);
19489 break;
19491 } else {
19492 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19493 (imm >> 8) & 0x7);
19495 break;
19497 case OPC_BZ_V:
19498 case OPC_BNZ_V:
19499 case OPC_BZ_B:
19500 case OPC_BZ_H:
19501 case OPC_BZ_W:
19502 case OPC_BZ_D:
19503 case OPC_BNZ_B:
19504 case OPC_BNZ_H:
19505 case OPC_BNZ_W:
19506 case OPC_BNZ_D:
19507 check_insn(ctx, ASE_MSA);
19508 gen_msa_branch(env, ctx, op1);
19509 break;
19510 default:
19511 MIPS_INVAL("cp1");
19512 generate_exception_end(ctx, EXCP_RI);
19513 break;
19515 break;
19517 /* Compact branches [R6] and COP2 [non-R6] */
19518 case OPC_BC: /* OPC_LWC2 */
19519 case OPC_BALC: /* OPC_SWC2 */
19520 if (ctx->insn_flags & ISA_MIPS32R6) {
19521 /* OPC_BC, OPC_BALC */
19522 gen_compute_compact_branch(ctx, op, 0, 0,
19523 sextract32(ctx->opcode << 2, 0, 28));
19524 } else {
19525 /* OPC_LWC2, OPC_SWC2 */
19526 /* COP2: Not implemented. */
19527 generate_exception_err(ctx, EXCP_CpU, 2);
19529 break;
19530 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
19531 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
19532 if (ctx->insn_flags & ISA_MIPS32R6) {
19533 if (rs != 0) {
19534 /* OPC_BEQZC, OPC_BNEZC */
19535 gen_compute_compact_branch(ctx, op, rs, 0,
19536 sextract32(ctx->opcode << 2, 0, 23));
19537 } else {
19538 /* OPC_JIC, OPC_JIALC */
19539 gen_compute_compact_branch(ctx, op, 0, rt, imm);
19541 } else {
19542 /* OPC_LWC2, OPC_SWC2 */
19543 /* COP2: Not implemented. */
19544 generate_exception_err(ctx, EXCP_CpU, 2);
19546 break;
19547 case OPC_CP2:
19548 check_insn(ctx, INSN_LOONGSON2F);
19549 /* Note that these instructions use different fields. */
19550 gen_loongson_multimedia(ctx, sa, rd, rt);
19551 break;
19553 case OPC_CP3:
19554 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19555 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19556 check_cp1_enabled(ctx);
19557 op1 = MASK_CP3(ctx->opcode);
19558 switch (op1) {
19559 case OPC_LUXC1:
19560 case OPC_SUXC1:
19561 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19562 /* Fallthrough */
19563 case OPC_LWXC1:
19564 case OPC_LDXC1:
19565 case OPC_SWXC1:
19566 case OPC_SDXC1:
19567 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19568 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
19569 break;
19570 case OPC_PREFX:
19571 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19572 /* Treat as NOP. */
19573 break;
19574 case OPC_ALNV_PS:
19575 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19576 /* Fallthrough */
19577 case OPC_MADD_S:
19578 case OPC_MADD_D:
19579 case OPC_MADD_PS:
19580 case OPC_MSUB_S:
19581 case OPC_MSUB_D:
19582 case OPC_MSUB_PS:
19583 case OPC_NMADD_S:
19584 case OPC_NMADD_D:
19585 case OPC_NMADD_PS:
19586 case OPC_NMSUB_S:
19587 case OPC_NMSUB_D:
19588 case OPC_NMSUB_PS:
19589 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19590 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
19591 break;
19592 default:
19593 MIPS_INVAL("cp3");
19594 generate_exception_end(ctx, EXCP_RI);
19595 break;
19597 } else {
19598 generate_exception_err(ctx, EXCP_CpU, 1);
19600 break;
19602 #if defined(TARGET_MIPS64)
19603 /* MIPS64 opcodes */
19604 case OPC_LDL ... OPC_LDR:
19605 case OPC_LLD:
19606 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19607 /* fall through */
19608 case OPC_LWU:
19609 case OPC_LD:
19610 check_insn(ctx, ISA_MIPS3);
19611 check_mips_64(ctx);
19612 gen_ld(ctx, op, rt, rs, imm);
19613 break;
19614 case OPC_SDL ... OPC_SDR:
19615 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19616 /* fall through */
19617 case OPC_SD:
19618 check_insn(ctx, ISA_MIPS3);
19619 check_mips_64(ctx);
19620 gen_st(ctx, op, rt, rs, imm);
19621 break;
19622 case OPC_SCD:
19623 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19624 check_insn(ctx, ISA_MIPS3);
19625 check_mips_64(ctx);
19626 gen_st_cond(ctx, op, rt, rs, imm);
19627 break;
19628 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
19629 if (ctx->insn_flags & ISA_MIPS32R6) {
19630 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
19631 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19632 } else {
19633 /* OPC_DADDI */
19634 check_insn(ctx, ISA_MIPS3);
19635 check_mips_64(ctx);
19636 gen_arith_imm(ctx, op, rt, rs, imm);
19638 break;
19639 case OPC_DADDIU:
19640 check_insn(ctx, ISA_MIPS3);
19641 check_mips_64(ctx);
19642 gen_arith_imm(ctx, op, rt, rs, imm);
19643 break;
19644 #else
19645 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
19646 if (ctx->insn_flags & ISA_MIPS32R6) {
19647 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19648 } else {
19649 MIPS_INVAL("major opcode");
19650 generate_exception_end(ctx, EXCP_RI);
19652 break;
19653 #endif
19654 case OPC_DAUI: /* OPC_JALX */
19655 if (ctx->insn_flags & ISA_MIPS32R6) {
19656 #if defined(TARGET_MIPS64)
19657 /* OPC_DAUI */
19658 check_mips_64(ctx);
19659 if (rs == 0) {
19660 generate_exception(ctx, EXCP_RI);
19661 } else if (rt != 0) {
19662 TCGv t0 = tcg_temp_new();
19663 gen_load_gpr(t0, rs);
19664 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
19665 tcg_temp_free(t0);
19667 #else
19668 generate_exception_end(ctx, EXCP_RI);
19669 MIPS_INVAL("major opcode");
19670 #endif
19671 } else {
19672 /* OPC_JALX */
19673 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
19674 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19675 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19677 break;
19678 case OPC_MSA: /* OPC_MDMX */
19679 /* MDMX: Not implemented. */
19680 gen_msa(env, ctx);
19681 break;
19682 case OPC_PCREL:
19683 check_insn(ctx, ISA_MIPS32R6);
19684 gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
19685 break;
19686 default: /* Invalid */
19687 MIPS_INVAL("major opcode");
19688 generate_exception_end(ctx, EXCP_RI);
19689 break;
19693 void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
19695 MIPSCPU *cpu = mips_env_get_cpu(env);
19696 CPUState *cs = CPU(cpu);
19697 DisasContext ctx;
19698 target_ulong pc_start;
19699 target_ulong next_page_start;
19700 int num_insns;
19701 int max_insns;
19702 int insn_bytes;
19703 int is_slot;
19705 pc_start = tb->pc;
19706 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
19707 ctx.pc = pc_start;
19708 ctx.saved_pc = -1;
19709 ctx.singlestep_enabled = cs->singlestep_enabled;
19710 ctx.insn_flags = env->insn_flags;
19711 ctx.CP0_Config1 = env->CP0_Config1;
19712 ctx.tb = tb;
19713 ctx.bstate = BS_NONE;
19714 ctx.btarget = 0;
19715 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
19716 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
19717 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
19718 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
19719 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
19720 ctx.PAMask = env->PAMask;
19721 ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
19722 ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
19723 ctx.cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
19724 /* Restore delay slot state from the tb context. */
19725 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
19726 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
19727 ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
19728 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
19729 ctx.vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
19730 restore_cpu_state(env, &ctx);
19731 #ifdef CONFIG_USER_ONLY
19732 ctx.mem_idx = MIPS_HFLAG_UM;
19733 #else
19734 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
19735 #endif
19736 ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
19737 MO_UNALN : MO_ALIGN;
19738 num_insns = 0;
19739 max_insns = tb->cflags & CF_COUNT_MASK;
19740 if (max_insns == 0) {
19741 max_insns = CF_COUNT_MASK;
19743 if (max_insns > TCG_MAX_INSNS) {
19744 max_insns = TCG_MAX_INSNS;
19747 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
19748 gen_tb_start(tb);
19749 while (ctx.bstate == BS_NONE) {
19750 tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
19751 num_insns++;
19753 if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
19754 save_cpu_state(&ctx, 1);
19755 ctx.bstate = BS_BRANCH;
19756 gen_helper_raise_exception_debug(cpu_env);
19757 /* The address covered by the breakpoint must be included in
19758 [tb->pc, tb->pc + tb->size) in order to for it to be
19759 properly cleared -- thus we increment the PC here so that
19760 the logic setting tb->size below does the right thing. */
19761 ctx.pc += 4;
19762 goto done_generating;
19765 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
19766 gen_io_start();
19769 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
19770 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
19771 ctx.opcode = cpu_ldl_code(env, ctx.pc);
19772 insn_bytes = 4;
19773 decode_opc(env, &ctx);
19774 } else if (ctx.insn_flags & ASE_MICROMIPS) {
19775 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19776 insn_bytes = decode_micromips_opc(env, &ctx);
19777 } else if (ctx.insn_flags & ASE_MIPS16) {
19778 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19779 insn_bytes = decode_mips16_opc(env, &ctx);
19780 } else {
19781 generate_exception_end(&ctx, EXCP_RI);
19782 break;
19785 if (ctx.hflags & MIPS_HFLAG_BMASK) {
19786 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
19787 MIPS_HFLAG_FBNSLOT))) {
19788 /* force to generate branch as there is neither delay nor
19789 forbidden slot */
19790 is_slot = 1;
19792 if ((ctx.hflags & MIPS_HFLAG_M16) &&
19793 (ctx.hflags & MIPS_HFLAG_FBNSLOT)) {
19794 /* Force to generate branch as microMIPS R6 doesn't restrict
19795 branches in the forbidden slot. */
19796 is_slot = 1;
19799 if (is_slot) {
19800 gen_branch(&ctx, insn_bytes);
19802 ctx.pc += insn_bytes;
19804 /* Execute a branch and its delay slot as a single instruction.
19805 This is what GDB expects and is consistent with what the
19806 hardware does (e.g. if a delay slot instruction faults, the
19807 reported PC is the PC of the branch). */
19808 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
19809 break;
19812 if (ctx.pc >= next_page_start) {
19813 break;
19816 if (tcg_op_buf_full()) {
19817 break;
19820 if (num_insns >= max_insns)
19821 break;
19823 if (singlestep)
19824 break;
19826 if (tb->cflags & CF_LAST_IO) {
19827 gen_io_end();
19829 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
19830 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
19831 gen_helper_raise_exception_debug(cpu_env);
19832 } else {
19833 switch (ctx.bstate) {
19834 case BS_STOP:
19835 gen_goto_tb(&ctx, 0, ctx.pc);
19836 break;
19837 case BS_NONE:
19838 save_cpu_state(&ctx, 0);
19839 gen_goto_tb(&ctx, 0, ctx.pc);
19840 break;
19841 case BS_EXCP:
19842 tcg_gen_exit_tb(0);
19843 break;
19844 case BS_BRANCH:
19845 default:
19846 break;
19849 done_generating:
19850 gen_tb_end(tb, num_insns);
19852 tb->size = ctx.pc - pc_start;
19853 tb->icount = num_insns;
19855 #ifdef DEBUG_DISAS
19856 LOG_DISAS("\n");
19857 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
19858 qemu_log("IN: %s\n", lookup_symbol(pc_start));
19859 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
19860 qemu_log("\n");
19862 #endif
19865 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
19866 int flags)
19868 int i;
19869 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
19871 #define printfpr(fp) \
19872 do { \
19873 if (is_fpu64) \
19874 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19875 " fd:%13g fs:%13g psu: %13g\n", \
19876 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
19877 (double)(fp)->fd, \
19878 (double)(fp)->fs[FP_ENDIAN_IDX], \
19879 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
19880 else { \
19881 fpr_t tmp; \
19882 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
19883 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
19884 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19885 " fd:%13g fs:%13g psu:%13g\n", \
19886 tmp.w[FP_ENDIAN_IDX], tmp.d, \
19887 (double)tmp.fd, \
19888 (double)tmp.fs[FP_ENDIAN_IDX], \
19889 (double)tmp.fs[!FP_ENDIAN_IDX]); \
19891 } while(0)
19894 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
19895 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
19896 get_float_exception_flags(&env->active_fpu.fp_status));
19897 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
19898 fpu_fprintf(f, "%3s: ", fregnames[i]);
19899 printfpr(&env->active_fpu.fpr[i]);
19902 #undef printfpr
19905 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
19906 int flags)
19908 MIPSCPU *cpu = MIPS_CPU(cs);
19909 CPUMIPSState *env = &cpu->env;
19910 int i;
19912 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
19913 " LO=0x" TARGET_FMT_lx " ds %04x "
19914 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
19915 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
19916 env->hflags, env->btarget, env->bcond);
19917 for (i = 0; i < 32; i++) {
19918 if ((i & 3) == 0)
19919 cpu_fprintf(f, "GPR%02d:", i);
19920 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
19921 if ((i & 3) == 3)
19922 cpu_fprintf(f, "\n");
19925 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
19926 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
19927 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
19928 PRIx64 "\n",
19929 env->CP0_Config0, env->CP0_Config1, env->lladdr);
19930 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
19931 env->CP0_Config2, env->CP0_Config3);
19932 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
19933 env->CP0_Config4, env->CP0_Config5);
19934 if (env->hflags & MIPS_HFLAG_FPU)
19935 fpu_dump_state(env, f, cpu_fprintf, flags);
19938 void mips_tcg_init(void)
19940 int i;
19941 static int inited;
19943 /* Initialize various static tables. */
19944 if (inited)
19945 return;
19947 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
19949 TCGV_UNUSED(cpu_gpr[0]);
19950 for (i = 1; i < 32; i++)
19951 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
19952 offsetof(CPUMIPSState, active_tc.gpr[i]),
19953 regnames[i]);
19955 for (i = 0; i < 32; i++) {
19956 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
19957 msa_wr_d[i * 2] =
19958 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
19959 /* The scalar floating-point unit (FPU) registers are mapped on
19960 * the MSA vector registers. */
19961 fpu_f64[i] = msa_wr_d[i * 2];
19962 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
19963 msa_wr_d[i * 2 + 1] =
19964 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
19967 cpu_PC = tcg_global_mem_new(cpu_env,
19968 offsetof(CPUMIPSState, active_tc.PC), "PC");
19969 for (i = 0; i < MIPS_DSP_ACC; i++) {
19970 cpu_HI[i] = tcg_global_mem_new(cpu_env,
19971 offsetof(CPUMIPSState, active_tc.HI[i]),
19972 regnames_HI[i]);
19973 cpu_LO[i] = tcg_global_mem_new(cpu_env,
19974 offsetof(CPUMIPSState, active_tc.LO[i]),
19975 regnames_LO[i]);
19977 cpu_dspctrl = tcg_global_mem_new(cpu_env,
19978 offsetof(CPUMIPSState, active_tc.DSPControl),
19979 "DSPControl");
19980 bcond = tcg_global_mem_new(cpu_env,
19981 offsetof(CPUMIPSState, bcond), "bcond");
19982 btarget = tcg_global_mem_new(cpu_env,
19983 offsetof(CPUMIPSState, btarget), "btarget");
19984 hflags = tcg_global_mem_new_i32(cpu_env,
19985 offsetof(CPUMIPSState, hflags), "hflags");
19987 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
19988 offsetof(CPUMIPSState, active_fpu.fcr0),
19989 "fcr0");
19990 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
19991 offsetof(CPUMIPSState, active_fpu.fcr31),
19992 "fcr31");
19994 inited = 1;
19997 #include "translate_init.c"
19999 MIPSCPU *cpu_mips_init(const char *cpu_model)
20001 MIPSCPU *cpu;
20002 CPUMIPSState *env;
20003 const mips_def_t *def;
20005 def = cpu_mips_find_by_name(cpu_model);
20006 if (!def)
20007 return NULL;
20008 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
20009 env = &cpu->env;
20010 env->cpu_model = def;
20012 #ifndef CONFIG_USER_ONLY
20013 mmu_init(env, def);
20014 #endif
20015 fpu_init(env, def);
20016 mvp_init(env, def);
20018 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
20020 return cpu;
20023 bool cpu_supports_cps_smp(const char *cpu_model)
20025 const mips_def_t *def = cpu_mips_find_by_name(cpu_model);
20026 if (!def) {
20027 return false;
20030 return (def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
20033 void cpu_state_reset(CPUMIPSState *env)
20035 MIPSCPU *cpu = mips_env_get_cpu(env);
20036 CPUState *cs = CPU(cpu);
20038 /* Reset registers to their default values */
20039 env->CP0_PRid = env->cpu_model->CP0_PRid;
20040 env->CP0_Config0 = env->cpu_model->CP0_Config0;
20041 #ifdef TARGET_WORDS_BIGENDIAN
20042 env->CP0_Config0 |= (1 << CP0C0_BE);
20043 #endif
20044 env->CP0_Config1 = env->cpu_model->CP0_Config1;
20045 env->CP0_Config2 = env->cpu_model->CP0_Config2;
20046 env->CP0_Config3 = env->cpu_model->CP0_Config3;
20047 env->CP0_Config4 = env->cpu_model->CP0_Config4;
20048 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
20049 env->CP0_Config5 = env->cpu_model->CP0_Config5;
20050 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
20051 env->CP0_Config6 = env->cpu_model->CP0_Config6;
20052 env->CP0_Config7 = env->cpu_model->CP0_Config7;
20053 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
20054 << env->cpu_model->CP0_LLAddr_shift;
20055 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
20056 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
20057 env->CCRes = env->cpu_model->CCRes;
20058 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
20059 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
20060 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
20061 env->current_tc = 0;
20062 env->SEGBITS = env->cpu_model->SEGBITS;
20063 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
20064 #if defined(TARGET_MIPS64)
20065 if (env->cpu_model->insn_flags & ISA_MIPS3) {
20066 env->SEGMask |= 3ULL << 62;
20068 #endif
20069 env->PABITS = env->cpu_model->PABITS;
20070 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
20071 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
20072 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
20073 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
20074 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
20075 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
20076 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
20077 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
20078 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
20079 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
20080 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
20081 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
20082 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
20083 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
20084 env->msair = env->cpu_model->MSAIR;
20085 env->insn_flags = env->cpu_model->insn_flags;
20087 #if defined(CONFIG_USER_ONLY)
20088 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
20089 # ifdef TARGET_MIPS64
20090 /* Enable 64-bit register mode. */
20091 env->CP0_Status |= (1 << CP0St_PX);
20092 # endif
20093 # ifdef TARGET_ABI_MIPSN64
20094 /* Enable 64-bit address mode. */
20095 env->CP0_Status |= (1 << CP0St_UX);
20096 # endif
20097 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
20098 hardware registers. */
20099 env->CP0_HWREna |= 0x0000000F;
20100 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
20101 env->CP0_Status |= (1 << CP0St_CU1);
20103 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
20104 env->CP0_Status |= (1 << CP0St_MX);
20106 # if defined(TARGET_MIPS64)
20107 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
20108 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
20109 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
20110 env->CP0_Status |= (1 << CP0St_FR);
20112 # endif
20113 #else
20114 if (env->hflags & MIPS_HFLAG_BMASK) {
20115 /* If the exception was raised from a delay slot,
20116 come back to the jump. */
20117 env->CP0_ErrorEPC = (env->active_tc.PC
20118 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
20119 } else {
20120 env->CP0_ErrorEPC = env->active_tc.PC;
20122 env->active_tc.PC = (int32_t)0xBFC00000;
20123 env->CP0_Random = env->tlb->nb_tlb - 1;
20124 env->tlb->tlb_in_use = env->tlb->nb_tlb;
20125 env->CP0_Wired = 0;
20126 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
20127 env->CP0_EBase = (cs->cpu_index & 0x3FF);
20128 if (kvm_enabled()) {
20129 env->CP0_EBase |= 0x40000000;
20130 } else {
20131 env->CP0_EBase |= 0x80000000;
20133 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
20134 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
20136 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
20137 /* vectored interrupts not implemented, timer on int 7,
20138 no performance counters. */
20139 env->CP0_IntCtl = 0xe0000000;
20141 int i;
20143 for (i = 0; i < 7; i++) {
20144 env->CP0_WatchLo[i] = 0;
20145 env->CP0_WatchHi[i] = 0x80000000;
20147 env->CP0_WatchLo[7] = 0;
20148 env->CP0_WatchHi[7] = 0;
20150 /* Count register increments in debug mode, EJTAG version 1 */
20151 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
20153 cpu_mips_store_count(env, 1);
20155 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
20156 int i;
20158 /* Only TC0 on VPE 0 starts as active. */
20159 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
20160 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
20161 env->tcs[i].CP0_TCHalt = 1;
20163 env->active_tc.CP0_TCHalt = 1;
20164 cs->halted = 1;
20166 if (cs->cpu_index == 0) {
20167 /* VPE0 starts up enabled. */
20168 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
20169 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
20171 /* TC0 starts up unhalted. */
20172 cs->halted = 0;
20173 env->active_tc.CP0_TCHalt = 0;
20174 env->tcs[0].CP0_TCHalt = 0;
20175 /* With thread 0 active. */
20176 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
20177 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
20180 #endif
20181 if ((env->insn_flags & ISA_MIPS32R6) &&
20182 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
20183 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
20184 env->CP0_Status |= (1 << CP0St_FR);
20187 /* MSA */
20188 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
20189 msa_reset(env);
20192 compute_hflags(env);
20193 restore_rounding_mode(env);
20194 restore_flush_mode(env);
20195 restore_pamask(env);
20196 cs->exception_index = EXCP_NONE;
20198 if (semihosting_get_argc()) {
20199 /* UHI interface can be used to obtain argc and argv */
20200 env->active_tc.gpr[4] = -1;
20204 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
20205 target_ulong *data)
20207 env->active_tc.PC = data[0];
20208 env->hflags &= ~MIPS_HFLAG_BMASK;
20209 env->hflags |= data[1];
20210 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
20211 case MIPS_HFLAG_BR:
20212 break;
20213 case MIPS_HFLAG_BC:
20214 case MIPS_HFLAG_BL:
20215 case MIPS_HFLAG_B:
20216 env->btarget = data[2];
20217 break;