tests/boot-sector: Use mkstemp() to create a unique file name
[qemu/rayw.git] / target-mips / translate.c
blob55c2ca0c7b4e8c95c0cde15cbe26b491a4154368
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "disas/disas.h"
27 #include "exec/exec-all.h"
28 #include "tcg-op.h"
29 #include "exec/cpu_ldst.h"
31 #include "exec/helper-proto.h"
32 #include "exec/helper-gen.h"
33 #include "sysemu/kvm.h"
34 #include "exec/semihost.h"
36 #include "trace-tcg.h"
37 #include "exec/log.h"
39 #define MIPS_DEBUG_DISAS 0
41 /* MIPS major opcodes */
42 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
44 enum {
45 /* indirect opcode tables */
46 OPC_SPECIAL = (0x00 << 26),
47 OPC_REGIMM = (0x01 << 26),
48 OPC_CP0 = (0x10 << 26),
49 OPC_CP1 = (0x11 << 26),
50 OPC_CP2 = (0x12 << 26),
51 OPC_CP3 = (0x13 << 26),
52 OPC_SPECIAL2 = (0x1C << 26),
53 OPC_SPECIAL3 = (0x1F << 26),
54 /* arithmetic with immediate */
55 OPC_ADDI = (0x08 << 26),
56 OPC_ADDIU = (0x09 << 26),
57 OPC_SLTI = (0x0A << 26),
58 OPC_SLTIU = (0x0B << 26),
59 /* logic with immediate */
60 OPC_ANDI = (0x0C << 26),
61 OPC_ORI = (0x0D << 26),
62 OPC_XORI = (0x0E << 26),
63 OPC_LUI = (0x0F << 26),
64 /* arithmetic with immediate */
65 OPC_DADDI = (0x18 << 26),
66 OPC_DADDIU = (0x19 << 26),
67 /* Jump and branches */
68 OPC_J = (0x02 << 26),
69 OPC_JAL = (0x03 << 26),
70 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
71 OPC_BEQL = (0x14 << 26),
72 OPC_BNE = (0x05 << 26),
73 OPC_BNEL = (0x15 << 26),
74 OPC_BLEZ = (0x06 << 26),
75 OPC_BLEZL = (0x16 << 26),
76 OPC_BGTZ = (0x07 << 26),
77 OPC_BGTZL = (0x17 << 26),
78 OPC_JALX = (0x1D << 26),
79 OPC_DAUI = (0x1D << 26),
80 /* Load and stores */
81 OPC_LDL = (0x1A << 26),
82 OPC_LDR = (0x1B << 26),
83 OPC_LB = (0x20 << 26),
84 OPC_LH = (0x21 << 26),
85 OPC_LWL = (0x22 << 26),
86 OPC_LW = (0x23 << 26),
87 OPC_LWPC = OPC_LW | 0x5,
88 OPC_LBU = (0x24 << 26),
89 OPC_LHU = (0x25 << 26),
90 OPC_LWR = (0x26 << 26),
91 OPC_LWU = (0x27 << 26),
92 OPC_SB = (0x28 << 26),
93 OPC_SH = (0x29 << 26),
94 OPC_SWL = (0x2A << 26),
95 OPC_SW = (0x2B << 26),
96 OPC_SDL = (0x2C << 26),
97 OPC_SDR = (0x2D << 26),
98 OPC_SWR = (0x2E << 26),
99 OPC_LL = (0x30 << 26),
100 OPC_LLD = (0x34 << 26),
101 OPC_LD = (0x37 << 26),
102 OPC_LDPC = OPC_LD | 0x5,
103 OPC_SC = (0x38 << 26),
104 OPC_SCD = (0x3C << 26),
105 OPC_SD = (0x3F << 26),
106 /* Floating point load/store */
107 OPC_LWC1 = (0x31 << 26),
108 OPC_LWC2 = (0x32 << 26),
109 OPC_LDC1 = (0x35 << 26),
110 OPC_LDC2 = (0x36 << 26),
111 OPC_SWC1 = (0x39 << 26),
112 OPC_SWC2 = (0x3A << 26),
113 OPC_SDC1 = (0x3D << 26),
114 OPC_SDC2 = (0x3E << 26),
115 /* Compact Branches */
116 OPC_BLEZALC = (0x06 << 26),
117 OPC_BGEZALC = (0x06 << 26),
118 OPC_BGEUC = (0x06 << 26),
119 OPC_BGTZALC = (0x07 << 26),
120 OPC_BLTZALC = (0x07 << 26),
121 OPC_BLTUC = (0x07 << 26),
122 OPC_BOVC = (0x08 << 26),
123 OPC_BEQZALC = (0x08 << 26),
124 OPC_BEQC = (0x08 << 26),
125 OPC_BLEZC = (0x16 << 26),
126 OPC_BGEZC = (0x16 << 26),
127 OPC_BGEC = (0x16 << 26),
128 OPC_BGTZC = (0x17 << 26),
129 OPC_BLTZC = (0x17 << 26),
130 OPC_BLTC = (0x17 << 26),
131 OPC_BNVC = (0x18 << 26),
132 OPC_BNEZALC = (0x18 << 26),
133 OPC_BNEC = (0x18 << 26),
134 OPC_BC = (0x32 << 26),
135 OPC_BEQZC = (0x36 << 26),
136 OPC_JIC = (0x36 << 26),
137 OPC_BALC = (0x3A << 26),
138 OPC_BNEZC = (0x3E << 26),
139 OPC_JIALC = (0x3E << 26),
140 /* MDMX ASE specific */
141 OPC_MDMX = (0x1E << 26),
142 /* MSA ASE, same as MDMX */
143 OPC_MSA = OPC_MDMX,
144 /* Cache and prefetch */
145 OPC_CACHE = (0x2F << 26),
146 OPC_PREF = (0x33 << 26),
147 /* PC-relative address computation / loads */
148 OPC_PCREL = (0x3B << 26),
151 /* PC-relative address computation / loads */
152 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
153 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
154 enum {
155 /* Instructions determined by bits 19 and 20 */
156 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
157 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
158 OPC_LWUPC = OPC_PCREL | (2 << 19),
160 /* Instructions determined by bits 16 ... 20 */
161 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
162 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
164 /* Other */
165 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
168 /* MIPS special opcodes */
169 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
171 enum {
172 /* Shifts */
173 OPC_SLL = 0x00 | OPC_SPECIAL,
174 /* NOP is SLL r0, r0, 0 */
175 /* SSNOP is SLL r0, r0, 1 */
176 /* EHB is SLL r0, r0, 3 */
177 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
178 OPC_ROTR = OPC_SRL | (1 << 21),
179 OPC_SRA = 0x03 | OPC_SPECIAL,
180 OPC_SLLV = 0x04 | OPC_SPECIAL,
181 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
182 OPC_ROTRV = OPC_SRLV | (1 << 6),
183 OPC_SRAV = 0x07 | OPC_SPECIAL,
184 OPC_DSLLV = 0x14 | OPC_SPECIAL,
185 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
186 OPC_DROTRV = OPC_DSRLV | (1 << 6),
187 OPC_DSRAV = 0x17 | OPC_SPECIAL,
188 OPC_DSLL = 0x38 | OPC_SPECIAL,
189 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
190 OPC_DROTR = OPC_DSRL | (1 << 21),
191 OPC_DSRA = 0x3B | OPC_SPECIAL,
192 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
193 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
194 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
195 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
196 /* Multiplication / division */
197 OPC_MULT = 0x18 | OPC_SPECIAL,
198 OPC_MULTU = 0x19 | OPC_SPECIAL,
199 OPC_DIV = 0x1A | OPC_SPECIAL,
200 OPC_DIVU = 0x1B | OPC_SPECIAL,
201 OPC_DMULT = 0x1C | OPC_SPECIAL,
202 OPC_DMULTU = 0x1D | OPC_SPECIAL,
203 OPC_DDIV = 0x1E | OPC_SPECIAL,
204 OPC_DDIVU = 0x1F | OPC_SPECIAL,
206 /* 2 registers arithmetic / logic */
207 OPC_ADD = 0x20 | OPC_SPECIAL,
208 OPC_ADDU = 0x21 | OPC_SPECIAL,
209 OPC_SUB = 0x22 | OPC_SPECIAL,
210 OPC_SUBU = 0x23 | OPC_SPECIAL,
211 OPC_AND = 0x24 | OPC_SPECIAL,
212 OPC_OR = 0x25 | OPC_SPECIAL,
213 OPC_XOR = 0x26 | OPC_SPECIAL,
214 OPC_NOR = 0x27 | OPC_SPECIAL,
215 OPC_SLT = 0x2A | OPC_SPECIAL,
216 OPC_SLTU = 0x2B | OPC_SPECIAL,
217 OPC_DADD = 0x2C | OPC_SPECIAL,
218 OPC_DADDU = 0x2D | OPC_SPECIAL,
219 OPC_DSUB = 0x2E | OPC_SPECIAL,
220 OPC_DSUBU = 0x2F | OPC_SPECIAL,
221 /* Jumps */
222 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
223 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
224 /* Traps */
225 OPC_TGE = 0x30 | OPC_SPECIAL,
226 OPC_TGEU = 0x31 | OPC_SPECIAL,
227 OPC_TLT = 0x32 | OPC_SPECIAL,
228 OPC_TLTU = 0x33 | OPC_SPECIAL,
229 OPC_TEQ = 0x34 | OPC_SPECIAL,
230 OPC_TNE = 0x36 | OPC_SPECIAL,
231 /* HI / LO registers load & stores */
232 OPC_MFHI = 0x10 | OPC_SPECIAL,
233 OPC_MTHI = 0x11 | OPC_SPECIAL,
234 OPC_MFLO = 0x12 | OPC_SPECIAL,
235 OPC_MTLO = 0x13 | OPC_SPECIAL,
236 /* Conditional moves */
237 OPC_MOVZ = 0x0A | OPC_SPECIAL,
238 OPC_MOVN = 0x0B | OPC_SPECIAL,
240 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
241 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
243 OPC_MOVCI = 0x01 | OPC_SPECIAL,
245 /* Special */
246 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
247 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
248 OPC_BREAK = 0x0D | OPC_SPECIAL,
249 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
250 OPC_SYNC = 0x0F | OPC_SPECIAL,
252 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
253 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
254 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
255 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
258 /* R6 Multiply and Divide instructions have the same Opcode
259 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
260 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
262 enum {
263 R6_OPC_MUL = OPC_MULT | (2 << 6),
264 R6_OPC_MUH = OPC_MULT | (3 << 6),
265 R6_OPC_MULU = OPC_MULTU | (2 << 6),
266 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
267 R6_OPC_DIV = OPC_DIV | (2 << 6),
268 R6_OPC_MOD = OPC_DIV | (3 << 6),
269 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
270 R6_OPC_MODU = OPC_DIVU | (3 << 6),
272 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
273 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
274 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
275 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
276 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
277 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
278 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
279 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
281 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
282 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
283 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
284 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
285 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
287 OPC_LSA = 0x05 | OPC_SPECIAL,
288 OPC_DLSA = 0x15 | OPC_SPECIAL,
291 /* Multiplication variants of the vr54xx. */
292 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
294 enum {
295 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
296 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
297 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
298 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
299 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
300 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
301 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
302 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
303 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
304 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
305 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
306 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
307 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
308 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
311 /* REGIMM (rt field) opcodes */
312 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
314 enum {
315 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
316 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
317 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
318 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
319 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
320 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
321 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
322 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
323 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
324 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
325 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
326 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
327 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
328 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
329 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
330 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
332 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
333 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
336 /* Special2 opcodes */
337 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
339 enum {
340 /* Multiply & xxx operations */
341 OPC_MADD = 0x00 | OPC_SPECIAL2,
342 OPC_MADDU = 0x01 | OPC_SPECIAL2,
343 OPC_MUL = 0x02 | OPC_SPECIAL2,
344 OPC_MSUB = 0x04 | OPC_SPECIAL2,
345 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
346 /* Loongson 2F */
347 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
348 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
349 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
350 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
351 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
352 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
353 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
354 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
355 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
356 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
357 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
358 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
359 /* Misc */
360 OPC_CLZ = 0x20 | OPC_SPECIAL2,
361 OPC_CLO = 0x21 | OPC_SPECIAL2,
362 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
363 OPC_DCLO = 0x25 | OPC_SPECIAL2,
364 /* Special */
365 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
368 /* Special3 opcodes */
369 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
371 enum {
372 OPC_EXT = 0x00 | OPC_SPECIAL3,
373 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
374 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
375 OPC_DEXT = 0x03 | OPC_SPECIAL3,
376 OPC_INS = 0x04 | OPC_SPECIAL3,
377 OPC_DINSM = 0x05 | OPC_SPECIAL3,
378 OPC_DINSU = 0x06 | OPC_SPECIAL3,
379 OPC_DINS = 0x07 | OPC_SPECIAL3,
380 OPC_FORK = 0x08 | OPC_SPECIAL3,
381 OPC_YIELD = 0x09 | OPC_SPECIAL3,
382 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
383 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
384 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
386 /* Loongson 2E */
387 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
388 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
389 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
390 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
391 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
392 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
393 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
394 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
395 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
396 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
397 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
398 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
400 /* MIPS DSP Load */
401 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
402 /* MIPS DSP Arithmetic */
403 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
404 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
405 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
406 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
407 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
408 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
409 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
410 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
411 /* MIPS DSP GPR-Based Shift Sub-class */
412 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
413 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
414 /* MIPS DSP Multiply Sub-class insns */
415 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
416 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
417 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
418 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
419 /* DSP Bit/Manipulation Sub-class */
420 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
421 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
422 /* MIPS DSP Append Sub-class */
423 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
424 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
425 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
426 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
427 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
429 /* R6 */
430 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
431 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
432 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
433 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
434 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
435 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
438 /* BSHFL opcodes */
439 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
441 enum {
442 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
443 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
444 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
445 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
446 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
447 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
450 /* DBSHFL opcodes */
451 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
453 enum {
454 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
455 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
456 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
457 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
458 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
461 /* MIPS DSP REGIMM opcodes */
462 enum {
463 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
464 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
467 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
468 /* MIPS DSP Load */
469 enum {
470 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
471 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
472 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
473 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
476 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
477 enum {
478 /* MIPS DSP Arithmetic Sub-class */
479 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
480 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
481 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
482 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
483 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
484 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
485 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
486 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
487 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
488 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
489 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
490 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
491 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
492 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
493 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
494 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
495 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
496 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
497 /* MIPS DSP Multiply Sub-class insns */
498 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
499 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
500 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
501 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
502 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
503 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
506 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
507 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
508 enum {
509 /* MIPS DSP Arithmetic Sub-class */
510 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
511 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
512 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
513 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
514 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
515 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
516 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
517 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
518 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
519 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
520 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
521 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
522 /* MIPS DSP Multiply Sub-class insns */
523 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
524 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
525 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
526 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
529 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
530 enum {
531 /* MIPS DSP Arithmetic Sub-class */
532 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
533 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
534 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
535 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
536 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
537 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
538 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
539 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
540 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
541 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
542 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
543 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
544 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
545 /* DSP Bit/Manipulation Sub-class */
546 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
547 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
548 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
549 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
550 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
553 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
554 enum {
555 /* MIPS DSP Arithmetic Sub-class */
556 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
557 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
558 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
559 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
560 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
561 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
562 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
563 /* DSP Compare-Pick Sub-class */
564 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
565 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
566 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
567 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
568 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
569 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
570 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
571 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
572 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
573 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
574 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
575 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
576 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
577 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
578 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
581 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
582 enum {
583 /* MIPS DSP GPR-Based Shift Sub-class */
584 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
585 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
586 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
587 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
588 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
589 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
590 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
591 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
592 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
593 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
594 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
595 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
596 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
597 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
598 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
599 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
600 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
601 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
602 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
603 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
604 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
605 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
608 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
609 enum {
610 /* MIPS DSP Multiply Sub-class insns */
611 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
612 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
613 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
614 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
615 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
616 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
617 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
618 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
619 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
620 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
621 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
622 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
623 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
624 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
625 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
626 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
627 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
628 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
629 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
630 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
631 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
632 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
635 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
636 enum {
637 /* DSP Bit/Manipulation Sub-class */
638 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
641 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
642 enum {
643 /* MIPS DSP Append Sub-class */
644 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
645 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
646 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
649 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
650 enum {
651 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
652 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
653 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
654 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
655 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
656 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
657 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
658 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
659 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
660 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
661 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
662 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
663 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
664 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
665 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
666 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
667 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
668 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
671 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
672 enum {
673 /* MIPS DSP Arithmetic Sub-class */
674 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
675 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
676 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
677 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
678 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
679 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
680 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
681 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
682 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
683 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
684 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
685 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
686 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
687 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
688 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
689 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
690 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
691 /* DSP Bit/Manipulation Sub-class */
692 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
693 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
694 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
695 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
697 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
700 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
701 enum {
702 /* MIPS DSP Multiply Sub-class insns */
703 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
704 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
705 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
706 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
707 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
708 /* MIPS DSP Arithmetic Sub-class */
709 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
710 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
711 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
712 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
713 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
714 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
715 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
716 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
717 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
718 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
719 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
720 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
721 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
722 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
723 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
724 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
725 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
726 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
727 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
728 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
729 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
732 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
733 enum {
734 /* DSP Compare-Pick Sub-class */
735 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
736 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
737 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
738 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
739 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
740 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
741 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
742 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
743 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
744 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
745 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
746 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
747 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
748 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
749 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
750 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
751 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
752 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
753 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
754 /* MIPS DSP Arithmetic Sub-class */
755 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
756 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
765 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
766 enum {
767 /* DSP Append Sub-class */
768 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
769 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
770 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
771 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
774 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
775 enum {
776 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
777 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
778 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
779 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
780 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
781 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
782 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
783 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
784 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
785 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
786 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
787 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
788 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
789 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
790 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
791 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
792 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
793 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
794 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
795 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
796 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
797 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
800 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
801 enum {
802 /* DSP Bit/Manipulation Sub-class */
803 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
806 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
807 enum {
808 /* MIPS DSP Multiply Sub-class insns */
809 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
810 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
811 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
812 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
813 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
814 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
815 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
816 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
817 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
818 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
819 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
820 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
821 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
822 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
823 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
824 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
825 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
826 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
827 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
828 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
829 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
830 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
837 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
838 enum {
839 /* MIPS DSP GPR-Based Shift Sub-class */
840 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
841 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
842 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
843 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
844 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
845 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
846 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
847 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
848 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
849 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
850 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
851 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
852 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
853 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
854 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
855 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
856 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
857 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
858 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
859 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
860 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
861 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
868 /* Coprocessor 0 (rs field) */
869 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
871 enum {
872 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
873 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
874 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
875 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
876 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
877 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
878 OPC_MFTR = (0x08 << 21) | OPC_CP0,
879 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
880 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
881 OPC_MTTR = (0x0C << 21) | OPC_CP0,
882 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
883 OPC_C0 = (0x10 << 21) | OPC_CP0,
884 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
885 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
888 /* MFMC0 opcodes */
889 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
891 enum {
892 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
893 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
894 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
895 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
896 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
897 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
898 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
899 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
902 /* Coprocessor 0 (with rs == C0) */
903 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
905 enum {
906 OPC_TLBR = 0x01 | OPC_C0,
907 OPC_TLBWI = 0x02 | OPC_C0,
908 OPC_TLBINV = 0x03 | OPC_C0,
909 OPC_TLBINVF = 0x04 | OPC_C0,
910 OPC_TLBWR = 0x06 | OPC_C0,
911 OPC_TLBP = 0x08 | OPC_C0,
912 OPC_RFE = 0x10 | OPC_C0,
913 OPC_ERET = 0x18 | OPC_C0,
914 OPC_DERET = 0x1F | OPC_C0,
915 OPC_WAIT = 0x20 | OPC_C0,
918 /* Coprocessor 1 (rs field) */
919 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
921 /* Values for the fmt field in FP instructions */
922 enum {
923 /* 0 - 15 are reserved */
924 FMT_S = 16, /* single fp */
925 FMT_D = 17, /* double fp */
926 FMT_E = 18, /* extended fp */
927 FMT_Q = 19, /* quad fp */
928 FMT_W = 20, /* 32-bit fixed */
929 FMT_L = 21, /* 64-bit fixed */
930 FMT_PS = 22, /* paired single fp */
931 /* 23 - 31 are reserved */
934 enum {
935 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
936 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
937 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
938 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
939 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
940 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
941 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
942 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
943 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
944 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
945 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
946 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
947 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
948 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
949 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
950 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
951 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
952 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
953 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
954 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
955 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
956 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
957 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
958 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
959 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
960 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
961 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
962 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
963 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
964 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
967 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
968 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
970 enum {
971 OPC_BC1F = (0x00 << 16) | OPC_BC1,
972 OPC_BC1T = (0x01 << 16) | OPC_BC1,
973 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
974 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
977 enum {
978 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
979 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
982 enum {
983 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
984 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
987 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
989 enum {
990 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
991 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
992 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
993 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
994 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
995 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
996 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
997 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
998 OPC_BC2 = (0x08 << 21) | OPC_CP2,
999 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1000 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1003 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1005 enum {
1006 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1007 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1008 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1009 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1010 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1011 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1012 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1013 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1015 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1016 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1018 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1019 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1020 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1021 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1022 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1024 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1025 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1026 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1027 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1028 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1029 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1030 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1031 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1033 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1034 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1035 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1036 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1037 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1038 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1039 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1040 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1042 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1043 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1044 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1045 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1046 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1047 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1049 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1050 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1051 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1052 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1053 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1054 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1056 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1057 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1058 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1059 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1060 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1061 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1063 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1064 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1065 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1066 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1067 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1068 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1070 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1071 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1072 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1073 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1074 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1075 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1077 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1078 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1079 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1080 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1081 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1082 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1084 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1085 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1086 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1087 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1088 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1089 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1091 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1092 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1093 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1094 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1095 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1096 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1100 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1102 enum {
1103 OPC_LWXC1 = 0x00 | OPC_CP3,
1104 OPC_LDXC1 = 0x01 | OPC_CP3,
1105 OPC_LUXC1 = 0x05 | OPC_CP3,
1106 OPC_SWXC1 = 0x08 | OPC_CP3,
1107 OPC_SDXC1 = 0x09 | OPC_CP3,
1108 OPC_SUXC1 = 0x0D | OPC_CP3,
1109 OPC_PREFX = 0x0F | OPC_CP3,
1110 OPC_ALNV_PS = 0x1E | OPC_CP3,
1111 OPC_MADD_S = 0x20 | OPC_CP3,
1112 OPC_MADD_D = 0x21 | OPC_CP3,
1113 OPC_MADD_PS = 0x26 | OPC_CP3,
1114 OPC_MSUB_S = 0x28 | OPC_CP3,
1115 OPC_MSUB_D = 0x29 | OPC_CP3,
1116 OPC_MSUB_PS = 0x2E | OPC_CP3,
1117 OPC_NMADD_S = 0x30 | OPC_CP3,
1118 OPC_NMADD_D = 0x31 | OPC_CP3,
1119 OPC_NMADD_PS= 0x36 | OPC_CP3,
1120 OPC_NMSUB_S = 0x38 | OPC_CP3,
1121 OPC_NMSUB_D = 0x39 | OPC_CP3,
1122 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1125 /* MSA Opcodes */
1126 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1127 enum {
1128 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1129 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1130 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1131 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1132 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1133 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1134 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1135 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1136 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1137 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1138 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1139 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1140 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1141 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1142 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1143 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1144 OPC_MSA_ELM = 0x19 | OPC_MSA,
1145 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1146 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1147 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1148 OPC_MSA_VEC = 0x1E | OPC_MSA,
1150 /* MI10 instruction */
1151 OPC_LD_B = (0x20) | OPC_MSA,
1152 OPC_LD_H = (0x21) | OPC_MSA,
1153 OPC_LD_W = (0x22) | OPC_MSA,
1154 OPC_LD_D = (0x23) | OPC_MSA,
1155 OPC_ST_B = (0x24) | OPC_MSA,
1156 OPC_ST_H = (0x25) | OPC_MSA,
1157 OPC_ST_W = (0x26) | OPC_MSA,
1158 OPC_ST_D = (0x27) | OPC_MSA,
1161 enum {
1162 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1163 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1164 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1165 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1166 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1167 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1168 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1169 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1170 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1171 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1172 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1173 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1174 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1176 /* I8 instruction */
1177 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1178 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1179 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1180 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1181 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1182 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1183 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1184 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1185 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1186 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1188 /* VEC/2R/2RF instruction */
1189 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1190 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1191 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1192 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1193 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1194 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1195 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1197 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1198 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1200 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1201 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1202 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1203 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1204 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1206 /* 2RF instruction df(bit 16) = _w, _d */
1207 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1208 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1209 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1210 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1211 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1212 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1213 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1214 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1215 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1216 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1217 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1218 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1219 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1220 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1221 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1222 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1224 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1225 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1226 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1227 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1228 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1229 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1230 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1231 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1232 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1233 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1234 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1235 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1236 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1237 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1238 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1239 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1240 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1241 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1242 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1243 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1244 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1245 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1246 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1247 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1248 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1249 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1250 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1251 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1252 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1253 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1254 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1255 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1256 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1257 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1258 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1259 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1260 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1261 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1262 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1263 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1264 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1265 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1266 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1267 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1268 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1269 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1270 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1271 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1272 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1273 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1274 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1275 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1276 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1277 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1278 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1279 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1280 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1281 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1282 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1283 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1284 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1285 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1286 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1287 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1289 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1290 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1291 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1292 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1293 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1294 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1295 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1296 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1297 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1298 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1300 /* 3RF instruction _df(bit 21) = _w, _d */
1301 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1302 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1303 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1304 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1305 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1306 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1307 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1308 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1309 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1310 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1311 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1312 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1313 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1314 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1315 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1316 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1317 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1318 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1319 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1320 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1321 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1322 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1323 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1324 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1325 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1326 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1327 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1328 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1329 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1330 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1331 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1332 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1333 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1334 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1335 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1336 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1337 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1338 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1339 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1340 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1341 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1343 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1344 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1345 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1346 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1347 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1348 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1349 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1350 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1351 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1352 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1353 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1354 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1355 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1358 /* global register indices */
1359 static TCGv_env cpu_env;
1360 static TCGv cpu_gpr[32], cpu_PC;
1361 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1362 static TCGv cpu_dspctrl, btarget, bcond;
1363 static TCGv_i32 hflags;
1364 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1365 static TCGv_i64 fpu_f64[32];
1366 static TCGv_i64 msa_wr_d[64];
1368 #include "exec/gen-icount.h"
1370 #define gen_helper_0e0i(name, arg) do { \
1371 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1372 gen_helper_##name(cpu_env, helper_tmp); \
1373 tcg_temp_free_i32(helper_tmp); \
1374 } while(0)
1376 #define gen_helper_0e1i(name, arg1, arg2) do { \
1377 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1378 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1379 tcg_temp_free_i32(helper_tmp); \
1380 } while(0)
1382 #define gen_helper_1e0i(name, ret, arg1) do { \
1383 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1384 gen_helper_##name(ret, cpu_env, helper_tmp); \
1385 tcg_temp_free_i32(helper_tmp); \
1386 } while(0)
1388 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1389 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1390 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1391 tcg_temp_free_i32(helper_tmp); \
1392 } while(0)
1394 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1395 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1396 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1397 tcg_temp_free_i32(helper_tmp); \
1398 } while(0)
1400 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1401 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1402 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1403 tcg_temp_free_i32(helper_tmp); \
1404 } while(0)
1406 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1407 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1408 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1409 tcg_temp_free_i32(helper_tmp); \
1410 } while(0)
1412 typedef struct DisasContext {
1413 struct TranslationBlock *tb;
1414 target_ulong pc, saved_pc;
1415 uint32_t opcode;
1416 int singlestep_enabled;
1417 int insn_flags;
1418 int32_t CP0_Config1;
1419 /* Routine used to access memory */
1420 int mem_idx;
1421 TCGMemOp default_tcg_memop_mask;
1422 uint32_t hflags, saved_hflags;
1423 int bstate;
1424 target_ulong btarget;
1425 bool ulri;
1426 int kscrexist;
1427 bool rxi;
1428 int ie;
1429 bool bi;
1430 bool bp;
1431 uint64_t PAMask;
1432 bool mvh;
1433 int CP0_LLAddr_shift;
1434 bool ps;
1435 bool vp;
1436 bool cmgcr;
1437 bool mrp;
1438 bool nan2008;
1439 bool abs2008;
1440 } DisasContext;
1442 enum {
1443 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1444 * exception condition */
1445 BS_STOP = 1, /* We want to stop translation for any reason */
1446 BS_BRANCH = 2, /* We reached a branch condition */
1447 BS_EXCP = 3, /* We reached an exception condition */
1450 static const char * const regnames[] = {
1451 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1452 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1453 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1454 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1457 static const char * const regnames_HI[] = {
1458 "HI0", "HI1", "HI2", "HI3",
1461 static const char * const regnames_LO[] = {
1462 "LO0", "LO1", "LO2", "LO3",
1465 static const char * const fregnames[] = {
1466 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1467 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1468 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1469 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1472 static const char * const msaregnames[] = {
1473 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1474 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1475 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1476 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1477 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1478 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1479 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1480 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1481 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1482 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1483 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1484 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1485 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1486 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1487 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1488 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1491 #define LOG_DISAS(...) \
1492 do { \
1493 if (MIPS_DEBUG_DISAS) { \
1494 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1496 } while (0)
1498 #define MIPS_INVAL(op) \
1499 do { \
1500 if (MIPS_DEBUG_DISAS) { \
1501 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1502 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
1503 ctx->pc, ctx->opcode, op, ctx->opcode >> 26, \
1504 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
1506 } while (0)
1508 /* General purpose registers moves. */
1509 static inline void gen_load_gpr (TCGv t, int reg)
1511 if (reg == 0)
1512 tcg_gen_movi_tl(t, 0);
1513 else
1514 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1517 static inline void gen_store_gpr (TCGv t, int reg)
1519 if (reg != 0)
1520 tcg_gen_mov_tl(cpu_gpr[reg], t);
1523 /* Moves to/from shadow registers. */
1524 static inline void gen_load_srsgpr (int from, int to)
1526 TCGv t0 = tcg_temp_new();
1528 if (from == 0)
1529 tcg_gen_movi_tl(t0, 0);
1530 else {
1531 TCGv_i32 t2 = tcg_temp_new_i32();
1532 TCGv_ptr addr = tcg_temp_new_ptr();
1534 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1535 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1536 tcg_gen_andi_i32(t2, t2, 0xf);
1537 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1538 tcg_gen_ext_i32_ptr(addr, t2);
1539 tcg_gen_add_ptr(addr, cpu_env, addr);
1541 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1542 tcg_temp_free_ptr(addr);
1543 tcg_temp_free_i32(t2);
1545 gen_store_gpr(t0, to);
1546 tcg_temp_free(t0);
1549 static inline void gen_store_srsgpr (int from, int to)
1551 if (to != 0) {
1552 TCGv t0 = tcg_temp_new();
1553 TCGv_i32 t2 = tcg_temp_new_i32();
1554 TCGv_ptr addr = tcg_temp_new_ptr();
1556 gen_load_gpr(t0, from);
1557 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1558 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1559 tcg_gen_andi_i32(t2, t2, 0xf);
1560 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1561 tcg_gen_ext_i32_ptr(addr, t2);
1562 tcg_gen_add_ptr(addr, cpu_env, addr);
1564 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1565 tcg_temp_free_ptr(addr);
1566 tcg_temp_free_i32(t2);
1567 tcg_temp_free(t0);
1571 /* Tests */
1572 static inline void gen_save_pc(target_ulong pc)
1574 tcg_gen_movi_tl(cpu_PC, pc);
1577 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1579 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1580 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1581 gen_save_pc(ctx->pc);
1582 ctx->saved_pc = ctx->pc;
1584 if (ctx->hflags != ctx->saved_hflags) {
1585 tcg_gen_movi_i32(hflags, ctx->hflags);
1586 ctx->saved_hflags = ctx->hflags;
1587 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1588 case MIPS_HFLAG_BR:
1589 break;
1590 case MIPS_HFLAG_BC:
1591 case MIPS_HFLAG_BL:
1592 case MIPS_HFLAG_B:
1593 tcg_gen_movi_tl(btarget, ctx->btarget);
1594 break;
1599 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1601 ctx->saved_hflags = ctx->hflags;
1602 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1603 case MIPS_HFLAG_BR:
1604 break;
1605 case MIPS_HFLAG_BC:
1606 case MIPS_HFLAG_BL:
1607 case MIPS_HFLAG_B:
1608 ctx->btarget = env->btarget;
1609 break;
1613 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1615 TCGv_i32 texcp = tcg_const_i32(excp);
1616 TCGv_i32 terr = tcg_const_i32(err);
1617 save_cpu_state(ctx, 1);
1618 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1619 tcg_temp_free_i32(terr);
1620 tcg_temp_free_i32(texcp);
1621 ctx->bstate = BS_EXCP;
1624 static inline void generate_exception(DisasContext *ctx, int excp)
1626 gen_helper_0e0i(raise_exception, excp);
1629 static inline void generate_exception_end(DisasContext *ctx, int excp)
1631 generate_exception_err(ctx, excp, 0);
1634 /* Floating point register moves. */
1635 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1637 if (ctx->hflags & MIPS_HFLAG_FRE) {
1638 generate_exception(ctx, EXCP_RI);
1640 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1643 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1645 TCGv_i64 t64;
1646 if (ctx->hflags & MIPS_HFLAG_FRE) {
1647 generate_exception(ctx, EXCP_RI);
1649 t64 = tcg_temp_new_i64();
1650 tcg_gen_extu_i32_i64(t64, t);
1651 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1652 tcg_temp_free_i64(t64);
1655 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1657 if (ctx->hflags & MIPS_HFLAG_F64) {
1658 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1659 } else {
1660 gen_load_fpr32(ctx, t, reg | 1);
1664 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1666 if (ctx->hflags & MIPS_HFLAG_F64) {
1667 TCGv_i64 t64 = tcg_temp_new_i64();
1668 tcg_gen_extu_i32_i64(t64, t);
1669 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1670 tcg_temp_free_i64(t64);
1671 } else {
1672 gen_store_fpr32(ctx, t, reg | 1);
1676 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1678 if (ctx->hflags & MIPS_HFLAG_F64) {
1679 tcg_gen_mov_i64(t, fpu_f64[reg]);
1680 } else {
1681 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1685 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1687 if (ctx->hflags & MIPS_HFLAG_F64) {
1688 tcg_gen_mov_i64(fpu_f64[reg], t);
1689 } else {
1690 TCGv_i64 t0;
1691 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1692 t0 = tcg_temp_new_i64();
1693 tcg_gen_shri_i64(t0, t, 32);
1694 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1695 tcg_temp_free_i64(t0);
1699 static inline int get_fp_bit (int cc)
1701 if (cc)
1702 return 24 + cc;
1703 else
1704 return 23;
1707 /* Addresses computation */
1708 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1710 tcg_gen_add_tl(ret, arg0, arg1);
1712 #if defined(TARGET_MIPS64)
1713 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1714 tcg_gen_ext32s_i64(ret, ret);
1716 #endif
1719 /* Addresses computation (translation time) */
1720 static target_long addr_add(DisasContext *ctx, target_long base,
1721 target_long offset)
1723 target_long sum = base + offset;
1725 #if defined(TARGET_MIPS64)
1726 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1727 sum = (int32_t)sum;
1729 #endif
1730 return sum;
1733 /* Sign-extract the low 32-bits to a target_long. */
1734 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
1736 #if defined(TARGET_MIPS64)
1737 tcg_gen_ext32s_i64(ret, arg);
1738 #else
1739 tcg_gen_extrl_i64_i32(ret, arg);
1740 #endif
1743 /* Sign-extract the high 32-bits to a target_long. */
1744 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
1746 #if defined(TARGET_MIPS64)
1747 tcg_gen_sari_i64(ret, arg, 32);
1748 #else
1749 tcg_gen_extrh_i64_i32(ret, arg);
1750 #endif
1753 static inline void check_cp0_enabled(DisasContext *ctx)
1755 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1756 generate_exception_err(ctx, EXCP_CpU, 0);
1759 static inline void check_cp1_enabled(DisasContext *ctx)
1761 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1762 generate_exception_err(ctx, EXCP_CpU, 1);
1765 /* Verify that the processor is running with COP1X instructions enabled.
1766 This is associated with the nabla symbol in the MIPS32 and MIPS64
1767 opcode tables. */
1769 static inline void check_cop1x(DisasContext *ctx)
1771 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1772 generate_exception_end(ctx, EXCP_RI);
1775 /* Verify that the processor is running with 64-bit floating-point
1776 operations enabled. */
1778 static inline void check_cp1_64bitmode(DisasContext *ctx)
1780 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1781 generate_exception_end(ctx, EXCP_RI);
1785 * Verify if floating point register is valid; an operation is not defined
1786 * if bit 0 of any register specification is set and the FR bit in the
1787 * Status register equals zero, since the register numbers specify an
1788 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1789 * in the Status register equals one, both even and odd register numbers
1790 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1792 * Multiple 64 bit wide registers can be checked by calling
1793 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1795 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1797 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1798 generate_exception_end(ctx, EXCP_RI);
1801 /* Verify that the processor is running with DSP instructions enabled.
1802 This is enabled by CP0 Status register MX(24) bit.
1805 static inline void check_dsp(DisasContext *ctx)
1807 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1808 if (ctx->insn_flags & ASE_DSP) {
1809 generate_exception_end(ctx, EXCP_DSPDIS);
1810 } else {
1811 generate_exception_end(ctx, EXCP_RI);
1816 static inline void check_dspr2(DisasContext *ctx)
1818 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1819 if (ctx->insn_flags & ASE_DSP) {
1820 generate_exception_end(ctx, EXCP_DSPDIS);
1821 } else {
1822 generate_exception_end(ctx, EXCP_RI);
1827 /* This code generates a "reserved instruction" exception if the
1828 CPU does not support the instruction set corresponding to flags. */
1829 static inline void check_insn(DisasContext *ctx, int flags)
1831 if (unlikely(!(ctx->insn_flags & flags))) {
1832 generate_exception_end(ctx, EXCP_RI);
1836 /* This code generates a "reserved instruction" exception if the
1837 CPU has corresponding flag set which indicates that the instruction
1838 has been removed. */
1839 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1841 if (unlikely(ctx->insn_flags & flags)) {
1842 generate_exception_end(ctx, EXCP_RI);
1846 /* This code generates a "reserved instruction" exception if the
1847 CPU does not support 64-bit paired-single (PS) floating point data type */
1848 static inline void check_ps(DisasContext *ctx)
1850 if (unlikely(!ctx->ps)) {
1851 generate_exception(ctx, EXCP_RI);
1853 check_cp1_64bitmode(ctx);
1856 #ifdef TARGET_MIPS64
1857 /* This code generates a "reserved instruction" exception if 64-bit
1858 instructions are not enabled. */
1859 static inline void check_mips_64(DisasContext *ctx)
1861 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1862 generate_exception_end(ctx, EXCP_RI);
1864 #endif
1866 #ifndef CONFIG_USER_ONLY
1867 static inline void check_mvh(DisasContext *ctx)
1869 if (unlikely(!ctx->mvh)) {
1870 generate_exception(ctx, EXCP_RI);
1873 #endif
1875 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1876 calling interface for 32 and 64-bit FPRs. No sense in changing
1877 all callers for gen_load_fpr32 when we need the CTX parameter for
1878 this one use. */
1879 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1880 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1881 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1882 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1883 int ft, int fs, int cc) \
1885 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1886 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1887 switch (ifmt) { \
1888 case FMT_PS: \
1889 check_ps(ctx); \
1890 break; \
1891 case FMT_D: \
1892 if (abs) { \
1893 check_cop1x(ctx); \
1895 check_cp1_registers(ctx, fs | ft); \
1896 break; \
1897 case FMT_S: \
1898 if (abs) { \
1899 check_cop1x(ctx); \
1901 break; \
1903 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1904 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1905 switch (n) { \
1906 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1907 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1908 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1909 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1910 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1911 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1912 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1913 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1914 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1915 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1916 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1917 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1918 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1919 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1920 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1921 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1922 default: abort(); \
1924 tcg_temp_free_i##bits (fp0); \
1925 tcg_temp_free_i##bits (fp1); \
1928 FOP_CONDS(, 0, d, FMT_D, 64)
1929 FOP_CONDS(abs, 1, d, FMT_D, 64)
1930 FOP_CONDS(, 0, s, FMT_S, 32)
1931 FOP_CONDS(abs, 1, s, FMT_S, 32)
1932 FOP_CONDS(, 0, ps, FMT_PS, 64)
1933 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1934 #undef FOP_CONDS
1936 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1937 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1938 int ft, int fs, int fd) \
1940 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1941 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1942 if (ifmt == FMT_D) { \
1943 check_cp1_registers(ctx, fs | ft | fd); \
1945 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1946 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1947 switch (n) { \
1948 case 0: \
1949 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1950 break; \
1951 case 1: \
1952 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1953 break; \
1954 case 2: \
1955 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1956 break; \
1957 case 3: \
1958 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1959 break; \
1960 case 4: \
1961 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1962 break; \
1963 case 5: \
1964 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1965 break; \
1966 case 6: \
1967 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1968 break; \
1969 case 7: \
1970 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1971 break; \
1972 case 8: \
1973 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1974 break; \
1975 case 9: \
1976 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1977 break; \
1978 case 10: \
1979 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1980 break; \
1981 case 11: \
1982 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1983 break; \
1984 case 12: \
1985 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1986 break; \
1987 case 13: \
1988 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1989 break; \
1990 case 14: \
1991 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1992 break; \
1993 case 15: \
1994 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1995 break; \
1996 case 17: \
1997 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1998 break; \
1999 case 18: \
2000 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2001 break; \
2002 case 19: \
2003 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2004 break; \
2005 case 25: \
2006 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2007 break; \
2008 case 26: \
2009 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2010 break; \
2011 case 27: \
2012 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2013 break; \
2014 default: \
2015 abort(); \
2017 STORE; \
2018 tcg_temp_free_i ## bits (fp0); \
2019 tcg_temp_free_i ## bits (fp1); \
2022 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2023 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2024 #undef FOP_CONDNS
2025 #undef gen_ldcmp_fpr32
2026 #undef gen_ldcmp_fpr64
2028 /* load/store instructions. */
2029 #ifdef CONFIG_USER_ONLY
2030 #define OP_LD_ATOMIC(insn,fname) \
2031 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2033 TCGv t0 = tcg_temp_new(); \
2034 tcg_gen_mov_tl(t0, arg1); \
2035 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2036 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2037 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2038 tcg_temp_free(t0); \
2040 #else
2041 #define OP_LD_ATOMIC(insn,fname) \
2042 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2044 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
2046 #endif
2047 OP_LD_ATOMIC(ll,ld32s);
2048 #if defined(TARGET_MIPS64)
2049 OP_LD_ATOMIC(lld,ld64);
2050 #endif
2051 #undef OP_LD_ATOMIC
2053 #ifdef CONFIG_USER_ONLY
2054 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2055 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2057 TCGv t0 = tcg_temp_new(); \
2058 TCGLabel *l1 = gen_new_label(); \
2059 TCGLabel *l2 = gen_new_label(); \
2061 tcg_gen_andi_tl(t0, arg2, almask); \
2062 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2063 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2064 generate_exception(ctx, EXCP_AdES); \
2065 gen_set_label(l1); \
2066 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2067 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2068 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2069 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2070 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2071 generate_exception_end(ctx, EXCP_SC); \
2072 gen_set_label(l2); \
2073 tcg_gen_movi_tl(t0, 0); \
2074 gen_store_gpr(t0, rt); \
2075 tcg_temp_free(t0); \
2077 #else
2078 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2079 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2081 TCGv t0 = tcg_temp_new(); \
2082 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
2083 gen_store_gpr(t0, rt); \
2084 tcg_temp_free(t0); \
2086 #endif
2087 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2088 #if defined(TARGET_MIPS64)
2089 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2090 #endif
2091 #undef OP_ST_ATOMIC
2093 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2094 int base, int16_t offset)
2096 if (base == 0) {
2097 tcg_gen_movi_tl(addr, offset);
2098 } else if (offset == 0) {
2099 gen_load_gpr(addr, base);
2100 } else {
2101 tcg_gen_movi_tl(addr, offset);
2102 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2106 static target_ulong pc_relative_pc (DisasContext *ctx)
2108 target_ulong pc = ctx->pc;
2110 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2111 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2113 pc -= branch_bytes;
2116 pc &= ~(target_ulong)3;
2117 return pc;
2120 /* Load */
2121 static void gen_ld(DisasContext *ctx, uint32_t opc,
2122 int rt, int base, int16_t offset)
2124 TCGv t0, t1, t2;
2126 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2127 /* Loongson CPU uses a load to zero register for prefetch.
2128 We emulate it as a NOP. On other CPU we must perform the
2129 actual memory access. */
2130 return;
2133 t0 = tcg_temp_new();
2134 gen_base_offset_addr(ctx, t0, base, offset);
2136 switch (opc) {
2137 #if defined(TARGET_MIPS64)
2138 case OPC_LWU:
2139 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL |
2140 ctx->default_tcg_memop_mask);
2141 gen_store_gpr(t0, rt);
2142 break;
2143 case OPC_LD:
2144 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
2145 ctx->default_tcg_memop_mask);
2146 gen_store_gpr(t0, rt);
2147 break;
2148 case OPC_LLD:
2149 case R6_OPC_LLD:
2150 op_ld_lld(t0, t0, ctx);
2151 gen_store_gpr(t0, rt);
2152 break;
2153 case OPC_LDL:
2154 t1 = tcg_temp_new();
2155 /* Do a byte access to possibly trigger a page
2156 fault with the unaligned address. */
2157 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2158 tcg_gen_andi_tl(t1, t0, 7);
2159 #ifndef TARGET_WORDS_BIGENDIAN
2160 tcg_gen_xori_tl(t1, t1, 7);
2161 #endif
2162 tcg_gen_shli_tl(t1, t1, 3);
2163 tcg_gen_andi_tl(t0, t0, ~7);
2164 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2165 tcg_gen_shl_tl(t0, t0, t1);
2166 t2 = tcg_const_tl(-1);
2167 tcg_gen_shl_tl(t2, t2, t1);
2168 gen_load_gpr(t1, rt);
2169 tcg_gen_andc_tl(t1, t1, t2);
2170 tcg_temp_free(t2);
2171 tcg_gen_or_tl(t0, t0, t1);
2172 tcg_temp_free(t1);
2173 gen_store_gpr(t0, rt);
2174 break;
2175 case OPC_LDR:
2176 t1 = tcg_temp_new();
2177 /* Do a byte access to possibly trigger a page
2178 fault with the unaligned address. */
2179 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2180 tcg_gen_andi_tl(t1, t0, 7);
2181 #ifdef TARGET_WORDS_BIGENDIAN
2182 tcg_gen_xori_tl(t1, t1, 7);
2183 #endif
2184 tcg_gen_shli_tl(t1, t1, 3);
2185 tcg_gen_andi_tl(t0, t0, ~7);
2186 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2187 tcg_gen_shr_tl(t0, t0, t1);
2188 tcg_gen_xori_tl(t1, t1, 63);
2189 t2 = tcg_const_tl(0xfffffffffffffffeull);
2190 tcg_gen_shl_tl(t2, t2, t1);
2191 gen_load_gpr(t1, rt);
2192 tcg_gen_and_tl(t1, t1, t2);
2193 tcg_temp_free(t2);
2194 tcg_gen_or_tl(t0, t0, t1);
2195 tcg_temp_free(t1);
2196 gen_store_gpr(t0, rt);
2197 break;
2198 case OPC_LDPC:
2199 t1 = tcg_const_tl(pc_relative_pc(ctx));
2200 gen_op_addr_add(ctx, t0, t0, t1);
2201 tcg_temp_free(t1);
2202 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2203 gen_store_gpr(t0, rt);
2204 break;
2205 #endif
2206 case OPC_LWPC:
2207 t1 = tcg_const_tl(pc_relative_pc(ctx));
2208 gen_op_addr_add(ctx, t0, t0, t1);
2209 tcg_temp_free(t1);
2210 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2211 gen_store_gpr(t0, rt);
2212 break;
2213 case OPC_LW:
2214 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
2215 ctx->default_tcg_memop_mask);
2216 gen_store_gpr(t0, rt);
2217 break;
2218 case OPC_LH:
2219 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
2220 ctx->default_tcg_memop_mask);
2221 gen_store_gpr(t0, rt);
2222 break;
2223 case OPC_LHU:
2224 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW |
2225 ctx->default_tcg_memop_mask);
2226 gen_store_gpr(t0, rt);
2227 break;
2228 case OPC_LB:
2229 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
2230 gen_store_gpr(t0, rt);
2231 break;
2232 case OPC_LBU:
2233 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
2234 gen_store_gpr(t0, rt);
2235 break;
2236 case OPC_LWL:
2237 t1 = tcg_temp_new();
2238 /* Do a byte access to possibly trigger a page
2239 fault with the unaligned address. */
2240 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2241 tcg_gen_andi_tl(t1, t0, 3);
2242 #ifndef TARGET_WORDS_BIGENDIAN
2243 tcg_gen_xori_tl(t1, t1, 3);
2244 #endif
2245 tcg_gen_shli_tl(t1, t1, 3);
2246 tcg_gen_andi_tl(t0, t0, ~3);
2247 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2248 tcg_gen_shl_tl(t0, t0, t1);
2249 t2 = tcg_const_tl(-1);
2250 tcg_gen_shl_tl(t2, t2, t1);
2251 gen_load_gpr(t1, rt);
2252 tcg_gen_andc_tl(t1, t1, t2);
2253 tcg_temp_free(t2);
2254 tcg_gen_or_tl(t0, t0, t1);
2255 tcg_temp_free(t1);
2256 tcg_gen_ext32s_tl(t0, t0);
2257 gen_store_gpr(t0, rt);
2258 break;
2259 case OPC_LWR:
2260 t1 = tcg_temp_new();
2261 /* Do a byte access to possibly trigger a page
2262 fault with the unaligned address. */
2263 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2264 tcg_gen_andi_tl(t1, t0, 3);
2265 #ifdef TARGET_WORDS_BIGENDIAN
2266 tcg_gen_xori_tl(t1, t1, 3);
2267 #endif
2268 tcg_gen_shli_tl(t1, t1, 3);
2269 tcg_gen_andi_tl(t0, t0, ~3);
2270 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2271 tcg_gen_shr_tl(t0, t0, t1);
2272 tcg_gen_xori_tl(t1, t1, 31);
2273 t2 = tcg_const_tl(0xfffffffeull);
2274 tcg_gen_shl_tl(t2, t2, t1);
2275 gen_load_gpr(t1, rt);
2276 tcg_gen_and_tl(t1, t1, t2);
2277 tcg_temp_free(t2);
2278 tcg_gen_or_tl(t0, t0, t1);
2279 tcg_temp_free(t1);
2280 tcg_gen_ext32s_tl(t0, t0);
2281 gen_store_gpr(t0, rt);
2282 break;
2283 case OPC_LL:
2284 case R6_OPC_LL:
2285 op_ld_ll(t0, t0, ctx);
2286 gen_store_gpr(t0, rt);
2287 break;
2289 tcg_temp_free(t0);
2292 /* Store */
2293 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2294 int base, int16_t offset)
2296 TCGv t0 = tcg_temp_new();
2297 TCGv t1 = tcg_temp_new();
2299 gen_base_offset_addr(ctx, t0, base, offset);
2300 gen_load_gpr(t1, rt);
2301 switch (opc) {
2302 #if defined(TARGET_MIPS64)
2303 case OPC_SD:
2304 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
2305 ctx->default_tcg_memop_mask);
2306 break;
2307 case OPC_SDL:
2308 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
2309 break;
2310 case OPC_SDR:
2311 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2312 break;
2313 #endif
2314 case OPC_SW:
2315 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
2316 ctx->default_tcg_memop_mask);
2317 break;
2318 case OPC_SH:
2319 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
2320 ctx->default_tcg_memop_mask);
2321 break;
2322 case OPC_SB:
2323 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2324 break;
2325 case OPC_SWL:
2326 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2327 break;
2328 case OPC_SWR:
2329 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2330 break;
2332 tcg_temp_free(t0);
2333 tcg_temp_free(t1);
2337 /* Store conditional */
2338 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2339 int base, int16_t offset)
2341 TCGv t0, t1;
2343 #ifdef CONFIG_USER_ONLY
2344 t0 = tcg_temp_local_new();
2345 t1 = tcg_temp_local_new();
2346 #else
2347 t0 = tcg_temp_new();
2348 t1 = tcg_temp_new();
2349 #endif
2350 gen_base_offset_addr(ctx, t0, base, offset);
2351 gen_load_gpr(t1, rt);
2352 switch (opc) {
2353 #if defined(TARGET_MIPS64)
2354 case OPC_SCD:
2355 case R6_OPC_SCD:
2356 op_st_scd(t1, t0, rt, ctx);
2357 break;
2358 #endif
2359 case OPC_SC:
2360 case R6_OPC_SC:
2361 op_st_sc(t1, t0, rt, ctx);
2362 break;
2364 tcg_temp_free(t1);
2365 tcg_temp_free(t0);
2368 /* Load and store */
2369 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2370 int base, int16_t offset)
2372 TCGv t0 = tcg_temp_new();
2374 gen_base_offset_addr(ctx, t0, base, offset);
2375 /* Don't do NOP if destination is zero: we must perform the actual
2376 memory access. */
2377 switch (opc) {
2378 case OPC_LWC1:
2380 TCGv_i32 fp0 = tcg_temp_new_i32();
2381 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2382 ctx->default_tcg_memop_mask);
2383 gen_store_fpr32(ctx, fp0, ft);
2384 tcg_temp_free_i32(fp0);
2386 break;
2387 case OPC_SWC1:
2389 TCGv_i32 fp0 = tcg_temp_new_i32();
2390 gen_load_fpr32(ctx, fp0, ft);
2391 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2392 ctx->default_tcg_memop_mask);
2393 tcg_temp_free_i32(fp0);
2395 break;
2396 case OPC_LDC1:
2398 TCGv_i64 fp0 = tcg_temp_new_i64();
2399 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2400 ctx->default_tcg_memop_mask);
2401 gen_store_fpr64(ctx, fp0, ft);
2402 tcg_temp_free_i64(fp0);
2404 break;
2405 case OPC_SDC1:
2407 TCGv_i64 fp0 = tcg_temp_new_i64();
2408 gen_load_fpr64(ctx, fp0, ft);
2409 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2410 ctx->default_tcg_memop_mask);
2411 tcg_temp_free_i64(fp0);
2413 break;
2414 default:
2415 MIPS_INVAL("flt_ldst");
2416 generate_exception_end(ctx, EXCP_RI);
2417 goto out;
2419 out:
2420 tcg_temp_free(t0);
2423 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2424 int rs, int16_t imm)
2426 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2427 check_cp1_enabled(ctx);
2428 switch (op) {
2429 case OPC_LDC1:
2430 case OPC_SDC1:
2431 check_insn(ctx, ISA_MIPS2);
2432 /* Fallthrough */
2433 default:
2434 gen_flt_ldst(ctx, op, rt, rs, imm);
2436 } else {
2437 generate_exception_err(ctx, EXCP_CpU, 1);
2441 /* Arithmetic with immediate operand */
2442 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2443 int rt, int rs, int16_t imm)
2445 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2447 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2448 /* If no destination, treat it as a NOP.
2449 For addi, we must generate the overflow exception when needed. */
2450 return;
2452 switch (opc) {
2453 case OPC_ADDI:
2455 TCGv t0 = tcg_temp_local_new();
2456 TCGv t1 = tcg_temp_new();
2457 TCGv t2 = tcg_temp_new();
2458 TCGLabel *l1 = gen_new_label();
2460 gen_load_gpr(t1, rs);
2461 tcg_gen_addi_tl(t0, t1, uimm);
2462 tcg_gen_ext32s_tl(t0, t0);
2464 tcg_gen_xori_tl(t1, t1, ~uimm);
2465 tcg_gen_xori_tl(t2, t0, uimm);
2466 tcg_gen_and_tl(t1, t1, t2);
2467 tcg_temp_free(t2);
2468 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2469 tcg_temp_free(t1);
2470 /* operands of same sign, result different sign */
2471 generate_exception(ctx, EXCP_OVERFLOW);
2472 gen_set_label(l1);
2473 tcg_gen_ext32s_tl(t0, t0);
2474 gen_store_gpr(t0, rt);
2475 tcg_temp_free(t0);
2477 break;
2478 case OPC_ADDIU:
2479 if (rs != 0) {
2480 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2481 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2482 } else {
2483 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2485 break;
2486 #if defined(TARGET_MIPS64)
2487 case OPC_DADDI:
2489 TCGv t0 = tcg_temp_local_new();
2490 TCGv t1 = tcg_temp_new();
2491 TCGv t2 = tcg_temp_new();
2492 TCGLabel *l1 = gen_new_label();
2494 gen_load_gpr(t1, rs);
2495 tcg_gen_addi_tl(t0, t1, uimm);
2497 tcg_gen_xori_tl(t1, t1, ~uimm);
2498 tcg_gen_xori_tl(t2, t0, uimm);
2499 tcg_gen_and_tl(t1, t1, t2);
2500 tcg_temp_free(t2);
2501 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2502 tcg_temp_free(t1);
2503 /* operands of same sign, result different sign */
2504 generate_exception(ctx, EXCP_OVERFLOW);
2505 gen_set_label(l1);
2506 gen_store_gpr(t0, rt);
2507 tcg_temp_free(t0);
2509 break;
2510 case OPC_DADDIU:
2511 if (rs != 0) {
2512 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2513 } else {
2514 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2516 break;
2517 #endif
2521 /* Logic with immediate operand */
2522 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2523 int rt, int rs, int16_t imm)
2525 target_ulong uimm;
2527 if (rt == 0) {
2528 /* If no destination, treat it as a NOP. */
2529 return;
2531 uimm = (uint16_t)imm;
2532 switch (opc) {
2533 case OPC_ANDI:
2534 if (likely(rs != 0))
2535 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2536 else
2537 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2538 break;
2539 case OPC_ORI:
2540 if (rs != 0)
2541 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2542 else
2543 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2544 break;
2545 case OPC_XORI:
2546 if (likely(rs != 0))
2547 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2548 else
2549 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2550 break;
2551 case OPC_LUI:
2552 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2553 /* OPC_AUI */
2554 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2555 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2556 } else {
2557 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2559 break;
2561 default:
2562 break;
2566 /* Set on less than with immediate operand */
2567 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2568 int rt, int rs, int16_t imm)
2570 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2571 TCGv t0;
2573 if (rt == 0) {
2574 /* If no destination, treat it as a NOP. */
2575 return;
2577 t0 = tcg_temp_new();
2578 gen_load_gpr(t0, rs);
2579 switch (opc) {
2580 case OPC_SLTI:
2581 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2582 break;
2583 case OPC_SLTIU:
2584 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2585 break;
2587 tcg_temp_free(t0);
2590 /* Shifts with immediate operand */
2591 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2592 int rt, int rs, int16_t imm)
2594 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2595 TCGv t0;
2597 if (rt == 0) {
2598 /* If no destination, treat it as a NOP. */
2599 return;
2602 t0 = tcg_temp_new();
2603 gen_load_gpr(t0, rs);
2604 switch (opc) {
2605 case OPC_SLL:
2606 tcg_gen_shli_tl(t0, t0, uimm);
2607 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2608 break;
2609 case OPC_SRA:
2610 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2611 break;
2612 case OPC_SRL:
2613 if (uimm != 0) {
2614 tcg_gen_ext32u_tl(t0, t0);
2615 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2616 } else {
2617 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2619 break;
2620 case OPC_ROTR:
2621 if (uimm != 0) {
2622 TCGv_i32 t1 = tcg_temp_new_i32();
2624 tcg_gen_trunc_tl_i32(t1, t0);
2625 tcg_gen_rotri_i32(t1, t1, uimm);
2626 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2627 tcg_temp_free_i32(t1);
2628 } else {
2629 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2631 break;
2632 #if defined(TARGET_MIPS64)
2633 case OPC_DSLL:
2634 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2635 break;
2636 case OPC_DSRA:
2637 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2638 break;
2639 case OPC_DSRL:
2640 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2641 break;
2642 case OPC_DROTR:
2643 if (uimm != 0) {
2644 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2645 } else {
2646 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2648 break;
2649 case OPC_DSLL32:
2650 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2651 break;
2652 case OPC_DSRA32:
2653 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2654 break;
2655 case OPC_DSRL32:
2656 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2657 break;
2658 case OPC_DROTR32:
2659 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2660 break;
2661 #endif
2663 tcg_temp_free(t0);
2666 /* Arithmetic */
2667 static void gen_arith(DisasContext *ctx, uint32_t opc,
2668 int rd, int rs, int rt)
2670 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2671 && opc != OPC_DADD && opc != OPC_DSUB) {
2672 /* If no destination, treat it as a NOP.
2673 For add & sub, we must generate the overflow exception when needed. */
2674 return;
2677 switch (opc) {
2678 case OPC_ADD:
2680 TCGv t0 = tcg_temp_local_new();
2681 TCGv t1 = tcg_temp_new();
2682 TCGv t2 = tcg_temp_new();
2683 TCGLabel *l1 = gen_new_label();
2685 gen_load_gpr(t1, rs);
2686 gen_load_gpr(t2, rt);
2687 tcg_gen_add_tl(t0, t1, t2);
2688 tcg_gen_ext32s_tl(t0, t0);
2689 tcg_gen_xor_tl(t1, t1, t2);
2690 tcg_gen_xor_tl(t2, t0, t2);
2691 tcg_gen_andc_tl(t1, t2, t1);
2692 tcg_temp_free(t2);
2693 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2694 tcg_temp_free(t1);
2695 /* operands of same sign, result different sign */
2696 generate_exception(ctx, EXCP_OVERFLOW);
2697 gen_set_label(l1);
2698 gen_store_gpr(t0, rd);
2699 tcg_temp_free(t0);
2701 break;
2702 case OPC_ADDU:
2703 if (rs != 0 && rt != 0) {
2704 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2705 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2706 } else if (rs == 0 && rt != 0) {
2707 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2708 } else if (rs != 0 && rt == 0) {
2709 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2710 } else {
2711 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2713 break;
2714 case OPC_SUB:
2716 TCGv t0 = tcg_temp_local_new();
2717 TCGv t1 = tcg_temp_new();
2718 TCGv t2 = tcg_temp_new();
2719 TCGLabel *l1 = gen_new_label();
2721 gen_load_gpr(t1, rs);
2722 gen_load_gpr(t2, rt);
2723 tcg_gen_sub_tl(t0, t1, t2);
2724 tcg_gen_ext32s_tl(t0, t0);
2725 tcg_gen_xor_tl(t2, t1, t2);
2726 tcg_gen_xor_tl(t1, t0, t1);
2727 tcg_gen_and_tl(t1, t1, t2);
2728 tcg_temp_free(t2);
2729 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2730 tcg_temp_free(t1);
2731 /* operands of different sign, first operand and result different sign */
2732 generate_exception(ctx, EXCP_OVERFLOW);
2733 gen_set_label(l1);
2734 gen_store_gpr(t0, rd);
2735 tcg_temp_free(t0);
2737 break;
2738 case OPC_SUBU:
2739 if (rs != 0 && rt != 0) {
2740 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2741 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2742 } else if (rs == 0 && rt != 0) {
2743 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2744 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2745 } else if (rs != 0 && rt == 0) {
2746 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2747 } else {
2748 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2750 break;
2751 #if defined(TARGET_MIPS64)
2752 case OPC_DADD:
2754 TCGv t0 = tcg_temp_local_new();
2755 TCGv t1 = tcg_temp_new();
2756 TCGv t2 = tcg_temp_new();
2757 TCGLabel *l1 = gen_new_label();
2759 gen_load_gpr(t1, rs);
2760 gen_load_gpr(t2, rt);
2761 tcg_gen_add_tl(t0, t1, t2);
2762 tcg_gen_xor_tl(t1, t1, t2);
2763 tcg_gen_xor_tl(t2, t0, t2);
2764 tcg_gen_andc_tl(t1, t2, t1);
2765 tcg_temp_free(t2);
2766 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2767 tcg_temp_free(t1);
2768 /* operands of same sign, result different sign */
2769 generate_exception(ctx, EXCP_OVERFLOW);
2770 gen_set_label(l1);
2771 gen_store_gpr(t0, rd);
2772 tcg_temp_free(t0);
2774 break;
2775 case OPC_DADDU:
2776 if (rs != 0 && rt != 0) {
2777 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2778 } else if (rs == 0 && rt != 0) {
2779 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2780 } else if (rs != 0 && rt == 0) {
2781 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2782 } else {
2783 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2785 break;
2786 case OPC_DSUB:
2788 TCGv t0 = tcg_temp_local_new();
2789 TCGv t1 = tcg_temp_new();
2790 TCGv t2 = tcg_temp_new();
2791 TCGLabel *l1 = gen_new_label();
2793 gen_load_gpr(t1, rs);
2794 gen_load_gpr(t2, rt);
2795 tcg_gen_sub_tl(t0, t1, t2);
2796 tcg_gen_xor_tl(t2, t1, t2);
2797 tcg_gen_xor_tl(t1, t0, t1);
2798 tcg_gen_and_tl(t1, t1, t2);
2799 tcg_temp_free(t2);
2800 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2801 tcg_temp_free(t1);
2802 /* operands of different sign, first operand and result different sign */
2803 generate_exception(ctx, EXCP_OVERFLOW);
2804 gen_set_label(l1);
2805 gen_store_gpr(t0, rd);
2806 tcg_temp_free(t0);
2808 break;
2809 case OPC_DSUBU:
2810 if (rs != 0 && rt != 0) {
2811 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2812 } else if (rs == 0 && rt != 0) {
2813 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2814 } else if (rs != 0 && rt == 0) {
2815 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2816 } else {
2817 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2819 break;
2820 #endif
2821 case OPC_MUL:
2822 if (likely(rs != 0 && rt != 0)) {
2823 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2824 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2825 } else {
2826 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2828 break;
2832 /* Conditional move */
2833 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2834 int rd, int rs, int rt)
2836 TCGv t0, t1, t2;
2838 if (rd == 0) {
2839 /* If no destination, treat it as a NOP. */
2840 return;
2843 t0 = tcg_temp_new();
2844 gen_load_gpr(t0, rt);
2845 t1 = tcg_const_tl(0);
2846 t2 = tcg_temp_new();
2847 gen_load_gpr(t2, rs);
2848 switch (opc) {
2849 case OPC_MOVN:
2850 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2851 break;
2852 case OPC_MOVZ:
2853 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2854 break;
2855 case OPC_SELNEZ:
2856 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2857 break;
2858 case OPC_SELEQZ:
2859 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2860 break;
2862 tcg_temp_free(t2);
2863 tcg_temp_free(t1);
2864 tcg_temp_free(t0);
2867 /* Logic */
2868 static void gen_logic(DisasContext *ctx, uint32_t opc,
2869 int rd, int rs, int rt)
2871 if (rd == 0) {
2872 /* If no destination, treat it as a NOP. */
2873 return;
2876 switch (opc) {
2877 case OPC_AND:
2878 if (likely(rs != 0 && rt != 0)) {
2879 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2880 } else {
2881 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2883 break;
2884 case OPC_NOR:
2885 if (rs != 0 && rt != 0) {
2886 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2887 } else if (rs == 0 && rt != 0) {
2888 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2889 } else if (rs != 0 && rt == 0) {
2890 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2891 } else {
2892 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2894 break;
2895 case OPC_OR:
2896 if (likely(rs != 0 && rt != 0)) {
2897 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2898 } else if (rs == 0 && rt != 0) {
2899 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2900 } else if (rs != 0 && rt == 0) {
2901 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2902 } else {
2903 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2905 break;
2906 case OPC_XOR:
2907 if (likely(rs != 0 && rt != 0)) {
2908 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2909 } else if (rs == 0 && rt != 0) {
2910 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2911 } else if (rs != 0 && rt == 0) {
2912 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2913 } else {
2914 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2916 break;
2920 /* Set on lower than */
2921 static void gen_slt(DisasContext *ctx, uint32_t opc,
2922 int rd, int rs, int rt)
2924 TCGv t0, t1;
2926 if (rd == 0) {
2927 /* If no destination, treat it as a NOP. */
2928 return;
2931 t0 = tcg_temp_new();
2932 t1 = tcg_temp_new();
2933 gen_load_gpr(t0, rs);
2934 gen_load_gpr(t1, rt);
2935 switch (opc) {
2936 case OPC_SLT:
2937 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2938 break;
2939 case OPC_SLTU:
2940 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2941 break;
2943 tcg_temp_free(t0);
2944 tcg_temp_free(t1);
2947 /* Shifts */
2948 static void gen_shift(DisasContext *ctx, uint32_t opc,
2949 int rd, int rs, int rt)
2951 TCGv t0, t1;
2953 if (rd == 0) {
2954 /* If no destination, treat it as a NOP.
2955 For add & sub, we must generate the overflow exception when needed. */
2956 return;
2959 t0 = tcg_temp_new();
2960 t1 = tcg_temp_new();
2961 gen_load_gpr(t0, rs);
2962 gen_load_gpr(t1, rt);
2963 switch (opc) {
2964 case OPC_SLLV:
2965 tcg_gen_andi_tl(t0, t0, 0x1f);
2966 tcg_gen_shl_tl(t0, t1, t0);
2967 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2968 break;
2969 case OPC_SRAV:
2970 tcg_gen_andi_tl(t0, t0, 0x1f);
2971 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2972 break;
2973 case OPC_SRLV:
2974 tcg_gen_ext32u_tl(t1, t1);
2975 tcg_gen_andi_tl(t0, t0, 0x1f);
2976 tcg_gen_shr_tl(t0, t1, t0);
2977 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2978 break;
2979 case OPC_ROTRV:
2981 TCGv_i32 t2 = tcg_temp_new_i32();
2982 TCGv_i32 t3 = tcg_temp_new_i32();
2984 tcg_gen_trunc_tl_i32(t2, t0);
2985 tcg_gen_trunc_tl_i32(t3, t1);
2986 tcg_gen_andi_i32(t2, t2, 0x1f);
2987 tcg_gen_rotr_i32(t2, t3, t2);
2988 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2989 tcg_temp_free_i32(t2);
2990 tcg_temp_free_i32(t3);
2992 break;
2993 #if defined(TARGET_MIPS64)
2994 case OPC_DSLLV:
2995 tcg_gen_andi_tl(t0, t0, 0x3f);
2996 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2997 break;
2998 case OPC_DSRAV:
2999 tcg_gen_andi_tl(t0, t0, 0x3f);
3000 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3001 break;
3002 case OPC_DSRLV:
3003 tcg_gen_andi_tl(t0, t0, 0x3f);
3004 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3005 break;
3006 case OPC_DROTRV:
3007 tcg_gen_andi_tl(t0, t0, 0x3f);
3008 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3009 break;
3010 #endif
3012 tcg_temp_free(t0);
3013 tcg_temp_free(t1);
3016 /* Arithmetic on HI/LO registers */
3017 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3019 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3020 /* Treat as NOP. */
3021 return;
3024 if (acc != 0) {
3025 check_dsp(ctx);
3028 switch (opc) {
3029 case OPC_MFHI:
3030 #if defined(TARGET_MIPS64)
3031 if (acc != 0) {
3032 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3033 } else
3034 #endif
3036 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3038 break;
3039 case OPC_MFLO:
3040 #if defined(TARGET_MIPS64)
3041 if (acc != 0) {
3042 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3043 } else
3044 #endif
3046 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3048 break;
3049 case OPC_MTHI:
3050 if (reg != 0) {
3051 #if defined(TARGET_MIPS64)
3052 if (acc != 0) {
3053 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3054 } else
3055 #endif
3057 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3059 } else {
3060 tcg_gen_movi_tl(cpu_HI[acc], 0);
3062 break;
3063 case OPC_MTLO:
3064 if (reg != 0) {
3065 #if defined(TARGET_MIPS64)
3066 if (acc != 0) {
3067 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3068 } else
3069 #endif
3071 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3073 } else {
3074 tcg_gen_movi_tl(cpu_LO[acc], 0);
3076 break;
3080 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3081 TCGMemOp memop)
3083 TCGv t0 = tcg_const_tl(addr);
3084 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3085 gen_store_gpr(t0, reg);
3086 tcg_temp_free(t0);
3089 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3090 int rs)
3092 target_long offset;
3093 target_long addr;
3095 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3096 case OPC_ADDIUPC:
3097 if (rs != 0) {
3098 offset = sextract32(ctx->opcode << 2, 0, 21);
3099 addr = addr_add(ctx, pc, offset);
3100 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3102 break;
3103 case R6_OPC_LWPC:
3104 offset = sextract32(ctx->opcode << 2, 0, 21);
3105 addr = addr_add(ctx, pc, offset);
3106 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3107 break;
3108 #if defined(TARGET_MIPS64)
3109 case OPC_LWUPC:
3110 check_mips_64(ctx);
3111 offset = sextract32(ctx->opcode << 2, 0, 21);
3112 addr = addr_add(ctx, pc, offset);
3113 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3114 break;
3115 #endif
3116 default:
3117 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3118 case OPC_AUIPC:
3119 if (rs != 0) {
3120 offset = sextract32(ctx->opcode, 0, 16) << 16;
3121 addr = addr_add(ctx, pc, offset);
3122 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3124 break;
3125 case OPC_ALUIPC:
3126 if (rs != 0) {
3127 offset = sextract32(ctx->opcode, 0, 16) << 16;
3128 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3129 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3131 break;
3132 #if defined(TARGET_MIPS64)
3133 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3134 case R6_OPC_LDPC + (1 << 16):
3135 case R6_OPC_LDPC + (2 << 16):
3136 case R6_OPC_LDPC + (3 << 16):
3137 check_mips_64(ctx);
3138 offset = sextract32(ctx->opcode << 3, 0, 21);
3139 addr = addr_add(ctx, (pc & ~0x7), offset);
3140 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3141 break;
3142 #endif
3143 default:
3144 MIPS_INVAL("OPC_PCREL");
3145 generate_exception_end(ctx, EXCP_RI);
3146 break;
3148 break;
3152 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3154 TCGv t0, t1;
3156 if (rd == 0) {
3157 /* Treat as NOP. */
3158 return;
3161 t0 = tcg_temp_new();
3162 t1 = tcg_temp_new();
3164 gen_load_gpr(t0, rs);
3165 gen_load_gpr(t1, rt);
3167 switch (opc) {
3168 case R6_OPC_DIV:
3170 TCGv t2 = tcg_temp_new();
3171 TCGv t3 = tcg_temp_new();
3172 tcg_gen_ext32s_tl(t0, t0);
3173 tcg_gen_ext32s_tl(t1, t1);
3174 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3175 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3176 tcg_gen_and_tl(t2, t2, t3);
3177 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3178 tcg_gen_or_tl(t2, t2, t3);
3179 tcg_gen_movi_tl(t3, 0);
3180 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3181 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3182 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3183 tcg_temp_free(t3);
3184 tcg_temp_free(t2);
3186 break;
3187 case R6_OPC_MOD:
3189 TCGv t2 = tcg_temp_new();
3190 TCGv t3 = tcg_temp_new();
3191 tcg_gen_ext32s_tl(t0, t0);
3192 tcg_gen_ext32s_tl(t1, t1);
3193 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3194 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3195 tcg_gen_and_tl(t2, t2, t3);
3196 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3197 tcg_gen_or_tl(t2, t2, t3);
3198 tcg_gen_movi_tl(t3, 0);
3199 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3200 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3201 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3202 tcg_temp_free(t3);
3203 tcg_temp_free(t2);
3205 break;
3206 case R6_OPC_DIVU:
3208 TCGv t2 = tcg_const_tl(0);
3209 TCGv t3 = tcg_const_tl(1);
3210 tcg_gen_ext32u_tl(t0, t0);
3211 tcg_gen_ext32u_tl(t1, t1);
3212 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3213 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3214 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3215 tcg_temp_free(t3);
3216 tcg_temp_free(t2);
3218 break;
3219 case R6_OPC_MODU:
3221 TCGv t2 = tcg_const_tl(0);
3222 TCGv t3 = tcg_const_tl(1);
3223 tcg_gen_ext32u_tl(t0, t0);
3224 tcg_gen_ext32u_tl(t1, t1);
3225 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3226 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3227 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3228 tcg_temp_free(t3);
3229 tcg_temp_free(t2);
3231 break;
3232 case R6_OPC_MUL:
3234 TCGv_i32 t2 = tcg_temp_new_i32();
3235 TCGv_i32 t3 = tcg_temp_new_i32();
3236 tcg_gen_trunc_tl_i32(t2, t0);
3237 tcg_gen_trunc_tl_i32(t3, t1);
3238 tcg_gen_mul_i32(t2, t2, t3);
3239 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3240 tcg_temp_free_i32(t2);
3241 tcg_temp_free_i32(t3);
3243 break;
3244 case R6_OPC_MUH:
3246 TCGv_i32 t2 = tcg_temp_new_i32();
3247 TCGv_i32 t3 = tcg_temp_new_i32();
3248 tcg_gen_trunc_tl_i32(t2, t0);
3249 tcg_gen_trunc_tl_i32(t3, t1);
3250 tcg_gen_muls2_i32(t2, t3, t2, t3);
3251 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3252 tcg_temp_free_i32(t2);
3253 tcg_temp_free_i32(t3);
3255 break;
3256 case R6_OPC_MULU:
3258 TCGv_i32 t2 = tcg_temp_new_i32();
3259 TCGv_i32 t3 = tcg_temp_new_i32();
3260 tcg_gen_trunc_tl_i32(t2, t0);
3261 tcg_gen_trunc_tl_i32(t3, t1);
3262 tcg_gen_mul_i32(t2, t2, t3);
3263 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3264 tcg_temp_free_i32(t2);
3265 tcg_temp_free_i32(t3);
3267 break;
3268 case R6_OPC_MUHU:
3270 TCGv_i32 t2 = tcg_temp_new_i32();
3271 TCGv_i32 t3 = tcg_temp_new_i32();
3272 tcg_gen_trunc_tl_i32(t2, t0);
3273 tcg_gen_trunc_tl_i32(t3, t1);
3274 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3275 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3276 tcg_temp_free_i32(t2);
3277 tcg_temp_free_i32(t3);
3279 break;
3280 #if defined(TARGET_MIPS64)
3281 case R6_OPC_DDIV:
3283 TCGv t2 = tcg_temp_new();
3284 TCGv t3 = tcg_temp_new();
3285 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3286 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3287 tcg_gen_and_tl(t2, t2, t3);
3288 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3289 tcg_gen_or_tl(t2, t2, t3);
3290 tcg_gen_movi_tl(t3, 0);
3291 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3292 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3293 tcg_temp_free(t3);
3294 tcg_temp_free(t2);
3296 break;
3297 case R6_OPC_DMOD:
3299 TCGv t2 = tcg_temp_new();
3300 TCGv t3 = tcg_temp_new();
3301 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3302 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3303 tcg_gen_and_tl(t2, t2, t3);
3304 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3305 tcg_gen_or_tl(t2, t2, t3);
3306 tcg_gen_movi_tl(t3, 0);
3307 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3308 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3309 tcg_temp_free(t3);
3310 tcg_temp_free(t2);
3312 break;
3313 case R6_OPC_DDIVU:
3315 TCGv t2 = tcg_const_tl(0);
3316 TCGv t3 = tcg_const_tl(1);
3317 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3318 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3319 tcg_temp_free(t3);
3320 tcg_temp_free(t2);
3322 break;
3323 case R6_OPC_DMODU:
3325 TCGv t2 = tcg_const_tl(0);
3326 TCGv t3 = tcg_const_tl(1);
3327 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3328 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3329 tcg_temp_free(t3);
3330 tcg_temp_free(t2);
3332 break;
3333 case R6_OPC_DMUL:
3334 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3335 break;
3336 case R6_OPC_DMUH:
3338 TCGv t2 = tcg_temp_new();
3339 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3340 tcg_temp_free(t2);
3342 break;
3343 case R6_OPC_DMULU:
3344 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3345 break;
3346 case R6_OPC_DMUHU:
3348 TCGv t2 = tcg_temp_new();
3349 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3350 tcg_temp_free(t2);
3352 break;
3353 #endif
3354 default:
3355 MIPS_INVAL("r6 mul/div");
3356 generate_exception_end(ctx, EXCP_RI);
3357 goto out;
3359 out:
3360 tcg_temp_free(t0);
3361 tcg_temp_free(t1);
3364 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3365 int acc, int rs, int rt)
3367 TCGv t0, t1;
3369 t0 = tcg_temp_new();
3370 t1 = tcg_temp_new();
3372 gen_load_gpr(t0, rs);
3373 gen_load_gpr(t1, rt);
3375 if (acc != 0) {
3376 check_dsp(ctx);
3379 switch (opc) {
3380 case OPC_DIV:
3382 TCGv t2 = tcg_temp_new();
3383 TCGv t3 = tcg_temp_new();
3384 tcg_gen_ext32s_tl(t0, t0);
3385 tcg_gen_ext32s_tl(t1, t1);
3386 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3387 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3388 tcg_gen_and_tl(t2, t2, t3);
3389 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3390 tcg_gen_or_tl(t2, t2, t3);
3391 tcg_gen_movi_tl(t3, 0);
3392 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3393 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3394 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3395 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3396 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3397 tcg_temp_free(t3);
3398 tcg_temp_free(t2);
3400 break;
3401 case OPC_DIVU:
3403 TCGv t2 = tcg_const_tl(0);
3404 TCGv t3 = tcg_const_tl(1);
3405 tcg_gen_ext32u_tl(t0, t0);
3406 tcg_gen_ext32u_tl(t1, t1);
3407 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3408 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3409 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3410 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3411 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3412 tcg_temp_free(t3);
3413 tcg_temp_free(t2);
3415 break;
3416 case OPC_MULT:
3418 TCGv_i32 t2 = tcg_temp_new_i32();
3419 TCGv_i32 t3 = tcg_temp_new_i32();
3420 tcg_gen_trunc_tl_i32(t2, t0);
3421 tcg_gen_trunc_tl_i32(t3, t1);
3422 tcg_gen_muls2_i32(t2, t3, t2, t3);
3423 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3424 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3425 tcg_temp_free_i32(t2);
3426 tcg_temp_free_i32(t3);
3428 break;
3429 case OPC_MULTU:
3431 TCGv_i32 t2 = tcg_temp_new_i32();
3432 TCGv_i32 t3 = tcg_temp_new_i32();
3433 tcg_gen_trunc_tl_i32(t2, t0);
3434 tcg_gen_trunc_tl_i32(t3, t1);
3435 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3436 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3437 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3438 tcg_temp_free_i32(t2);
3439 tcg_temp_free_i32(t3);
3441 break;
3442 #if defined(TARGET_MIPS64)
3443 case OPC_DDIV:
3445 TCGv t2 = tcg_temp_new();
3446 TCGv t3 = tcg_temp_new();
3447 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3448 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3449 tcg_gen_and_tl(t2, t2, t3);
3450 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3451 tcg_gen_or_tl(t2, t2, t3);
3452 tcg_gen_movi_tl(t3, 0);
3453 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3454 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3455 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3456 tcg_temp_free(t3);
3457 tcg_temp_free(t2);
3459 break;
3460 case OPC_DDIVU:
3462 TCGv t2 = tcg_const_tl(0);
3463 TCGv t3 = tcg_const_tl(1);
3464 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3465 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3466 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3467 tcg_temp_free(t3);
3468 tcg_temp_free(t2);
3470 break;
3471 case OPC_DMULT:
3472 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3473 break;
3474 case OPC_DMULTU:
3475 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3476 break;
3477 #endif
3478 case OPC_MADD:
3480 TCGv_i64 t2 = tcg_temp_new_i64();
3481 TCGv_i64 t3 = tcg_temp_new_i64();
3483 tcg_gen_ext_tl_i64(t2, t0);
3484 tcg_gen_ext_tl_i64(t3, t1);
3485 tcg_gen_mul_i64(t2, t2, t3);
3486 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3487 tcg_gen_add_i64(t2, t2, t3);
3488 tcg_temp_free_i64(t3);
3489 gen_move_low32(cpu_LO[acc], t2);
3490 gen_move_high32(cpu_HI[acc], t2);
3491 tcg_temp_free_i64(t2);
3493 break;
3494 case OPC_MADDU:
3496 TCGv_i64 t2 = tcg_temp_new_i64();
3497 TCGv_i64 t3 = tcg_temp_new_i64();
3499 tcg_gen_ext32u_tl(t0, t0);
3500 tcg_gen_ext32u_tl(t1, t1);
3501 tcg_gen_extu_tl_i64(t2, t0);
3502 tcg_gen_extu_tl_i64(t3, t1);
3503 tcg_gen_mul_i64(t2, t2, t3);
3504 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3505 tcg_gen_add_i64(t2, t2, t3);
3506 tcg_temp_free_i64(t3);
3507 gen_move_low32(cpu_LO[acc], t2);
3508 gen_move_high32(cpu_HI[acc], t2);
3509 tcg_temp_free_i64(t2);
3511 break;
3512 case OPC_MSUB:
3514 TCGv_i64 t2 = tcg_temp_new_i64();
3515 TCGv_i64 t3 = tcg_temp_new_i64();
3517 tcg_gen_ext_tl_i64(t2, t0);
3518 tcg_gen_ext_tl_i64(t3, t1);
3519 tcg_gen_mul_i64(t2, t2, t3);
3520 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3521 tcg_gen_sub_i64(t2, t3, t2);
3522 tcg_temp_free_i64(t3);
3523 gen_move_low32(cpu_LO[acc], t2);
3524 gen_move_high32(cpu_HI[acc], t2);
3525 tcg_temp_free_i64(t2);
3527 break;
3528 case OPC_MSUBU:
3530 TCGv_i64 t2 = tcg_temp_new_i64();
3531 TCGv_i64 t3 = tcg_temp_new_i64();
3533 tcg_gen_ext32u_tl(t0, t0);
3534 tcg_gen_ext32u_tl(t1, t1);
3535 tcg_gen_extu_tl_i64(t2, t0);
3536 tcg_gen_extu_tl_i64(t3, t1);
3537 tcg_gen_mul_i64(t2, t2, t3);
3538 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3539 tcg_gen_sub_i64(t2, t3, t2);
3540 tcg_temp_free_i64(t3);
3541 gen_move_low32(cpu_LO[acc], t2);
3542 gen_move_high32(cpu_HI[acc], t2);
3543 tcg_temp_free_i64(t2);
3545 break;
3546 default:
3547 MIPS_INVAL("mul/div");
3548 generate_exception_end(ctx, EXCP_RI);
3549 goto out;
3551 out:
3552 tcg_temp_free(t0);
3553 tcg_temp_free(t1);
3556 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3557 int rd, int rs, int rt)
3559 TCGv t0 = tcg_temp_new();
3560 TCGv t1 = tcg_temp_new();
3562 gen_load_gpr(t0, rs);
3563 gen_load_gpr(t1, rt);
3565 switch (opc) {
3566 case OPC_VR54XX_MULS:
3567 gen_helper_muls(t0, cpu_env, t0, t1);
3568 break;
3569 case OPC_VR54XX_MULSU:
3570 gen_helper_mulsu(t0, cpu_env, t0, t1);
3571 break;
3572 case OPC_VR54XX_MACC:
3573 gen_helper_macc(t0, cpu_env, t0, t1);
3574 break;
3575 case OPC_VR54XX_MACCU:
3576 gen_helper_maccu(t0, cpu_env, t0, t1);
3577 break;
3578 case OPC_VR54XX_MSAC:
3579 gen_helper_msac(t0, cpu_env, t0, t1);
3580 break;
3581 case OPC_VR54XX_MSACU:
3582 gen_helper_msacu(t0, cpu_env, t0, t1);
3583 break;
3584 case OPC_VR54XX_MULHI:
3585 gen_helper_mulhi(t0, cpu_env, t0, t1);
3586 break;
3587 case OPC_VR54XX_MULHIU:
3588 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3589 break;
3590 case OPC_VR54XX_MULSHI:
3591 gen_helper_mulshi(t0, cpu_env, t0, t1);
3592 break;
3593 case OPC_VR54XX_MULSHIU:
3594 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3595 break;
3596 case OPC_VR54XX_MACCHI:
3597 gen_helper_macchi(t0, cpu_env, t0, t1);
3598 break;
3599 case OPC_VR54XX_MACCHIU:
3600 gen_helper_macchiu(t0, cpu_env, t0, t1);
3601 break;
3602 case OPC_VR54XX_MSACHI:
3603 gen_helper_msachi(t0, cpu_env, t0, t1);
3604 break;
3605 case OPC_VR54XX_MSACHIU:
3606 gen_helper_msachiu(t0, cpu_env, t0, t1);
3607 break;
3608 default:
3609 MIPS_INVAL("mul vr54xx");
3610 generate_exception_end(ctx, EXCP_RI);
3611 goto out;
3613 gen_store_gpr(t0, rd);
3615 out:
3616 tcg_temp_free(t0);
3617 tcg_temp_free(t1);
3620 static void gen_cl (DisasContext *ctx, uint32_t opc,
3621 int rd, int rs)
3623 TCGv t0;
3625 if (rd == 0) {
3626 /* Treat as NOP. */
3627 return;
3629 t0 = tcg_temp_new();
3630 gen_load_gpr(t0, rs);
3631 switch (opc) {
3632 case OPC_CLO:
3633 case R6_OPC_CLO:
3634 gen_helper_clo(cpu_gpr[rd], t0);
3635 break;
3636 case OPC_CLZ:
3637 case R6_OPC_CLZ:
3638 gen_helper_clz(cpu_gpr[rd], t0);
3639 break;
3640 #if defined(TARGET_MIPS64)
3641 case OPC_DCLO:
3642 case R6_OPC_DCLO:
3643 gen_helper_dclo(cpu_gpr[rd], t0);
3644 break;
3645 case OPC_DCLZ:
3646 case R6_OPC_DCLZ:
3647 gen_helper_dclz(cpu_gpr[rd], t0);
3648 break;
3649 #endif
3651 tcg_temp_free(t0);
3654 /* Godson integer instructions */
3655 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3656 int rd, int rs, int rt)
3658 TCGv t0, t1;
3660 if (rd == 0) {
3661 /* Treat as NOP. */
3662 return;
3665 switch (opc) {
3666 case OPC_MULT_G_2E:
3667 case OPC_MULT_G_2F:
3668 case OPC_MULTU_G_2E:
3669 case OPC_MULTU_G_2F:
3670 #if defined(TARGET_MIPS64)
3671 case OPC_DMULT_G_2E:
3672 case OPC_DMULT_G_2F:
3673 case OPC_DMULTU_G_2E:
3674 case OPC_DMULTU_G_2F:
3675 #endif
3676 t0 = tcg_temp_new();
3677 t1 = tcg_temp_new();
3678 break;
3679 default:
3680 t0 = tcg_temp_local_new();
3681 t1 = tcg_temp_local_new();
3682 break;
3685 gen_load_gpr(t0, rs);
3686 gen_load_gpr(t1, rt);
3688 switch (opc) {
3689 case OPC_MULT_G_2E:
3690 case OPC_MULT_G_2F:
3691 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3692 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3693 break;
3694 case OPC_MULTU_G_2E:
3695 case OPC_MULTU_G_2F:
3696 tcg_gen_ext32u_tl(t0, t0);
3697 tcg_gen_ext32u_tl(t1, t1);
3698 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3699 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3700 break;
3701 case OPC_DIV_G_2E:
3702 case OPC_DIV_G_2F:
3704 TCGLabel *l1 = gen_new_label();
3705 TCGLabel *l2 = gen_new_label();
3706 TCGLabel *l3 = gen_new_label();
3707 tcg_gen_ext32s_tl(t0, t0);
3708 tcg_gen_ext32s_tl(t1, t1);
3709 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3710 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3711 tcg_gen_br(l3);
3712 gen_set_label(l1);
3713 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3714 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3715 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3716 tcg_gen_br(l3);
3717 gen_set_label(l2);
3718 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3719 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3720 gen_set_label(l3);
3722 break;
3723 case OPC_DIVU_G_2E:
3724 case OPC_DIVU_G_2F:
3726 TCGLabel *l1 = gen_new_label();
3727 TCGLabel *l2 = gen_new_label();
3728 tcg_gen_ext32u_tl(t0, t0);
3729 tcg_gen_ext32u_tl(t1, t1);
3730 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3731 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3732 tcg_gen_br(l2);
3733 gen_set_label(l1);
3734 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3735 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3736 gen_set_label(l2);
3738 break;
3739 case OPC_MOD_G_2E:
3740 case OPC_MOD_G_2F:
3742 TCGLabel *l1 = gen_new_label();
3743 TCGLabel *l2 = gen_new_label();
3744 TCGLabel *l3 = gen_new_label();
3745 tcg_gen_ext32u_tl(t0, t0);
3746 tcg_gen_ext32u_tl(t1, t1);
3747 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3748 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3749 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3750 gen_set_label(l1);
3751 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3752 tcg_gen_br(l3);
3753 gen_set_label(l2);
3754 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3755 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3756 gen_set_label(l3);
3758 break;
3759 case OPC_MODU_G_2E:
3760 case OPC_MODU_G_2F:
3762 TCGLabel *l1 = gen_new_label();
3763 TCGLabel *l2 = gen_new_label();
3764 tcg_gen_ext32u_tl(t0, t0);
3765 tcg_gen_ext32u_tl(t1, t1);
3766 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3767 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3768 tcg_gen_br(l2);
3769 gen_set_label(l1);
3770 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3771 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3772 gen_set_label(l2);
3774 break;
3775 #if defined(TARGET_MIPS64)
3776 case OPC_DMULT_G_2E:
3777 case OPC_DMULT_G_2F:
3778 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3779 break;
3780 case OPC_DMULTU_G_2E:
3781 case OPC_DMULTU_G_2F:
3782 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3783 break;
3784 case OPC_DDIV_G_2E:
3785 case OPC_DDIV_G_2F:
3787 TCGLabel *l1 = gen_new_label();
3788 TCGLabel *l2 = gen_new_label();
3789 TCGLabel *l3 = gen_new_label();
3790 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3791 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3792 tcg_gen_br(l3);
3793 gen_set_label(l1);
3794 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3795 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3796 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3797 tcg_gen_br(l3);
3798 gen_set_label(l2);
3799 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3800 gen_set_label(l3);
3802 break;
3803 case OPC_DDIVU_G_2E:
3804 case OPC_DDIVU_G_2F:
3806 TCGLabel *l1 = gen_new_label();
3807 TCGLabel *l2 = gen_new_label();
3808 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3809 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3810 tcg_gen_br(l2);
3811 gen_set_label(l1);
3812 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3813 gen_set_label(l2);
3815 break;
3816 case OPC_DMOD_G_2E:
3817 case OPC_DMOD_G_2F:
3819 TCGLabel *l1 = gen_new_label();
3820 TCGLabel *l2 = gen_new_label();
3821 TCGLabel *l3 = gen_new_label();
3822 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3823 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3824 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3825 gen_set_label(l1);
3826 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3827 tcg_gen_br(l3);
3828 gen_set_label(l2);
3829 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3830 gen_set_label(l3);
3832 break;
3833 case OPC_DMODU_G_2E:
3834 case OPC_DMODU_G_2F:
3836 TCGLabel *l1 = gen_new_label();
3837 TCGLabel *l2 = gen_new_label();
3838 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3839 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3840 tcg_gen_br(l2);
3841 gen_set_label(l1);
3842 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3843 gen_set_label(l2);
3845 break;
3846 #endif
3849 tcg_temp_free(t0);
3850 tcg_temp_free(t1);
3853 /* Loongson multimedia instructions */
3854 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3856 uint32_t opc, shift_max;
3857 TCGv_i64 t0, t1;
3859 opc = MASK_LMI(ctx->opcode);
3860 switch (opc) {
3861 case OPC_ADD_CP2:
3862 case OPC_SUB_CP2:
3863 case OPC_DADD_CP2:
3864 case OPC_DSUB_CP2:
3865 t0 = tcg_temp_local_new_i64();
3866 t1 = tcg_temp_local_new_i64();
3867 break;
3868 default:
3869 t0 = tcg_temp_new_i64();
3870 t1 = tcg_temp_new_i64();
3871 break;
3874 gen_load_fpr64(ctx, t0, rs);
3875 gen_load_fpr64(ctx, t1, rt);
3877 #define LMI_HELPER(UP, LO) \
3878 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
3879 #define LMI_HELPER_1(UP, LO) \
3880 case OPC_##UP: gen_helper_##LO(t0, t0); break
3881 #define LMI_DIRECT(UP, LO, OP) \
3882 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
3884 switch (opc) {
3885 LMI_HELPER(PADDSH, paddsh);
3886 LMI_HELPER(PADDUSH, paddush);
3887 LMI_HELPER(PADDH, paddh);
3888 LMI_HELPER(PADDW, paddw);
3889 LMI_HELPER(PADDSB, paddsb);
3890 LMI_HELPER(PADDUSB, paddusb);
3891 LMI_HELPER(PADDB, paddb);
3893 LMI_HELPER(PSUBSH, psubsh);
3894 LMI_HELPER(PSUBUSH, psubush);
3895 LMI_HELPER(PSUBH, psubh);
3896 LMI_HELPER(PSUBW, psubw);
3897 LMI_HELPER(PSUBSB, psubsb);
3898 LMI_HELPER(PSUBUSB, psubusb);
3899 LMI_HELPER(PSUBB, psubb);
3901 LMI_HELPER(PSHUFH, pshufh);
3902 LMI_HELPER(PACKSSWH, packsswh);
3903 LMI_HELPER(PACKSSHB, packsshb);
3904 LMI_HELPER(PACKUSHB, packushb);
3906 LMI_HELPER(PUNPCKLHW, punpcklhw);
3907 LMI_HELPER(PUNPCKHHW, punpckhhw);
3908 LMI_HELPER(PUNPCKLBH, punpcklbh);
3909 LMI_HELPER(PUNPCKHBH, punpckhbh);
3910 LMI_HELPER(PUNPCKLWD, punpcklwd);
3911 LMI_HELPER(PUNPCKHWD, punpckhwd);
3913 LMI_HELPER(PAVGH, pavgh);
3914 LMI_HELPER(PAVGB, pavgb);
3915 LMI_HELPER(PMAXSH, pmaxsh);
3916 LMI_HELPER(PMINSH, pminsh);
3917 LMI_HELPER(PMAXUB, pmaxub);
3918 LMI_HELPER(PMINUB, pminub);
3920 LMI_HELPER(PCMPEQW, pcmpeqw);
3921 LMI_HELPER(PCMPGTW, pcmpgtw);
3922 LMI_HELPER(PCMPEQH, pcmpeqh);
3923 LMI_HELPER(PCMPGTH, pcmpgth);
3924 LMI_HELPER(PCMPEQB, pcmpeqb);
3925 LMI_HELPER(PCMPGTB, pcmpgtb);
3927 LMI_HELPER(PSLLW, psllw);
3928 LMI_HELPER(PSLLH, psllh);
3929 LMI_HELPER(PSRLW, psrlw);
3930 LMI_HELPER(PSRLH, psrlh);
3931 LMI_HELPER(PSRAW, psraw);
3932 LMI_HELPER(PSRAH, psrah);
3934 LMI_HELPER(PMULLH, pmullh);
3935 LMI_HELPER(PMULHH, pmulhh);
3936 LMI_HELPER(PMULHUH, pmulhuh);
3937 LMI_HELPER(PMADDHW, pmaddhw);
3939 LMI_HELPER(PASUBUB, pasubub);
3940 LMI_HELPER_1(BIADD, biadd);
3941 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3943 LMI_DIRECT(PADDD, paddd, add);
3944 LMI_DIRECT(PSUBD, psubd, sub);
3945 LMI_DIRECT(XOR_CP2, xor, xor);
3946 LMI_DIRECT(NOR_CP2, nor, nor);
3947 LMI_DIRECT(AND_CP2, and, and);
3948 LMI_DIRECT(PANDN, pandn, andc);
3949 LMI_DIRECT(OR, or, or);
3951 case OPC_PINSRH_0:
3952 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3953 break;
3954 case OPC_PINSRH_1:
3955 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3956 break;
3957 case OPC_PINSRH_2:
3958 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3959 break;
3960 case OPC_PINSRH_3:
3961 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3962 break;
3964 case OPC_PEXTRH:
3965 tcg_gen_andi_i64(t1, t1, 3);
3966 tcg_gen_shli_i64(t1, t1, 4);
3967 tcg_gen_shr_i64(t0, t0, t1);
3968 tcg_gen_ext16u_i64(t0, t0);
3969 break;
3971 case OPC_ADDU_CP2:
3972 tcg_gen_add_i64(t0, t0, t1);
3973 tcg_gen_ext32s_i64(t0, t0);
3974 break;
3975 case OPC_SUBU_CP2:
3976 tcg_gen_sub_i64(t0, t0, t1);
3977 tcg_gen_ext32s_i64(t0, t0);
3978 break;
3980 case OPC_SLL_CP2:
3981 shift_max = 32;
3982 goto do_shift;
3983 case OPC_SRL_CP2:
3984 shift_max = 32;
3985 goto do_shift;
3986 case OPC_SRA_CP2:
3987 shift_max = 32;
3988 goto do_shift;
3989 case OPC_DSLL_CP2:
3990 shift_max = 64;
3991 goto do_shift;
3992 case OPC_DSRL_CP2:
3993 shift_max = 64;
3994 goto do_shift;
3995 case OPC_DSRA_CP2:
3996 shift_max = 64;
3997 goto do_shift;
3998 do_shift:
3999 /* Make sure shift count isn't TCG undefined behaviour. */
4000 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4002 switch (opc) {
4003 case OPC_SLL_CP2:
4004 case OPC_DSLL_CP2:
4005 tcg_gen_shl_i64(t0, t0, t1);
4006 break;
4007 case OPC_SRA_CP2:
4008 case OPC_DSRA_CP2:
4009 /* Since SRA is UndefinedResult without sign-extended inputs,
4010 we can treat SRA and DSRA the same. */
4011 tcg_gen_sar_i64(t0, t0, t1);
4012 break;
4013 case OPC_SRL_CP2:
4014 /* We want to shift in zeros for SRL; zero-extend first. */
4015 tcg_gen_ext32u_i64(t0, t0);
4016 /* FALLTHRU */
4017 case OPC_DSRL_CP2:
4018 tcg_gen_shr_i64(t0, t0, t1);
4019 break;
4022 if (shift_max == 32) {
4023 tcg_gen_ext32s_i64(t0, t0);
4026 /* Shifts larger than MAX produce zero. */
4027 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4028 tcg_gen_neg_i64(t1, t1);
4029 tcg_gen_and_i64(t0, t0, t1);
4030 break;
4032 case OPC_ADD_CP2:
4033 case OPC_DADD_CP2:
4035 TCGv_i64 t2 = tcg_temp_new_i64();
4036 TCGLabel *lab = gen_new_label();
4038 tcg_gen_mov_i64(t2, t0);
4039 tcg_gen_add_i64(t0, t1, t2);
4040 if (opc == OPC_ADD_CP2) {
4041 tcg_gen_ext32s_i64(t0, t0);
4043 tcg_gen_xor_i64(t1, t1, t2);
4044 tcg_gen_xor_i64(t2, t2, t0);
4045 tcg_gen_andc_i64(t1, t2, t1);
4046 tcg_temp_free_i64(t2);
4047 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4048 generate_exception(ctx, EXCP_OVERFLOW);
4049 gen_set_label(lab);
4050 break;
4053 case OPC_SUB_CP2:
4054 case OPC_DSUB_CP2:
4056 TCGv_i64 t2 = tcg_temp_new_i64();
4057 TCGLabel *lab = gen_new_label();
4059 tcg_gen_mov_i64(t2, t0);
4060 tcg_gen_sub_i64(t0, t1, t2);
4061 if (opc == OPC_SUB_CP2) {
4062 tcg_gen_ext32s_i64(t0, t0);
4064 tcg_gen_xor_i64(t1, t1, t2);
4065 tcg_gen_xor_i64(t2, t2, t0);
4066 tcg_gen_and_i64(t1, t1, t2);
4067 tcg_temp_free_i64(t2);
4068 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4069 generate_exception(ctx, EXCP_OVERFLOW);
4070 gen_set_label(lab);
4071 break;
4074 case OPC_PMULUW:
4075 tcg_gen_ext32u_i64(t0, t0);
4076 tcg_gen_ext32u_i64(t1, t1);
4077 tcg_gen_mul_i64(t0, t0, t1);
4078 break;
4080 case OPC_SEQU_CP2:
4081 case OPC_SEQ_CP2:
4082 case OPC_SLTU_CP2:
4083 case OPC_SLT_CP2:
4084 case OPC_SLEU_CP2:
4085 case OPC_SLE_CP2:
4086 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4087 FD field is the CC field? */
4088 default:
4089 MIPS_INVAL("loongson_cp2");
4090 generate_exception_end(ctx, EXCP_RI);
4091 return;
4094 #undef LMI_HELPER
4095 #undef LMI_DIRECT
4097 gen_store_fpr64(ctx, t0, rd);
4099 tcg_temp_free_i64(t0);
4100 tcg_temp_free_i64(t1);
4103 /* Traps */
4104 static void gen_trap (DisasContext *ctx, uint32_t opc,
4105 int rs, int rt, int16_t imm)
4107 int cond;
4108 TCGv t0 = tcg_temp_new();
4109 TCGv t1 = tcg_temp_new();
4111 cond = 0;
4112 /* Load needed operands */
4113 switch (opc) {
4114 case OPC_TEQ:
4115 case OPC_TGE:
4116 case OPC_TGEU:
4117 case OPC_TLT:
4118 case OPC_TLTU:
4119 case OPC_TNE:
4120 /* Compare two registers */
4121 if (rs != rt) {
4122 gen_load_gpr(t0, rs);
4123 gen_load_gpr(t1, rt);
4124 cond = 1;
4126 break;
4127 case OPC_TEQI:
4128 case OPC_TGEI:
4129 case OPC_TGEIU:
4130 case OPC_TLTI:
4131 case OPC_TLTIU:
4132 case OPC_TNEI:
4133 /* Compare register to immediate */
4134 if (rs != 0 || imm != 0) {
4135 gen_load_gpr(t0, rs);
4136 tcg_gen_movi_tl(t1, (int32_t)imm);
4137 cond = 1;
4139 break;
4141 if (cond == 0) {
4142 switch (opc) {
4143 case OPC_TEQ: /* rs == rs */
4144 case OPC_TEQI: /* r0 == 0 */
4145 case OPC_TGE: /* rs >= rs */
4146 case OPC_TGEI: /* r0 >= 0 */
4147 case OPC_TGEU: /* rs >= rs unsigned */
4148 case OPC_TGEIU: /* r0 >= 0 unsigned */
4149 /* Always trap */
4150 generate_exception_end(ctx, EXCP_TRAP);
4151 break;
4152 case OPC_TLT: /* rs < rs */
4153 case OPC_TLTI: /* r0 < 0 */
4154 case OPC_TLTU: /* rs < rs unsigned */
4155 case OPC_TLTIU: /* r0 < 0 unsigned */
4156 case OPC_TNE: /* rs != rs */
4157 case OPC_TNEI: /* r0 != 0 */
4158 /* Never trap: treat as NOP. */
4159 break;
4161 } else {
4162 TCGLabel *l1 = gen_new_label();
4164 switch (opc) {
4165 case OPC_TEQ:
4166 case OPC_TEQI:
4167 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4168 break;
4169 case OPC_TGE:
4170 case OPC_TGEI:
4171 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4172 break;
4173 case OPC_TGEU:
4174 case OPC_TGEIU:
4175 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4176 break;
4177 case OPC_TLT:
4178 case OPC_TLTI:
4179 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4180 break;
4181 case OPC_TLTU:
4182 case OPC_TLTIU:
4183 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4184 break;
4185 case OPC_TNE:
4186 case OPC_TNEI:
4187 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4188 break;
4190 generate_exception(ctx, EXCP_TRAP);
4191 gen_set_label(l1);
4193 tcg_temp_free(t0);
4194 tcg_temp_free(t1);
4197 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4199 if (unlikely(ctx->singlestep_enabled)) {
4200 return false;
4203 #ifndef CONFIG_USER_ONLY
4204 return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4205 #else
4206 return true;
4207 #endif
4210 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4212 if (use_goto_tb(ctx, dest)) {
4213 tcg_gen_goto_tb(n);
4214 gen_save_pc(dest);
4215 tcg_gen_exit_tb((uintptr_t)ctx->tb + n);
4216 } else {
4217 gen_save_pc(dest);
4218 if (ctx->singlestep_enabled) {
4219 save_cpu_state(ctx, 0);
4220 gen_helper_raise_exception_debug(cpu_env);
4222 tcg_gen_exit_tb(0);
4226 /* Branches (before delay slot) */
4227 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4228 int insn_bytes,
4229 int rs, int rt, int32_t offset,
4230 int delayslot_size)
4232 target_ulong btgt = -1;
4233 int blink = 0;
4234 int bcond_compute = 0;
4235 TCGv t0 = tcg_temp_new();
4236 TCGv t1 = tcg_temp_new();
4238 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4239 #ifdef MIPS_DEBUG_DISAS
4240 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4241 TARGET_FMT_lx "\n", ctx->pc);
4242 #endif
4243 generate_exception_end(ctx, EXCP_RI);
4244 goto out;
4247 /* Load needed operands */
4248 switch (opc) {
4249 case OPC_BEQ:
4250 case OPC_BEQL:
4251 case OPC_BNE:
4252 case OPC_BNEL:
4253 /* Compare two registers */
4254 if (rs != rt) {
4255 gen_load_gpr(t0, rs);
4256 gen_load_gpr(t1, rt);
4257 bcond_compute = 1;
4259 btgt = ctx->pc + insn_bytes + offset;
4260 break;
4261 case OPC_BGEZ:
4262 case OPC_BGEZAL:
4263 case OPC_BGEZALL:
4264 case OPC_BGEZL:
4265 case OPC_BGTZ:
4266 case OPC_BGTZL:
4267 case OPC_BLEZ:
4268 case OPC_BLEZL:
4269 case OPC_BLTZ:
4270 case OPC_BLTZAL:
4271 case OPC_BLTZALL:
4272 case OPC_BLTZL:
4273 /* Compare to zero */
4274 if (rs != 0) {
4275 gen_load_gpr(t0, rs);
4276 bcond_compute = 1;
4278 btgt = ctx->pc + insn_bytes + offset;
4279 break;
4280 case OPC_BPOSGE32:
4281 #if defined(TARGET_MIPS64)
4282 case OPC_BPOSGE64:
4283 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4284 #else
4285 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4286 #endif
4287 bcond_compute = 1;
4288 btgt = ctx->pc + insn_bytes + offset;
4289 break;
4290 case OPC_J:
4291 case OPC_JAL:
4292 case OPC_JALX:
4293 /* Jump to immediate */
4294 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4295 break;
4296 case OPC_JR:
4297 case OPC_JALR:
4298 /* Jump to register */
4299 if (offset != 0 && offset != 16) {
4300 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4301 others are reserved. */
4302 MIPS_INVAL("jump hint");
4303 generate_exception_end(ctx, EXCP_RI);
4304 goto out;
4306 gen_load_gpr(btarget, rs);
4307 break;
4308 default:
4309 MIPS_INVAL("branch/jump");
4310 generate_exception_end(ctx, EXCP_RI);
4311 goto out;
4313 if (bcond_compute == 0) {
4314 /* No condition to be computed */
4315 switch (opc) {
4316 case OPC_BEQ: /* rx == rx */
4317 case OPC_BEQL: /* rx == rx likely */
4318 case OPC_BGEZ: /* 0 >= 0 */
4319 case OPC_BGEZL: /* 0 >= 0 likely */
4320 case OPC_BLEZ: /* 0 <= 0 */
4321 case OPC_BLEZL: /* 0 <= 0 likely */
4322 /* Always take */
4323 ctx->hflags |= MIPS_HFLAG_B;
4324 break;
4325 case OPC_BGEZAL: /* 0 >= 0 */
4326 case OPC_BGEZALL: /* 0 >= 0 likely */
4327 /* Always take and link */
4328 blink = 31;
4329 ctx->hflags |= MIPS_HFLAG_B;
4330 break;
4331 case OPC_BNE: /* rx != rx */
4332 case OPC_BGTZ: /* 0 > 0 */
4333 case OPC_BLTZ: /* 0 < 0 */
4334 /* Treat as NOP. */
4335 goto out;
4336 case OPC_BLTZAL: /* 0 < 0 */
4337 /* Handle as an unconditional branch to get correct delay
4338 slot checking. */
4339 blink = 31;
4340 btgt = ctx->pc + insn_bytes + delayslot_size;
4341 ctx->hflags |= MIPS_HFLAG_B;
4342 break;
4343 case OPC_BLTZALL: /* 0 < 0 likely */
4344 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4345 /* Skip the instruction in the delay slot */
4346 ctx->pc += 4;
4347 goto out;
4348 case OPC_BNEL: /* rx != rx likely */
4349 case OPC_BGTZL: /* 0 > 0 likely */
4350 case OPC_BLTZL: /* 0 < 0 likely */
4351 /* Skip the instruction in the delay slot */
4352 ctx->pc += 4;
4353 goto out;
4354 case OPC_J:
4355 ctx->hflags |= MIPS_HFLAG_B;
4356 break;
4357 case OPC_JALX:
4358 ctx->hflags |= MIPS_HFLAG_BX;
4359 /* Fallthrough */
4360 case OPC_JAL:
4361 blink = 31;
4362 ctx->hflags |= MIPS_HFLAG_B;
4363 break;
4364 case OPC_JR:
4365 ctx->hflags |= MIPS_HFLAG_BR;
4366 break;
4367 case OPC_JALR:
4368 blink = rt;
4369 ctx->hflags |= MIPS_HFLAG_BR;
4370 break;
4371 default:
4372 MIPS_INVAL("branch/jump");
4373 generate_exception_end(ctx, EXCP_RI);
4374 goto out;
4376 } else {
4377 switch (opc) {
4378 case OPC_BEQ:
4379 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4380 goto not_likely;
4381 case OPC_BEQL:
4382 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4383 goto likely;
4384 case OPC_BNE:
4385 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4386 goto not_likely;
4387 case OPC_BNEL:
4388 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4389 goto likely;
4390 case OPC_BGEZ:
4391 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4392 goto not_likely;
4393 case OPC_BGEZL:
4394 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4395 goto likely;
4396 case OPC_BGEZAL:
4397 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4398 blink = 31;
4399 goto not_likely;
4400 case OPC_BGEZALL:
4401 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4402 blink = 31;
4403 goto likely;
4404 case OPC_BGTZ:
4405 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4406 goto not_likely;
4407 case OPC_BGTZL:
4408 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4409 goto likely;
4410 case OPC_BLEZ:
4411 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4412 goto not_likely;
4413 case OPC_BLEZL:
4414 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4415 goto likely;
4416 case OPC_BLTZ:
4417 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4418 goto not_likely;
4419 case OPC_BLTZL:
4420 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4421 goto likely;
4422 case OPC_BPOSGE32:
4423 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4424 goto not_likely;
4425 #if defined(TARGET_MIPS64)
4426 case OPC_BPOSGE64:
4427 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4428 goto not_likely;
4429 #endif
4430 case OPC_BLTZAL:
4431 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4432 blink = 31;
4433 not_likely:
4434 ctx->hflags |= MIPS_HFLAG_BC;
4435 break;
4436 case OPC_BLTZALL:
4437 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4438 blink = 31;
4439 likely:
4440 ctx->hflags |= MIPS_HFLAG_BL;
4441 break;
4442 default:
4443 MIPS_INVAL("conditional branch/jump");
4444 generate_exception_end(ctx, EXCP_RI);
4445 goto out;
4449 ctx->btarget = btgt;
4451 switch (delayslot_size) {
4452 case 2:
4453 ctx->hflags |= MIPS_HFLAG_BDS16;
4454 break;
4455 case 4:
4456 ctx->hflags |= MIPS_HFLAG_BDS32;
4457 break;
4460 if (blink > 0) {
4461 int post_delay = insn_bytes + delayslot_size;
4462 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4464 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4467 out:
4468 if (insn_bytes == 2)
4469 ctx->hflags |= MIPS_HFLAG_B16;
4470 tcg_temp_free(t0);
4471 tcg_temp_free(t1);
4474 /* special3 bitfield operations */
4475 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4476 int rs, int lsb, int msb)
4478 TCGv t0 = tcg_temp_new();
4479 TCGv t1 = tcg_temp_new();
4481 gen_load_gpr(t1, rs);
4482 switch (opc) {
4483 case OPC_EXT:
4484 if (lsb + msb > 31) {
4485 goto fail;
4487 tcg_gen_shri_tl(t0, t1, lsb);
4488 if (msb != 31) {
4489 tcg_gen_andi_tl(t0, t0, (1U << (msb + 1)) - 1);
4490 } else {
4491 tcg_gen_ext32s_tl(t0, t0);
4493 break;
4494 #if defined(TARGET_MIPS64)
4495 case OPC_DEXTU:
4496 lsb += 32;
4497 goto do_dext;
4498 case OPC_DEXTM:
4499 msb += 32;
4500 goto do_dext;
4501 case OPC_DEXT:
4502 do_dext:
4503 if (lsb + msb > 63) {
4504 goto fail;
4506 tcg_gen_shri_tl(t0, t1, lsb);
4507 if (msb != 63) {
4508 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4510 break;
4511 #endif
4512 case OPC_INS:
4513 if (lsb > msb) {
4514 goto fail;
4516 gen_load_gpr(t0, rt);
4517 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4518 tcg_gen_ext32s_tl(t0, t0);
4519 break;
4520 #if defined(TARGET_MIPS64)
4521 case OPC_DINSU:
4522 lsb += 32;
4523 /* FALLTHRU */
4524 case OPC_DINSM:
4525 msb += 32;
4526 /* FALLTHRU */
4527 case OPC_DINS:
4528 if (lsb > msb) {
4529 goto fail;
4531 gen_load_gpr(t0, rt);
4532 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4533 break;
4534 #endif
4535 default:
4536 fail:
4537 MIPS_INVAL("bitops");
4538 generate_exception_end(ctx, EXCP_RI);
4539 tcg_temp_free(t0);
4540 tcg_temp_free(t1);
4541 return;
4543 gen_store_gpr(t0, rt);
4544 tcg_temp_free(t0);
4545 tcg_temp_free(t1);
4548 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4550 TCGv t0;
4552 if (rd == 0) {
4553 /* If no destination, treat it as a NOP. */
4554 return;
4557 t0 = tcg_temp_new();
4558 gen_load_gpr(t0, rt);
4559 switch (op2) {
4560 case OPC_WSBH:
4562 TCGv t1 = tcg_temp_new();
4564 tcg_gen_shri_tl(t1, t0, 8);
4565 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4566 tcg_gen_shli_tl(t0, t0, 8);
4567 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4568 tcg_gen_or_tl(t0, t0, t1);
4569 tcg_temp_free(t1);
4570 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4572 break;
4573 case OPC_SEB:
4574 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4575 break;
4576 case OPC_SEH:
4577 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4578 break;
4579 #if defined(TARGET_MIPS64)
4580 case OPC_DSBH:
4582 TCGv t1 = tcg_temp_new();
4584 tcg_gen_shri_tl(t1, t0, 8);
4585 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4586 tcg_gen_shli_tl(t0, t0, 8);
4587 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4588 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4589 tcg_temp_free(t1);
4591 break;
4592 case OPC_DSHD:
4594 TCGv t1 = tcg_temp_new();
4596 tcg_gen_shri_tl(t1, t0, 16);
4597 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4598 tcg_gen_shli_tl(t0, t0, 16);
4599 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4600 tcg_gen_or_tl(t0, t0, t1);
4601 tcg_gen_shri_tl(t1, t0, 32);
4602 tcg_gen_shli_tl(t0, t0, 32);
4603 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4604 tcg_temp_free(t1);
4606 break;
4607 #endif
4608 default:
4609 MIPS_INVAL("bsfhl");
4610 generate_exception_end(ctx, EXCP_RI);
4611 tcg_temp_free(t0);
4612 return;
4614 tcg_temp_free(t0);
4617 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4618 int imm2)
4620 TCGv t0;
4621 TCGv t1;
4622 if (rd == 0) {
4623 /* Treat as NOP. */
4624 return;
4626 t0 = tcg_temp_new();
4627 t1 = tcg_temp_new();
4628 gen_load_gpr(t0, rs);
4629 gen_load_gpr(t1, rt);
4630 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4631 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4632 if (opc == OPC_LSA) {
4633 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4636 tcg_temp_free(t1);
4637 tcg_temp_free(t0);
4639 return;
4642 static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
4643 int bp)
4645 TCGv t0;
4646 if (rd == 0) {
4647 /* Treat as NOP. */
4648 return;
4650 t0 = tcg_temp_new();
4651 gen_load_gpr(t0, rt);
4652 if (bp == 0) {
4653 switch (opc) {
4654 case OPC_ALIGN:
4655 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4656 break;
4657 #if defined(TARGET_MIPS64)
4658 case OPC_DALIGN:
4659 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4660 break;
4661 #endif
4663 } else {
4664 TCGv t1 = tcg_temp_new();
4665 gen_load_gpr(t1, rs);
4666 switch (opc) {
4667 case OPC_ALIGN:
4669 TCGv_i64 t2 = tcg_temp_new_i64();
4670 tcg_gen_concat_tl_i64(t2, t1, t0);
4671 tcg_gen_shri_i64(t2, t2, 8 * (4 - bp));
4672 gen_move_low32(cpu_gpr[rd], t2);
4673 tcg_temp_free_i64(t2);
4675 break;
4676 #if defined(TARGET_MIPS64)
4677 case OPC_DALIGN:
4678 tcg_gen_shli_tl(t0, t0, 8 * bp);
4679 tcg_gen_shri_tl(t1, t1, 8 * (8 - bp));
4680 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4681 break;
4682 #endif
4684 tcg_temp_free(t1);
4687 tcg_temp_free(t0);
4690 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4692 TCGv t0;
4693 if (rd == 0) {
4694 /* Treat as NOP. */
4695 return;
4697 t0 = tcg_temp_new();
4698 gen_load_gpr(t0, rt);
4699 switch (opc) {
4700 case OPC_BITSWAP:
4701 gen_helper_bitswap(cpu_gpr[rd], t0);
4702 break;
4703 #if defined(TARGET_MIPS64)
4704 case OPC_DBITSWAP:
4705 gen_helper_dbitswap(cpu_gpr[rd], t0);
4706 break;
4707 #endif
4709 tcg_temp_free(t0);
4712 #ifndef CONFIG_USER_ONLY
4713 /* CP0 (MMU and control) */
4714 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4716 TCGv_i64 t0 = tcg_temp_new_i64();
4717 TCGv_i64 t1 = tcg_temp_new_i64();
4719 tcg_gen_ext_tl_i64(t0, arg);
4720 tcg_gen_ld_i64(t1, cpu_env, off);
4721 #if defined(TARGET_MIPS64)
4722 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4723 #else
4724 tcg_gen_concat32_i64(t1, t1, t0);
4725 #endif
4726 tcg_gen_st_i64(t1, cpu_env, off);
4727 tcg_temp_free_i64(t1);
4728 tcg_temp_free_i64(t0);
4731 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4733 TCGv_i64 t0 = tcg_temp_new_i64();
4734 TCGv_i64 t1 = tcg_temp_new_i64();
4736 tcg_gen_ext_tl_i64(t0, arg);
4737 tcg_gen_ld_i64(t1, cpu_env, off);
4738 tcg_gen_concat32_i64(t1, t1, t0);
4739 tcg_gen_st_i64(t1, cpu_env, off);
4740 tcg_temp_free_i64(t1);
4741 tcg_temp_free_i64(t0);
4744 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
4746 TCGv_i64 t0 = tcg_temp_new_i64();
4748 tcg_gen_ld_i64(t0, cpu_env, off);
4749 #if defined(TARGET_MIPS64)
4750 tcg_gen_shri_i64(t0, t0, 30);
4751 #else
4752 tcg_gen_shri_i64(t0, t0, 32);
4753 #endif
4754 gen_move_low32(arg, t0);
4755 tcg_temp_free_i64(t0);
4758 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
4760 TCGv_i64 t0 = tcg_temp_new_i64();
4762 tcg_gen_ld_i64(t0, cpu_env, off);
4763 tcg_gen_shri_i64(t0, t0, 32 + shift);
4764 gen_move_low32(arg, t0);
4765 tcg_temp_free_i64(t0);
4768 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4770 TCGv_i32 t0 = tcg_temp_new_i32();
4772 tcg_gen_ld_i32(t0, cpu_env, off);
4773 tcg_gen_ext_i32_tl(arg, t0);
4774 tcg_temp_free_i32(t0);
4777 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4779 tcg_gen_ld_tl(arg, cpu_env, off);
4780 tcg_gen_ext32s_tl(arg, arg);
4783 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4785 TCGv_i32 t0 = tcg_temp_new_i32();
4787 tcg_gen_trunc_tl_i32(t0, arg);
4788 tcg_gen_st_i32(t0, cpu_env, off);
4789 tcg_temp_free_i32(t0);
4792 #define CP0_CHECK(c) \
4793 do { \
4794 if (!(c)) { \
4795 goto cp0_unimplemented; \
4797 } while (0)
4799 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4801 const char *rn = "invalid";
4803 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4805 switch (reg) {
4806 case 2:
4807 switch (sel) {
4808 case 0:
4809 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4810 rn = "EntryLo0";
4811 break;
4812 default:
4813 goto cp0_unimplemented;
4815 break;
4816 case 3:
4817 switch (sel) {
4818 case 0:
4819 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4820 rn = "EntryLo1";
4821 break;
4822 default:
4823 goto cp0_unimplemented;
4825 break;
4826 case 17:
4827 switch (sel) {
4828 case 0:
4829 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
4830 ctx->CP0_LLAddr_shift);
4831 rn = "LLAddr";
4832 break;
4833 case 1:
4834 CP0_CHECK(ctx->mrp);
4835 gen_helper_mfhc0_maar(arg, cpu_env);
4836 rn = "MAAR";
4837 break;
4838 default:
4839 goto cp0_unimplemented;
4841 break;
4842 case 28:
4843 switch (sel) {
4844 case 0:
4845 case 2:
4846 case 4:
4847 case 6:
4848 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
4849 rn = "TagLo";
4850 break;
4851 default:
4852 goto cp0_unimplemented;
4854 break;
4855 default:
4856 goto cp0_unimplemented;
4859 (void)rn; /* avoid a compiler warning */
4860 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4861 return;
4863 cp0_unimplemented:
4864 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4865 tcg_gen_movi_tl(arg, 0);
4868 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4870 const char *rn = "invalid";
4871 uint64_t mask = ctx->PAMask >> 36;
4873 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4875 switch (reg) {
4876 case 2:
4877 switch (sel) {
4878 case 0:
4879 tcg_gen_andi_tl(arg, arg, mask);
4880 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4881 rn = "EntryLo0";
4882 break;
4883 default:
4884 goto cp0_unimplemented;
4886 break;
4887 case 3:
4888 switch (sel) {
4889 case 0:
4890 tcg_gen_andi_tl(arg, arg, mask);
4891 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4892 rn = "EntryLo1";
4893 break;
4894 default:
4895 goto cp0_unimplemented;
4897 break;
4898 case 17:
4899 switch (sel) {
4900 case 0:
4901 /* LLAddr is read-only (the only exception is bit 0 if LLB is
4902 supported); the CP0_LLAddr_rw_bitmask does not seem to be
4903 relevant for modern MIPS cores supporting MTHC0, therefore
4904 treating MTHC0 to LLAddr as NOP. */
4905 rn = "LLAddr";
4906 break;
4907 case 1:
4908 CP0_CHECK(ctx->mrp);
4909 gen_helper_mthc0_maar(cpu_env, arg);
4910 rn = "MAAR";
4911 break;
4912 default:
4913 goto cp0_unimplemented;
4915 break;
4916 case 28:
4917 switch (sel) {
4918 case 0:
4919 case 2:
4920 case 4:
4921 case 6:
4922 tcg_gen_andi_tl(arg, arg, mask);
4923 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
4924 rn = "TagLo";
4925 break;
4926 default:
4927 goto cp0_unimplemented;
4929 break;
4930 default:
4931 goto cp0_unimplemented;
4934 (void)rn; /* avoid a compiler warning */
4935 cp0_unimplemented:
4936 LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
4939 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
4941 if (ctx->insn_flags & ISA_MIPS32R6) {
4942 tcg_gen_movi_tl(arg, 0);
4943 } else {
4944 tcg_gen_movi_tl(arg, ~0);
4948 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4950 const char *rn = "invalid";
4952 if (sel != 0)
4953 check_insn(ctx, ISA_MIPS32);
4955 switch (reg) {
4956 case 0:
4957 switch (sel) {
4958 case 0:
4959 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4960 rn = "Index";
4961 break;
4962 case 1:
4963 CP0_CHECK(ctx->insn_flags & ASE_MT);
4964 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4965 rn = "MVPControl";
4966 break;
4967 case 2:
4968 CP0_CHECK(ctx->insn_flags & ASE_MT);
4969 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4970 rn = "MVPConf0";
4971 break;
4972 case 3:
4973 CP0_CHECK(ctx->insn_flags & ASE_MT);
4974 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4975 rn = "MVPConf1";
4976 break;
4977 case 4:
4978 CP0_CHECK(ctx->vp);
4979 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
4980 rn = "VPControl";
4981 break;
4982 default:
4983 goto cp0_unimplemented;
4985 break;
4986 case 1:
4987 switch (sel) {
4988 case 0:
4989 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
4990 gen_helper_mfc0_random(arg, cpu_env);
4991 rn = "Random";
4992 break;
4993 case 1:
4994 CP0_CHECK(ctx->insn_flags & ASE_MT);
4995 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4996 rn = "VPEControl";
4997 break;
4998 case 2:
4999 CP0_CHECK(ctx->insn_flags & ASE_MT);
5000 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5001 rn = "VPEConf0";
5002 break;
5003 case 3:
5004 CP0_CHECK(ctx->insn_flags & ASE_MT);
5005 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5006 rn = "VPEConf1";
5007 break;
5008 case 4:
5009 CP0_CHECK(ctx->insn_flags & ASE_MT);
5010 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5011 rn = "YQMask";
5012 break;
5013 case 5:
5014 CP0_CHECK(ctx->insn_flags & ASE_MT);
5015 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5016 rn = "VPESchedule";
5017 break;
5018 case 6:
5019 CP0_CHECK(ctx->insn_flags & ASE_MT);
5020 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5021 rn = "VPEScheFBack";
5022 break;
5023 case 7:
5024 CP0_CHECK(ctx->insn_flags & ASE_MT);
5025 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5026 rn = "VPEOpt";
5027 break;
5028 default:
5029 goto cp0_unimplemented;
5031 break;
5032 case 2:
5033 switch (sel) {
5034 case 0:
5036 TCGv_i64 tmp = tcg_temp_new_i64();
5037 tcg_gen_ld_i64(tmp, cpu_env,
5038 offsetof(CPUMIPSState, CP0_EntryLo0));
5039 #if defined(TARGET_MIPS64)
5040 if (ctx->rxi) {
5041 /* Move RI/XI fields to bits 31:30 */
5042 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5043 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5045 #endif
5046 gen_move_low32(arg, tmp);
5047 tcg_temp_free_i64(tmp);
5049 rn = "EntryLo0";
5050 break;
5051 case 1:
5052 CP0_CHECK(ctx->insn_flags & ASE_MT);
5053 gen_helper_mfc0_tcstatus(arg, cpu_env);
5054 rn = "TCStatus";
5055 break;
5056 case 2:
5057 CP0_CHECK(ctx->insn_flags & ASE_MT);
5058 gen_helper_mfc0_tcbind(arg, cpu_env);
5059 rn = "TCBind";
5060 break;
5061 case 3:
5062 CP0_CHECK(ctx->insn_flags & ASE_MT);
5063 gen_helper_mfc0_tcrestart(arg, cpu_env);
5064 rn = "TCRestart";
5065 break;
5066 case 4:
5067 CP0_CHECK(ctx->insn_flags & ASE_MT);
5068 gen_helper_mfc0_tchalt(arg, cpu_env);
5069 rn = "TCHalt";
5070 break;
5071 case 5:
5072 CP0_CHECK(ctx->insn_flags & ASE_MT);
5073 gen_helper_mfc0_tccontext(arg, cpu_env);
5074 rn = "TCContext";
5075 break;
5076 case 6:
5077 CP0_CHECK(ctx->insn_flags & ASE_MT);
5078 gen_helper_mfc0_tcschedule(arg, cpu_env);
5079 rn = "TCSchedule";
5080 break;
5081 case 7:
5082 CP0_CHECK(ctx->insn_flags & ASE_MT);
5083 gen_helper_mfc0_tcschefback(arg, cpu_env);
5084 rn = "TCScheFBack";
5085 break;
5086 default:
5087 goto cp0_unimplemented;
5089 break;
5090 case 3:
5091 switch (sel) {
5092 case 0:
5094 TCGv_i64 tmp = tcg_temp_new_i64();
5095 tcg_gen_ld_i64(tmp, cpu_env,
5096 offsetof(CPUMIPSState, CP0_EntryLo1));
5097 #if defined(TARGET_MIPS64)
5098 if (ctx->rxi) {
5099 /* Move RI/XI fields to bits 31:30 */
5100 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5101 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5103 #endif
5104 gen_move_low32(arg, tmp);
5105 tcg_temp_free_i64(tmp);
5107 rn = "EntryLo1";
5108 break;
5109 case 1:
5110 CP0_CHECK(ctx->vp);
5111 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5112 rn = "GlobalNumber";
5113 break;
5114 default:
5115 goto cp0_unimplemented;
5117 break;
5118 case 4:
5119 switch (sel) {
5120 case 0:
5121 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5122 tcg_gen_ext32s_tl(arg, arg);
5123 rn = "Context";
5124 break;
5125 case 1:
5126 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5127 rn = "ContextConfig";
5128 goto cp0_unimplemented;
5129 // break;
5130 case 2:
5131 CP0_CHECK(ctx->ulri);
5132 tcg_gen_ld32s_tl(arg, cpu_env,
5133 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5134 rn = "UserLocal";
5135 break;
5136 default:
5137 goto cp0_unimplemented;
5139 break;
5140 case 5:
5141 switch (sel) {
5142 case 0:
5143 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5144 rn = "PageMask";
5145 break;
5146 case 1:
5147 check_insn(ctx, ISA_MIPS32R2);
5148 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5149 rn = "PageGrain";
5150 break;
5151 default:
5152 goto cp0_unimplemented;
5154 break;
5155 case 6:
5156 switch (sel) {
5157 case 0:
5158 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5159 rn = "Wired";
5160 break;
5161 case 1:
5162 check_insn(ctx, ISA_MIPS32R2);
5163 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5164 rn = "SRSConf0";
5165 break;
5166 case 2:
5167 check_insn(ctx, ISA_MIPS32R2);
5168 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5169 rn = "SRSConf1";
5170 break;
5171 case 3:
5172 check_insn(ctx, ISA_MIPS32R2);
5173 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5174 rn = "SRSConf2";
5175 break;
5176 case 4:
5177 check_insn(ctx, ISA_MIPS32R2);
5178 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5179 rn = "SRSConf3";
5180 break;
5181 case 5:
5182 check_insn(ctx, ISA_MIPS32R2);
5183 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5184 rn = "SRSConf4";
5185 break;
5186 default:
5187 goto cp0_unimplemented;
5189 break;
5190 case 7:
5191 switch (sel) {
5192 case 0:
5193 check_insn(ctx, ISA_MIPS32R2);
5194 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5195 rn = "HWREna";
5196 break;
5197 default:
5198 goto cp0_unimplemented;
5200 break;
5201 case 8:
5202 switch (sel) {
5203 case 0:
5204 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5205 tcg_gen_ext32s_tl(arg, arg);
5206 rn = "BadVAddr";
5207 break;
5208 case 1:
5209 CP0_CHECK(ctx->bi);
5210 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5211 rn = "BadInstr";
5212 break;
5213 case 2:
5214 CP0_CHECK(ctx->bp);
5215 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5216 rn = "BadInstrP";
5217 break;
5218 default:
5219 goto cp0_unimplemented;
5221 break;
5222 case 9:
5223 switch (sel) {
5224 case 0:
5225 /* Mark as an IO operation because we read the time. */
5226 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5227 gen_io_start();
5229 gen_helper_mfc0_count(arg, cpu_env);
5230 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5231 gen_io_end();
5233 /* Break the TB to be able to take timer interrupts immediately
5234 after reading count. */
5235 ctx->bstate = BS_STOP;
5236 rn = "Count";
5237 break;
5238 /* 6,7 are implementation dependent */
5239 default:
5240 goto cp0_unimplemented;
5242 break;
5243 case 10:
5244 switch (sel) {
5245 case 0:
5246 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5247 tcg_gen_ext32s_tl(arg, arg);
5248 rn = "EntryHi";
5249 break;
5250 default:
5251 goto cp0_unimplemented;
5253 break;
5254 case 11:
5255 switch (sel) {
5256 case 0:
5257 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5258 rn = "Compare";
5259 break;
5260 /* 6,7 are implementation dependent */
5261 default:
5262 goto cp0_unimplemented;
5264 break;
5265 case 12:
5266 switch (sel) {
5267 case 0:
5268 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5269 rn = "Status";
5270 break;
5271 case 1:
5272 check_insn(ctx, ISA_MIPS32R2);
5273 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5274 rn = "IntCtl";
5275 break;
5276 case 2:
5277 check_insn(ctx, ISA_MIPS32R2);
5278 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5279 rn = "SRSCtl";
5280 break;
5281 case 3:
5282 check_insn(ctx, ISA_MIPS32R2);
5283 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5284 rn = "SRSMap";
5285 break;
5286 default:
5287 goto cp0_unimplemented;
5289 break;
5290 case 13:
5291 switch (sel) {
5292 case 0:
5293 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5294 rn = "Cause";
5295 break;
5296 default:
5297 goto cp0_unimplemented;
5299 break;
5300 case 14:
5301 switch (sel) {
5302 case 0:
5303 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5304 tcg_gen_ext32s_tl(arg, arg);
5305 rn = "EPC";
5306 break;
5307 default:
5308 goto cp0_unimplemented;
5310 break;
5311 case 15:
5312 switch (sel) {
5313 case 0:
5314 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5315 rn = "PRid";
5316 break;
5317 case 1:
5318 check_insn(ctx, ISA_MIPS32R2);
5319 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5320 rn = "EBase";
5321 break;
5322 case 3:
5323 check_insn(ctx, ISA_MIPS32R2);
5324 CP0_CHECK(ctx->cmgcr);
5325 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
5326 tcg_gen_ext32s_tl(arg, arg);
5327 rn = "CMGCRBase";
5328 break;
5329 default:
5330 goto cp0_unimplemented;
5332 break;
5333 case 16:
5334 switch (sel) {
5335 case 0:
5336 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5337 rn = "Config";
5338 break;
5339 case 1:
5340 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5341 rn = "Config1";
5342 break;
5343 case 2:
5344 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5345 rn = "Config2";
5346 break;
5347 case 3:
5348 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5349 rn = "Config3";
5350 break;
5351 case 4:
5352 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5353 rn = "Config4";
5354 break;
5355 case 5:
5356 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5357 rn = "Config5";
5358 break;
5359 /* 6,7 are implementation dependent */
5360 case 6:
5361 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5362 rn = "Config6";
5363 break;
5364 case 7:
5365 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5366 rn = "Config7";
5367 break;
5368 default:
5369 goto cp0_unimplemented;
5371 break;
5372 case 17:
5373 switch (sel) {
5374 case 0:
5375 gen_helper_mfc0_lladdr(arg, cpu_env);
5376 rn = "LLAddr";
5377 break;
5378 case 1:
5379 CP0_CHECK(ctx->mrp);
5380 gen_helper_mfc0_maar(arg, cpu_env);
5381 rn = "MAAR";
5382 break;
5383 case 2:
5384 CP0_CHECK(ctx->mrp);
5385 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
5386 rn = "MAARI";
5387 break;
5388 default:
5389 goto cp0_unimplemented;
5391 break;
5392 case 18:
5393 switch (sel) {
5394 case 0 ... 7:
5395 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5396 rn = "WatchLo";
5397 break;
5398 default:
5399 goto cp0_unimplemented;
5401 break;
5402 case 19:
5403 switch (sel) {
5404 case 0 ...7:
5405 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5406 rn = "WatchHi";
5407 break;
5408 default:
5409 goto cp0_unimplemented;
5411 break;
5412 case 20:
5413 switch (sel) {
5414 case 0:
5415 #if defined(TARGET_MIPS64)
5416 check_insn(ctx, ISA_MIPS3);
5417 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5418 tcg_gen_ext32s_tl(arg, arg);
5419 rn = "XContext";
5420 break;
5421 #endif
5422 default:
5423 goto cp0_unimplemented;
5425 break;
5426 case 21:
5427 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5428 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5429 switch (sel) {
5430 case 0:
5431 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5432 rn = "Framemask";
5433 break;
5434 default:
5435 goto cp0_unimplemented;
5437 break;
5438 case 22:
5439 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5440 rn = "'Diagnostic"; /* implementation dependent */
5441 break;
5442 case 23:
5443 switch (sel) {
5444 case 0:
5445 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5446 rn = "Debug";
5447 break;
5448 case 1:
5449 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5450 rn = "TraceControl";
5451 // break;
5452 case 2:
5453 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5454 rn = "TraceControl2";
5455 // break;
5456 case 3:
5457 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5458 rn = "UserTraceData";
5459 // break;
5460 case 4:
5461 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5462 rn = "TraceBPC";
5463 // break;
5464 default:
5465 goto cp0_unimplemented;
5467 break;
5468 case 24:
5469 switch (sel) {
5470 case 0:
5471 /* EJTAG support */
5472 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5473 tcg_gen_ext32s_tl(arg, arg);
5474 rn = "DEPC";
5475 break;
5476 default:
5477 goto cp0_unimplemented;
5479 break;
5480 case 25:
5481 switch (sel) {
5482 case 0:
5483 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5484 rn = "Performance0";
5485 break;
5486 case 1:
5487 // gen_helper_mfc0_performance1(arg);
5488 rn = "Performance1";
5489 // break;
5490 case 2:
5491 // gen_helper_mfc0_performance2(arg);
5492 rn = "Performance2";
5493 // break;
5494 case 3:
5495 // gen_helper_mfc0_performance3(arg);
5496 rn = "Performance3";
5497 // break;
5498 case 4:
5499 // gen_helper_mfc0_performance4(arg);
5500 rn = "Performance4";
5501 // break;
5502 case 5:
5503 // gen_helper_mfc0_performance5(arg);
5504 rn = "Performance5";
5505 // break;
5506 case 6:
5507 // gen_helper_mfc0_performance6(arg);
5508 rn = "Performance6";
5509 // break;
5510 case 7:
5511 // gen_helper_mfc0_performance7(arg);
5512 rn = "Performance7";
5513 // break;
5514 default:
5515 goto cp0_unimplemented;
5517 break;
5518 case 26:
5519 switch (sel) {
5520 case 0:
5521 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
5522 rn = "ErrCtl";
5523 break;
5524 default:
5525 goto cp0_unimplemented;
5527 break;
5528 case 27:
5529 switch (sel) {
5530 case 0 ... 3:
5531 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5532 rn = "CacheErr";
5533 break;
5534 default:
5535 goto cp0_unimplemented;
5537 break;
5538 case 28:
5539 switch (sel) {
5540 case 0:
5541 case 2:
5542 case 4:
5543 case 6:
5545 TCGv_i64 tmp = tcg_temp_new_i64();
5546 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5547 gen_move_low32(arg, tmp);
5548 tcg_temp_free_i64(tmp);
5550 rn = "TagLo";
5551 break;
5552 case 1:
5553 case 3:
5554 case 5:
5555 case 7:
5556 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5557 rn = "DataLo";
5558 break;
5559 default:
5560 goto cp0_unimplemented;
5562 break;
5563 case 29:
5564 switch (sel) {
5565 case 0:
5566 case 2:
5567 case 4:
5568 case 6:
5569 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5570 rn = "TagHi";
5571 break;
5572 case 1:
5573 case 3:
5574 case 5:
5575 case 7:
5576 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5577 rn = "DataHi";
5578 break;
5579 default:
5580 goto cp0_unimplemented;
5582 break;
5583 case 30:
5584 switch (sel) {
5585 case 0:
5586 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5587 tcg_gen_ext32s_tl(arg, arg);
5588 rn = "ErrorEPC";
5589 break;
5590 default:
5591 goto cp0_unimplemented;
5593 break;
5594 case 31:
5595 switch (sel) {
5596 case 0:
5597 /* EJTAG support */
5598 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5599 rn = "DESAVE";
5600 break;
5601 case 2 ... 7:
5602 CP0_CHECK(ctx->kscrexist & (1 << sel));
5603 tcg_gen_ld_tl(arg, cpu_env,
5604 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5605 tcg_gen_ext32s_tl(arg, arg);
5606 rn = "KScratch";
5607 break;
5608 default:
5609 goto cp0_unimplemented;
5611 break;
5612 default:
5613 goto cp0_unimplemented;
5615 (void)rn; /* avoid a compiler warning */
5616 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5617 return;
5619 cp0_unimplemented:
5620 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5621 gen_mfc0_unimplemented(ctx, arg);
5624 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5626 const char *rn = "invalid";
5628 if (sel != 0)
5629 check_insn(ctx, ISA_MIPS32);
5631 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5632 gen_io_start();
5635 switch (reg) {
5636 case 0:
5637 switch (sel) {
5638 case 0:
5639 gen_helper_mtc0_index(cpu_env, arg);
5640 rn = "Index";
5641 break;
5642 case 1:
5643 CP0_CHECK(ctx->insn_flags & ASE_MT);
5644 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5645 rn = "MVPControl";
5646 break;
5647 case 2:
5648 CP0_CHECK(ctx->insn_flags & ASE_MT);
5649 /* ignored */
5650 rn = "MVPConf0";
5651 break;
5652 case 3:
5653 CP0_CHECK(ctx->insn_flags & ASE_MT);
5654 /* ignored */
5655 rn = "MVPConf1";
5656 break;
5657 case 4:
5658 CP0_CHECK(ctx->vp);
5659 /* ignored */
5660 rn = "VPControl";
5661 break;
5662 default:
5663 goto cp0_unimplemented;
5665 break;
5666 case 1:
5667 switch (sel) {
5668 case 0:
5669 /* ignored */
5670 rn = "Random";
5671 break;
5672 case 1:
5673 CP0_CHECK(ctx->insn_flags & ASE_MT);
5674 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5675 rn = "VPEControl";
5676 break;
5677 case 2:
5678 CP0_CHECK(ctx->insn_flags & ASE_MT);
5679 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5680 rn = "VPEConf0";
5681 break;
5682 case 3:
5683 CP0_CHECK(ctx->insn_flags & ASE_MT);
5684 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5685 rn = "VPEConf1";
5686 break;
5687 case 4:
5688 CP0_CHECK(ctx->insn_flags & ASE_MT);
5689 gen_helper_mtc0_yqmask(cpu_env, arg);
5690 rn = "YQMask";
5691 break;
5692 case 5:
5693 CP0_CHECK(ctx->insn_flags & ASE_MT);
5694 tcg_gen_st_tl(arg, cpu_env,
5695 offsetof(CPUMIPSState, CP0_VPESchedule));
5696 rn = "VPESchedule";
5697 break;
5698 case 6:
5699 CP0_CHECK(ctx->insn_flags & ASE_MT);
5700 tcg_gen_st_tl(arg, cpu_env,
5701 offsetof(CPUMIPSState, CP0_VPEScheFBack));
5702 rn = "VPEScheFBack";
5703 break;
5704 case 7:
5705 CP0_CHECK(ctx->insn_flags & ASE_MT);
5706 gen_helper_mtc0_vpeopt(cpu_env, arg);
5707 rn = "VPEOpt";
5708 break;
5709 default:
5710 goto cp0_unimplemented;
5712 break;
5713 case 2:
5714 switch (sel) {
5715 case 0:
5716 gen_helper_mtc0_entrylo0(cpu_env, arg);
5717 rn = "EntryLo0";
5718 break;
5719 case 1:
5720 CP0_CHECK(ctx->insn_flags & ASE_MT);
5721 gen_helper_mtc0_tcstatus(cpu_env, arg);
5722 rn = "TCStatus";
5723 break;
5724 case 2:
5725 CP0_CHECK(ctx->insn_flags & ASE_MT);
5726 gen_helper_mtc0_tcbind(cpu_env, arg);
5727 rn = "TCBind";
5728 break;
5729 case 3:
5730 CP0_CHECK(ctx->insn_flags & ASE_MT);
5731 gen_helper_mtc0_tcrestart(cpu_env, arg);
5732 rn = "TCRestart";
5733 break;
5734 case 4:
5735 CP0_CHECK(ctx->insn_flags & ASE_MT);
5736 gen_helper_mtc0_tchalt(cpu_env, arg);
5737 rn = "TCHalt";
5738 break;
5739 case 5:
5740 CP0_CHECK(ctx->insn_flags & ASE_MT);
5741 gen_helper_mtc0_tccontext(cpu_env, arg);
5742 rn = "TCContext";
5743 break;
5744 case 6:
5745 CP0_CHECK(ctx->insn_flags & ASE_MT);
5746 gen_helper_mtc0_tcschedule(cpu_env, arg);
5747 rn = "TCSchedule";
5748 break;
5749 case 7:
5750 CP0_CHECK(ctx->insn_flags & ASE_MT);
5751 gen_helper_mtc0_tcschefback(cpu_env, arg);
5752 rn = "TCScheFBack";
5753 break;
5754 default:
5755 goto cp0_unimplemented;
5757 break;
5758 case 3:
5759 switch (sel) {
5760 case 0:
5761 gen_helper_mtc0_entrylo1(cpu_env, arg);
5762 rn = "EntryLo1";
5763 break;
5764 case 1:
5765 CP0_CHECK(ctx->vp);
5766 /* ignored */
5767 rn = "GlobalNumber";
5768 break;
5769 default:
5770 goto cp0_unimplemented;
5772 break;
5773 case 4:
5774 switch (sel) {
5775 case 0:
5776 gen_helper_mtc0_context(cpu_env, arg);
5777 rn = "Context";
5778 break;
5779 case 1:
5780 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5781 rn = "ContextConfig";
5782 goto cp0_unimplemented;
5783 // break;
5784 case 2:
5785 CP0_CHECK(ctx->ulri);
5786 tcg_gen_st_tl(arg, cpu_env,
5787 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5788 rn = "UserLocal";
5789 break;
5790 default:
5791 goto cp0_unimplemented;
5793 break;
5794 case 5:
5795 switch (sel) {
5796 case 0:
5797 gen_helper_mtc0_pagemask(cpu_env, arg);
5798 rn = "PageMask";
5799 break;
5800 case 1:
5801 check_insn(ctx, ISA_MIPS32R2);
5802 gen_helper_mtc0_pagegrain(cpu_env, arg);
5803 rn = "PageGrain";
5804 ctx->bstate = BS_STOP;
5805 break;
5806 default:
5807 goto cp0_unimplemented;
5809 break;
5810 case 6:
5811 switch (sel) {
5812 case 0:
5813 gen_helper_mtc0_wired(cpu_env, arg);
5814 rn = "Wired";
5815 break;
5816 case 1:
5817 check_insn(ctx, ISA_MIPS32R2);
5818 gen_helper_mtc0_srsconf0(cpu_env, arg);
5819 rn = "SRSConf0";
5820 break;
5821 case 2:
5822 check_insn(ctx, ISA_MIPS32R2);
5823 gen_helper_mtc0_srsconf1(cpu_env, arg);
5824 rn = "SRSConf1";
5825 break;
5826 case 3:
5827 check_insn(ctx, ISA_MIPS32R2);
5828 gen_helper_mtc0_srsconf2(cpu_env, arg);
5829 rn = "SRSConf2";
5830 break;
5831 case 4:
5832 check_insn(ctx, ISA_MIPS32R2);
5833 gen_helper_mtc0_srsconf3(cpu_env, arg);
5834 rn = "SRSConf3";
5835 break;
5836 case 5:
5837 check_insn(ctx, ISA_MIPS32R2);
5838 gen_helper_mtc0_srsconf4(cpu_env, arg);
5839 rn = "SRSConf4";
5840 break;
5841 default:
5842 goto cp0_unimplemented;
5844 break;
5845 case 7:
5846 switch (sel) {
5847 case 0:
5848 check_insn(ctx, ISA_MIPS32R2);
5849 gen_helper_mtc0_hwrena(cpu_env, arg);
5850 ctx->bstate = BS_STOP;
5851 rn = "HWREna";
5852 break;
5853 default:
5854 goto cp0_unimplemented;
5856 break;
5857 case 8:
5858 switch (sel) {
5859 case 0:
5860 /* ignored */
5861 rn = "BadVAddr";
5862 break;
5863 case 1:
5864 /* ignored */
5865 rn = "BadInstr";
5866 break;
5867 case 2:
5868 /* ignored */
5869 rn = "BadInstrP";
5870 break;
5871 default:
5872 goto cp0_unimplemented;
5874 break;
5875 case 9:
5876 switch (sel) {
5877 case 0:
5878 gen_helper_mtc0_count(cpu_env, arg);
5879 rn = "Count";
5880 break;
5881 /* 6,7 are implementation dependent */
5882 default:
5883 goto cp0_unimplemented;
5885 break;
5886 case 10:
5887 switch (sel) {
5888 case 0:
5889 gen_helper_mtc0_entryhi(cpu_env, arg);
5890 rn = "EntryHi";
5891 break;
5892 default:
5893 goto cp0_unimplemented;
5895 break;
5896 case 11:
5897 switch (sel) {
5898 case 0:
5899 gen_helper_mtc0_compare(cpu_env, arg);
5900 rn = "Compare";
5901 break;
5902 /* 6,7 are implementation dependent */
5903 default:
5904 goto cp0_unimplemented;
5906 break;
5907 case 12:
5908 switch (sel) {
5909 case 0:
5910 save_cpu_state(ctx, 1);
5911 gen_helper_mtc0_status(cpu_env, arg);
5912 /* BS_STOP isn't good enough here, hflags may have changed. */
5913 gen_save_pc(ctx->pc + 4);
5914 ctx->bstate = BS_EXCP;
5915 rn = "Status";
5916 break;
5917 case 1:
5918 check_insn(ctx, ISA_MIPS32R2);
5919 gen_helper_mtc0_intctl(cpu_env, arg);
5920 /* Stop translation as we may have switched the execution mode */
5921 ctx->bstate = BS_STOP;
5922 rn = "IntCtl";
5923 break;
5924 case 2:
5925 check_insn(ctx, ISA_MIPS32R2);
5926 gen_helper_mtc0_srsctl(cpu_env, arg);
5927 /* Stop translation as we may have switched the execution mode */
5928 ctx->bstate = BS_STOP;
5929 rn = "SRSCtl";
5930 break;
5931 case 3:
5932 check_insn(ctx, ISA_MIPS32R2);
5933 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5934 /* Stop translation as we may have switched the execution mode */
5935 ctx->bstate = BS_STOP;
5936 rn = "SRSMap";
5937 break;
5938 default:
5939 goto cp0_unimplemented;
5941 break;
5942 case 13:
5943 switch (sel) {
5944 case 0:
5945 save_cpu_state(ctx, 1);
5946 gen_helper_mtc0_cause(cpu_env, arg);
5947 rn = "Cause";
5948 break;
5949 default:
5950 goto cp0_unimplemented;
5952 break;
5953 case 14:
5954 switch (sel) {
5955 case 0:
5956 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5957 rn = "EPC";
5958 break;
5959 default:
5960 goto cp0_unimplemented;
5962 break;
5963 case 15:
5964 switch (sel) {
5965 case 0:
5966 /* ignored */
5967 rn = "PRid";
5968 break;
5969 case 1:
5970 check_insn(ctx, ISA_MIPS32R2);
5971 gen_helper_mtc0_ebase(cpu_env, arg);
5972 rn = "EBase";
5973 break;
5974 default:
5975 goto cp0_unimplemented;
5977 break;
5978 case 16:
5979 switch (sel) {
5980 case 0:
5981 gen_helper_mtc0_config0(cpu_env, arg);
5982 rn = "Config";
5983 /* Stop translation as we may have switched the execution mode */
5984 ctx->bstate = BS_STOP;
5985 break;
5986 case 1:
5987 /* ignored, read only */
5988 rn = "Config1";
5989 break;
5990 case 2:
5991 gen_helper_mtc0_config2(cpu_env, arg);
5992 rn = "Config2";
5993 /* Stop translation as we may have switched the execution mode */
5994 ctx->bstate = BS_STOP;
5995 break;
5996 case 3:
5997 gen_helper_mtc0_config3(cpu_env, arg);
5998 rn = "Config3";
5999 /* Stop translation as we may have switched the execution mode */
6000 ctx->bstate = BS_STOP;
6001 break;
6002 case 4:
6003 gen_helper_mtc0_config4(cpu_env, arg);
6004 rn = "Config4";
6005 ctx->bstate = BS_STOP;
6006 break;
6007 case 5:
6008 gen_helper_mtc0_config5(cpu_env, arg);
6009 rn = "Config5";
6010 /* Stop translation as we may have switched the execution mode */
6011 ctx->bstate = BS_STOP;
6012 break;
6013 /* 6,7 are implementation dependent */
6014 case 6:
6015 /* ignored */
6016 rn = "Config6";
6017 break;
6018 case 7:
6019 /* ignored */
6020 rn = "Config7";
6021 break;
6022 default:
6023 rn = "Invalid config selector";
6024 goto cp0_unimplemented;
6026 break;
6027 case 17:
6028 switch (sel) {
6029 case 0:
6030 gen_helper_mtc0_lladdr(cpu_env, arg);
6031 rn = "LLAddr";
6032 break;
6033 case 1:
6034 CP0_CHECK(ctx->mrp);
6035 gen_helper_mtc0_maar(cpu_env, arg);
6036 rn = "MAAR";
6037 break;
6038 case 2:
6039 CP0_CHECK(ctx->mrp);
6040 gen_helper_mtc0_maari(cpu_env, arg);
6041 rn = "MAARI";
6042 break;
6043 default:
6044 goto cp0_unimplemented;
6046 break;
6047 case 18:
6048 switch (sel) {
6049 case 0 ... 7:
6050 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6051 rn = "WatchLo";
6052 break;
6053 default:
6054 goto cp0_unimplemented;
6056 break;
6057 case 19:
6058 switch (sel) {
6059 case 0 ... 7:
6060 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6061 rn = "WatchHi";
6062 break;
6063 default:
6064 goto cp0_unimplemented;
6066 break;
6067 case 20:
6068 switch (sel) {
6069 case 0:
6070 #if defined(TARGET_MIPS64)
6071 check_insn(ctx, ISA_MIPS3);
6072 gen_helper_mtc0_xcontext(cpu_env, arg);
6073 rn = "XContext";
6074 break;
6075 #endif
6076 default:
6077 goto cp0_unimplemented;
6079 break;
6080 case 21:
6081 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6082 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6083 switch (sel) {
6084 case 0:
6085 gen_helper_mtc0_framemask(cpu_env, arg);
6086 rn = "Framemask";
6087 break;
6088 default:
6089 goto cp0_unimplemented;
6091 break;
6092 case 22:
6093 /* ignored */
6094 rn = "Diagnostic"; /* implementation dependent */
6095 break;
6096 case 23:
6097 switch (sel) {
6098 case 0:
6099 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6100 /* BS_STOP isn't good enough here, hflags may have changed. */
6101 gen_save_pc(ctx->pc + 4);
6102 ctx->bstate = BS_EXCP;
6103 rn = "Debug";
6104 break;
6105 case 1:
6106 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6107 rn = "TraceControl";
6108 /* Stop translation as we may have switched the execution mode */
6109 ctx->bstate = BS_STOP;
6110 // break;
6111 case 2:
6112 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6113 rn = "TraceControl2";
6114 /* Stop translation as we may have switched the execution mode */
6115 ctx->bstate = BS_STOP;
6116 // break;
6117 case 3:
6118 /* Stop translation as we may have switched the execution mode */
6119 ctx->bstate = BS_STOP;
6120 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6121 rn = "UserTraceData";
6122 /* Stop translation as we may have switched the execution mode */
6123 ctx->bstate = BS_STOP;
6124 // break;
6125 case 4:
6126 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6127 /* Stop translation as we may have switched the execution mode */
6128 ctx->bstate = BS_STOP;
6129 rn = "TraceBPC";
6130 // break;
6131 default:
6132 goto cp0_unimplemented;
6134 break;
6135 case 24:
6136 switch (sel) {
6137 case 0:
6138 /* EJTAG support */
6139 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6140 rn = "DEPC";
6141 break;
6142 default:
6143 goto cp0_unimplemented;
6145 break;
6146 case 25:
6147 switch (sel) {
6148 case 0:
6149 gen_helper_mtc0_performance0(cpu_env, arg);
6150 rn = "Performance0";
6151 break;
6152 case 1:
6153 // gen_helper_mtc0_performance1(arg);
6154 rn = "Performance1";
6155 // break;
6156 case 2:
6157 // gen_helper_mtc0_performance2(arg);
6158 rn = "Performance2";
6159 // break;
6160 case 3:
6161 // gen_helper_mtc0_performance3(arg);
6162 rn = "Performance3";
6163 // break;
6164 case 4:
6165 // gen_helper_mtc0_performance4(arg);
6166 rn = "Performance4";
6167 // break;
6168 case 5:
6169 // gen_helper_mtc0_performance5(arg);
6170 rn = "Performance5";
6171 // break;
6172 case 6:
6173 // gen_helper_mtc0_performance6(arg);
6174 rn = "Performance6";
6175 // break;
6176 case 7:
6177 // gen_helper_mtc0_performance7(arg);
6178 rn = "Performance7";
6179 // break;
6180 default:
6181 goto cp0_unimplemented;
6183 break;
6184 case 26:
6185 switch (sel) {
6186 case 0:
6187 gen_helper_mtc0_errctl(cpu_env, arg);
6188 ctx->bstate = BS_STOP;
6189 rn = "ErrCtl";
6190 break;
6191 default:
6192 goto cp0_unimplemented;
6194 break;
6195 case 27:
6196 switch (sel) {
6197 case 0 ... 3:
6198 /* ignored */
6199 rn = "CacheErr";
6200 break;
6201 default:
6202 goto cp0_unimplemented;
6204 break;
6205 case 28:
6206 switch (sel) {
6207 case 0:
6208 case 2:
6209 case 4:
6210 case 6:
6211 gen_helper_mtc0_taglo(cpu_env, arg);
6212 rn = "TagLo";
6213 break;
6214 case 1:
6215 case 3:
6216 case 5:
6217 case 7:
6218 gen_helper_mtc0_datalo(cpu_env, arg);
6219 rn = "DataLo";
6220 break;
6221 default:
6222 goto cp0_unimplemented;
6224 break;
6225 case 29:
6226 switch (sel) {
6227 case 0:
6228 case 2:
6229 case 4:
6230 case 6:
6231 gen_helper_mtc0_taghi(cpu_env, arg);
6232 rn = "TagHi";
6233 break;
6234 case 1:
6235 case 3:
6236 case 5:
6237 case 7:
6238 gen_helper_mtc0_datahi(cpu_env, arg);
6239 rn = "DataHi";
6240 break;
6241 default:
6242 rn = "invalid sel";
6243 goto cp0_unimplemented;
6245 break;
6246 case 30:
6247 switch (sel) {
6248 case 0:
6249 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6250 rn = "ErrorEPC";
6251 break;
6252 default:
6253 goto cp0_unimplemented;
6255 break;
6256 case 31:
6257 switch (sel) {
6258 case 0:
6259 /* EJTAG support */
6260 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6261 rn = "DESAVE";
6262 break;
6263 case 2 ... 7:
6264 CP0_CHECK(ctx->kscrexist & (1 << sel));
6265 tcg_gen_st_tl(arg, cpu_env,
6266 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6267 rn = "KScratch";
6268 break;
6269 default:
6270 goto cp0_unimplemented;
6272 /* Stop translation as we may have switched the execution mode */
6273 ctx->bstate = BS_STOP;
6274 break;
6275 default:
6276 goto cp0_unimplemented;
6278 (void)rn; /* avoid a compiler warning */
6279 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6280 /* For simplicity assume that all writes can cause interrupts. */
6281 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6282 gen_io_end();
6283 ctx->bstate = BS_STOP;
6285 return;
6287 cp0_unimplemented:
6288 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6291 #if defined(TARGET_MIPS64)
6292 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6294 const char *rn = "invalid";
6296 if (sel != 0)
6297 check_insn(ctx, ISA_MIPS64);
6299 switch (reg) {
6300 case 0:
6301 switch (sel) {
6302 case 0:
6303 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6304 rn = "Index";
6305 break;
6306 case 1:
6307 CP0_CHECK(ctx->insn_flags & ASE_MT);
6308 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6309 rn = "MVPControl";
6310 break;
6311 case 2:
6312 CP0_CHECK(ctx->insn_flags & ASE_MT);
6313 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6314 rn = "MVPConf0";
6315 break;
6316 case 3:
6317 CP0_CHECK(ctx->insn_flags & ASE_MT);
6318 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6319 rn = "MVPConf1";
6320 break;
6321 case 4:
6322 CP0_CHECK(ctx->vp);
6323 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6324 rn = "VPControl";
6325 break;
6326 default:
6327 goto cp0_unimplemented;
6329 break;
6330 case 1:
6331 switch (sel) {
6332 case 0:
6333 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6334 gen_helper_mfc0_random(arg, cpu_env);
6335 rn = "Random";
6336 break;
6337 case 1:
6338 CP0_CHECK(ctx->insn_flags & ASE_MT);
6339 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6340 rn = "VPEControl";
6341 break;
6342 case 2:
6343 CP0_CHECK(ctx->insn_flags & ASE_MT);
6344 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6345 rn = "VPEConf0";
6346 break;
6347 case 3:
6348 CP0_CHECK(ctx->insn_flags & ASE_MT);
6349 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6350 rn = "VPEConf1";
6351 break;
6352 case 4:
6353 CP0_CHECK(ctx->insn_flags & ASE_MT);
6354 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6355 rn = "YQMask";
6356 break;
6357 case 5:
6358 CP0_CHECK(ctx->insn_flags & ASE_MT);
6359 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6360 rn = "VPESchedule";
6361 break;
6362 case 6:
6363 CP0_CHECK(ctx->insn_flags & ASE_MT);
6364 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6365 rn = "VPEScheFBack";
6366 break;
6367 case 7:
6368 CP0_CHECK(ctx->insn_flags & ASE_MT);
6369 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6370 rn = "VPEOpt";
6371 break;
6372 default:
6373 goto cp0_unimplemented;
6375 break;
6376 case 2:
6377 switch (sel) {
6378 case 0:
6379 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6380 rn = "EntryLo0";
6381 break;
6382 case 1:
6383 CP0_CHECK(ctx->insn_flags & ASE_MT);
6384 gen_helper_mfc0_tcstatus(arg, cpu_env);
6385 rn = "TCStatus";
6386 break;
6387 case 2:
6388 CP0_CHECK(ctx->insn_flags & ASE_MT);
6389 gen_helper_mfc0_tcbind(arg, cpu_env);
6390 rn = "TCBind";
6391 break;
6392 case 3:
6393 CP0_CHECK(ctx->insn_flags & ASE_MT);
6394 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6395 rn = "TCRestart";
6396 break;
6397 case 4:
6398 CP0_CHECK(ctx->insn_flags & ASE_MT);
6399 gen_helper_dmfc0_tchalt(arg, cpu_env);
6400 rn = "TCHalt";
6401 break;
6402 case 5:
6403 CP0_CHECK(ctx->insn_flags & ASE_MT);
6404 gen_helper_dmfc0_tccontext(arg, cpu_env);
6405 rn = "TCContext";
6406 break;
6407 case 6:
6408 CP0_CHECK(ctx->insn_flags & ASE_MT);
6409 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6410 rn = "TCSchedule";
6411 break;
6412 case 7:
6413 CP0_CHECK(ctx->insn_flags & ASE_MT);
6414 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6415 rn = "TCScheFBack";
6416 break;
6417 default:
6418 goto cp0_unimplemented;
6420 break;
6421 case 3:
6422 switch (sel) {
6423 case 0:
6424 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6425 rn = "EntryLo1";
6426 break;
6427 case 1:
6428 CP0_CHECK(ctx->vp);
6429 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6430 rn = "GlobalNumber";
6431 break;
6432 default:
6433 goto cp0_unimplemented;
6435 break;
6436 case 4:
6437 switch (sel) {
6438 case 0:
6439 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6440 rn = "Context";
6441 break;
6442 case 1:
6443 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6444 rn = "ContextConfig";
6445 goto cp0_unimplemented;
6446 // break;
6447 case 2:
6448 CP0_CHECK(ctx->ulri);
6449 tcg_gen_ld_tl(arg, cpu_env,
6450 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6451 rn = "UserLocal";
6452 break;
6453 default:
6454 goto cp0_unimplemented;
6456 break;
6457 case 5:
6458 switch (sel) {
6459 case 0:
6460 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6461 rn = "PageMask";
6462 break;
6463 case 1:
6464 check_insn(ctx, ISA_MIPS32R2);
6465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6466 rn = "PageGrain";
6467 break;
6468 default:
6469 goto cp0_unimplemented;
6471 break;
6472 case 6:
6473 switch (sel) {
6474 case 0:
6475 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6476 rn = "Wired";
6477 break;
6478 case 1:
6479 check_insn(ctx, ISA_MIPS32R2);
6480 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6481 rn = "SRSConf0";
6482 break;
6483 case 2:
6484 check_insn(ctx, ISA_MIPS32R2);
6485 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6486 rn = "SRSConf1";
6487 break;
6488 case 3:
6489 check_insn(ctx, ISA_MIPS32R2);
6490 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6491 rn = "SRSConf2";
6492 break;
6493 case 4:
6494 check_insn(ctx, ISA_MIPS32R2);
6495 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6496 rn = "SRSConf3";
6497 break;
6498 case 5:
6499 check_insn(ctx, ISA_MIPS32R2);
6500 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6501 rn = "SRSConf4";
6502 break;
6503 default:
6504 goto cp0_unimplemented;
6506 break;
6507 case 7:
6508 switch (sel) {
6509 case 0:
6510 check_insn(ctx, ISA_MIPS32R2);
6511 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6512 rn = "HWREna";
6513 break;
6514 default:
6515 goto cp0_unimplemented;
6517 break;
6518 case 8:
6519 switch (sel) {
6520 case 0:
6521 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6522 rn = "BadVAddr";
6523 break;
6524 case 1:
6525 CP0_CHECK(ctx->bi);
6526 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6527 rn = "BadInstr";
6528 break;
6529 case 2:
6530 CP0_CHECK(ctx->bp);
6531 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6532 rn = "BadInstrP";
6533 break;
6534 default:
6535 goto cp0_unimplemented;
6537 break;
6538 case 9:
6539 switch (sel) {
6540 case 0:
6541 /* Mark as an IO operation because we read the time. */
6542 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6543 gen_io_start();
6545 gen_helper_mfc0_count(arg, cpu_env);
6546 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6547 gen_io_end();
6549 /* Break the TB to be able to take timer interrupts immediately
6550 after reading count. */
6551 ctx->bstate = BS_STOP;
6552 rn = "Count";
6553 break;
6554 /* 6,7 are implementation dependent */
6555 default:
6556 goto cp0_unimplemented;
6558 break;
6559 case 10:
6560 switch (sel) {
6561 case 0:
6562 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6563 rn = "EntryHi";
6564 break;
6565 default:
6566 goto cp0_unimplemented;
6568 break;
6569 case 11:
6570 switch (sel) {
6571 case 0:
6572 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6573 rn = "Compare";
6574 break;
6575 /* 6,7 are implementation dependent */
6576 default:
6577 goto cp0_unimplemented;
6579 break;
6580 case 12:
6581 switch (sel) {
6582 case 0:
6583 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6584 rn = "Status";
6585 break;
6586 case 1:
6587 check_insn(ctx, ISA_MIPS32R2);
6588 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6589 rn = "IntCtl";
6590 break;
6591 case 2:
6592 check_insn(ctx, ISA_MIPS32R2);
6593 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6594 rn = "SRSCtl";
6595 break;
6596 case 3:
6597 check_insn(ctx, ISA_MIPS32R2);
6598 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6599 rn = "SRSMap";
6600 break;
6601 default:
6602 goto cp0_unimplemented;
6604 break;
6605 case 13:
6606 switch (sel) {
6607 case 0:
6608 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6609 rn = "Cause";
6610 break;
6611 default:
6612 goto cp0_unimplemented;
6614 break;
6615 case 14:
6616 switch (sel) {
6617 case 0:
6618 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6619 rn = "EPC";
6620 break;
6621 default:
6622 goto cp0_unimplemented;
6624 break;
6625 case 15:
6626 switch (sel) {
6627 case 0:
6628 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6629 rn = "PRid";
6630 break;
6631 case 1:
6632 check_insn(ctx, ISA_MIPS32R2);
6633 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6634 rn = "EBase";
6635 break;
6636 case 3:
6637 check_insn(ctx, ISA_MIPS32R2);
6638 CP0_CHECK(ctx->cmgcr);
6639 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6640 rn = "CMGCRBase";
6641 break;
6642 default:
6643 goto cp0_unimplemented;
6645 break;
6646 case 16:
6647 switch (sel) {
6648 case 0:
6649 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6650 rn = "Config";
6651 break;
6652 case 1:
6653 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6654 rn = "Config1";
6655 break;
6656 case 2:
6657 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6658 rn = "Config2";
6659 break;
6660 case 3:
6661 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6662 rn = "Config3";
6663 break;
6664 case 4:
6665 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6666 rn = "Config4";
6667 break;
6668 case 5:
6669 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6670 rn = "Config5";
6671 break;
6672 /* 6,7 are implementation dependent */
6673 case 6:
6674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6675 rn = "Config6";
6676 break;
6677 case 7:
6678 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6679 rn = "Config7";
6680 break;
6681 default:
6682 goto cp0_unimplemented;
6684 break;
6685 case 17:
6686 switch (sel) {
6687 case 0:
6688 gen_helper_dmfc0_lladdr(arg, cpu_env);
6689 rn = "LLAddr";
6690 break;
6691 case 1:
6692 CP0_CHECK(ctx->mrp);
6693 gen_helper_dmfc0_maar(arg, cpu_env);
6694 rn = "MAAR";
6695 break;
6696 case 2:
6697 CP0_CHECK(ctx->mrp);
6698 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6699 rn = "MAARI";
6700 break;
6701 default:
6702 goto cp0_unimplemented;
6704 break;
6705 case 18:
6706 switch (sel) {
6707 case 0 ... 7:
6708 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6709 rn = "WatchLo";
6710 break;
6711 default:
6712 goto cp0_unimplemented;
6714 break;
6715 case 19:
6716 switch (sel) {
6717 case 0 ... 7:
6718 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6719 rn = "WatchHi";
6720 break;
6721 default:
6722 goto cp0_unimplemented;
6724 break;
6725 case 20:
6726 switch (sel) {
6727 case 0:
6728 check_insn(ctx, ISA_MIPS3);
6729 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6730 rn = "XContext";
6731 break;
6732 default:
6733 goto cp0_unimplemented;
6735 break;
6736 case 21:
6737 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6738 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6739 switch (sel) {
6740 case 0:
6741 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6742 rn = "Framemask";
6743 break;
6744 default:
6745 goto cp0_unimplemented;
6747 break;
6748 case 22:
6749 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6750 rn = "'Diagnostic"; /* implementation dependent */
6751 break;
6752 case 23:
6753 switch (sel) {
6754 case 0:
6755 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6756 rn = "Debug";
6757 break;
6758 case 1:
6759 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6760 rn = "TraceControl";
6761 // break;
6762 case 2:
6763 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6764 rn = "TraceControl2";
6765 // break;
6766 case 3:
6767 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6768 rn = "UserTraceData";
6769 // break;
6770 case 4:
6771 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6772 rn = "TraceBPC";
6773 // break;
6774 default:
6775 goto cp0_unimplemented;
6777 break;
6778 case 24:
6779 switch (sel) {
6780 case 0:
6781 /* EJTAG support */
6782 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6783 rn = "DEPC";
6784 break;
6785 default:
6786 goto cp0_unimplemented;
6788 break;
6789 case 25:
6790 switch (sel) {
6791 case 0:
6792 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6793 rn = "Performance0";
6794 break;
6795 case 1:
6796 // gen_helper_dmfc0_performance1(arg);
6797 rn = "Performance1";
6798 // break;
6799 case 2:
6800 // gen_helper_dmfc0_performance2(arg);
6801 rn = "Performance2";
6802 // break;
6803 case 3:
6804 // gen_helper_dmfc0_performance3(arg);
6805 rn = "Performance3";
6806 // break;
6807 case 4:
6808 // gen_helper_dmfc0_performance4(arg);
6809 rn = "Performance4";
6810 // break;
6811 case 5:
6812 // gen_helper_dmfc0_performance5(arg);
6813 rn = "Performance5";
6814 // break;
6815 case 6:
6816 // gen_helper_dmfc0_performance6(arg);
6817 rn = "Performance6";
6818 // break;
6819 case 7:
6820 // gen_helper_dmfc0_performance7(arg);
6821 rn = "Performance7";
6822 // break;
6823 default:
6824 goto cp0_unimplemented;
6826 break;
6827 case 26:
6828 switch (sel) {
6829 case 0:
6830 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6831 rn = "ErrCtl";
6832 break;
6833 default:
6834 goto cp0_unimplemented;
6836 break;
6837 case 27:
6838 switch (sel) {
6839 /* ignored */
6840 case 0 ... 3:
6841 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6842 rn = "CacheErr";
6843 break;
6844 default:
6845 goto cp0_unimplemented;
6847 break;
6848 case 28:
6849 switch (sel) {
6850 case 0:
6851 case 2:
6852 case 4:
6853 case 6:
6854 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
6855 rn = "TagLo";
6856 break;
6857 case 1:
6858 case 3:
6859 case 5:
6860 case 7:
6861 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6862 rn = "DataLo";
6863 break;
6864 default:
6865 goto cp0_unimplemented;
6867 break;
6868 case 29:
6869 switch (sel) {
6870 case 0:
6871 case 2:
6872 case 4:
6873 case 6:
6874 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6875 rn = "TagHi";
6876 break;
6877 case 1:
6878 case 3:
6879 case 5:
6880 case 7:
6881 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6882 rn = "DataHi";
6883 break;
6884 default:
6885 goto cp0_unimplemented;
6887 break;
6888 case 30:
6889 switch (sel) {
6890 case 0:
6891 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6892 rn = "ErrorEPC";
6893 break;
6894 default:
6895 goto cp0_unimplemented;
6897 break;
6898 case 31:
6899 switch (sel) {
6900 case 0:
6901 /* EJTAG support */
6902 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6903 rn = "DESAVE";
6904 break;
6905 case 2 ... 7:
6906 CP0_CHECK(ctx->kscrexist & (1 << sel));
6907 tcg_gen_ld_tl(arg, cpu_env,
6908 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6909 rn = "KScratch";
6910 break;
6911 default:
6912 goto cp0_unimplemented;
6914 break;
6915 default:
6916 goto cp0_unimplemented;
6918 (void)rn; /* avoid a compiler warning */
6919 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6920 return;
6922 cp0_unimplemented:
6923 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6924 gen_mfc0_unimplemented(ctx, arg);
6927 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6929 const char *rn = "invalid";
6931 if (sel != 0)
6932 check_insn(ctx, ISA_MIPS64);
6934 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6935 gen_io_start();
6938 switch (reg) {
6939 case 0:
6940 switch (sel) {
6941 case 0:
6942 gen_helper_mtc0_index(cpu_env, arg);
6943 rn = "Index";
6944 break;
6945 case 1:
6946 CP0_CHECK(ctx->insn_flags & ASE_MT);
6947 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6948 rn = "MVPControl";
6949 break;
6950 case 2:
6951 CP0_CHECK(ctx->insn_flags & ASE_MT);
6952 /* ignored */
6953 rn = "MVPConf0";
6954 break;
6955 case 3:
6956 CP0_CHECK(ctx->insn_flags & ASE_MT);
6957 /* ignored */
6958 rn = "MVPConf1";
6959 break;
6960 case 4:
6961 CP0_CHECK(ctx->vp);
6962 /* ignored */
6963 rn = "VPControl";
6964 break;
6965 default:
6966 goto cp0_unimplemented;
6968 break;
6969 case 1:
6970 switch (sel) {
6971 case 0:
6972 /* ignored */
6973 rn = "Random";
6974 break;
6975 case 1:
6976 CP0_CHECK(ctx->insn_flags & ASE_MT);
6977 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6978 rn = "VPEControl";
6979 break;
6980 case 2:
6981 CP0_CHECK(ctx->insn_flags & ASE_MT);
6982 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6983 rn = "VPEConf0";
6984 break;
6985 case 3:
6986 CP0_CHECK(ctx->insn_flags & ASE_MT);
6987 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6988 rn = "VPEConf1";
6989 break;
6990 case 4:
6991 CP0_CHECK(ctx->insn_flags & ASE_MT);
6992 gen_helper_mtc0_yqmask(cpu_env, arg);
6993 rn = "YQMask";
6994 break;
6995 case 5:
6996 CP0_CHECK(ctx->insn_flags & ASE_MT);
6997 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6998 rn = "VPESchedule";
6999 break;
7000 case 6:
7001 CP0_CHECK(ctx->insn_flags & ASE_MT);
7002 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7003 rn = "VPEScheFBack";
7004 break;
7005 case 7:
7006 CP0_CHECK(ctx->insn_flags & ASE_MT);
7007 gen_helper_mtc0_vpeopt(cpu_env, arg);
7008 rn = "VPEOpt";
7009 break;
7010 default:
7011 goto cp0_unimplemented;
7013 break;
7014 case 2:
7015 switch (sel) {
7016 case 0:
7017 gen_helper_dmtc0_entrylo0(cpu_env, arg);
7018 rn = "EntryLo0";
7019 break;
7020 case 1:
7021 CP0_CHECK(ctx->insn_flags & ASE_MT);
7022 gen_helper_mtc0_tcstatus(cpu_env, arg);
7023 rn = "TCStatus";
7024 break;
7025 case 2:
7026 CP0_CHECK(ctx->insn_flags & ASE_MT);
7027 gen_helper_mtc0_tcbind(cpu_env, arg);
7028 rn = "TCBind";
7029 break;
7030 case 3:
7031 CP0_CHECK(ctx->insn_flags & ASE_MT);
7032 gen_helper_mtc0_tcrestart(cpu_env, arg);
7033 rn = "TCRestart";
7034 break;
7035 case 4:
7036 CP0_CHECK(ctx->insn_flags & ASE_MT);
7037 gen_helper_mtc0_tchalt(cpu_env, arg);
7038 rn = "TCHalt";
7039 break;
7040 case 5:
7041 CP0_CHECK(ctx->insn_flags & ASE_MT);
7042 gen_helper_mtc0_tccontext(cpu_env, arg);
7043 rn = "TCContext";
7044 break;
7045 case 6:
7046 CP0_CHECK(ctx->insn_flags & ASE_MT);
7047 gen_helper_mtc0_tcschedule(cpu_env, arg);
7048 rn = "TCSchedule";
7049 break;
7050 case 7:
7051 CP0_CHECK(ctx->insn_flags & ASE_MT);
7052 gen_helper_mtc0_tcschefback(cpu_env, arg);
7053 rn = "TCScheFBack";
7054 break;
7055 default:
7056 goto cp0_unimplemented;
7058 break;
7059 case 3:
7060 switch (sel) {
7061 case 0:
7062 gen_helper_dmtc0_entrylo1(cpu_env, arg);
7063 rn = "EntryLo1";
7064 break;
7065 case 1:
7066 CP0_CHECK(ctx->vp);
7067 /* ignored */
7068 rn = "GlobalNumber";
7069 break;
7070 default:
7071 goto cp0_unimplemented;
7073 break;
7074 case 4:
7075 switch (sel) {
7076 case 0:
7077 gen_helper_mtc0_context(cpu_env, arg);
7078 rn = "Context";
7079 break;
7080 case 1:
7081 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7082 rn = "ContextConfig";
7083 goto cp0_unimplemented;
7084 // break;
7085 case 2:
7086 CP0_CHECK(ctx->ulri);
7087 tcg_gen_st_tl(arg, cpu_env,
7088 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7089 rn = "UserLocal";
7090 break;
7091 default:
7092 goto cp0_unimplemented;
7094 break;
7095 case 5:
7096 switch (sel) {
7097 case 0:
7098 gen_helper_mtc0_pagemask(cpu_env, arg);
7099 rn = "PageMask";
7100 break;
7101 case 1:
7102 check_insn(ctx, ISA_MIPS32R2);
7103 gen_helper_mtc0_pagegrain(cpu_env, arg);
7104 rn = "PageGrain";
7105 break;
7106 default:
7107 goto cp0_unimplemented;
7109 break;
7110 case 6:
7111 switch (sel) {
7112 case 0:
7113 gen_helper_mtc0_wired(cpu_env, arg);
7114 rn = "Wired";
7115 break;
7116 case 1:
7117 check_insn(ctx, ISA_MIPS32R2);
7118 gen_helper_mtc0_srsconf0(cpu_env, arg);
7119 rn = "SRSConf0";
7120 break;
7121 case 2:
7122 check_insn(ctx, ISA_MIPS32R2);
7123 gen_helper_mtc0_srsconf1(cpu_env, arg);
7124 rn = "SRSConf1";
7125 break;
7126 case 3:
7127 check_insn(ctx, ISA_MIPS32R2);
7128 gen_helper_mtc0_srsconf2(cpu_env, arg);
7129 rn = "SRSConf2";
7130 break;
7131 case 4:
7132 check_insn(ctx, ISA_MIPS32R2);
7133 gen_helper_mtc0_srsconf3(cpu_env, arg);
7134 rn = "SRSConf3";
7135 break;
7136 case 5:
7137 check_insn(ctx, ISA_MIPS32R2);
7138 gen_helper_mtc0_srsconf4(cpu_env, arg);
7139 rn = "SRSConf4";
7140 break;
7141 default:
7142 goto cp0_unimplemented;
7144 break;
7145 case 7:
7146 switch (sel) {
7147 case 0:
7148 check_insn(ctx, ISA_MIPS32R2);
7149 gen_helper_mtc0_hwrena(cpu_env, arg);
7150 ctx->bstate = BS_STOP;
7151 rn = "HWREna";
7152 break;
7153 default:
7154 goto cp0_unimplemented;
7156 break;
7157 case 8:
7158 switch (sel) {
7159 case 0:
7160 /* ignored */
7161 rn = "BadVAddr";
7162 break;
7163 case 1:
7164 /* ignored */
7165 rn = "BadInstr";
7166 break;
7167 case 2:
7168 /* ignored */
7169 rn = "BadInstrP";
7170 break;
7171 default:
7172 goto cp0_unimplemented;
7174 break;
7175 case 9:
7176 switch (sel) {
7177 case 0:
7178 gen_helper_mtc0_count(cpu_env, arg);
7179 rn = "Count";
7180 break;
7181 /* 6,7 are implementation dependent */
7182 default:
7183 goto cp0_unimplemented;
7185 /* Stop translation as we may have switched the execution mode */
7186 ctx->bstate = BS_STOP;
7187 break;
7188 case 10:
7189 switch (sel) {
7190 case 0:
7191 gen_helper_mtc0_entryhi(cpu_env, arg);
7192 rn = "EntryHi";
7193 break;
7194 default:
7195 goto cp0_unimplemented;
7197 break;
7198 case 11:
7199 switch (sel) {
7200 case 0:
7201 gen_helper_mtc0_compare(cpu_env, arg);
7202 rn = "Compare";
7203 break;
7204 /* 6,7 are implementation dependent */
7205 default:
7206 goto cp0_unimplemented;
7208 /* Stop translation as we may have switched the execution mode */
7209 ctx->bstate = BS_STOP;
7210 break;
7211 case 12:
7212 switch (sel) {
7213 case 0:
7214 save_cpu_state(ctx, 1);
7215 gen_helper_mtc0_status(cpu_env, arg);
7216 /* BS_STOP isn't good enough here, hflags may have changed. */
7217 gen_save_pc(ctx->pc + 4);
7218 ctx->bstate = BS_EXCP;
7219 rn = "Status";
7220 break;
7221 case 1:
7222 check_insn(ctx, ISA_MIPS32R2);
7223 gen_helper_mtc0_intctl(cpu_env, arg);
7224 /* Stop translation as we may have switched the execution mode */
7225 ctx->bstate = BS_STOP;
7226 rn = "IntCtl";
7227 break;
7228 case 2:
7229 check_insn(ctx, ISA_MIPS32R2);
7230 gen_helper_mtc0_srsctl(cpu_env, arg);
7231 /* Stop translation as we may have switched the execution mode */
7232 ctx->bstate = BS_STOP;
7233 rn = "SRSCtl";
7234 break;
7235 case 3:
7236 check_insn(ctx, ISA_MIPS32R2);
7237 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7238 /* Stop translation as we may have switched the execution mode */
7239 ctx->bstate = BS_STOP;
7240 rn = "SRSMap";
7241 break;
7242 default:
7243 goto cp0_unimplemented;
7245 break;
7246 case 13:
7247 switch (sel) {
7248 case 0:
7249 save_cpu_state(ctx, 1);
7250 /* Mark as an IO operation because we may trigger a software
7251 interrupt. */
7252 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7253 gen_io_start();
7255 gen_helper_mtc0_cause(cpu_env, arg);
7256 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7257 gen_io_end();
7259 /* Stop translation as we may have triggered an intetrupt */
7260 ctx->bstate = BS_STOP;
7261 rn = "Cause";
7262 break;
7263 default:
7264 goto cp0_unimplemented;
7266 break;
7267 case 14:
7268 switch (sel) {
7269 case 0:
7270 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7271 rn = "EPC";
7272 break;
7273 default:
7274 goto cp0_unimplemented;
7276 break;
7277 case 15:
7278 switch (sel) {
7279 case 0:
7280 /* ignored */
7281 rn = "PRid";
7282 break;
7283 case 1:
7284 check_insn(ctx, ISA_MIPS32R2);
7285 gen_helper_mtc0_ebase(cpu_env, arg);
7286 rn = "EBase";
7287 break;
7288 default:
7289 goto cp0_unimplemented;
7291 break;
7292 case 16:
7293 switch (sel) {
7294 case 0:
7295 gen_helper_mtc0_config0(cpu_env, arg);
7296 rn = "Config";
7297 /* Stop translation as we may have switched the execution mode */
7298 ctx->bstate = BS_STOP;
7299 break;
7300 case 1:
7301 /* ignored, read only */
7302 rn = "Config1";
7303 break;
7304 case 2:
7305 gen_helper_mtc0_config2(cpu_env, arg);
7306 rn = "Config2";
7307 /* Stop translation as we may have switched the execution mode */
7308 ctx->bstate = BS_STOP;
7309 break;
7310 case 3:
7311 gen_helper_mtc0_config3(cpu_env, arg);
7312 rn = "Config3";
7313 /* Stop translation as we may have switched the execution mode */
7314 ctx->bstate = BS_STOP;
7315 break;
7316 case 4:
7317 /* currently ignored */
7318 rn = "Config4";
7319 break;
7320 case 5:
7321 gen_helper_mtc0_config5(cpu_env, arg);
7322 rn = "Config5";
7323 /* Stop translation as we may have switched the execution mode */
7324 ctx->bstate = BS_STOP;
7325 break;
7326 /* 6,7 are implementation dependent */
7327 default:
7328 rn = "Invalid config selector";
7329 goto cp0_unimplemented;
7331 break;
7332 case 17:
7333 switch (sel) {
7334 case 0:
7335 gen_helper_mtc0_lladdr(cpu_env, arg);
7336 rn = "LLAddr";
7337 break;
7338 case 1:
7339 CP0_CHECK(ctx->mrp);
7340 gen_helper_mtc0_maar(cpu_env, arg);
7341 rn = "MAAR";
7342 break;
7343 case 2:
7344 CP0_CHECK(ctx->mrp);
7345 gen_helper_mtc0_maari(cpu_env, arg);
7346 rn = "MAARI";
7347 break;
7348 default:
7349 goto cp0_unimplemented;
7351 break;
7352 case 18:
7353 switch (sel) {
7354 case 0 ... 7:
7355 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7356 rn = "WatchLo";
7357 break;
7358 default:
7359 goto cp0_unimplemented;
7361 break;
7362 case 19:
7363 switch (sel) {
7364 case 0 ... 7:
7365 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7366 rn = "WatchHi";
7367 break;
7368 default:
7369 goto cp0_unimplemented;
7371 break;
7372 case 20:
7373 switch (sel) {
7374 case 0:
7375 check_insn(ctx, ISA_MIPS3);
7376 gen_helper_mtc0_xcontext(cpu_env, arg);
7377 rn = "XContext";
7378 break;
7379 default:
7380 goto cp0_unimplemented;
7382 break;
7383 case 21:
7384 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7385 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7386 switch (sel) {
7387 case 0:
7388 gen_helper_mtc0_framemask(cpu_env, arg);
7389 rn = "Framemask";
7390 break;
7391 default:
7392 goto cp0_unimplemented;
7394 break;
7395 case 22:
7396 /* ignored */
7397 rn = "Diagnostic"; /* implementation dependent */
7398 break;
7399 case 23:
7400 switch (sel) {
7401 case 0:
7402 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7403 /* BS_STOP isn't good enough here, hflags may have changed. */
7404 gen_save_pc(ctx->pc + 4);
7405 ctx->bstate = BS_EXCP;
7406 rn = "Debug";
7407 break;
7408 case 1:
7409 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7410 /* Stop translation as we may have switched the execution mode */
7411 ctx->bstate = BS_STOP;
7412 rn = "TraceControl";
7413 // break;
7414 case 2:
7415 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7416 /* Stop translation as we may have switched the execution mode */
7417 ctx->bstate = BS_STOP;
7418 rn = "TraceControl2";
7419 // break;
7420 case 3:
7421 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7422 /* Stop translation as we may have switched the execution mode */
7423 ctx->bstate = BS_STOP;
7424 rn = "UserTraceData";
7425 // break;
7426 case 4:
7427 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7428 /* Stop translation as we may have switched the execution mode */
7429 ctx->bstate = BS_STOP;
7430 rn = "TraceBPC";
7431 // break;
7432 default:
7433 goto cp0_unimplemented;
7435 break;
7436 case 24:
7437 switch (sel) {
7438 case 0:
7439 /* EJTAG support */
7440 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7441 rn = "DEPC";
7442 break;
7443 default:
7444 goto cp0_unimplemented;
7446 break;
7447 case 25:
7448 switch (sel) {
7449 case 0:
7450 gen_helper_mtc0_performance0(cpu_env, arg);
7451 rn = "Performance0";
7452 break;
7453 case 1:
7454 // gen_helper_mtc0_performance1(cpu_env, arg);
7455 rn = "Performance1";
7456 // break;
7457 case 2:
7458 // gen_helper_mtc0_performance2(cpu_env, arg);
7459 rn = "Performance2";
7460 // break;
7461 case 3:
7462 // gen_helper_mtc0_performance3(cpu_env, arg);
7463 rn = "Performance3";
7464 // break;
7465 case 4:
7466 // gen_helper_mtc0_performance4(cpu_env, arg);
7467 rn = "Performance4";
7468 // break;
7469 case 5:
7470 // gen_helper_mtc0_performance5(cpu_env, arg);
7471 rn = "Performance5";
7472 // break;
7473 case 6:
7474 // gen_helper_mtc0_performance6(cpu_env, arg);
7475 rn = "Performance6";
7476 // break;
7477 case 7:
7478 // gen_helper_mtc0_performance7(cpu_env, arg);
7479 rn = "Performance7";
7480 // break;
7481 default:
7482 goto cp0_unimplemented;
7484 break;
7485 case 26:
7486 switch (sel) {
7487 case 0:
7488 gen_helper_mtc0_errctl(cpu_env, arg);
7489 ctx->bstate = BS_STOP;
7490 rn = "ErrCtl";
7491 break;
7492 default:
7493 goto cp0_unimplemented;
7495 break;
7496 case 27:
7497 switch (sel) {
7498 case 0 ... 3:
7499 /* ignored */
7500 rn = "CacheErr";
7501 break;
7502 default:
7503 goto cp0_unimplemented;
7505 break;
7506 case 28:
7507 switch (sel) {
7508 case 0:
7509 case 2:
7510 case 4:
7511 case 6:
7512 gen_helper_mtc0_taglo(cpu_env, arg);
7513 rn = "TagLo";
7514 break;
7515 case 1:
7516 case 3:
7517 case 5:
7518 case 7:
7519 gen_helper_mtc0_datalo(cpu_env, arg);
7520 rn = "DataLo";
7521 break;
7522 default:
7523 goto cp0_unimplemented;
7525 break;
7526 case 29:
7527 switch (sel) {
7528 case 0:
7529 case 2:
7530 case 4:
7531 case 6:
7532 gen_helper_mtc0_taghi(cpu_env, arg);
7533 rn = "TagHi";
7534 break;
7535 case 1:
7536 case 3:
7537 case 5:
7538 case 7:
7539 gen_helper_mtc0_datahi(cpu_env, arg);
7540 rn = "DataHi";
7541 break;
7542 default:
7543 rn = "invalid sel";
7544 goto cp0_unimplemented;
7546 break;
7547 case 30:
7548 switch (sel) {
7549 case 0:
7550 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7551 rn = "ErrorEPC";
7552 break;
7553 default:
7554 goto cp0_unimplemented;
7556 break;
7557 case 31:
7558 switch (sel) {
7559 case 0:
7560 /* EJTAG support */
7561 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7562 rn = "DESAVE";
7563 break;
7564 case 2 ... 7:
7565 CP0_CHECK(ctx->kscrexist & (1 << sel));
7566 tcg_gen_st_tl(arg, cpu_env,
7567 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7568 rn = "KScratch";
7569 break;
7570 default:
7571 goto cp0_unimplemented;
7573 /* Stop translation as we may have switched the execution mode */
7574 ctx->bstate = BS_STOP;
7575 break;
7576 default:
7577 goto cp0_unimplemented;
7579 (void)rn; /* avoid a compiler warning */
7580 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7581 /* For simplicity assume that all writes can cause interrupts. */
7582 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7583 gen_io_end();
7584 ctx->bstate = BS_STOP;
7586 return;
7588 cp0_unimplemented:
7589 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7591 #endif /* TARGET_MIPS64 */
7593 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7594 int u, int sel, int h)
7596 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7597 TCGv t0 = tcg_temp_local_new();
7599 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7600 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7601 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7602 tcg_gen_movi_tl(t0, -1);
7603 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7604 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7605 tcg_gen_movi_tl(t0, -1);
7606 else if (u == 0) {
7607 switch (rt) {
7608 case 1:
7609 switch (sel) {
7610 case 1:
7611 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7612 break;
7613 case 2:
7614 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7615 break;
7616 default:
7617 goto die;
7618 break;
7620 break;
7621 case 2:
7622 switch (sel) {
7623 case 1:
7624 gen_helper_mftc0_tcstatus(t0, cpu_env);
7625 break;
7626 case 2:
7627 gen_helper_mftc0_tcbind(t0, cpu_env);
7628 break;
7629 case 3:
7630 gen_helper_mftc0_tcrestart(t0, cpu_env);
7631 break;
7632 case 4:
7633 gen_helper_mftc0_tchalt(t0, cpu_env);
7634 break;
7635 case 5:
7636 gen_helper_mftc0_tccontext(t0, cpu_env);
7637 break;
7638 case 6:
7639 gen_helper_mftc0_tcschedule(t0, cpu_env);
7640 break;
7641 case 7:
7642 gen_helper_mftc0_tcschefback(t0, cpu_env);
7643 break;
7644 default:
7645 gen_mfc0(ctx, t0, rt, sel);
7646 break;
7648 break;
7649 case 10:
7650 switch (sel) {
7651 case 0:
7652 gen_helper_mftc0_entryhi(t0, cpu_env);
7653 break;
7654 default:
7655 gen_mfc0(ctx, t0, rt, sel);
7656 break;
7658 case 12:
7659 switch (sel) {
7660 case 0:
7661 gen_helper_mftc0_status(t0, cpu_env);
7662 break;
7663 default:
7664 gen_mfc0(ctx, t0, rt, sel);
7665 break;
7667 case 13:
7668 switch (sel) {
7669 case 0:
7670 gen_helper_mftc0_cause(t0, cpu_env);
7671 break;
7672 default:
7673 goto die;
7674 break;
7676 break;
7677 case 14:
7678 switch (sel) {
7679 case 0:
7680 gen_helper_mftc0_epc(t0, cpu_env);
7681 break;
7682 default:
7683 goto die;
7684 break;
7686 break;
7687 case 15:
7688 switch (sel) {
7689 case 1:
7690 gen_helper_mftc0_ebase(t0, cpu_env);
7691 break;
7692 default:
7693 goto die;
7694 break;
7696 break;
7697 case 16:
7698 switch (sel) {
7699 case 0 ... 7:
7700 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7701 break;
7702 default:
7703 goto die;
7704 break;
7706 break;
7707 case 23:
7708 switch (sel) {
7709 case 0:
7710 gen_helper_mftc0_debug(t0, cpu_env);
7711 break;
7712 default:
7713 gen_mfc0(ctx, t0, rt, sel);
7714 break;
7716 break;
7717 default:
7718 gen_mfc0(ctx, t0, rt, sel);
7720 } else switch (sel) {
7721 /* GPR registers. */
7722 case 0:
7723 gen_helper_1e0i(mftgpr, t0, rt);
7724 break;
7725 /* Auxiliary CPU registers */
7726 case 1:
7727 switch (rt) {
7728 case 0:
7729 gen_helper_1e0i(mftlo, t0, 0);
7730 break;
7731 case 1:
7732 gen_helper_1e0i(mfthi, t0, 0);
7733 break;
7734 case 2:
7735 gen_helper_1e0i(mftacx, t0, 0);
7736 break;
7737 case 4:
7738 gen_helper_1e0i(mftlo, t0, 1);
7739 break;
7740 case 5:
7741 gen_helper_1e0i(mfthi, t0, 1);
7742 break;
7743 case 6:
7744 gen_helper_1e0i(mftacx, t0, 1);
7745 break;
7746 case 8:
7747 gen_helper_1e0i(mftlo, t0, 2);
7748 break;
7749 case 9:
7750 gen_helper_1e0i(mfthi, t0, 2);
7751 break;
7752 case 10:
7753 gen_helper_1e0i(mftacx, t0, 2);
7754 break;
7755 case 12:
7756 gen_helper_1e0i(mftlo, t0, 3);
7757 break;
7758 case 13:
7759 gen_helper_1e0i(mfthi, t0, 3);
7760 break;
7761 case 14:
7762 gen_helper_1e0i(mftacx, t0, 3);
7763 break;
7764 case 16:
7765 gen_helper_mftdsp(t0, cpu_env);
7766 break;
7767 default:
7768 goto die;
7770 break;
7771 /* Floating point (COP1). */
7772 case 2:
7773 /* XXX: For now we support only a single FPU context. */
7774 if (h == 0) {
7775 TCGv_i32 fp0 = tcg_temp_new_i32();
7777 gen_load_fpr32(ctx, fp0, rt);
7778 tcg_gen_ext_i32_tl(t0, fp0);
7779 tcg_temp_free_i32(fp0);
7780 } else {
7781 TCGv_i32 fp0 = tcg_temp_new_i32();
7783 gen_load_fpr32h(ctx, fp0, rt);
7784 tcg_gen_ext_i32_tl(t0, fp0);
7785 tcg_temp_free_i32(fp0);
7787 break;
7788 case 3:
7789 /* XXX: For now we support only a single FPU context. */
7790 gen_helper_1e0i(cfc1, t0, rt);
7791 break;
7792 /* COP2: Not implemented. */
7793 case 4:
7794 case 5:
7795 /* fall through */
7796 default:
7797 goto die;
7799 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7800 gen_store_gpr(t0, rd);
7801 tcg_temp_free(t0);
7802 return;
7804 die:
7805 tcg_temp_free(t0);
7806 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7807 generate_exception_end(ctx, EXCP_RI);
7810 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7811 int u, int sel, int h)
7813 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7814 TCGv t0 = tcg_temp_local_new();
7816 gen_load_gpr(t0, rt);
7817 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7818 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7819 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7820 /* NOP */ ;
7821 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7822 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7823 /* NOP */ ;
7824 else if (u == 0) {
7825 switch (rd) {
7826 case 1:
7827 switch (sel) {
7828 case 1:
7829 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7830 break;
7831 case 2:
7832 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7833 break;
7834 default:
7835 goto die;
7836 break;
7838 break;
7839 case 2:
7840 switch (sel) {
7841 case 1:
7842 gen_helper_mttc0_tcstatus(cpu_env, t0);
7843 break;
7844 case 2:
7845 gen_helper_mttc0_tcbind(cpu_env, t0);
7846 break;
7847 case 3:
7848 gen_helper_mttc0_tcrestart(cpu_env, t0);
7849 break;
7850 case 4:
7851 gen_helper_mttc0_tchalt(cpu_env, t0);
7852 break;
7853 case 5:
7854 gen_helper_mttc0_tccontext(cpu_env, t0);
7855 break;
7856 case 6:
7857 gen_helper_mttc0_tcschedule(cpu_env, t0);
7858 break;
7859 case 7:
7860 gen_helper_mttc0_tcschefback(cpu_env, t0);
7861 break;
7862 default:
7863 gen_mtc0(ctx, t0, rd, sel);
7864 break;
7866 break;
7867 case 10:
7868 switch (sel) {
7869 case 0:
7870 gen_helper_mttc0_entryhi(cpu_env, t0);
7871 break;
7872 default:
7873 gen_mtc0(ctx, t0, rd, sel);
7874 break;
7876 case 12:
7877 switch (sel) {
7878 case 0:
7879 gen_helper_mttc0_status(cpu_env, t0);
7880 break;
7881 default:
7882 gen_mtc0(ctx, t0, rd, sel);
7883 break;
7885 case 13:
7886 switch (sel) {
7887 case 0:
7888 gen_helper_mttc0_cause(cpu_env, t0);
7889 break;
7890 default:
7891 goto die;
7892 break;
7894 break;
7895 case 15:
7896 switch (sel) {
7897 case 1:
7898 gen_helper_mttc0_ebase(cpu_env, t0);
7899 break;
7900 default:
7901 goto die;
7902 break;
7904 break;
7905 case 23:
7906 switch (sel) {
7907 case 0:
7908 gen_helper_mttc0_debug(cpu_env, t0);
7909 break;
7910 default:
7911 gen_mtc0(ctx, t0, rd, sel);
7912 break;
7914 break;
7915 default:
7916 gen_mtc0(ctx, t0, rd, sel);
7918 } else switch (sel) {
7919 /* GPR registers. */
7920 case 0:
7921 gen_helper_0e1i(mttgpr, t0, rd);
7922 break;
7923 /* Auxiliary CPU registers */
7924 case 1:
7925 switch (rd) {
7926 case 0:
7927 gen_helper_0e1i(mttlo, t0, 0);
7928 break;
7929 case 1:
7930 gen_helper_0e1i(mtthi, t0, 0);
7931 break;
7932 case 2:
7933 gen_helper_0e1i(mttacx, t0, 0);
7934 break;
7935 case 4:
7936 gen_helper_0e1i(mttlo, t0, 1);
7937 break;
7938 case 5:
7939 gen_helper_0e1i(mtthi, t0, 1);
7940 break;
7941 case 6:
7942 gen_helper_0e1i(mttacx, t0, 1);
7943 break;
7944 case 8:
7945 gen_helper_0e1i(mttlo, t0, 2);
7946 break;
7947 case 9:
7948 gen_helper_0e1i(mtthi, t0, 2);
7949 break;
7950 case 10:
7951 gen_helper_0e1i(mttacx, t0, 2);
7952 break;
7953 case 12:
7954 gen_helper_0e1i(mttlo, t0, 3);
7955 break;
7956 case 13:
7957 gen_helper_0e1i(mtthi, t0, 3);
7958 break;
7959 case 14:
7960 gen_helper_0e1i(mttacx, t0, 3);
7961 break;
7962 case 16:
7963 gen_helper_mttdsp(cpu_env, t0);
7964 break;
7965 default:
7966 goto die;
7968 break;
7969 /* Floating point (COP1). */
7970 case 2:
7971 /* XXX: For now we support only a single FPU context. */
7972 if (h == 0) {
7973 TCGv_i32 fp0 = tcg_temp_new_i32();
7975 tcg_gen_trunc_tl_i32(fp0, t0);
7976 gen_store_fpr32(ctx, fp0, rd);
7977 tcg_temp_free_i32(fp0);
7978 } else {
7979 TCGv_i32 fp0 = tcg_temp_new_i32();
7981 tcg_gen_trunc_tl_i32(fp0, t0);
7982 gen_store_fpr32h(ctx, fp0, rd);
7983 tcg_temp_free_i32(fp0);
7985 break;
7986 case 3:
7987 /* XXX: For now we support only a single FPU context. */
7989 TCGv_i32 fs_tmp = tcg_const_i32(rd);
7991 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7992 tcg_temp_free_i32(fs_tmp);
7994 /* Stop translation as we may have changed hflags */
7995 ctx->bstate = BS_STOP;
7996 break;
7997 /* COP2: Not implemented. */
7998 case 4:
7999 case 5:
8000 /* fall through */
8001 default:
8002 goto die;
8004 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8005 tcg_temp_free(t0);
8006 return;
8008 die:
8009 tcg_temp_free(t0);
8010 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8011 generate_exception_end(ctx, EXCP_RI);
8014 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
8016 const char *opn = "ldst";
8018 check_cp0_enabled(ctx);
8019 switch (opc) {
8020 case OPC_MFC0:
8021 if (rt == 0) {
8022 /* Treat as NOP. */
8023 return;
8025 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8026 opn = "mfc0";
8027 break;
8028 case OPC_MTC0:
8030 TCGv t0 = tcg_temp_new();
8032 gen_load_gpr(t0, rt);
8033 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8034 tcg_temp_free(t0);
8036 opn = "mtc0";
8037 break;
8038 #if defined(TARGET_MIPS64)
8039 case OPC_DMFC0:
8040 check_insn(ctx, ISA_MIPS3);
8041 if (rt == 0) {
8042 /* Treat as NOP. */
8043 return;
8045 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8046 opn = "dmfc0";
8047 break;
8048 case OPC_DMTC0:
8049 check_insn(ctx, ISA_MIPS3);
8051 TCGv t0 = tcg_temp_new();
8053 gen_load_gpr(t0, rt);
8054 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8055 tcg_temp_free(t0);
8057 opn = "dmtc0";
8058 break;
8059 #endif
8060 case OPC_MFHC0:
8061 check_mvh(ctx);
8062 if (rt == 0) {
8063 /* Treat as NOP. */
8064 return;
8066 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8067 opn = "mfhc0";
8068 break;
8069 case OPC_MTHC0:
8070 check_mvh(ctx);
8072 TCGv t0 = tcg_temp_new();
8073 gen_load_gpr(t0, rt);
8074 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8075 tcg_temp_free(t0);
8077 opn = "mthc0";
8078 break;
8079 case OPC_MFTR:
8080 check_insn(ctx, ASE_MT);
8081 if (rd == 0) {
8082 /* Treat as NOP. */
8083 return;
8085 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8086 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8087 opn = "mftr";
8088 break;
8089 case OPC_MTTR:
8090 check_insn(ctx, ASE_MT);
8091 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8092 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8093 opn = "mttr";
8094 break;
8095 case OPC_TLBWI:
8096 opn = "tlbwi";
8097 if (!env->tlb->helper_tlbwi)
8098 goto die;
8099 gen_helper_tlbwi(cpu_env);
8100 break;
8101 case OPC_TLBINV:
8102 opn = "tlbinv";
8103 if (ctx->ie >= 2) {
8104 if (!env->tlb->helper_tlbinv) {
8105 goto die;
8107 gen_helper_tlbinv(cpu_env);
8108 } /* treat as nop if TLBINV not supported */
8109 break;
8110 case OPC_TLBINVF:
8111 opn = "tlbinvf";
8112 if (ctx->ie >= 2) {
8113 if (!env->tlb->helper_tlbinvf) {
8114 goto die;
8116 gen_helper_tlbinvf(cpu_env);
8117 } /* treat as nop if TLBINV not supported */
8118 break;
8119 case OPC_TLBWR:
8120 opn = "tlbwr";
8121 if (!env->tlb->helper_tlbwr)
8122 goto die;
8123 gen_helper_tlbwr(cpu_env);
8124 break;
8125 case OPC_TLBP:
8126 opn = "tlbp";
8127 if (!env->tlb->helper_tlbp)
8128 goto die;
8129 gen_helper_tlbp(cpu_env);
8130 break;
8131 case OPC_TLBR:
8132 opn = "tlbr";
8133 if (!env->tlb->helper_tlbr)
8134 goto die;
8135 gen_helper_tlbr(cpu_env);
8136 break;
8137 case OPC_ERET: /* OPC_ERETNC */
8138 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8139 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8140 goto die;
8141 } else {
8142 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8143 if (ctx->opcode & (1 << bit_shift)) {
8144 /* OPC_ERETNC */
8145 opn = "eretnc";
8146 check_insn(ctx, ISA_MIPS32R5);
8147 gen_helper_eretnc(cpu_env);
8148 } else {
8149 /* OPC_ERET */
8150 opn = "eret";
8151 check_insn(ctx, ISA_MIPS2);
8152 gen_helper_eret(cpu_env);
8154 ctx->bstate = BS_EXCP;
8156 break;
8157 case OPC_DERET:
8158 opn = "deret";
8159 check_insn(ctx, ISA_MIPS32);
8160 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8161 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8162 goto die;
8164 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8165 MIPS_INVAL(opn);
8166 generate_exception_end(ctx, EXCP_RI);
8167 } else {
8168 gen_helper_deret(cpu_env);
8169 ctx->bstate = BS_EXCP;
8171 break;
8172 case OPC_WAIT:
8173 opn = "wait";
8174 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8175 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8176 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8177 goto die;
8179 /* If we get an exception, we want to restart at next instruction */
8180 ctx->pc += 4;
8181 save_cpu_state(ctx, 1);
8182 ctx->pc -= 4;
8183 gen_helper_wait(cpu_env);
8184 ctx->bstate = BS_EXCP;
8185 break;
8186 default:
8187 die:
8188 MIPS_INVAL(opn);
8189 generate_exception_end(ctx, EXCP_RI);
8190 return;
8192 (void)opn; /* avoid a compiler warning */
8194 #endif /* !CONFIG_USER_ONLY */
8196 /* CP1 Branches (before delay slot) */
8197 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8198 int32_t cc, int32_t offset)
8200 target_ulong btarget;
8201 TCGv_i32 t0 = tcg_temp_new_i32();
8203 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8204 generate_exception_end(ctx, EXCP_RI);
8205 goto out;
8208 if (cc != 0)
8209 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8211 btarget = ctx->pc + 4 + offset;
8213 switch (op) {
8214 case OPC_BC1F:
8215 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8216 tcg_gen_not_i32(t0, t0);
8217 tcg_gen_andi_i32(t0, t0, 1);
8218 tcg_gen_extu_i32_tl(bcond, t0);
8219 goto not_likely;
8220 case OPC_BC1FL:
8221 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8222 tcg_gen_not_i32(t0, t0);
8223 tcg_gen_andi_i32(t0, t0, 1);
8224 tcg_gen_extu_i32_tl(bcond, t0);
8225 goto likely;
8226 case OPC_BC1T:
8227 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8228 tcg_gen_andi_i32(t0, t0, 1);
8229 tcg_gen_extu_i32_tl(bcond, t0);
8230 goto not_likely;
8231 case OPC_BC1TL:
8232 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8233 tcg_gen_andi_i32(t0, t0, 1);
8234 tcg_gen_extu_i32_tl(bcond, t0);
8235 likely:
8236 ctx->hflags |= MIPS_HFLAG_BL;
8237 break;
8238 case OPC_BC1FANY2:
8240 TCGv_i32 t1 = tcg_temp_new_i32();
8241 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8242 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8243 tcg_gen_nand_i32(t0, t0, t1);
8244 tcg_temp_free_i32(t1);
8245 tcg_gen_andi_i32(t0, t0, 1);
8246 tcg_gen_extu_i32_tl(bcond, t0);
8248 goto not_likely;
8249 case OPC_BC1TANY2:
8251 TCGv_i32 t1 = tcg_temp_new_i32();
8252 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8253 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8254 tcg_gen_or_i32(t0, t0, t1);
8255 tcg_temp_free_i32(t1);
8256 tcg_gen_andi_i32(t0, t0, 1);
8257 tcg_gen_extu_i32_tl(bcond, t0);
8259 goto not_likely;
8260 case OPC_BC1FANY4:
8262 TCGv_i32 t1 = tcg_temp_new_i32();
8263 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8264 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8265 tcg_gen_and_i32(t0, t0, t1);
8266 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8267 tcg_gen_and_i32(t0, t0, t1);
8268 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8269 tcg_gen_nand_i32(t0, t0, t1);
8270 tcg_temp_free_i32(t1);
8271 tcg_gen_andi_i32(t0, t0, 1);
8272 tcg_gen_extu_i32_tl(bcond, t0);
8274 goto not_likely;
8275 case OPC_BC1TANY4:
8277 TCGv_i32 t1 = tcg_temp_new_i32();
8278 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8279 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8280 tcg_gen_or_i32(t0, t0, t1);
8281 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8282 tcg_gen_or_i32(t0, t0, t1);
8283 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8284 tcg_gen_or_i32(t0, t0, t1);
8285 tcg_temp_free_i32(t1);
8286 tcg_gen_andi_i32(t0, t0, 1);
8287 tcg_gen_extu_i32_tl(bcond, t0);
8289 not_likely:
8290 ctx->hflags |= MIPS_HFLAG_BC;
8291 break;
8292 default:
8293 MIPS_INVAL("cp1 cond branch");
8294 generate_exception_end(ctx, EXCP_RI);
8295 goto out;
8297 ctx->btarget = btarget;
8298 ctx->hflags |= MIPS_HFLAG_BDS32;
8299 out:
8300 tcg_temp_free_i32(t0);
8303 /* R6 CP1 Branches */
8304 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8305 int32_t ft, int32_t offset,
8306 int delayslot_size)
8308 target_ulong btarget;
8309 TCGv_i64 t0 = tcg_temp_new_i64();
8311 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8312 #ifdef MIPS_DEBUG_DISAS
8313 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8314 "\n", ctx->pc);
8315 #endif
8316 generate_exception_end(ctx, EXCP_RI);
8317 goto out;
8320 gen_load_fpr64(ctx, t0, ft);
8321 tcg_gen_andi_i64(t0, t0, 1);
8323 btarget = addr_add(ctx, ctx->pc + 4, offset);
8325 switch (op) {
8326 case OPC_BC1EQZ:
8327 tcg_gen_xori_i64(t0, t0, 1);
8328 ctx->hflags |= MIPS_HFLAG_BC;
8329 break;
8330 case OPC_BC1NEZ:
8331 /* t0 already set */
8332 ctx->hflags |= MIPS_HFLAG_BC;
8333 break;
8334 default:
8335 MIPS_INVAL("cp1 cond branch");
8336 generate_exception_end(ctx, EXCP_RI);
8337 goto out;
8340 tcg_gen_trunc_i64_tl(bcond, t0);
8342 ctx->btarget = btarget;
8344 switch (delayslot_size) {
8345 case 2:
8346 ctx->hflags |= MIPS_HFLAG_BDS16;
8347 break;
8348 case 4:
8349 ctx->hflags |= MIPS_HFLAG_BDS32;
8350 break;
8353 out:
8354 tcg_temp_free_i64(t0);
8357 /* Coprocessor 1 (FPU) */
8359 #define FOP(func, fmt) (((fmt) << 21) | (func))
8361 enum fopcode {
8362 OPC_ADD_S = FOP(0, FMT_S),
8363 OPC_SUB_S = FOP(1, FMT_S),
8364 OPC_MUL_S = FOP(2, FMT_S),
8365 OPC_DIV_S = FOP(3, FMT_S),
8366 OPC_SQRT_S = FOP(4, FMT_S),
8367 OPC_ABS_S = FOP(5, FMT_S),
8368 OPC_MOV_S = FOP(6, FMT_S),
8369 OPC_NEG_S = FOP(7, FMT_S),
8370 OPC_ROUND_L_S = FOP(8, FMT_S),
8371 OPC_TRUNC_L_S = FOP(9, FMT_S),
8372 OPC_CEIL_L_S = FOP(10, FMT_S),
8373 OPC_FLOOR_L_S = FOP(11, FMT_S),
8374 OPC_ROUND_W_S = FOP(12, FMT_S),
8375 OPC_TRUNC_W_S = FOP(13, FMT_S),
8376 OPC_CEIL_W_S = FOP(14, FMT_S),
8377 OPC_FLOOR_W_S = FOP(15, FMT_S),
8378 OPC_SEL_S = FOP(16, FMT_S),
8379 OPC_MOVCF_S = FOP(17, FMT_S),
8380 OPC_MOVZ_S = FOP(18, FMT_S),
8381 OPC_MOVN_S = FOP(19, FMT_S),
8382 OPC_SELEQZ_S = FOP(20, FMT_S),
8383 OPC_RECIP_S = FOP(21, FMT_S),
8384 OPC_RSQRT_S = FOP(22, FMT_S),
8385 OPC_SELNEZ_S = FOP(23, FMT_S),
8386 OPC_MADDF_S = FOP(24, FMT_S),
8387 OPC_MSUBF_S = FOP(25, FMT_S),
8388 OPC_RINT_S = FOP(26, FMT_S),
8389 OPC_CLASS_S = FOP(27, FMT_S),
8390 OPC_MIN_S = FOP(28, FMT_S),
8391 OPC_RECIP2_S = FOP(28, FMT_S),
8392 OPC_MINA_S = FOP(29, FMT_S),
8393 OPC_RECIP1_S = FOP(29, FMT_S),
8394 OPC_MAX_S = FOP(30, FMT_S),
8395 OPC_RSQRT1_S = FOP(30, FMT_S),
8396 OPC_MAXA_S = FOP(31, FMT_S),
8397 OPC_RSQRT2_S = FOP(31, FMT_S),
8398 OPC_CVT_D_S = FOP(33, FMT_S),
8399 OPC_CVT_W_S = FOP(36, FMT_S),
8400 OPC_CVT_L_S = FOP(37, FMT_S),
8401 OPC_CVT_PS_S = FOP(38, FMT_S),
8402 OPC_CMP_F_S = FOP (48, FMT_S),
8403 OPC_CMP_UN_S = FOP (49, FMT_S),
8404 OPC_CMP_EQ_S = FOP (50, FMT_S),
8405 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8406 OPC_CMP_OLT_S = FOP (52, FMT_S),
8407 OPC_CMP_ULT_S = FOP (53, FMT_S),
8408 OPC_CMP_OLE_S = FOP (54, FMT_S),
8409 OPC_CMP_ULE_S = FOP (55, FMT_S),
8410 OPC_CMP_SF_S = FOP (56, FMT_S),
8411 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8412 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8413 OPC_CMP_NGL_S = FOP (59, FMT_S),
8414 OPC_CMP_LT_S = FOP (60, FMT_S),
8415 OPC_CMP_NGE_S = FOP (61, FMT_S),
8416 OPC_CMP_LE_S = FOP (62, FMT_S),
8417 OPC_CMP_NGT_S = FOP (63, FMT_S),
8419 OPC_ADD_D = FOP(0, FMT_D),
8420 OPC_SUB_D = FOP(1, FMT_D),
8421 OPC_MUL_D = FOP(2, FMT_D),
8422 OPC_DIV_D = FOP(3, FMT_D),
8423 OPC_SQRT_D = FOP(4, FMT_D),
8424 OPC_ABS_D = FOP(5, FMT_D),
8425 OPC_MOV_D = FOP(6, FMT_D),
8426 OPC_NEG_D = FOP(7, FMT_D),
8427 OPC_ROUND_L_D = FOP(8, FMT_D),
8428 OPC_TRUNC_L_D = FOP(9, FMT_D),
8429 OPC_CEIL_L_D = FOP(10, FMT_D),
8430 OPC_FLOOR_L_D = FOP(11, FMT_D),
8431 OPC_ROUND_W_D = FOP(12, FMT_D),
8432 OPC_TRUNC_W_D = FOP(13, FMT_D),
8433 OPC_CEIL_W_D = FOP(14, FMT_D),
8434 OPC_FLOOR_W_D = FOP(15, FMT_D),
8435 OPC_SEL_D = FOP(16, FMT_D),
8436 OPC_MOVCF_D = FOP(17, FMT_D),
8437 OPC_MOVZ_D = FOP(18, FMT_D),
8438 OPC_MOVN_D = FOP(19, FMT_D),
8439 OPC_SELEQZ_D = FOP(20, FMT_D),
8440 OPC_RECIP_D = FOP(21, FMT_D),
8441 OPC_RSQRT_D = FOP(22, FMT_D),
8442 OPC_SELNEZ_D = FOP(23, FMT_D),
8443 OPC_MADDF_D = FOP(24, FMT_D),
8444 OPC_MSUBF_D = FOP(25, FMT_D),
8445 OPC_RINT_D = FOP(26, FMT_D),
8446 OPC_CLASS_D = FOP(27, FMT_D),
8447 OPC_MIN_D = FOP(28, FMT_D),
8448 OPC_RECIP2_D = FOP(28, FMT_D),
8449 OPC_MINA_D = FOP(29, FMT_D),
8450 OPC_RECIP1_D = FOP(29, FMT_D),
8451 OPC_MAX_D = FOP(30, FMT_D),
8452 OPC_RSQRT1_D = FOP(30, FMT_D),
8453 OPC_MAXA_D = FOP(31, FMT_D),
8454 OPC_RSQRT2_D = FOP(31, FMT_D),
8455 OPC_CVT_S_D = FOP(32, FMT_D),
8456 OPC_CVT_W_D = FOP(36, FMT_D),
8457 OPC_CVT_L_D = FOP(37, FMT_D),
8458 OPC_CMP_F_D = FOP (48, FMT_D),
8459 OPC_CMP_UN_D = FOP (49, FMT_D),
8460 OPC_CMP_EQ_D = FOP (50, FMT_D),
8461 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8462 OPC_CMP_OLT_D = FOP (52, FMT_D),
8463 OPC_CMP_ULT_D = FOP (53, FMT_D),
8464 OPC_CMP_OLE_D = FOP (54, FMT_D),
8465 OPC_CMP_ULE_D = FOP (55, FMT_D),
8466 OPC_CMP_SF_D = FOP (56, FMT_D),
8467 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8468 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8469 OPC_CMP_NGL_D = FOP (59, FMT_D),
8470 OPC_CMP_LT_D = FOP (60, FMT_D),
8471 OPC_CMP_NGE_D = FOP (61, FMT_D),
8472 OPC_CMP_LE_D = FOP (62, FMT_D),
8473 OPC_CMP_NGT_D = FOP (63, FMT_D),
8475 OPC_CVT_S_W = FOP(32, FMT_W),
8476 OPC_CVT_D_W = FOP(33, FMT_W),
8477 OPC_CVT_S_L = FOP(32, FMT_L),
8478 OPC_CVT_D_L = FOP(33, FMT_L),
8479 OPC_CVT_PS_PW = FOP(38, FMT_W),
8481 OPC_ADD_PS = FOP(0, FMT_PS),
8482 OPC_SUB_PS = FOP(1, FMT_PS),
8483 OPC_MUL_PS = FOP(2, FMT_PS),
8484 OPC_DIV_PS = FOP(3, FMT_PS),
8485 OPC_ABS_PS = FOP(5, FMT_PS),
8486 OPC_MOV_PS = FOP(6, FMT_PS),
8487 OPC_NEG_PS = FOP(7, FMT_PS),
8488 OPC_MOVCF_PS = FOP(17, FMT_PS),
8489 OPC_MOVZ_PS = FOP(18, FMT_PS),
8490 OPC_MOVN_PS = FOP(19, FMT_PS),
8491 OPC_ADDR_PS = FOP(24, FMT_PS),
8492 OPC_MULR_PS = FOP(26, FMT_PS),
8493 OPC_RECIP2_PS = FOP(28, FMT_PS),
8494 OPC_RECIP1_PS = FOP(29, FMT_PS),
8495 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8496 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8498 OPC_CVT_S_PU = FOP(32, FMT_PS),
8499 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8500 OPC_CVT_S_PL = FOP(40, FMT_PS),
8501 OPC_PLL_PS = FOP(44, FMT_PS),
8502 OPC_PLU_PS = FOP(45, FMT_PS),
8503 OPC_PUL_PS = FOP(46, FMT_PS),
8504 OPC_PUU_PS = FOP(47, FMT_PS),
8505 OPC_CMP_F_PS = FOP (48, FMT_PS),
8506 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8507 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8508 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8509 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8510 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8511 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8512 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8513 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8514 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8515 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8516 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8517 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8518 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8519 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8520 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8523 enum r6_f_cmp_op {
8524 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8525 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8526 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8527 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8528 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8529 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8530 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8531 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8532 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8533 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8534 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8535 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8536 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8537 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8538 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8539 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8540 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8541 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8542 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8543 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8544 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8545 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8547 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8548 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8549 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8550 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8551 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8552 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8553 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8554 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8555 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8556 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8557 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8558 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8559 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8560 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8561 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8562 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8563 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8564 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8565 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8566 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8567 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8568 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8570 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8572 TCGv t0 = tcg_temp_new();
8574 switch (opc) {
8575 case OPC_MFC1:
8577 TCGv_i32 fp0 = tcg_temp_new_i32();
8579 gen_load_fpr32(ctx, fp0, fs);
8580 tcg_gen_ext_i32_tl(t0, fp0);
8581 tcg_temp_free_i32(fp0);
8583 gen_store_gpr(t0, rt);
8584 break;
8585 case OPC_MTC1:
8586 gen_load_gpr(t0, rt);
8588 TCGv_i32 fp0 = tcg_temp_new_i32();
8590 tcg_gen_trunc_tl_i32(fp0, t0);
8591 gen_store_fpr32(ctx, fp0, fs);
8592 tcg_temp_free_i32(fp0);
8594 break;
8595 case OPC_CFC1:
8596 gen_helper_1e0i(cfc1, t0, fs);
8597 gen_store_gpr(t0, rt);
8598 break;
8599 case OPC_CTC1:
8600 gen_load_gpr(t0, rt);
8601 save_cpu_state(ctx, 0);
8603 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8605 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8606 tcg_temp_free_i32(fs_tmp);
8608 /* Stop translation as we may have changed hflags */
8609 ctx->bstate = BS_STOP;
8610 break;
8611 #if defined(TARGET_MIPS64)
8612 case OPC_DMFC1:
8613 gen_load_fpr64(ctx, t0, fs);
8614 gen_store_gpr(t0, rt);
8615 break;
8616 case OPC_DMTC1:
8617 gen_load_gpr(t0, rt);
8618 gen_store_fpr64(ctx, t0, fs);
8619 break;
8620 #endif
8621 case OPC_MFHC1:
8623 TCGv_i32 fp0 = tcg_temp_new_i32();
8625 gen_load_fpr32h(ctx, fp0, fs);
8626 tcg_gen_ext_i32_tl(t0, fp0);
8627 tcg_temp_free_i32(fp0);
8629 gen_store_gpr(t0, rt);
8630 break;
8631 case OPC_MTHC1:
8632 gen_load_gpr(t0, rt);
8634 TCGv_i32 fp0 = tcg_temp_new_i32();
8636 tcg_gen_trunc_tl_i32(fp0, t0);
8637 gen_store_fpr32h(ctx, fp0, fs);
8638 tcg_temp_free_i32(fp0);
8640 break;
8641 default:
8642 MIPS_INVAL("cp1 move");
8643 generate_exception_end(ctx, EXCP_RI);
8644 goto out;
8647 out:
8648 tcg_temp_free(t0);
8651 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8653 TCGLabel *l1;
8654 TCGCond cond;
8655 TCGv_i32 t0;
8657 if (rd == 0) {
8658 /* Treat as NOP. */
8659 return;
8662 if (tf)
8663 cond = TCG_COND_EQ;
8664 else
8665 cond = TCG_COND_NE;
8667 l1 = gen_new_label();
8668 t0 = tcg_temp_new_i32();
8669 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8670 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8671 tcg_temp_free_i32(t0);
8672 if (rs == 0) {
8673 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8674 } else {
8675 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8677 gen_set_label(l1);
8680 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
8681 int tf)
8683 int cond;
8684 TCGv_i32 t0 = tcg_temp_new_i32();
8685 TCGLabel *l1 = gen_new_label();
8687 if (tf)
8688 cond = TCG_COND_EQ;
8689 else
8690 cond = TCG_COND_NE;
8692 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8693 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8694 gen_load_fpr32(ctx, t0, fs);
8695 gen_store_fpr32(ctx, t0, fd);
8696 gen_set_label(l1);
8697 tcg_temp_free_i32(t0);
8700 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8702 int cond;
8703 TCGv_i32 t0 = tcg_temp_new_i32();
8704 TCGv_i64 fp0;
8705 TCGLabel *l1 = gen_new_label();
8707 if (tf)
8708 cond = TCG_COND_EQ;
8709 else
8710 cond = TCG_COND_NE;
8712 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8713 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8714 tcg_temp_free_i32(t0);
8715 fp0 = tcg_temp_new_i64();
8716 gen_load_fpr64(ctx, fp0, fs);
8717 gen_store_fpr64(ctx, fp0, fd);
8718 tcg_temp_free_i64(fp0);
8719 gen_set_label(l1);
8722 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8723 int cc, int tf)
8725 int cond;
8726 TCGv_i32 t0 = tcg_temp_new_i32();
8727 TCGLabel *l1 = gen_new_label();
8728 TCGLabel *l2 = gen_new_label();
8730 if (tf)
8731 cond = TCG_COND_EQ;
8732 else
8733 cond = TCG_COND_NE;
8735 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8736 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8737 gen_load_fpr32(ctx, t0, fs);
8738 gen_store_fpr32(ctx, t0, fd);
8739 gen_set_label(l1);
8741 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8742 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8743 gen_load_fpr32h(ctx, t0, fs);
8744 gen_store_fpr32h(ctx, t0, fd);
8745 tcg_temp_free_i32(t0);
8746 gen_set_label(l2);
8749 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8750 int fs)
8752 TCGv_i32 t1 = tcg_const_i32(0);
8753 TCGv_i32 fp0 = tcg_temp_new_i32();
8754 TCGv_i32 fp1 = tcg_temp_new_i32();
8755 TCGv_i32 fp2 = tcg_temp_new_i32();
8756 gen_load_fpr32(ctx, fp0, fd);
8757 gen_load_fpr32(ctx, fp1, ft);
8758 gen_load_fpr32(ctx, fp2, fs);
8760 switch (op1) {
8761 case OPC_SEL_S:
8762 tcg_gen_andi_i32(fp0, fp0, 1);
8763 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8764 break;
8765 case OPC_SELEQZ_S:
8766 tcg_gen_andi_i32(fp1, fp1, 1);
8767 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8768 break;
8769 case OPC_SELNEZ_S:
8770 tcg_gen_andi_i32(fp1, fp1, 1);
8771 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8772 break;
8773 default:
8774 MIPS_INVAL("gen_sel_s");
8775 generate_exception_end(ctx, EXCP_RI);
8776 break;
8779 gen_store_fpr32(ctx, fp0, fd);
8780 tcg_temp_free_i32(fp2);
8781 tcg_temp_free_i32(fp1);
8782 tcg_temp_free_i32(fp0);
8783 tcg_temp_free_i32(t1);
8786 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8787 int fs)
8789 TCGv_i64 t1 = tcg_const_i64(0);
8790 TCGv_i64 fp0 = tcg_temp_new_i64();
8791 TCGv_i64 fp1 = tcg_temp_new_i64();
8792 TCGv_i64 fp2 = tcg_temp_new_i64();
8793 gen_load_fpr64(ctx, fp0, fd);
8794 gen_load_fpr64(ctx, fp1, ft);
8795 gen_load_fpr64(ctx, fp2, fs);
8797 switch (op1) {
8798 case OPC_SEL_D:
8799 tcg_gen_andi_i64(fp0, fp0, 1);
8800 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8801 break;
8802 case OPC_SELEQZ_D:
8803 tcg_gen_andi_i64(fp1, fp1, 1);
8804 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8805 break;
8806 case OPC_SELNEZ_D:
8807 tcg_gen_andi_i64(fp1, fp1, 1);
8808 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8809 break;
8810 default:
8811 MIPS_INVAL("gen_sel_d");
8812 generate_exception_end(ctx, EXCP_RI);
8813 break;
8816 gen_store_fpr64(ctx, fp0, fd);
8817 tcg_temp_free_i64(fp2);
8818 tcg_temp_free_i64(fp1);
8819 tcg_temp_free_i64(fp0);
8820 tcg_temp_free_i64(t1);
8823 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8824 int ft, int fs, int fd, int cc)
8826 uint32_t func = ctx->opcode & 0x3f;
8827 switch (op1) {
8828 case OPC_ADD_S:
8830 TCGv_i32 fp0 = tcg_temp_new_i32();
8831 TCGv_i32 fp1 = tcg_temp_new_i32();
8833 gen_load_fpr32(ctx, fp0, fs);
8834 gen_load_fpr32(ctx, fp1, ft);
8835 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
8836 tcg_temp_free_i32(fp1);
8837 gen_store_fpr32(ctx, fp0, fd);
8838 tcg_temp_free_i32(fp0);
8840 break;
8841 case OPC_SUB_S:
8843 TCGv_i32 fp0 = tcg_temp_new_i32();
8844 TCGv_i32 fp1 = tcg_temp_new_i32();
8846 gen_load_fpr32(ctx, fp0, fs);
8847 gen_load_fpr32(ctx, fp1, ft);
8848 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
8849 tcg_temp_free_i32(fp1);
8850 gen_store_fpr32(ctx, fp0, fd);
8851 tcg_temp_free_i32(fp0);
8853 break;
8854 case OPC_MUL_S:
8856 TCGv_i32 fp0 = tcg_temp_new_i32();
8857 TCGv_i32 fp1 = tcg_temp_new_i32();
8859 gen_load_fpr32(ctx, fp0, fs);
8860 gen_load_fpr32(ctx, fp1, ft);
8861 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
8862 tcg_temp_free_i32(fp1);
8863 gen_store_fpr32(ctx, fp0, fd);
8864 tcg_temp_free_i32(fp0);
8866 break;
8867 case OPC_DIV_S:
8869 TCGv_i32 fp0 = tcg_temp_new_i32();
8870 TCGv_i32 fp1 = tcg_temp_new_i32();
8872 gen_load_fpr32(ctx, fp0, fs);
8873 gen_load_fpr32(ctx, fp1, ft);
8874 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
8875 tcg_temp_free_i32(fp1);
8876 gen_store_fpr32(ctx, fp0, fd);
8877 tcg_temp_free_i32(fp0);
8879 break;
8880 case OPC_SQRT_S:
8882 TCGv_i32 fp0 = tcg_temp_new_i32();
8884 gen_load_fpr32(ctx, fp0, fs);
8885 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
8886 gen_store_fpr32(ctx, fp0, fd);
8887 tcg_temp_free_i32(fp0);
8889 break;
8890 case OPC_ABS_S:
8892 TCGv_i32 fp0 = tcg_temp_new_i32();
8894 gen_load_fpr32(ctx, fp0, fs);
8895 if (ctx->abs2008) {
8896 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
8897 } else {
8898 gen_helper_float_abs_s(fp0, fp0);
8900 gen_store_fpr32(ctx, fp0, fd);
8901 tcg_temp_free_i32(fp0);
8903 break;
8904 case OPC_MOV_S:
8906 TCGv_i32 fp0 = tcg_temp_new_i32();
8908 gen_load_fpr32(ctx, fp0, fs);
8909 gen_store_fpr32(ctx, fp0, fd);
8910 tcg_temp_free_i32(fp0);
8912 break;
8913 case OPC_NEG_S:
8915 TCGv_i32 fp0 = tcg_temp_new_i32();
8917 gen_load_fpr32(ctx, fp0, fs);
8918 if (ctx->abs2008) {
8919 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
8920 } else {
8921 gen_helper_float_chs_s(fp0, fp0);
8923 gen_store_fpr32(ctx, fp0, fd);
8924 tcg_temp_free_i32(fp0);
8926 break;
8927 case OPC_ROUND_L_S:
8928 check_cp1_64bitmode(ctx);
8930 TCGv_i32 fp32 = tcg_temp_new_i32();
8931 TCGv_i64 fp64 = tcg_temp_new_i64();
8933 gen_load_fpr32(ctx, fp32, fs);
8934 if (ctx->nan2008) {
8935 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
8936 } else {
8937 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
8939 tcg_temp_free_i32(fp32);
8940 gen_store_fpr64(ctx, fp64, fd);
8941 tcg_temp_free_i64(fp64);
8943 break;
8944 case OPC_TRUNC_L_S:
8945 check_cp1_64bitmode(ctx);
8947 TCGv_i32 fp32 = tcg_temp_new_i32();
8948 TCGv_i64 fp64 = tcg_temp_new_i64();
8950 gen_load_fpr32(ctx, fp32, fs);
8951 if (ctx->nan2008) {
8952 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
8953 } else {
8954 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
8956 tcg_temp_free_i32(fp32);
8957 gen_store_fpr64(ctx, fp64, fd);
8958 tcg_temp_free_i64(fp64);
8960 break;
8961 case OPC_CEIL_L_S:
8962 check_cp1_64bitmode(ctx);
8964 TCGv_i32 fp32 = tcg_temp_new_i32();
8965 TCGv_i64 fp64 = tcg_temp_new_i64();
8967 gen_load_fpr32(ctx, fp32, fs);
8968 if (ctx->nan2008) {
8969 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
8970 } else {
8971 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
8973 tcg_temp_free_i32(fp32);
8974 gen_store_fpr64(ctx, fp64, fd);
8975 tcg_temp_free_i64(fp64);
8977 break;
8978 case OPC_FLOOR_L_S:
8979 check_cp1_64bitmode(ctx);
8981 TCGv_i32 fp32 = tcg_temp_new_i32();
8982 TCGv_i64 fp64 = tcg_temp_new_i64();
8984 gen_load_fpr32(ctx, fp32, fs);
8985 if (ctx->nan2008) {
8986 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
8987 } else {
8988 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
8990 tcg_temp_free_i32(fp32);
8991 gen_store_fpr64(ctx, fp64, fd);
8992 tcg_temp_free_i64(fp64);
8994 break;
8995 case OPC_ROUND_W_S:
8997 TCGv_i32 fp0 = tcg_temp_new_i32();
8999 gen_load_fpr32(ctx, fp0, fs);
9000 if (ctx->nan2008) {
9001 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
9002 } else {
9003 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
9005 gen_store_fpr32(ctx, fp0, fd);
9006 tcg_temp_free_i32(fp0);
9008 break;
9009 case OPC_TRUNC_W_S:
9011 TCGv_i32 fp0 = tcg_temp_new_i32();
9013 gen_load_fpr32(ctx, fp0, fs);
9014 if (ctx->nan2008) {
9015 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
9016 } else {
9017 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
9019 gen_store_fpr32(ctx, fp0, fd);
9020 tcg_temp_free_i32(fp0);
9022 break;
9023 case OPC_CEIL_W_S:
9025 TCGv_i32 fp0 = tcg_temp_new_i32();
9027 gen_load_fpr32(ctx, fp0, fs);
9028 if (ctx->nan2008) {
9029 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
9030 } else {
9031 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
9033 gen_store_fpr32(ctx, fp0, fd);
9034 tcg_temp_free_i32(fp0);
9036 break;
9037 case OPC_FLOOR_W_S:
9039 TCGv_i32 fp0 = tcg_temp_new_i32();
9041 gen_load_fpr32(ctx, fp0, fs);
9042 if (ctx->nan2008) {
9043 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
9044 } else {
9045 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
9047 gen_store_fpr32(ctx, fp0, fd);
9048 tcg_temp_free_i32(fp0);
9050 break;
9051 case OPC_SEL_S:
9052 check_insn(ctx, ISA_MIPS32R6);
9053 gen_sel_s(ctx, op1, fd, ft, fs);
9054 break;
9055 case OPC_SELEQZ_S:
9056 check_insn(ctx, ISA_MIPS32R6);
9057 gen_sel_s(ctx, op1, fd, ft, fs);
9058 break;
9059 case OPC_SELNEZ_S:
9060 check_insn(ctx, ISA_MIPS32R6);
9061 gen_sel_s(ctx, op1, fd, ft, fs);
9062 break;
9063 case OPC_MOVCF_S:
9064 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9065 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9066 break;
9067 case OPC_MOVZ_S:
9068 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9070 TCGLabel *l1 = gen_new_label();
9071 TCGv_i32 fp0;
9073 if (ft != 0) {
9074 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9076 fp0 = tcg_temp_new_i32();
9077 gen_load_fpr32(ctx, fp0, fs);
9078 gen_store_fpr32(ctx, fp0, fd);
9079 tcg_temp_free_i32(fp0);
9080 gen_set_label(l1);
9082 break;
9083 case OPC_MOVN_S:
9084 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9086 TCGLabel *l1 = gen_new_label();
9087 TCGv_i32 fp0;
9089 if (ft != 0) {
9090 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9091 fp0 = tcg_temp_new_i32();
9092 gen_load_fpr32(ctx, fp0, fs);
9093 gen_store_fpr32(ctx, fp0, fd);
9094 tcg_temp_free_i32(fp0);
9095 gen_set_label(l1);
9098 break;
9099 case OPC_RECIP_S:
9101 TCGv_i32 fp0 = tcg_temp_new_i32();
9103 gen_load_fpr32(ctx, fp0, fs);
9104 gen_helper_float_recip_s(fp0, cpu_env, fp0);
9105 gen_store_fpr32(ctx, fp0, fd);
9106 tcg_temp_free_i32(fp0);
9108 break;
9109 case OPC_RSQRT_S:
9111 TCGv_i32 fp0 = tcg_temp_new_i32();
9113 gen_load_fpr32(ctx, fp0, fs);
9114 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
9115 gen_store_fpr32(ctx, fp0, fd);
9116 tcg_temp_free_i32(fp0);
9118 break;
9119 case OPC_MADDF_S:
9120 check_insn(ctx, ISA_MIPS32R6);
9122 TCGv_i32 fp0 = tcg_temp_new_i32();
9123 TCGv_i32 fp1 = tcg_temp_new_i32();
9124 TCGv_i32 fp2 = tcg_temp_new_i32();
9125 gen_load_fpr32(ctx, fp0, fs);
9126 gen_load_fpr32(ctx, fp1, ft);
9127 gen_load_fpr32(ctx, fp2, fd);
9128 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
9129 gen_store_fpr32(ctx, fp2, fd);
9130 tcg_temp_free_i32(fp2);
9131 tcg_temp_free_i32(fp1);
9132 tcg_temp_free_i32(fp0);
9134 break;
9135 case OPC_MSUBF_S:
9136 check_insn(ctx, ISA_MIPS32R6);
9138 TCGv_i32 fp0 = tcg_temp_new_i32();
9139 TCGv_i32 fp1 = tcg_temp_new_i32();
9140 TCGv_i32 fp2 = tcg_temp_new_i32();
9141 gen_load_fpr32(ctx, fp0, fs);
9142 gen_load_fpr32(ctx, fp1, ft);
9143 gen_load_fpr32(ctx, fp2, fd);
9144 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9145 gen_store_fpr32(ctx, fp2, fd);
9146 tcg_temp_free_i32(fp2);
9147 tcg_temp_free_i32(fp1);
9148 tcg_temp_free_i32(fp0);
9150 break;
9151 case OPC_RINT_S:
9152 check_insn(ctx, ISA_MIPS32R6);
9154 TCGv_i32 fp0 = tcg_temp_new_i32();
9155 gen_load_fpr32(ctx, fp0, fs);
9156 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9157 gen_store_fpr32(ctx, fp0, fd);
9158 tcg_temp_free_i32(fp0);
9160 break;
9161 case OPC_CLASS_S:
9162 check_insn(ctx, ISA_MIPS32R6);
9164 TCGv_i32 fp0 = tcg_temp_new_i32();
9165 gen_load_fpr32(ctx, fp0, fs);
9166 gen_helper_float_class_s(fp0, cpu_env, fp0);
9167 gen_store_fpr32(ctx, fp0, fd);
9168 tcg_temp_free_i32(fp0);
9170 break;
9171 case OPC_MIN_S: /* OPC_RECIP2_S */
9172 if (ctx->insn_flags & ISA_MIPS32R6) {
9173 /* OPC_MIN_S */
9174 TCGv_i32 fp0 = tcg_temp_new_i32();
9175 TCGv_i32 fp1 = tcg_temp_new_i32();
9176 TCGv_i32 fp2 = tcg_temp_new_i32();
9177 gen_load_fpr32(ctx, fp0, fs);
9178 gen_load_fpr32(ctx, fp1, ft);
9179 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9180 gen_store_fpr32(ctx, fp2, fd);
9181 tcg_temp_free_i32(fp2);
9182 tcg_temp_free_i32(fp1);
9183 tcg_temp_free_i32(fp0);
9184 } else {
9185 /* OPC_RECIP2_S */
9186 check_cp1_64bitmode(ctx);
9188 TCGv_i32 fp0 = tcg_temp_new_i32();
9189 TCGv_i32 fp1 = tcg_temp_new_i32();
9191 gen_load_fpr32(ctx, fp0, fs);
9192 gen_load_fpr32(ctx, fp1, ft);
9193 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9194 tcg_temp_free_i32(fp1);
9195 gen_store_fpr32(ctx, fp0, fd);
9196 tcg_temp_free_i32(fp0);
9199 break;
9200 case OPC_MINA_S: /* OPC_RECIP1_S */
9201 if (ctx->insn_flags & ISA_MIPS32R6) {
9202 /* OPC_MINA_S */
9203 TCGv_i32 fp0 = tcg_temp_new_i32();
9204 TCGv_i32 fp1 = tcg_temp_new_i32();
9205 TCGv_i32 fp2 = tcg_temp_new_i32();
9206 gen_load_fpr32(ctx, fp0, fs);
9207 gen_load_fpr32(ctx, fp1, ft);
9208 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9209 gen_store_fpr32(ctx, fp2, fd);
9210 tcg_temp_free_i32(fp2);
9211 tcg_temp_free_i32(fp1);
9212 tcg_temp_free_i32(fp0);
9213 } else {
9214 /* OPC_RECIP1_S */
9215 check_cp1_64bitmode(ctx);
9217 TCGv_i32 fp0 = tcg_temp_new_i32();
9219 gen_load_fpr32(ctx, fp0, fs);
9220 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9221 gen_store_fpr32(ctx, fp0, fd);
9222 tcg_temp_free_i32(fp0);
9225 break;
9226 case OPC_MAX_S: /* OPC_RSQRT1_S */
9227 if (ctx->insn_flags & ISA_MIPS32R6) {
9228 /* OPC_MAX_S */
9229 TCGv_i32 fp0 = tcg_temp_new_i32();
9230 TCGv_i32 fp1 = tcg_temp_new_i32();
9231 gen_load_fpr32(ctx, fp0, fs);
9232 gen_load_fpr32(ctx, fp1, ft);
9233 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9234 gen_store_fpr32(ctx, fp1, fd);
9235 tcg_temp_free_i32(fp1);
9236 tcg_temp_free_i32(fp0);
9237 } else {
9238 /* OPC_RSQRT1_S */
9239 check_cp1_64bitmode(ctx);
9241 TCGv_i32 fp0 = tcg_temp_new_i32();
9243 gen_load_fpr32(ctx, fp0, fs);
9244 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9245 gen_store_fpr32(ctx, fp0, fd);
9246 tcg_temp_free_i32(fp0);
9249 break;
9250 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9251 if (ctx->insn_flags & ISA_MIPS32R6) {
9252 /* OPC_MAXA_S */
9253 TCGv_i32 fp0 = tcg_temp_new_i32();
9254 TCGv_i32 fp1 = tcg_temp_new_i32();
9255 gen_load_fpr32(ctx, fp0, fs);
9256 gen_load_fpr32(ctx, fp1, ft);
9257 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9258 gen_store_fpr32(ctx, fp1, fd);
9259 tcg_temp_free_i32(fp1);
9260 tcg_temp_free_i32(fp0);
9261 } else {
9262 /* OPC_RSQRT2_S */
9263 check_cp1_64bitmode(ctx);
9265 TCGv_i32 fp0 = tcg_temp_new_i32();
9266 TCGv_i32 fp1 = tcg_temp_new_i32();
9268 gen_load_fpr32(ctx, fp0, fs);
9269 gen_load_fpr32(ctx, fp1, ft);
9270 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9271 tcg_temp_free_i32(fp1);
9272 gen_store_fpr32(ctx, fp0, fd);
9273 tcg_temp_free_i32(fp0);
9276 break;
9277 case OPC_CVT_D_S:
9278 check_cp1_registers(ctx, fd);
9280 TCGv_i32 fp32 = tcg_temp_new_i32();
9281 TCGv_i64 fp64 = tcg_temp_new_i64();
9283 gen_load_fpr32(ctx, fp32, fs);
9284 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9285 tcg_temp_free_i32(fp32);
9286 gen_store_fpr64(ctx, fp64, fd);
9287 tcg_temp_free_i64(fp64);
9289 break;
9290 case OPC_CVT_W_S:
9292 TCGv_i32 fp0 = tcg_temp_new_i32();
9294 gen_load_fpr32(ctx, fp0, fs);
9295 if (ctx->nan2008) {
9296 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
9297 } else {
9298 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
9300 gen_store_fpr32(ctx, fp0, fd);
9301 tcg_temp_free_i32(fp0);
9303 break;
9304 case OPC_CVT_L_S:
9305 check_cp1_64bitmode(ctx);
9307 TCGv_i32 fp32 = tcg_temp_new_i32();
9308 TCGv_i64 fp64 = tcg_temp_new_i64();
9310 gen_load_fpr32(ctx, fp32, fs);
9311 if (ctx->nan2008) {
9312 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
9313 } else {
9314 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
9316 tcg_temp_free_i32(fp32);
9317 gen_store_fpr64(ctx, fp64, fd);
9318 tcg_temp_free_i64(fp64);
9320 break;
9321 case OPC_CVT_PS_S:
9322 check_ps(ctx);
9324 TCGv_i64 fp64 = tcg_temp_new_i64();
9325 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9326 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9328 gen_load_fpr32(ctx, fp32_0, fs);
9329 gen_load_fpr32(ctx, fp32_1, ft);
9330 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9331 tcg_temp_free_i32(fp32_1);
9332 tcg_temp_free_i32(fp32_0);
9333 gen_store_fpr64(ctx, fp64, fd);
9334 tcg_temp_free_i64(fp64);
9336 break;
9337 case OPC_CMP_F_S:
9338 case OPC_CMP_UN_S:
9339 case OPC_CMP_EQ_S:
9340 case OPC_CMP_UEQ_S:
9341 case OPC_CMP_OLT_S:
9342 case OPC_CMP_ULT_S:
9343 case OPC_CMP_OLE_S:
9344 case OPC_CMP_ULE_S:
9345 case OPC_CMP_SF_S:
9346 case OPC_CMP_NGLE_S:
9347 case OPC_CMP_SEQ_S:
9348 case OPC_CMP_NGL_S:
9349 case OPC_CMP_LT_S:
9350 case OPC_CMP_NGE_S:
9351 case OPC_CMP_LE_S:
9352 case OPC_CMP_NGT_S:
9353 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9354 if (ctx->opcode & (1 << 6)) {
9355 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9356 } else {
9357 gen_cmp_s(ctx, func-48, ft, fs, cc);
9359 break;
9360 case OPC_ADD_D:
9361 check_cp1_registers(ctx, fs | ft | fd);
9363 TCGv_i64 fp0 = tcg_temp_new_i64();
9364 TCGv_i64 fp1 = tcg_temp_new_i64();
9366 gen_load_fpr64(ctx, fp0, fs);
9367 gen_load_fpr64(ctx, fp1, ft);
9368 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9369 tcg_temp_free_i64(fp1);
9370 gen_store_fpr64(ctx, fp0, fd);
9371 tcg_temp_free_i64(fp0);
9373 break;
9374 case OPC_SUB_D:
9375 check_cp1_registers(ctx, fs | ft | fd);
9377 TCGv_i64 fp0 = tcg_temp_new_i64();
9378 TCGv_i64 fp1 = tcg_temp_new_i64();
9380 gen_load_fpr64(ctx, fp0, fs);
9381 gen_load_fpr64(ctx, fp1, ft);
9382 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9383 tcg_temp_free_i64(fp1);
9384 gen_store_fpr64(ctx, fp0, fd);
9385 tcg_temp_free_i64(fp0);
9387 break;
9388 case OPC_MUL_D:
9389 check_cp1_registers(ctx, fs | ft | fd);
9391 TCGv_i64 fp0 = tcg_temp_new_i64();
9392 TCGv_i64 fp1 = tcg_temp_new_i64();
9394 gen_load_fpr64(ctx, fp0, fs);
9395 gen_load_fpr64(ctx, fp1, ft);
9396 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9397 tcg_temp_free_i64(fp1);
9398 gen_store_fpr64(ctx, fp0, fd);
9399 tcg_temp_free_i64(fp0);
9401 break;
9402 case OPC_DIV_D:
9403 check_cp1_registers(ctx, fs | ft | fd);
9405 TCGv_i64 fp0 = tcg_temp_new_i64();
9406 TCGv_i64 fp1 = tcg_temp_new_i64();
9408 gen_load_fpr64(ctx, fp0, fs);
9409 gen_load_fpr64(ctx, fp1, ft);
9410 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9411 tcg_temp_free_i64(fp1);
9412 gen_store_fpr64(ctx, fp0, fd);
9413 tcg_temp_free_i64(fp0);
9415 break;
9416 case OPC_SQRT_D:
9417 check_cp1_registers(ctx, fs | fd);
9419 TCGv_i64 fp0 = tcg_temp_new_i64();
9421 gen_load_fpr64(ctx, fp0, fs);
9422 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9423 gen_store_fpr64(ctx, fp0, fd);
9424 tcg_temp_free_i64(fp0);
9426 break;
9427 case OPC_ABS_D:
9428 check_cp1_registers(ctx, fs | fd);
9430 TCGv_i64 fp0 = tcg_temp_new_i64();
9432 gen_load_fpr64(ctx, fp0, fs);
9433 if (ctx->abs2008) {
9434 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
9435 } else {
9436 gen_helper_float_abs_d(fp0, fp0);
9438 gen_store_fpr64(ctx, fp0, fd);
9439 tcg_temp_free_i64(fp0);
9441 break;
9442 case OPC_MOV_D:
9443 check_cp1_registers(ctx, fs | fd);
9445 TCGv_i64 fp0 = tcg_temp_new_i64();
9447 gen_load_fpr64(ctx, fp0, fs);
9448 gen_store_fpr64(ctx, fp0, fd);
9449 tcg_temp_free_i64(fp0);
9451 break;
9452 case OPC_NEG_D:
9453 check_cp1_registers(ctx, fs | fd);
9455 TCGv_i64 fp0 = tcg_temp_new_i64();
9457 gen_load_fpr64(ctx, fp0, fs);
9458 if (ctx->abs2008) {
9459 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
9460 } else {
9461 gen_helper_float_chs_d(fp0, fp0);
9463 gen_store_fpr64(ctx, fp0, fd);
9464 tcg_temp_free_i64(fp0);
9466 break;
9467 case OPC_ROUND_L_D:
9468 check_cp1_64bitmode(ctx);
9470 TCGv_i64 fp0 = tcg_temp_new_i64();
9472 gen_load_fpr64(ctx, fp0, fs);
9473 if (ctx->nan2008) {
9474 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
9475 } else {
9476 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
9478 gen_store_fpr64(ctx, fp0, fd);
9479 tcg_temp_free_i64(fp0);
9481 break;
9482 case OPC_TRUNC_L_D:
9483 check_cp1_64bitmode(ctx);
9485 TCGv_i64 fp0 = tcg_temp_new_i64();
9487 gen_load_fpr64(ctx, fp0, fs);
9488 if (ctx->nan2008) {
9489 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
9490 } else {
9491 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
9493 gen_store_fpr64(ctx, fp0, fd);
9494 tcg_temp_free_i64(fp0);
9496 break;
9497 case OPC_CEIL_L_D:
9498 check_cp1_64bitmode(ctx);
9500 TCGv_i64 fp0 = tcg_temp_new_i64();
9502 gen_load_fpr64(ctx, fp0, fs);
9503 if (ctx->nan2008) {
9504 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
9505 } else {
9506 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
9508 gen_store_fpr64(ctx, fp0, fd);
9509 tcg_temp_free_i64(fp0);
9511 break;
9512 case OPC_FLOOR_L_D:
9513 check_cp1_64bitmode(ctx);
9515 TCGv_i64 fp0 = tcg_temp_new_i64();
9517 gen_load_fpr64(ctx, fp0, fs);
9518 if (ctx->nan2008) {
9519 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
9520 } else {
9521 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
9523 gen_store_fpr64(ctx, fp0, fd);
9524 tcg_temp_free_i64(fp0);
9526 break;
9527 case OPC_ROUND_W_D:
9528 check_cp1_registers(ctx, fs);
9530 TCGv_i32 fp32 = tcg_temp_new_i32();
9531 TCGv_i64 fp64 = tcg_temp_new_i64();
9533 gen_load_fpr64(ctx, fp64, fs);
9534 if (ctx->nan2008) {
9535 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
9536 } else {
9537 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
9539 tcg_temp_free_i64(fp64);
9540 gen_store_fpr32(ctx, fp32, fd);
9541 tcg_temp_free_i32(fp32);
9543 break;
9544 case OPC_TRUNC_W_D:
9545 check_cp1_registers(ctx, fs);
9547 TCGv_i32 fp32 = tcg_temp_new_i32();
9548 TCGv_i64 fp64 = tcg_temp_new_i64();
9550 gen_load_fpr64(ctx, fp64, fs);
9551 if (ctx->nan2008) {
9552 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
9553 } else {
9554 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
9556 tcg_temp_free_i64(fp64);
9557 gen_store_fpr32(ctx, fp32, fd);
9558 tcg_temp_free_i32(fp32);
9560 break;
9561 case OPC_CEIL_W_D:
9562 check_cp1_registers(ctx, fs);
9564 TCGv_i32 fp32 = tcg_temp_new_i32();
9565 TCGv_i64 fp64 = tcg_temp_new_i64();
9567 gen_load_fpr64(ctx, fp64, fs);
9568 if (ctx->nan2008) {
9569 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
9570 } else {
9571 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
9573 tcg_temp_free_i64(fp64);
9574 gen_store_fpr32(ctx, fp32, fd);
9575 tcg_temp_free_i32(fp32);
9577 break;
9578 case OPC_FLOOR_W_D:
9579 check_cp1_registers(ctx, fs);
9581 TCGv_i32 fp32 = tcg_temp_new_i32();
9582 TCGv_i64 fp64 = tcg_temp_new_i64();
9584 gen_load_fpr64(ctx, fp64, fs);
9585 if (ctx->nan2008) {
9586 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
9587 } else {
9588 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
9590 tcg_temp_free_i64(fp64);
9591 gen_store_fpr32(ctx, fp32, fd);
9592 tcg_temp_free_i32(fp32);
9594 break;
9595 case OPC_SEL_D:
9596 check_insn(ctx, ISA_MIPS32R6);
9597 gen_sel_d(ctx, op1, fd, ft, fs);
9598 break;
9599 case OPC_SELEQZ_D:
9600 check_insn(ctx, ISA_MIPS32R6);
9601 gen_sel_d(ctx, op1, fd, ft, fs);
9602 break;
9603 case OPC_SELNEZ_D:
9604 check_insn(ctx, ISA_MIPS32R6);
9605 gen_sel_d(ctx, op1, fd, ft, fs);
9606 break;
9607 case OPC_MOVCF_D:
9608 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9609 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9610 break;
9611 case OPC_MOVZ_D:
9612 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9614 TCGLabel *l1 = gen_new_label();
9615 TCGv_i64 fp0;
9617 if (ft != 0) {
9618 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9620 fp0 = tcg_temp_new_i64();
9621 gen_load_fpr64(ctx, fp0, fs);
9622 gen_store_fpr64(ctx, fp0, fd);
9623 tcg_temp_free_i64(fp0);
9624 gen_set_label(l1);
9626 break;
9627 case OPC_MOVN_D:
9628 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9630 TCGLabel *l1 = gen_new_label();
9631 TCGv_i64 fp0;
9633 if (ft != 0) {
9634 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9635 fp0 = tcg_temp_new_i64();
9636 gen_load_fpr64(ctx, fp0, fs);
9637 gen_store_fpr64(ctx, fp0, fd);
9638 tcg_temp_free_i64(fp0);
9639 gen_set_label(l1);
9642 break;
9643 case OPC_RECIP_D:
9644 check_cp1_registers(ctx, fs | fd);
9646 TCGv_i64 fp0 = tcg_temp_new_i64();
9648 gen_load_fpr64(ctx, fp0, fs);
9649 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9650 gen_store_fpr64(ctx, fp0, fd);
9651 tcg_temp_free_i64(fp0);
9653 break;
9654 case OPC_RSQRT_D:
9655 check_cp1_registers(ctx, fs | fd);
9657 TCGv_i64 fp0 = tcg_temp_new_i64();
9659 gen_load_fpr64(ctx, fp0, fs);
9660 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9661 gen_store_fpr64(ctx, fp0, fd);
9662 tcg_temp_free_i64(fp0);
9664 break;
9665 case OPC_MADDF_D:
9666 check_insn(ctx, ISA_MIPS32R6);
9668 TCGv_i64 fp0 = tcg_temp_new_i64();
9669 TCGv_i64 fp1 = tcg_temp_new_i64();
9670 TCGv_i64 fp2 = tcg_temp_new_i64();
9671 gen_load_fpr64(ctx, fp0, fs);
9672 gen_load_fpr64(ctx, fp1, ft);
9673 gen_load_fpr64(ctx, fp2, fd);
9674 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9675 gen_store_fpr64(ctx, fp2, fd);
9676 tcg_temp_free_i64(fp2);
9677 tcg_temp_free_i64(fp1);
9678 tcg_temp_free_i64(fp0);
9680 break;
9681 case OPC_MSUBF_D:
9682 check_insn(ctx, ISA_MIPS32R6);
9684 TCGv_i64 fp0 = tcg_temp_new_i64();
9685 TCGv_i64 fp1 = tcg_temp_new_i64();
9686 TCGv_i64 fp2 = tcg_temp_new_i64();
9687 gen_load_fpr64(ctx, fp0, fs);
9688 gen_load_fpr64(ctx, fp1, ft);
9689 gen_load_fpr64(ctx, fp2, fd);
9690 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9691 gen_store_fpr64(ctx, fp2, fd);
9692 tcg_temp_free_i64(fp2);
9693 tcg_temp_free_i64(fp1);
9694 tcg_temp_free_i64(fp0);
9696 break;
9697 case OPC_RINT_D:
9698 check_insn(ctx, ISA_MIPS32R6);
9700 TCGv_i64 fp0 = tcg_temp_new_i64();
9701 gen_load_fpr64(ctx, fp0, fs);
9702 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9703 gen_store_fpr64(ctx, fp0, fd);
9704 tcg_temp_free_i64(fp0);
9706 break;
9707 case OPC_CLASS_D:
9708 check_insn(ctx, ISA_MIPS32R6);
9710 TCGv_i64 fp0 = tcg_temp_new_i64();
9711 gen_load_fpr64(ctx, fp0, fs);
9712 gen_helper_float_class_d(fp0, cpu_env, fp0);
9713 gen_store_fpr64(ctx, fp0, fd);
9714 tcg_temp_free_i64(fp0);
9716 break;
9717 case OPC_MIN_D: /* OPC_RECIP2_D */
9718 if (ctx->insn_flags & ISA_MIPS32R6) {
9719 /* OPC_MIN_D */
9720 TCGv_i64 fp0 = tcg_temp_new_i64();
9721 TCGv_i64 fp1 = tcg_temp_new_i64();
9722 gen_load_fpr64(ctx, fp0, fs);
9723 gen_load_fpr64(ctx, fp1, ft);
9724 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9725 gen_store_fpr64(ctx, fp1, fd);
9726 tcg_temp_free_i64(fp1);
9727 tcg_temp_free_i64(fp0);
9728 } else {
9729 /* OPC_RECIP2_D */
9730 check_cp1_64bitmode(ctx);
9732 TCGv_i64 fp0 = tcg_temp_new_i64();
9733 TCGv_i64 fp1 = tcg_temp_new_i64();
9735 gen_load_fpr64(ctx, fp0, fs);
9736 gen_load_fpr64(ctx, fp1, ft);
9737 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9738 tcg_temp_free_i64(fp1);
9739 gen_store_fpr64(ctx, fp0, fd);
9740 tcg_temp_free_i64(fp0);
9743 break;
9744 case OPC_MINA_D: /* OPC_RECIP1_D */
9745 if (ctx->insn_flags & ISA_MIPS32R6) {
9746 /* OPC_MINA_D */
9747 TCGv_i64 fp0 = tcg_temp_new_i64();
9748 TCGv_i64 fp1 = tcg_temp_new_i64();
9749 gen_load_fpr64(ctx, fp0, fs);
9750 gen_load_fpr64(ctx, fp1, ft);
9751 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9752 gen_store_fpr64(ctx, fp1, fd);
9753 tcg_temp_free_i64(fp1);
9754 tcg_temp_free_i64(fp0);
9755 } else {
9756 /* OPC_RECIP1_D */
9757 check_cp1_64bitmode(ctx);
9759 TCGv_i64 fp0 = tcg_temp_new_i64();
9761 gen_load_fpr64(ctx, fp0, fs);
9762 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9763 gen_store_fpr64(ctx, fp0, fd);
9764 tcg_temp_free_i64(fp0);
9767 break;
9768 case OPC_MAX_D: /* OPC_RSQRT1_D */
9769 if (ctx->insn_flags & ISA_MIPS32R6) {
9770 /* OPC_MAX_D */
9771 TCGv_i64 fp0 = tcg_temp_new_i64();
9772 TCGv_i64 fp1 = tcg_temp_new_i64();
9773 gen_load_fpr64(ctx, fp0, fs);
9774 gen_load_fpr64(ctx, fp1, ft);
9775 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9776 gen_store_fpr64(ctx, fp1, fd);
9777 tcg_temp_free_i64(fp1);
9778 tcg_temp_free_i64(fp0);
9779 } else {
9780 /* OPC_RSQRT1_D */
9781 check_cp1_64bitmode(ctx);
9783 TCGv_i64 fp0 = tcg_temp_new_i64();
9785 gen_load_fpr64(ctx, fp0, fs);
9786 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9787 gen_store_fpr64(ctx, fp0, fd);
9788 tcg_temp_free_i64(fp0);
9791 break;
9792 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9793 if (ctx->insn_flags & ISA_MIPS32R6) {
9794 /* OPC_MAXA_D */
9795 TCGv_i64 fp0 = tcg_temp_new_i64();
9796 TCGv_i64 fp1 = tcg_temp_new_i64();
9797 gen_load_fpr64(ctx, fp0, fs);
9798 gen_load_fpr64(ctx, fp1, ft);
9799 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9800 gen_store_fpr64(ctx, fp1, fd);
9801 tcg_temp_free_i64(fp1);
9802 tcg_temp_free_i64(fp0);
9803 } else {
9804 /* OPC_RSQRT2_D */
9805 check_cp1_64bitmode(ctx);
9807 TCGv_i64 fp0 = tcg_temp_new_i64();
9808 TCGv_i64 fp1 = tcg_temp_new_i64();
9810 gen_load_fpr64(ctx, fp0, fs);
9811 gen_load_fpr64(ctx, fp1, ft);
9812 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9813 tcg_temp_free_i64(fp1);
9814 gen_store_fpr64(ctx, fp0, fd);
9815 tcg_temp_free_i64(fp0);
9818 break;
9819 case OPC_CMP_F_D:
9820 case OPC_CMP_UN_D:
9821 case OPC_CMP_EQ_D:
9822 case OPC_CMP_UEQ_D:
9823 case OPC_CMP_OLT_D:
9824 case OPC_CMP_ULT_D:
9825 case OPC_CMP_OLE_D:
9826 case OPC_CMP_ULE_D:
9827 case OPC_CMP_SF_D:
9828 case OPC_CMP_NGLE_D:
9829 case OPC_CMP_SEQ_D:
9830 case OPC_CMP_NGL_D:
9831 case OPC_CMP_LT_D:
9832 case OPC_CMP_NGE_D:
9833 case OPC_CMP_LE_D:
9834 case OPC_CMP_NGT_D:
9835 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9836 if (ctx->opcode & (1 << 6)) {
9837 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9838 } else {
9839 gen_cmp_d(ctx, func-48, ft, fs, cc);
9841 break;
9842 case OPC_CVT_S_D:
9843 check_cp1_registers(ctx, fs);
9845 TCGv_i32 fp32 = tcg_temp_new_i32();
9846 TCGv_i64 fp64 = tcg_temp_new_i64();
9848 gen_load_fpr64(ctx, fp64, fs);
9849 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
9850 tcg_temp_free_i64(fp64);
9851 gen_store_fpr32(ctx, fp32, fd);
9852 tcg_temp_free_i32(fp32);
9854 break;
9855 case OPC_CVT_W_D:
9856 check_cp1_registers(ctx, fs);
9858 TCGv_i32 fp32 = tcg_temp_new_i32();
9859 TCGv_i64 fp64 = tcg_temp_new_i64();
9861 gen_load_fpr64(ctx, fp64, fs);
9862 if (ctx->nan2008) {
9863 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
9864 } else {
9865 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
9867 tcg_temp_free_i64(fp64);
9868 gen_store_fpr32(ctx, fp32, fd);
9869 tcg_temp_free_i32(fp32);
9871 break;
9872 case OPC_CVT_L_D:
9873 check_cp1_64bitmode(ctx);
9875 TCGv_i64 fp0 = tcg_temp_new_i64();
9877 gen_load_fpr64(ctx, fp0, fs);
9878 if (ctx->nan2008) {
9879 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
9880 } else {
9881 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
9883 gen_store_fpr64(ctx, fp0, fd);
9884 tcg_temp_free_i64(fp0);
9886 break;
9887 case OPC_CVT_S_W:
9889 TCGv_i32 fp0 = tcg_temp_new_i32();
9891 gen_load_fpr32(ctx, fp0, fs);
9892 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
9893 gen_store_fpr32(ctx, fp0, fd);
9894 tcg_temp_free_i32(fp0);
9896 break;
9897 case OPC_CVT_D_W:
9898 check_cp1_registers(ctx, fd);
9900 TCGv_i32 fp32 = tcg_temp_new_i32();
9901 TCGv_i64 fp64 = tcg_temp_new_i64();
9903 gen_load_fpr32(ctx, fp32, fs);
9904 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
9905 tcg_temp_free_i32(fp32);
9906 gen_store_fpr64(ctx, fp64, fd);
9907 tcg_temp_free_i64(fp64);
9909 break;
9910 case OPC_CVT_S_L:
9911 check_cp1_64bitmode(ctx);
9913 TCGv_i32 fp32 = tcg_temp_new_i32();
9914 TCGv_i64 fp64 = tcg_temp_new_i64();
9916 gen_load_fpr64(ctx, fp64, fs);
9917 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
9918 tcg_temp_free_i64(fp64);
9919 gen_store_fpr32(ctx, fp32, fd);
9920 tcg_temp_free_i32(fp32);
9922 break;
9923 case OPC_CVT_D_L:
9924 check_cp1_64bitmode(ctx);
9926 TCGv_i64 fp0 = tcg_temp_new_i64();
9928 gen_load_fpr64(ctx, fp0, fs);
9929 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
9930 gen_store_fpr64(ctx, fp0, fd);
9931 tcg_temp_free_i64(fp0);
9933 break;
9934 case OPC_CVT_PS_PW:
9935 check_ps(ctx);
9937 TCGv_i64 fp0 = tcg_temp_new_i64();
9939 gen_load_fpr64(ctx, fp0, fs);
9940 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
9941 gen_store_fpr64(ctx, fp0, fd);
9942 tcg_temp_free_i64(fp0);
9944 break;
9945 case OPC_ADD_PS:
9946 check_ps(ctx);
9948 TCGv_i64 fp0 = tcg_temp_new_i64();
9949 TCGv_i64 fp1 = tcg_temp_new_i64();
9951 gen_load_fpr64(ctx, fp0, fs);
9952 gen_load_fpr64(ctx, fp1, ft);
9953 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
9954 tcg_temp_free_i64(fp1);
9955 gen_store_fpr64(ctx, fp0, fd);
9956 tcg_temp_free_i64(fp0);
9958 break;
9959 case OPC_SUB_PS:
9960 check_ps(ctx);
9962 TCGv_i64 fp0 = tcg_temp_new_i64();
9963 TCGv_i64 fp1 = tcg_temp_new_i64();
9965 gen_load_fpr64(ctx, fp0, fs);
9966 gen_load_fpr64(ctx, fp1, ft);
9967 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
9968 tcg_temp_free_i64(fp1);
9969 gen_store_fpr64(ctx, fp0, fd);
9970 tcg_temp_free_i64(fp0);
9972 break;
9973 case OPC_MUL_PS:
9974 check_ps(ctx);
9976 TCGv_i64 fp0 = tcg_temp_new_i64();
9977 TCGv_i64 fp1 = tcg_temp_new_i64();
9979 gen_load_fpr64(ctx, fp0, fs);
9980 gen_load_fpr64(ctx, fp1, ft);
9981 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
9982 tcg_temp_free_i64(fp1);
9983 gen_store_fpr64(ctx, fp0, fd);
9984 tcg_temp_free_i64(fp0);
9986 break;
9987 case OPC_ABS_PS:
9988 check_ps(ctx);
9990 TCGv_i64 fp0 = tcg_temp_new_i64();
9992 gen_load_fpr64(ctx, fp0, fs);
9993 gen_helper_float_abs_ps(fp0, fp0);
9994 gen_store_fpr64(ctx, fp0, fd);
9995 tcg_temp_free_i64(fp0);
9997 break;
9998 case OPC_MOV_PS:
9999 check_ps(ctx);
10001 TCGv_i64 fp0 = tcg_temp_new_i64();
10003 gen_load_fpr64(ctx, fp0, fs);
10004 gen_store_fpr64(ctx, fp0, fd);
10005 tcg_temp_free_i64(fp0);
10007 break;
10008 case OPC_NEG_PS:
10009 check_ps(ctx);
10011 TCGv_i64 fp0 = tcg_temp_new_i64();
10013 gen_load_fpr64(ctx, fp0, fs);
10014 gen_helper_float_chs_ps(fp0, fp0);
10015 gen_store_fpr64(ctx, fp0, fd);
10016 tcg_temp_free_i64(fp0);
10018 break;
10019 case OPC_MOVCF_PS:
10020 check_ps(ctx);
10021 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10022 break;
10023 case OPC_MOVZ_PS:
10024 check_ps(ctx);
10026 TCGLabel *l1 = gen_new_label();
10027 TCGv_i64 fp0;
10029 if (ft != 0)
10030 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10031 fp0 = tcg_temp_new_i64();
10032 gen_load_fpr64(ctx, fp0, fs);
10033 gen_store_fpr64(ctx, fp0, fd);
10034 tcg_temp_free_i64(fp0);
10035 gen_set_label(l1);
10037 break;
10038 case OPC_MOVN_PS:
10039 check_ps(ctx);
10041 TCGLabel *l1 = gen_new_label();
10042 TCGv_i64 fp0;
10044 if (ft != 0) {
10045 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10046 fp0 = tcg_temp_new_i64();
10047 gen_load_fpr64(ctx, fp0, fs);
10048 gen_store_fpr64(ctx, fp0, fd);
10049 tcg_temp_free_i64(fp0);
10050 gen_set_label(l1);
10053 break;
10054 case OPC_ADDR_PS:
10055 check_ps(ctx);
10057 TCGv_i64 fp0 = tcg_temp_new_i64();
10058 TCGv_i64 fp1 = tcg_temp_new_i64();
10060 gen_load_fpr64(ctx, fp0, ft);
10061 gen_load_fpr64(ctx, fp1, fs);
10062 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
10063 tcg_temp_free_i64(fp1);
10064 gen_store_fpr64(ctx, fp0, fd);
10065 tcg_temp_free_i64(fp0);
10067 break;
10068 case OPC_MULR_PS:
10069 check_ps(ctx);
10071 TCGv_i64 fp0 = tcg_temp_new_i64();
10072 TCGv_i64 fp1 = tcg_temp_new_i64();
10074 gen_load_fpr64(ctx, fp0, ft);
10075 gen_load_fpr64(ctx, fp1, fs);
10076 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
10077 tcg_temp_free_i64(fp1);
10078 gen_store_fpr64(ctx, fp0, fd);
10079 tcg_temp_free_i64(fp0);
10081 break;
10082 case OPC_RECIP2_PS:
10083 check_ps(ctx);
10085 TCGv_i64 fp0 = tcg_temp_new_i64();
10086 TCGv_i64 fp1 = tcg_temp_new_i64();
10088 gen_load_fpr64(ctx, fp0, fs);
10089 gen_load_fpr64(ctx, fp1, ft);
10090 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
10091 tcg_temp_free_i64(fp1);
10092 gen_store_fpr64(ctx, fp0, fd);
10093 tcg_temp_free_i64(fp0);
10095 break;
10096 case OPC_RECIP1_PS:
10097 check_ps(ctx);
10099 TCGv_i64 fp0 = tcg_temp_new_i64();
10101 gen_load_fpr64(ctx, fp0, fs);
10102 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
10103 gen_store_fpr64(ctx, fp0, fd);
10104 tcg_temp_free_i64(fp0);
10106 break;
10107 case OPC_RSQRT1_PS:
10108 check_ps(ctx);
10110 TCGv_i64 fp0 = tcg_temp_new_i64();
10112 gen_load_fpr64(ctx, fp0, fs);
10113 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
10114 gen_store_fpr64(ctx, fp0, fd);
10115 tcg_temp_free_i64(fp0);
10117 break;
10118 case OPC_RSQRT2_PS:
10119 check_ps(ctx);
10121 TCGv_i64 fp0 = tcg_temp_new_i64();
10122 TCGv_i64 fp1 = tcg_temp_new_i64();
10124 gen_load_fpr64(ctx, fp0, fs);
10125 gen_load_fpr64(ctx, fp1, ft);
10126 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
10127 tcg_temp_free_i64(fp1);
10128 gen_store_fpr64(ctx, fp0, fd);
10129 tcg_temp_free_i64(fp0);
10131 break;
10132 case OPC_CVT_S_PU:
10133 check_cp1_64bitmode(ctx);
10135 TCGv_i32 fp0 = tcg_temp_new_i32();
10137 gen_load_fpr32h(ctx, fp0, fs);
10138 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
10139 gen_store_fpr32(ctx, fp0, fd);
10140 tcg_temp_free_i32(fp0);
10142 break;
10143 case OPC_CVT_PW_PS:
10144 check_ps(ctx);
10146 TCGv_i64 fp0 = tcg_temp_new_i64();
10148 gen_load_fpr64(ctx, fp0, fs);
10149 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
10150 gen_store_fpr64(ctx, fp0, fd);
10151 tcg_temp_free_i64(fp0);
10153 break;
10154 case OPC_CVT_S_PL:
10155 check_cp1_64bitmode(ctx);
10157 TCGv_i32 fp0 = tcg_temp_new_i32();
10159 gen_load_fpr32(ctx, fp0, fs);
10160 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10161 gen_store_fpr32(ctx, fp0, fd);
10162 tcg_temp_free_i32(fp0);
10164 break;
10165 case OPC_PLL_PS:
10166 check_ps(ctx);
10168 TCGv_i32 fp0 = tcg_temp_new_i32();
10169 TCGv_i32 fp1 = tcg_temp_new_i32();
10171 gen_load_fpr32(ctx, fp0, fs);
10172 gen_load_fpr32(ctx, fp1, ft);
10173 gen_store_fpr32h(ctx, fp0, fd);
10174 gen_store_fpr32(ctx, fp1, fd);
10175 tcg_temp_free_i32(fp0);
10176 tcg_temp_free_i32(fp1);
10178 break;
10179 case OPC_PLU_PS:
10180 check_ps(ctx);
10182 TCGv_i32 fp0 = tcg_temp_new_i32();
10183 TCGv_i32 fp1 = tcg_temp_new_i32();
10185 gen_load_fpr32(ctx, fp0, fs);
10186 gen_load_fpr32h(ctx, fp1, ft);
10187 gen_store_fpr32(ctx, fp1, fd);
10188 gen_store_fpr32h(ctx, fp0, fd);
10189 tcg_temp_free_i32(fp0);
10190 tcg_temp_free_i32(fp1);
10192 break;
10193 case OPC_PUL_PS:
10194 check_ps(ctx);
10196 TCGv_i32 fp0 = tcg_temp_new_i32();
10197 TCGv_i32 fp1 = tcg_temp_new_i32();
10199 gen_load_fpr32h(ctx, fp0, fs);
10200 gen_load_fpr32(ctx, fp1, ft);
10201 gen_store_fpr32(ctx, fp1, fd);
10202 gen_store_fpr32h(ctx, fp0, fd);
10203 tcg_temp_free_i32(fp0);
10204 tcg_temp_free_i32(fp1);
10206 break;
10207 case OPC_PUU_PS:
10208 check_ps(ctx);
10210 TCGv_i32 fp0 = tcg_temp_new_i32();
10211 TCGv_i32 fp1 = tcg_temp_new_i32();
10213 gen_load_fpr32h(ctx, fp0, fs);
10214 gen_load_fpr32h(ctx, fp1, ft);
10215 gen_store_fpr32(ctx, fp1, fd);
10216 gen_store_fpr32h(ctx, fp0, fd);
10217 tcg_temp_free_i32(fp0);
10218 tcg_temp_free_i32(fp1);
10220 break;
10221 case OPC_CMP_F_PS:
10222 case OPC_CMP_UN_PS:
10223 case OPC_CMP_EQ_PS:
10224 case OPC_CMP_UEQ_PS:
10225 case OPC_CMP_OLT_PS:
10226 case OPC_CMP_ULT_PS:
10227 case OPC_CMP_OLE_PS:
10228 case OPC_CMP_ULE_PS:
10229 case OPC_CMP_SF_PS:
10230 case OPC_CMP_NGLE_PS:
10231 case OPC_CMP_SEQ_PS:
10232 case OPC_CMP_NGL_PS:
10233 case OPC_CMP_LT_PS:
10234 case OPC_CMP_NGE_PS:
10235 case OPC_CMP_LE_PS:
10236 case OPC_CMP_NGT_PS:
10237 if (ctx->opcode & (1 << 6)) {
10238 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10239 } else {
10240 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10242 break;
10243 default:
10244 MIPS_INVAL("farith");
10245 generate_exception_end(ctx, EXCP_RI);
10246 return;
10250 /* Coprocessor 3 (FPU) */
10251 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10252 int fd, int fs, int base, int index)
10254 TCGv t0 = tcg_temp_new();
10256 if (base == 0) {
10257 gen_load_gpr(t0, index);
10258 } else if (index == 0) {
10259 gen_load_gpr(t0, base);
10260 } else {
10261 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10263 /* Don't do NOP if destination is zero: we must perform the actual
10264 memory access. */
10265 switch (opc) {
10266 case OPC_LWXC1:
10267 check_cop1x(ctx);
10269 TCGv_i32 fp0 = tcg_temp_new_i32();
10271 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10272 tcg_gen_trunc_tl_i32(fp0, t0);
10273 gen_store_fpr32(ctx, fp0, fd);
10274 tcg_temp_free_i32(fp0);
10276 break;
10277 case OPC_LDXC1:
10278 check_cop1x(ctx);
10279 check_cp1_registers(ctx, fd);
10281 TCGv_i64 fp0 = tcg_temp_new_i64();
10282 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10283 gen_store_fpr64(ctx, fp0, fd);
10284 tcg_temp_free_i64(fp0);
10286 break;
10287 case OPC_LUXC1:
10288 check_cp1_64bitmode(ctx);
10289 tcg_gen_andi_tl(t0, t0, ~0x7);
10291 TCGv_i64 fp0 = tcg_temp_new_i64();
10293 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10294 gen_store_fpr64(ctx, fp0, fd);
10295 tcg_temp_free_i64(fp0);
10297 break;
10298 case OPC_SWXC1:
10299 check_cop1x(ctx);
10301 TCGv_i32 fp0 = tcg_temp_new_i32();
10302 gen_load_fpr32(ctx, fp0, fs);
10303 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10304 tcg_temp_free_i32(fp0);
10306 break;
10307 case OPC_SDXC1:
10308 check_cop1x(ctx);
10309 check_cp1_registers(ctx, fs);
10311 TCGv_i64 fp0 = tcg_temp_new_i64();
10312 gen_load_fpr64(ctx, fp0, fs);
10313 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10314 tcg_temp_free_i64(fp0);
10316 break;
10317 case OPC_SUXC1:
10318 check_cp1_64bitmode(ctx);
10319 tcg_gen_andi_tl(t0, t0, ~0x7);
10321 TCGv_i64 fp0 = tcg_temp_new_i64();
10322 gen_load_fpr64(ctx, fp0, fs);
10323 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10324 tcg_temp_free_i64(fp0);
10326 break;
10328 tcg_temp_free(t0);
10331 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10332 int fd, int fr, int fs, int ft)
10334 switch (opc) {
10335 case OPC_ALNV_PS:
10336 check_ps(ctx);
10338 TCGv t0 = tcg_temp_local_new();
10339 TCGv_i32 fp = tcg_temp_new_i32();
10340 TCGv_i32 fph = tcg_temp_new_i32();
10341 TCGLabel *l1 = gen_new_label();
10342 TCGLabel *l2 = gen_new_label();
10344 gen_load_gpr(t0, fr);
10345 tcg_gen_andi_tl(t0, t0, 0x7);
10347 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10348 gen_load_fpr32(ctx, fp, fs);
10349 gen_load_fpr32h(ctx, fph, fs);
10350 gen_store_fpr32(ctx, fp, fd);
10351 gen_store_fpr32h(ctx, fph, fd);
10352 tcg_gen_br(l2);
10353 gen_set_label(l1);
10354 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10355 tcg_temp_free(t0);
10356 #ifdef TARGET_WORDS_BIGENDIAN
10357 gen_load_fpr32(ctx, fp, fs);
10358 gen_load_fpr32h(ctx, fph, ft);
10359 gen_store_fpr32h(ctx, fp, fd);
10360 gen_store_fpr32(ctx, fph, fd);
10361 #else
10362 gen_load_fpr32h(ctx, fph, fs);
10363 gen_load_fpr32(ctx, fp, ft);
10364 gen_store_fpr32(ctx, fph, fd);
10365 gen_store_fpr32h(ctx, fp, fd);
10366 #endif
10367 gen_set_label(l2);
10368 tcg_temp_free_i32(fp);
10369 tcg_temp_free_i32(fph);
10371 break;
10372 case OPC_MADD_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_madd_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_MADD_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_madd_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_MADD_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_madd_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 case OPC_MSUB_S:
10425 check_cop1x(ctx);
10427 TCGv_i32 fp0 = tcg_temp_new_i32();
10428 TCGv_i32 fp1 = tcg_temp_new_i32();
10429 TCGv_i32 fp2 = tcg_temp_new_i32();
10431 gen_load_fpr32(ctx, fp0, fs);
10432 gen_load_fpr32(ctx, fp1, ft);
10433 gen_load_fpr32(ctx, fp2, fr);
10434 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10435 tcg_temp_free_i32(fp0);
10436 tcg_temp_free_i32(fp1);
10437 gen_store_fpr32(ctx, fp2, fd);
10438 tcg_temp_free_i32(fp2);
10440 break;
10441 case OPC_MSUB_D:
10442 check_cop1x(ctx);
10443 check_cp1_registers(ctx, fd | fs | ft | fr);
10445 TCGv_i64 fp0 = tcg_temp_new_i64();
10446 TCGv_i64 fp1 = tcg_temp_new_i64();
10447 TCGv_i64 fp2 = tcg_temp_new_i64();
10449 gen_load_fpr64(ctx, fp0, fs);
10450 gen_load_fpr64(ctx, fp1, ft);
10451 gen_load_fpr64(ctx, fp2, fr);
10452 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10453 tcg_temp_free_i64(fp0);
10454 tcg_temp_free_i64(fp1);
10455 gen_store_fpr64(ctx, fp2, fd);
10456 tcg_temp_free_i64(fp2);
10458 break;
10459 case OPC_MSUB_PS:
10460 check_ps(ctx);
10462 TCGv_i64 fp0 = tcg_temp_new_i64();
10463 TCGv_i64 fp1 = tcg_temp_new_i64();
10464 TCGv_i64 fp2 = tcg_temp_new_i64();
10466 gen_load_fpr64(ctx, fp0, fs);
10467 gen_load_fpr64(ctx, fp1, ft);
10468 gen_load_fpr64(ctx, fp2, fr);
10469 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10470 tcg_temp_free_i64(fp0);
10471 tcg_temp_free_i64(fp1);
10472 gen_store_fpr64(ctx, fp2, fd);
10473 tcg_temp_free_i64(fp2);
10475 break;
10476 case OPC_NMADD_S:
10477 check_cop1x(ctx);
10479 TCGv_i32 fp0 = tcg_temp_new_i32();
10480 TCGv_i32 fp1 = tcg_temp_new_i32();
10481 TCGv_i32 fp2 = tcg_temp_new_i32();
10483 gen_load_fpr32(ctx, fp0, fs);
10484 gen_load_fpr32(ctx, fp1, ft);
10485 gen_load_fpr32(ctx, fp2, fr);
10486 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10487 tcg_temp_free_i32(fp0);
10488 tcg_temp_free_i32(fp1);
10489 gen_store_fpr32(ctx, fp2, fd);
10490 tcg_temp_free_i32(fp2);
10492 break;
10493 case OPC_NMADD_D:
10494 check_cop1x(ctx);
10495 check_cp1_registers(ctx, fd | fs | ft | fr);
10497 TCGv_i64 fp0 = tcg_temp_new_i64();
10498 TCGv_i64 fp1 = tcg_temp_new_i64();
10499 TCGv_i64 fp2 = tcg_temp_new_i64();
10501 gen_load_fpr64(ctx, fp0, fs);
10502 gen_load_fpr64(ctx, fp1, ft);
10503 gen_load_fpr64(ctx, fp2, fr);
10504 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10505 tcg_temp_free_i64(fp0);
10506 tcg_temp_free_i64(fp1);
10507 gen_store_fpr64(ctx, fp2, fd);
10508 tcg_temp_free_i64(fp2);
10510 break;
10511 case OPC_NMADD_PS:
10512 check_ps(ctx);
10514 TCGv_i64 fp0 = tcg_temp_new_i64();
10515 TCGv_i64 fp1 = tcg_temp_new_i64();
10516 TCGv_i64 fp2 = tcg_temp_new_i64();
10518 gen_load_fpr64(ctx, fp0, fs);
10519 gen_load_fpr64(ctx, fp1, ft);
10520 gen_load_fpr64(ctx, fp2, fr);
10521 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10522 tcg_temp_free_i64(fp0);
10523 tcg_temp_free_i64(fp1);
10524 gen_store_fpr64(ctx, fp2, fd);
10525 tcg_temp_free_i64(fp2);
10527 break;
10528 case OPC_NMSUB_S:
10529 check_cop1x(ctx);
10531 TCGv_i32 fp0 = tcg_temp_new_i32();
10532 TCGv_i32 fp1 = tcg_temp_new_i32();
10533 TCGv_i32 fp2 = tcg_temp_new_i32();
10535 gen_load_fpr32(ctx, fp0, fs);
10536 gen_load_fpr32(ctx, fp1, ft);
10537 gen_load_fpr32(ctx, fp2, fr);
10538 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10539 tcg_temp_free_i32(fp0);
10540 tcg_temp_free_i32(fp1);
10541 gen_store_fpr32(ctx, fp2, fd);
10542 tcg_temp_free_i32(fp2);
10544 break;
10545 case OPC_NMSUB_D:
10546 check_cop1x(ctx);
10547 check_cp1_registers(ctx, fd | fs | ft | fr);
10549 TCGv_i64 fp0 = tcg_temp_new_i64();
10550 TCGv_i64 fp1 = tcg_temp_new_i64();
10551 TCGv_i64 fp2 = tcg_temp_new_i64();
10553 gen_load_fpr64(ctx, fp0, fs);
10554 gen_load_fpr64(ctx, fp1, ft);
10555 gen_load_fpr64(ctx, fp2, fr);
10556 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10557 tcg_temp_free_i64(fp0);
10558 tcg_temp_free_i64(fp1);
10559 gen_store_fpr64(ctx, fp2, fd);
10560 tcg_temp_free_i64(fp2);
10562 break;
10563 case OPC_NMSUB_PS:
10564 check_ps(ctx);
10566 TCGv_i64 fp0 = tcg_temp_new_i64();
10567 TCGv_i64 fp1 = tcg_temp_new_i64();
10568 TCGv_i64 fp2 = tcg_temp_new_i64();
10570 gen_load_fpr64(ctx, fp0, fs);
10571 gen_load_fpr64(ctx, fp1, ft);
10572 gen_load_fpr64(ctx, fp2, fr);
10573 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10574 tcg_temp_free_i64(fp0);
10575 tcg_temp_free_i64(fp1);
10576 gen_store_fpr64(ctx, fp2, fd);
10577 tcg_temp_free_i64(fp2);
10579 break;
10580 default:
10581 MIPS_INVAL("flt3_arith");
10582 generate_exception_end(ctx, EXCP_RI);
10583 return;
10587 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
10589 TCGv t0;
10591 #if !defined(CONFIG_USER_ONLY)
10592 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10593 Therefore only check the ISA in system mode. */
10594 check_insn(ctx, ISA_MIPS32R2);
10595 #endif
10596 t0 = tcg_temp_new();
10598 switch (rd) {
10599 case 0:
10600 gen_helper_rdhwr_cpunum(t0, cpu_env);
10601 gen_store_gpr(t0, rt);
10602 break;
10603 case 1:
10604 gen_helper_rdhwr_synci_step(t0, cpu_env);
10605 gen_store_gpr(t0, rt);
10606 break;
10607 case 2:
10608 gen_helper_rdhwr_cc(t0, cpu_env);
10609 gen_store_gpr(t0, rt);
10610 break;
10611 case 3:
10612 gen_helper_rdhwr_ccres(t0, cpu_env);
10613 gen_store_gpr(t0, rt);
10614 break;
10615 case 4:
10616 check_insn(ctx, ISA_MIPS32R6);
10617 if (sel != 0) {
10618 /* Performance counter registers are not implemented other than
10619 * control register 0.
10621 generate_exception(ctx, EXCP_RI);
10623 gen_helper_rdhwr_performance(t0, cpu_env);
10624 gen_store_gpr(t0, rt);
10625 break;
10626 case 5:
10627 check_insn(ctx, ISA_MIPS32R6);
10628 gen_helper_rdhwr_xnp(t0, cpu_env);
10629 gen_store_gpr(t0, rt);
10630 break;
10631 case 29:
10632 #if defined(CONFIG_USER_ONLY)
10633 tcg_gen_ld_tl(t0, cpu_env,
10634 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10635 gen_store_gpr(t0, rt);
10636 break;
10637 #else
10638 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10639 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10640 tcg_gen_ld_tl(t0, cpu_env,
10641 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10642 gen_store_gpr(t0, rt);
10643 } else {
10644 generate_exception_end(ctx, EXCP_RI);
10646 break;
10647 #endif
10648 default: /* Invalid */
10649 MIPS_INVAL("rdhwr");
10650 generate_exception_end(ctx, EXCP_RI);
10651 break;
10653 tcg_temp_free(t0);
10656 static inline void clear_branch_hflags(DisasContext *ctx)
10658 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10659 if (ctx->bstate == BS_NONE) {
10660 save_cpu_state(ctx, 0);
10661 } else {
10662 /* it is not safe to save ctx->hflags as hflags may be changed
10663 in execution time by the instruction in delay / forbidden slot. */
10664 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10668 static void gen_branch(DisasContext *ctx, int insn_bytes)
10670 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10671 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10672 /* Branches completion */
10673 clear_branch_hflags(ctx);
10674 ctx->bstate = BS_BRANCH;
10675 /* FIXME: Need to clear can_do_io. */
10676 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10677 case MIPS_HFLAG_FBNSLOT:
10678 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10679 break;
10680 case MIPS_HFLAG_B:
10681 /* unconditional branch */
10682 if (proc_hflags & MIPS_HFLAG_BX) {
10683 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10685 gen_goto_tb(ctx, 0, ctx->btarget);
10686 break;
10687 case MIPS_HFLAG_BL:
10688 /* blikely taken case */
10689 gen_goto_tb(ctx, 0, ctx->btarget);
10690 break;
10691 case MIPS_HFLAG_BC:
10692 /* Conditional branch */
10694 TCGLabel *l1 = gen_new_label();
10696 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10697 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10698 gen_set_label(l1);
10699 gen_goto_tb(ctx, 0, ctx->btarget);
10701 break;
10702 case MIPS_HFLAG_BR:
10703 /* unconditional branch to register */
10704 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10705 TCGv t0 = tcg_temp_new();
10706 TCGv_i32 t1 = tcg_temp_new_i32();
10708 tcg_gen_andi_tl(t0, btarget, 0x1);
10709 tcg_gen_trunc_tl_i32(t1, t0);
10710 tcg_temp_free(t0);
10711 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10712 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10713 tcg_gen_or_i32(hflags, hflags, t1);
10714 tcg_temp_free_i32(t1);
10716 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10717 } else {
10718 tcg_gen_mov_tl(cpu_PC, btarget);
10720 if (ctx->singlestep_enabled) {
10721 save_cpu_state(ctx, 0);
10722 gen_helper_raise_exception_debug(cpu_env);
10724 tcg_gen_exit_tb(0);
10725 break;
10726 default:
10727 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
10728 abort();
10733 /* Compact Branches */
10734 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
10735 int rs, int rt, int32_t offset)
10737 int bcond_compute = 0;
10738 TCGv t0 = tcg_temp_new();
10739 TCGv t1 = tcg_temp_new();
10740 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
10742 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10743 #ifdef MIPS_DEBUG_DISAS
10744 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10745 "\n", ctx->pc);
10746 #endif
10747 generate_exception_end(ctx, EXCP_RI);
10748 goto out;
10751 /* Load needed operands and calculate btarget */
10752 switch (opc) {
10753 /* compact branch */
10754 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10755 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10756 gen_load_gpr(t0, rs);
10757 gen_load_gpr(t1, rt);
10758 bcond_compute = 1;
10759 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10760 if (rs <= rt && rs == 0) {
10761 /* OPC_BEQZALC, OPC_BNEZALC */
10762 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10764 break;
10765 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10766 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10767 gen_load_gpr(t0, rs);
10768 gen_load_gpr(t1, rt);
10769 bcond_compute = 1;
10770 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10771 break;
10772 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10773 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10774 if (rs == 0 || rs == rt) {
10775 /* OPC_BLEZALC, OPC_BGEZALC */
10776 /* OPC_BGTZALC, OPC_BLTZALC */
10777 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10779 gen_load_gpr(t0, rs);
10780 gen_load_gpr(t1, rt);
10781 bcond_compute = 1;
10782 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10783 break;
10784 case OPC_BC:
10785 case OPC_BALC:
10786 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10787 break;
10788 case OPC_BEQZC:
10789 case OPC_BNEZC:
10790 if (rs != 0) {
10791 /* OPC_BEQZC, OPC_BNEZC */
10792 gen_load_gpr(t0, rs);
10793 bcond_compute = 1;
10794 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10795 } else {
10796 /* OPC_JIC, OPC_JIALC */
10797 TCGv tbase = tcg_temp_new();
10798 TCGv toffset = tcg_temp_new();
10800 gen_load_gpr(tbase, rt);
10801 tcg_gen_movi_tl(toffset, offset);
10802 gen_op_addr_add(ctx, btarget, tbase, toffset);
10803 tcg_temp_free(tbase);
10804 tcg_temp_free(toffset);
10806 break;
10807 default:
10808 MIPS_INVAL("Compact branch/jump");
10809 generate_exception_end(ctx, EXCP_RI);
10810 goto out;
10813 if (bcond_compute == 0) {
10814 /* Uncoditional compact branch */
10815 switch (opc) {
10816 case OPC_JIALC:
10817 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10818 /* Fallthrough */
10819 case OPC_JIC:
10820 ctx->hflags |= MIPS_HFLAG_BR;
10821 break;
10822 case OPC_BALC:
10823 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10824 /* Fallthrough */
10825 case OPC_BC:
10826 ctx->hflags |= MIPS_HFLAG_B;
10827 break;
10828 default:
10829 MIPS_INVAL("Compact branch/jump");
10830 generate_exception_end(ctx, EXCP_RI);
10831 goto out;
10834 /* Generating branch here as compact branches don't have delay slot */
10835 gen_branch(ctx, 4);
10836 } else {
10837 /* Conditional compact branch */
10838 TCGLabel *fs = gen_new_label();
10839 save_cpu_state(ctx, 0);
10841 switch (opc) {
10842 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10843 if (rs == 0 && rt != 0) {
10844 /* OPC_BLEZALC */
10845 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10846 } else if (rs != 0 && rt != 0 && rs == rt) {
10847 /* OPC_BGEZALC */
10848 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10849 } else {
10850 /* OPC_BGEUC */
10851 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
10853 break;
10854 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10855 if (rs == 0 && rt != 0) {
10856 /* OPC_BGTZALC */
10857 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10858 } else if (rs != 0 && rt != 0 && rs == rt) {
10859 /* OPC_BLTZALC */
10860 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10861 } else {
10862 /* OPC_BLTUC */
10863 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
10865 break;
10866 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10867 if (rs == 0 && rt != 0) {
10868 /* OPC_BLEZC */
10869 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10870 } else if (rs != 0 && rt != 0 && rs == rt) {
10871 /* OPC_BGEZC */
10872 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10873 } else {
10874 /* OPC_BGEC */
10875 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
10877 break;
10878 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10879 if (rs == 0 && rt != 0) {
10880 /* OPC_BGTZC */
10881 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10882 } else if (rs != 0 && rt != 0 && rs == rt) {
10883 /* OPC_BLTZC */
10884 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10885 } else {
10886 /* OPC_BLTC */
10887 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
10889 break;
10890 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10891 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10892 if (rs >= rt) {
10893 /* OPC_BOVC, OPC_BNVC */
10894 TCGv t2 = tcg_temp_new();
10895 TCGv t3 = tcg_temp_new();
10896 TCGv t4 = tcg_temp_new();
10897 TCGv input_overflow = tcg_temp_new();
10899 gen_load_gpr(t0, rs);
10900 gen_load_gpr(t1, rt);
10901 tcg_gen_ext32s_tl(t2, t0);
10902 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
10903 tcg_gen_ext32s_tl(t3, t1);
10904 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
10905 tcg_gen_or_tl(input_overflow, input_overflow, t4);
10907 tcg_gen_add_tl(t4, t2, t3);
10908 tcg_gen_ext32s_tl(t4, t4);
10909 tcg_gen_xor_tl(t2, t2, t3);
10910 tcg_gen_xor_tl(t3, t4, t3);
10911 tcg_gen_andc_tl(t2, t3, t2);
10912 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
10913 tcg_gen_or_tl(t4, t4, input_overflow);
10914 if (opc == OPC_BOVC) {
10915 /* OPC_BOVC */
10916 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
10917 } else {
10918 /* OPC_BNVC */
10919 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
10921 tcg_temp_free(input_overflow);
10922 tcg_temp_free(t4);
10923 tcg_temp_free(t3);
10924 tcg_temp_free(t2);
10925 } else if (rs < rt && rs == 0) {
10926 /* OPC_BEQZALC, OPC_BNEZALC */
10927 if (opc == OPC_BEQZALC) {
10928 /* OPC_BEQZALC */
10929 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
10930 } else {
10931 /* OPC_BNEZALC */
10932 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
10934 } else {
10935 /* OPC_BEQC, OPC_BNEC */
10936 if (opc == OPC_BEQC) {
10937 /* OPC_BEQC */
10938 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
10939 } else {
10940 /* OPC_BNEC */
10941 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
10944 break;
10945 case OPC_BEQZC:
10946 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
10947 break;
10948 case OPC_BNEZC:
10949 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
10950 break;
10951 default:
10952 MIPS_INVAL("Compact conditional branch/jump");
10953 generate_exception_end(ctx, EXCP_RI);
10954 goto out;
10957 /* Generating branch here as compact branches don't have delay slot */
10958 gen_goto_tb(ctx, 1, ctx->btarget);
10959 gen_set_label(fs);
10961 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
10964 out:
10965 tcg_temp_free(t0);
10966 tcg_temp_free(t1);
10969 /* ISA extensions (ASEs) */
10970 /* MIPS16 extension to MIPS32 */
10972 /* MIPS16 major opcodes */
10973 enum {
10974 M16_OPC_ADDIUSP = 0x00,
10975 M16_OPC_ADDIUPC = 0x01,
10976 M16_OPC_B = 0x02,
10977 M16_OPC_JAL = 0x03,
10978 M16_OPC_BEQZ = 0x04,
10979 M16_OPC_BNEQZ = 0x05,
10980 M16_OPC_SHIFT = 0x06,
10981 M16_OPC_LD = 0x07,
10982 M16_OPC_RRIA = 0x08,
10983 M16_OPC_ADDIU8 = 0x09,
10984 M16_OPC_SLTI = 0x0a,
10985 M16_OPC_SLTIU = 0x0b,
10986 M16_OPC_I8 = 0x0c,
10987 M16_OPC_LI = 0x0d,
10988 M16_OPC_CMPI = 0x0e,
10989 M16_OPC_SD = 0x0f,
10990 M16_OPC_LB = 0x10,
10991 M16_OPC_LH = 0x11,
10992 M16_OPC_LWSP = 0x12,
10993 M16_OPC_LW = 0x13,
10994 M16_OPC_LBU = 0x14,
10995 M16_OPC_LHU = 0x15,
10996 M16_OPC_LWPC = 0x16,
10997 M16_OPC_LWU = 0x17,
10998 M16_OPC_SB = 0x18,
10999 M16_OPC_SH = 0x19,
11000 M16_OPC_SWSP = 0x1a,
11001 M16_OPC_SW = 0x1b,
11002 M16_OPC_RRR = 0x1c,
11003 M16_OPC_RR = 0x1d,
11004 M16_OPC_EXTEND = 0x1e,
11005 M16_OPC_I64 = 0x1f
11008 /* I8 funct field */
11009 enum {
11010 I8_BTEQZ = 0x0,
11011 I8_BTNEZ = 0x1,
11012 I8_SWRASP = 0x2,
11013 I8_ADJSP = 0x3,
11014 I8_SVRS = 0x4,
11015 I8_MOV32R = 0x5,
11016 I8_MOVR32 = 0x7
11019 /* RRR f field */
11020 enum {
11021 RRR_DADDU = 0x0,
11022 RRR_ADDU = 0x1,
11023 RRR_DSUBU = 0x2,
11024 RRR_SUBU = 0x3
11027 /* RR funct field */
11028 enum {
11029 RR_JR = 0x00,
11030 RR_SDBBP = 0x01,
11031 RR_SLT = 0x02,
11032 RR_SLTU = 0x03,
11033 RR_SLLV = 0x04,
11034 RR_BREAK = 0x05,
11035 RR_SRLV = 0x06,
11036 RR_SRAV = 0x07,
11037 RR_DSRL = 0x08,
11038 RR_CMP = 0x0a,
11039 RR_NEG = 0x0b,
11040 RR_AND = 0x0c,
11041 RR_OR = 0x0d,
11042 RR_XOR = 0x0e,
11043 RR_NOT = 0x0f,
11044 RR_MFHI = 0x10,
11045 RR_CNVT = 0x11,
11046 RR_MFLO = 0x12,
11047 RR_DSRA = 0x13,
11048 RR_DSLLV = 0x14,
11049 RR_DSRLV = 0x16,
11050 RR_DSRAV = 0x17,
11051 RR_MULT = 0x18,
11052 RR_MULTU = 0x19,
11053 RR_DIV = 0x1a,
11054 RR_DIVU = 0x1b,
11055 RR_DMULT = 0x1c,
11056 RR_DMULTU = 0x1d,
11057 RR_DDIV = 0x1e,
11058 RR_DDIVU = 0x1f
11061 /* I64 funct field */
11062 enum {
11063 I64_LDSP = 0x0,
11064 I64_SDSP = 0x1,
11065 I64_SDRASP = 0x2,
11066 I64_DADJSP = 0x3,
11067 I64_LDPC = 0x4,
11068 I64_DADDIU5 = 0x5,
11069 I64_DADDIUPC = 0x6,
11070 I64_DADDIUSP = 0x7
11073 /* RR ry field for CNVT */
11074 enum {
11075 RR_RY_CNVT_ZEB = 0x0,
11076 RR_RY_CNVT_ZEH = 0x1,
11077 RR_RY_CNVT_ZEW = 0x2,
11078 RR_RY_CNVT_SEB = 0x4,
11079 RR_RY_CNVT_SEH = 0x5,
11080 RR_RY_CNVT_SEW = 0x6,
11083 static int xlat (int r)
11085 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11087 return map[r];
11090 static void gen_mips16_save (DisasContext *ctx,
11091 int xsregs, int aregs,
11092 int do_ra, int do_s0, int do_s1,
11093 int framesize)
11095 TCGv t0 = tcg_temp_new();
11096 TCGv t1 = tcg_temp_new();
11097 TCGv t2 = tcg_temp_new();
11098 int args, astatic;
11100 switch (aregs) {
11101 case 0:
11102 case 1:
11103 case 2:
11104 case 3:
11105 case 11:
11106 args = 0;
11107 break;
11108 case 4:
11109 case 5:
11110 case 6:
11111 case 7:
11112 args = 1;
11113 break;
11114 case 8:
11115 case 9:
11116 case 10:
11117 args = 2;
11118 break;
11119 case 12:
11120 case 13:
11121 args = 3;
11122 break;
11123 case 14:
11124 args = 4;
11125 break;
11126 default:
11127 generate_exception_end(ctx, EXCP_RI);
11128 return;
11131 switch (args) {
11132 case 4:
11133 gen_base_offset_addr(ctx, t0, 29, 12);
11134 gen_load_gpr(t1, 7);
11135 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11136 /* Fall through */
11137 case 3:
11138 gen_base_offset_addr(ctx, t0, 29, 8);
11139 gen_load_gpr(t1, 6);
11140 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11141 /* Fall through */
11142 case 2:
11143 gen_base_offset_addr(ctx, t0, 29, 4);
11144 gen_load_gpr(t1, 5);
11145 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11146 /* Fall through */
11147 case 1:
11148 gen_base_offset_addr(ctx, t0, 29, 0);
11149 gen_load_gpr(t1, 4);
11150 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11153 gen_load_gpr(t0, 29);
11155 #define DECR_AND_STORE(reg) do { \
11156 tcg_gen_movi_tl(t2, -4); \
11157 gen_op_addr_add(ctx, t0, t0, t2); \
11158 gen_load_gpr(t1, reg); \
11159 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
11160 } while (0)
11162 if (do_ra) {
11163 DECR_AND_STORE(31);
11166 switch (xsregs) {
11167 case 7:
11168 DECR_AND_STORE(30);
11169 /* Fall through */
11170 case 6:
11171 DECR_AND_STORE(23);
11172 /* Fall through */
11173 case 5:
11174 DECR_AND_STORE(22);
11175 /* Fall through */
11176 case 4:
11177 DECR_AND_STORE(21);
11178 /* Fall through */
11179 case 3:
11180 DECR_AND_STORE(20);
11181 /* Fall through */
11182 case 2:
11183 DECR_AND_STORE(19);
11184 /* Fall through */
11185 case 1:
11186 DECR_AND_STORE(18);
11189 if (do_s1) {
11190 DECR_AND_STORE(17);
11192 if (do_s0) {
11193 DECR_AND_STORE(16);
11196 switch (aregs) {
11197 case 0:
11198 case 4:
11199 case 8:
11200 case 12:
11201 case 14:
11202 astatic = 0;
11203 break;
11204 case 1:
11205 case 5:
11206 case 9:
11207 case 13:
11208 astatic = 1;
11209 break;
11210 case 2:
11211 case 6:
11212 case 10:
11213 astatic = 2;
11214 break;
11215 case 3:
11216 case 7:
11217 astatic = 3;
11218 break;
11219 case 11:
11220 astatic = 4;
11221 break;
11222 default:
11223 generate_exception_end(ctx, EXCP_RI);
11224 return;
11227 if (astatic > 0) {
11228 DECR_AND_STORE(7);
11229 if (astatic > 1) {
11230 DECR_AND_STORE(6);
11231 if (astatic > 2) {
11232 DECR_AND_STORE(5);
11233 if (astatic > 3) {
11234 DECR_AND_STORE(4);
11239 #undef DECR_AND_STORE
11241 tcg_gen_movi_tl(t2, -framesize);
11242 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11243 tcg_temp_free(t0);
11244 tcg_temp_free(t1);
11245 tcg_temp_free(t2);
11248 static void gen_mips16_restore (DisasContext *ctx,
11249 int xsregs, int aregs,
11250 int do_ra, int do_s0, int do_s1,
11251 int framesize)
11253 int astatic;
11254 TCGv t0 = tcg_temp_new();
11255 TCGv t1 = tcg_temp_new();
11256 TCGv t2 = tcg_temp_new();
11258 tcg_gen_movi_tl(t2, framesize);
11259 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11261 #define DECR_AND_LOAD(reg) do { \
11262 tcg_gen_movi_tl(t2, -4); \
11263 gen_op_addr_add(ctx, t0, t0, t2); \
11264 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11265 gen_store_gpr(t1, reg); \
11266 } while (0)
11268 if (do_ra) {
11269 DECR_AND_LOAD(31);
11272 switch (xsregs) {
11273 case 7:
11274 DECR_AND_LOAD(30);
11275 /* Fall through */
11276 case 6:
11277 DECR_AND_LOAD(23);
11278 /* Fall through */
11279 case 5:
11280 DECR_AND_LOAD(22);
11281 /* Fall through */
11282 case 4:
11283 DECR_AND_LOAD(21);
11284 /* Fall through */
11285 case 3:
11286 DECR_AND_LOAD(20);
11287 /* Fall through */
11288 case 2:
11289 DECR_AND_LOAD(19);
11290 /* Fall through */
11291 case 1:
11292 DECR_AND_LOAD(18);
11295 if (do_s1) {
11296 DECR_AND_LOAD(17);
11298 if (do_s0) {
11299 DECR_AND_LOAD(16);
11302 switch (aregs) {
11303 case 0:
11304 case 4:
11305 case 8:
11306 case 12:
11307 case 14:
11308 astatic = 0;
11309 break;
11310 case 1:
11311 case 5:
11312 case 9:
11313 case 13:
11314 astatic = 1;
11315 break;
11316 case 2:
11317 case 6:
11318 case 10:
11319 astatic = 2;
11320 break;
11321 case 3:
11322 case 7:
11323 astatic = 3;
11324 break;
11325 case 11:
11326 astatic = 4;
11327 break;
11328 default:
11329 generate_exception_end(ctx, EXCP_RI);
11330 return;
11333 if (astatic > 0) {
11334 DECR_AND_LOAD(7);
11335 if (astatic > 1) {
11336 DECR_AND_LOAD(6);
11337 if (astatic > 2) {
11338 DECR_AND_LOAD(5);
11339 if (astatic > 3) {
11340 DECR_AND_LOAD(4);
11345 #undef DECR_AND_LOAD
11347 tcg_gen_movi_tl(t2, framesize);
11348 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11349 tcg_temp_free(t0);
11350 tcg_temp_free(t1);
11351 tcg_temp_free(t2);
11354 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11355 int is_64_bit, int extended)
11357 TCGv t0;
11359 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11360 generate_exception_end(ctx, EXCP_RI);
11361 return;
11364 t0 = tcg_temp_new();
11366 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11367 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11368 if (!is_64_bit) {
11369 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11372 tcg_temp_free(t0);
11375 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
11376 int16_t offset)
11378 TCGv_i32 t0 = tcg_const_i32(op);
11379 TCGv t1 = tcg_temp_new();
11380 gen_base_offset_addr(ctx, t1, base, offset);
11381 gen_helper_cache(cpu_env, t1, t0);
11384 #if defined(TARGET_MIPS64)
11385 static void decode_i64_mips16 (DisasContext *ctx,
11386 int ry, int funct, int16_t offset,
11387 int extended)
11389 switch (funct) {
11390 case I64_LDSP:
11391 check_insn(ctx, ISA_MIPS3);
11392 check_mips_64(ctx);
11393 offset = extended ? offset : offset << 3;
11394 gen_ld(ctx, OPC_LD, ry, 29, offset);
11395 break;
11396 case I64_SDSP:
11397 check_insn(ctx, ISA_MIPS3);
11398 check_mips_64(ctx);
11399 offset = extended ? offset : offset << 3;
11400 gen_st(ctx, OPC_SD, ry, 29, offset);
11401 break;
11402 case I64_SDRASP:
11403 check_insn(ctx, ISA_MIPS3);
11404 check_mips_64(ctx);
11405 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11406 gen_st(ctx, OPC_SD, 31, 29, offset);
11407 break;
11408 case I64_DADJSP:
11409 check_insn(ctx, ISA_MIPS3);
11410 check_mips_64(ctx);
11411 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11412 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11413 break;
11414 case I64_LDPC:
11415 check_insn(ctx, ISA_MIPS3);
11416 check_mips_64(ctx);
11417 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11418 generate_exception_end(ctx, EXCP_RI);
11419 } else {
11420 offset = extended ? offset : offset << 3;
11421 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11423 break;
11424 case I64_DADDIU5:
11425 check_insn(ctx, ISA_MIPS3);
11426 check_mips_64(ctx);
11427 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11428 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11429 break;
11430 case I64_DADDIUPC:
11431 check_insn(ctx, ISA_MIPS3);
11432 check_mips_64(ctx);
11433 offset = extended ? offset : offset << 2;
11434 gen_addiupc(ctx, ry, offset, 1, extended);
11435 break;
11436 case I64_DADDIUSP:
11437 check_insn(ctx, ISA_MIPS3);
11438 check_mips_64(ctx);
11439 offset = extended ? offset : offset << 2;
11440 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11441 break;
11444 #endif
11446 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11448 int extend = cpu_lduw_code(env, ctx->pc + 2);
11449 int op, rx, ry, funct, sa;
11450 int16_t imm, offset;
11452 ctx->opcode = (ctx->opcode << 16) | extend;
11453 op = (ctx->opcode >> 11) & 0x1f;
11454 sa = (ctx->opcode >> 22) & 0x1f;
11455 funct = (ctx->opcode >> 8) & 0x7;
11456 rx = xlat((ctx->opcode >> 8) & 0x7);
11457 ry = xlat((ctx->opcode >> 5) & 0x7);
11458 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11459 | ((ctx->opcode >> 21) & 0x3f) << 5
11460 | (ctx->opcode & 0x1f));
11462 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11463 counterparts. */
11464 switch (op) {
11465 case M16_OPC_ADDIUSP:
11466 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11467 break;
11468 case M16_OPC_ADDIUPC:
11469 gen_addiupc(ctx, rx, imm, 0, 1);
11470 break;
11471 case M16_OPC_B:
11472 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11473 /* No delay slot, so just process as a normal instruction */
11474 break;
11475 case M16_OPC_BEQZ:
11476 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11477 /* No delay slot, so just process as a normal instruction */
11478 break;
11479 case M16_OPC_BNEQZ:
11480 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11481 /* No delay slot, so just process as a normal instruction */
11482 break;
11483 case M16_OPC_SHIFT:
11484 switch (ctx->opcode & 0x3) {
11485 case 0x0:
11486 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11487 break;
11488 case 0x1:
11489 #if defined(TARGET_MIPS64)
11490 check_mips_64(ctx);
11491 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11492 #else
11493 generate_exception_end(ctx, EXCP_RI);
11494 #endif
11495 break;
11496 case 0x2:
11497 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11498 break;
11499 case 0x3:
11500 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11501 break;
11503 break;
11504 #if defined(TARGET_MIPS64)
11505 case M16_OPC_LD:
11506 check_insn(ctx, ISA_MIPS3);
11507 check_mips_64(ctx);
11508 gen_ld(ctx, OPC_LD, ry, rx, offset);
11509 break;
11510 #endif
11511 case M16_OPC_RRIA:
11512 imm = ctx->opcode & 0xf;
11513 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11514 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11515 imm = (int16_t) (imm << 1) >> 1;
11516 if ((ctx->opcode >> 4) & 0x1) {
11517 #if defined(TARGET_MIPS64)
11518 check_mips_64(ctx);
11519 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11520 #else
11521 generate_exception_end(ctx, EXCP_RI);
11522 #endif
11523 } else {
11524 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11526 break;
11527 case M16_OPC_ADDIU8:
11528 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11529 break;
11530 case M16_OPC_SLTI:
11531 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11532 break;
11533 case M16_OPC_SLTIU:
11534 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11535 break;
11536 case M16_OPC_I8:
11537 switch (funct) {
11538 case I8_BTEQZ:
11539 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11540 break;
11541 case I8_BTNEZ:
11542 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11543 break;
11544 case I8_SWRASP:
11545 gen_st(ctx, OPC_SW, 31, 29, imm);
11546 break;
11547 case I8_ADJSP:
11548 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11549 break;
11550 case I8_SVRS:
11551 check_insn(ctx, ISA_MIPS32);
11553 int xsregs = (ctx->opcode >> 24) & 0x7;
11554 int aregs = (ctx->opcode >> 16) & 0xf;
11555 int do_ra = (ctx->opcode >> 6) & 0x1;
11556 int do_s0 = (ctx->opcode >> 5) & 0x1;
11557 int do_s1 = (ctx->opcode >> 4) & 0x1;
11558 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11559 | (ctx->opcode & 0xf)) << 3;
11561 if (ctx->opcode & (1 << 7)) {
11562 gen_mips16_save(ctx, xsregs, aregs,
11563 do_ra, do_s0, do_s1,
11564 framesize);
11565 } else {
11566 gen_mips16_restore(ctx, xsregs, aregs,
11567 do_ra, do_s0, do_s1,
11568 framesize);
11571 break;
11572 default:
11573 generate_exception_end(ctx, EXCP_RI);
11574 break;
11576 break;
11577 case M16_OPC_LI:
11578 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11579 break;
11580 case M16_OPC_CMPI:
11581 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11582 break;
11583 #if defined(TARGET_MIPS64)
11584 case M16_OPC_SD:
11585 check_insn(ctx, ISA_MIPS3);
11586 check_mips_64(ctx);
11587 gen_st(ctx, OPC_SD, ry, rx, offset);
11588 break;
11589 #endif
11590 case M16_OPC_LB:
11591 gen_ld(ctx, OPC_LB, ry, rx, offset);
11592 break;
11593 case M16_OPC_LH:
11594 gen_ld(ctx, OPC_LH, ry, rx, offset);
11595 break;
11596 case M16_OPC_LWSP:
11597 gen_ld(ctx, OPC_LW, rx, 29, offset);
11598 break;
11599 case M16_OPC_LW:
11600 gen_ld(ctx, OPC_LW, ry, rx, offset);
11601 break;
11602 case M16_OPC_LBU:
11603 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11604 break;
11605 case M16_OPC_LHU:
11606 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11607 break;
11608 case M16_OPC_LWPC:
11609 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11610 break;
11611 #if defined(TARGET_MIPS64)
11612 case M16_OPC_LWU:
11613 check_insn(ctx, ISA_MIPS3);
11614 check_mips_64(ctx);
11615 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11616 break;
11617 #endif
11618 case M16_OPC_SB:
11619 gen_st(ctx, OPC_SB, ry, rx, offset);
11620 break;
11621 case M16_OPC_SH:
11622 gen_st(ctx, OPC_SH, ry, rx, offset);
11623 break;
11624 case M16_OPC_SWSP:
11625 gen_st(ctx, OPC_SW, rx, 29, offset);
11626 break;
11627 case M16_OPC_SW:
11628 gen_st(ctx, OPC_SW, ry, rx, offset);
11629 break;
11630 #if defined(TARGET_MIPS64)
11631 case M16_OPC_I64:
11632 decode_i64_mips16(ctx, ry, funct, offset, 1);
11633 break;
11634 #endif
11635 default:
11636 generate_exception_end(ctx, EXCP_RI);
11637 break;
11640 return 4;
11643 static inline bool is_uhi(int sdbbp_code)
11645 #ifdef CONFIG_USER_ONLY
11646 return false;
11647 #else
11648 return semihosting_enabled() && sdbbp_code == 1;
11649 #endif
11652 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11654 int rx, ry;
11655 int sa;
11656 int op, cnvt_op, op1, offset;
11657 int funct;
11658 int n_bytes;
11660 op = (ctx->opcode >> 11) & 0x1f;
11661 sa = (ctx->opcode >> 2) & 0x7;
11662 sa = sa == 0 ? 8 : sa;
11663 rx = xlat((ctx->opcode >> 8) & 0x7);
11664 cnvt_op = (ctx->opcode >> 5) & 0x7;
11665 ry = xlat((ctx->opcode >> 5) & 0x7);
11666 op1 = offset = ctx->opcode & 0x1f;
11668 n_bytes = 2;
11670 switch (op) {
11671 case M16_OPC_ADDIUSP:
11673 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11675 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11677 break;
11678 case M16_OPC_ADDIUPC:
11679 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11680 break;
11681 case M16_OPC_B:
11682 offset = (ctx->opcode & 0x7ff) << 1;
11683 offset = (int16_t)(offset << 4) >> 4;
11684 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11685 /* No delay slot, so just process as a normal instruction */
11686 break;
11687 case M16_OPC_JAL:
11688 offset = cpu_lduw_code(env, ctx->pc + 2);
11689 offset = (((ctx->opcode & 0x1f) << 21)
11690 | ((ctx->opcode >> 5) & 0x1f) << 16
11691 | offset) << 2;
11692 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11693 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11694 n_bytes = 4;
11695 break;
11696 case M16_OPC_BEQZ:
11697 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11698 ((int8_t)ctx->opcode) << 1, 0);
11699 /* No delay slot, so just process as a normal instruction */
11700 break;
11701 case M16_OPC_BNEQZ:
11702 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11703 ((int8_t)ctx->opcode) << 1, 0);
11704 /* No delay slot, so just process as a normal instruction */
11705 break;
11706 case M16_OPC_SHIFT:
11707 switch (ctx->opcode & 0x3) {
11708 case 0x0:
11709 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11710 break;
11711 case 0x1:
11712 #if defined(TARGET_MIPS64)
11713 check_insn(ctx, ISA_MIPS3);
11714 check_mips_64(ctx);
11715 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11716 #else
11717 generate_exception_end(ctx, EXCP_RI);
11718 #endif
11719 break;
11720 case 0x2:
11721 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11722 break;
11723 case 0x3:
11724 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11725 break;
11727 break;
11728 #if defined(TARGET_MIPS64)
11729 case M16_OPC_LD:
11730 check_insn(ctx, ISA_MIPS3);
11731 check_mips_64(ctx);
11732 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
11733 break;
11734 #endif
11735 case M16_OPC_RRIA:
11737 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
11739 if ((ctx->opcode >> 4) & 1) {
11740 #if defined(TARGET_MIPS64)
11741 check_insn(ctx, ISA_MIPS3);
11742 check_mips_64(ctx);
11743 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11744 #else
11745 generate_exception_end(ctx, EXCP_RI);
11746 #endif
11747 } else {
11748 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11751 break;
11752 case M16_OPC_ADDIU8:
11754 int16_t imm = (int8_t) ctx->opcode;
11756 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11758 break;
11759 case M16_OPC_SLTI:
11761 int16_t imm = (uint8_t) ctx->opcode;
11762 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11764 break;
11765 case M16_OPC_SLTIU:
11767 int16_t imm = (uint8_t) ctx->opcode;
11768 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11770 break;
11771 case M16_OPC_I8:
11773 int reg32;
11775 funct = (ctx->opcode >> 8) & 0x7;
11776 switch (funct) {
11777 case I8_BTEQZ:
11778 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
11779 ((int8_t)ctx->opcode) << 1, 0);
11780 break;
11781 case I8_BTNEZ:
11782 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
11783 ((int8_t)ctx->opcode) << 1, 0);
11784 break;
11785 case I8_SWRASP:
11786 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
11787 break;
11788 case I8_ADJSP:
11789 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
11790 ((int8_t)ctx->opcode) << 3);
11791 break;
11792 case I8_SVRS:
11793 check_insn(ctx, ISA_MIPS32);
11795 int do_ra = ctx->opcode & (1 << 6);
11796 int do_s0 = ctx->opcode & (1 << 5);
11797 int do_s1 = ctx->opcode & (1 << 4);
11798 int framesize = ctx->opcode & 0xf;
11800 if (framesize == 0) {
11801 framesize = 128;
11802 } else {
11803 framesize = framesize << 3;
11806 if (ctx->opcode & (1 << 7)) {
11807 gen_mips16_save(ctx, 0, 0,
11808 do_ra, do_s0, do_s1, framesize);
11809 } else {
11810 gen_mips16_restore(ctx, 0, 0,
11811 do_ra, do_s0, do_s1, framesize);
11814 break;
11815 case I8_MOV32R:
11817 int rz = xlat(ctx->opcode & 0x7);
11819 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
11820 ((ctx->opcode >> 5) & 0x7);
11821 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
11823 break;
11824 case I8_MOVR32:
11825 reg32 = ctx->opcode & 0x1f;
11826 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
11827 break;
11828 default:
11829 generate_exception_end(ctx, EXCP_RI);
11830 break;
11833 break;
11834 case M16_OPC_LI:
11836 int16_t imm = (uint8_t) ctx->opcode;
11838 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
11840 break;
11841 case M16_OPC_CMPI:
11843 int16_t imm = (uint8_t) ctx->opcode;
11844 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
11846 break;
11847 #if defined(TARGET_MIPS64)
11848 case M16_OPC_SD:
11849 check_insn(ctx, ISA_MIPS3);
11850 check_mips_64(ctx);
11851 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
11852 break;
11853 #endif
11854 case M16_OPC_LB:
11855 gen_ld(ctx, OPC_LB, ry, rx, offset);
11856 break;
11857 case M16_OPC_LH:
11858 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
11859 break;
11860 case M16_OPC_LWSP:
11861 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11862 break;
11863 case M16_OPC_LW:
11864 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
11865 break;
11866 case M16_OPC_LBU:
11867 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11868 break;
11869 case M16_OPC_LHU:
11870 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
11871 break;
11872 case M16_OPC_LWPC:
11873 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
11874 break;
11875 #if defined (TARGET_MIPS64)
11876 case M16_OPC_LWU:
11877 check_insn(ctx, ISA_MIPS3);
11878 check_mips_64(ctx);
11879 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
11880 break;
11881 #endif
11882 case M16_OPC_SB:
11883 gen_st(ctx, OPC_SB, ry, rx, offset);
11884 break;
11885 case M16_OPC_SH:
11886 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
11887 break;
11888 case M16_OPC_SWSP:
11889 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11890 break;
11891 case M16_OPC_SW:
11892 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
11893 break;
11894 case M16_OPC_RRR:
11896 int rz = xlat((ctx->opcode >> 2) & 0x7);
11897 int mips32_op;
11899 switch (ctx->opcode & 0x3) {
11900 case RRR_ADDU:
11901 mips32_op = OPC_ADDU;
11902 break;
11903 case RRR_SUBU:
11904 mips32_op = OPC_SUBU;
11905 break;
11906 #if defined(TARGET_MIPS64)
11907 case RRR_DADDU:
11908 mips32_op = OPC_DADDU;
11909 check_insn(ctx, ISA_MIPS3);
11910 check_mips_64(ctx);
11911 break;
11912 case RRR_DSUBU:
11913 mips32_op = OPC_DSUBU;
11914 check_insn(ctx, ISA_MIPS3);
11915 check_mips_64(ctx);
11916 break;
11917 #endif
11918 default:
11919 generate_exception_end(ctx, EXCP_RI);
11920 goto done;
11923 gen_arith(ctx, mips32_op, rz, rx, ry);
11924 done:
11927 break;
11928 case M16_OPC_RR:
11929 switch (op1) {
11930 case RR_JR:
11932 int nd = (ctx->opcode >> 7) & 0x1;
11933 int link = (ctx->opcode >> 6) & 0x1;
11934 int ra = (ctx->opcode >> 5) & 0x1;
11936 if (nd) {
11937 check_insn(ctx, ISA_MIPS32);
11940 if (link) {
11941 op = OPC_JALR;
11942 } else {
11943 op = OPC_JR;
11946 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
11947 (nd ? 0 : 2));
11949 break;
11950 case RR_SDBBP:
11951 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
11952 gen_helper_do_semihosting(cpu_env);
11953 } else {
11954 /* XXX: not clear which exception should be raised
11955 * when in debug mode...
11957 check_insn(ctx, ISA_MIPS32);
11958 generate_exception_end(ctx, EXCP_DBp);
11960 break;
11961 case RR_SLT:
11962 gen_slt(ctx, OPC_SLT, 24, rx, ry);
11963 break;
11964 case RR_SLTU:
11965 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
11966 break;
11967 case RR_BREAK:
11968 generate_exception_end(ctx, EXCP_BREAK);
11969 break;
11970 case RR_SLLV:
11971 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
11972 break;
11973 case RR_SRLV:
11974 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
11975 break;
11976 case RR_SRAV:
11977 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
11978 break;
11979 #if defined (TARGET_MIPS64)
11980 case RR_DSRL:
11981 check_insn(ctx, ISA_MIPS3);
11982 check_mips_64(ctx);
11983 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
11984 break;
11985 #endif
11986 case RR_CMP:
11987 gen_logic(ctx, OPC_XOR, 24, rx, ry);
11988 break;
11989 case RR_NEG:
11990 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
11991 break;
11992 case RR_AND:
11993 gen_logic(ctx, OPC_AND, rx, rx, ry);
11994 break;
11995 case RR_OR:
11996 gen_logic(ctx, OPC_OR, rx, rx, ry);
11997 break;
11998 case RR_XOR:
11999 gen_logic(ctx, OPC_XOR, rx, rx, ry);
12000 break;
12001 case RR_NOT:
12002 gen_logic(ctx, OPC_NOR, rx, ry, 0);
12003 break;
12004 case RR_MFHI:
12005 gen_HILO(ctx, OPC_MFHI, 0, rx);
12006 break;
12007 case RR_CNVT:
12008 check_insn(ctx, ISA_MIPS32);
12009 switch (cnvt_op) {
12010 case RR_RY_CNVT_ZEB:
12011 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12012 break;
12013 case RR_RY_CNVT_ZEH:
12014 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12015 break;
12016 case RR_RY_CNVT_SEB:
12017 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12018 break;
12019 case RR_RY_CNVT_SEH:
12020 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12021 break;
12022 #if defined (TARGET_MIPS64)
12023 case RR_RY_CNVT_ZEW:
12024 check_insn(ctx, ISA_MIPS64);
12025 check_mips_64(ctx);
12026 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12027 break;
12028 case RR_RY_CNVT_SEW:
12029 check_insn(ctx, ISA_MIPS64);
12030 check_mips_64(ctx);
12031 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12032 break;
12033 #endif
12034 default:
12035 generate_exception_end(ctx, EXCP_RI);
12036 break;
12038 break;
12039 case RR_MFLO:
12040 gen_HILO(ctx, OPC_MFLO, 0, rx);
12041 break;
12042 #if defined (TARGET_MIPS64)
12043 case RR_DSRA:
12044 check_insn(ctx, ISA_MIPS3);
12045 check_mips_64(ctx);
12046 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
12047 break;
12048 case RR_DSLLV:
12049 check_insn(ctx, ISA_MIPS3);
12050 check_mips_64(ctx);
12051 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
12052 break;
12053 case RR_DSRLV:
12054 check_insn(ctx, ISA_MIPS3);
12055 check_mips_64(ctx);
12056 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
12057 break;
12058 case RR_DSRAV:
12059 check_insn(ctx, ISA_MIPS3);
12060 check_mips_64(ctx);
12061 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
12062 break;
12063 #endif
12064 case RR_MULT:
12065 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
12066 break;
12067 case RR_MULTU:
12068 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
12069 break;
12070 case RR_DIV:
12071 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
12072 break;
12073 case RR_DIVU:
12074 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
12075 break;
12076 #if defined (TARGET_MIPS64)
12077 case RR_DMULT:
12078 check_insn(ctx, ISA_MIPS3);
12079 check_mips_64(ctx);
12080 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
12081 break;
12082 case RR_DMULTU:
12083 check_insn(ctx, ISA_MIPS3);
12084 check_mips_64(ctx);
12085 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
12086 break;
12087 case RR_DDIV:
12088 check_insn(ctx, ISA_MIPS3);
12089 check_mips_64(ctx);
12090 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
12091 break;
12092 case RR_DDIVU:
12093 check_insn(ctx, ISA_MIPS3);
12094 check_mips_64(ctx);
12095 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
12096 break;
12097 #endif
12098 default:
12099 generate_exception_end(ctx, EXCP_RI);
12100 break;
12102 break;
12103 case M16_OPC_EXTEND:
12104 decode_extended_mips16_opc(env, ctx);
12105 n_bytes = 4;
12106 break;
12107 #if defined(TARGET_MIPS64)
12108 case M16_OPC_I64:
12109 funct = (ctx->opcode >> 8) & 0x7;
12110 decode_i64_mips16(ctx, ry, funct, offset, 0);
12111 break;
12112 #endif
12113 default:
12114 generate_exception_end(ctx, EXCP_RI);
12115 break;
12118 return n_bytes;
12121 /* microMIPS extension to MIPS32/MIPS64 */
12124 * microMIPS32/microMIPS64 major opcodes
12126 * 1. MIPS Architecture for Programmers Volume II-B:
12127 * The microMIPS32 Instruction Set (Revision 3.05)
12129 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12131 * 2. MIPS Architecture For Programmers Volume II-A:
12132 * The MIPS64 Instruction Set (Revision 3.51)
12135 enum {
12136 POOL32A = 0x00,
12137 POOL16A = 0x01,
12138 LBU16 = 0x02,
12139 MOVE16 = 0x03,
12140 ADDI32 = 0x04,
12141 R6_LUI = 0x04,
12142 AUI = 0x04,
12143 LBU32 = 0x05,
12144 SB32 = 0x06,
12145 LB32 = 0x07,
12147 POOL32B = 0x08,
12148 POOL16B = 0x09,
12149 LHU16 = 0x0a,
12150 ANDI16 = 0x0b,
12151 ADDIU32 = 0x0c,
12152 LHU32 = 0x0d,
12153 SH32 = 0x0e,
12154 LH32 = 0x0f,
12156 POOL32I = 0x10,
12157 POOL16C = 0x11,
12158 LWSP16 = 0x12,
12159 POOL16D = 0x13,
12160 ORI32 = 0x14,
12161 POOL32F = 0x15,
12162 POOL32S = 0x16, /* MIPS64 */
12163 DADDIU32 = 0x17, /* MIPS64 */
12165 POOL32C = 0x18,
12166 LWGP16 = 0x19,
12167 LW16 = 0x1a,
12168 POOL16E = 0x1b,
12169 XORI32 = 0x1c,
12170 JALS32 = 0x1d,
12171 BOVC = 0x1d,
12172 BEQC = 0x1d,
12173 BEQZALC = 0x1d,
12174 ADDIUPC = 0x1e,
12175 PCREL = 0x1e,
12176 BNVC = 0x1f,
12177 BNEC = 0x1f,
12178 BNEZALC = 0x1f,
12180 R6_BEQZC = 0x20,
12181 JIC = 0x20,
12182 POOL16F = 0x21,
12183 SB16 = 0x22,
12184 BEQZ16 = 0x23,
12185 BEQZC16 = 0x23,
12186 SLTI32 = 0x24,
12187 BEQ32 = 0x25,
12188 BC = 0x25,
12189 SWC132 = 0x26,
12190 LWC132 = 0x27,
12192 /* 0x29 is reserved */
12193 RES_29 = 0x29,
12194 R6_BNEZC = 0x28,
12195 JIALC = 0x28,
12196 SH16 = 0x2a,
12197 BNEZ16 = 0x2b,
12198 BNEZC16 = 0x2b,
12199 SLTIU32 = 0x2c,
12200 BNE32 = 0x2d,
12201 BALC = 0x2d,
12202 SDC132 = 0x2e,
12203 LDC132 = 0x2f,
12205 /* 0x31 is reserved */
12206 RES_31 = 0x31,
12207 BLEZALC = 0x30,
12208 BGEZALC = 0x30,
12209 BGEUC = 0x30,
12210 SWSP16 = 0x32,
12211 B16 = 0x33,
12212 BC16 = 0x33,
12213 ANDI32 = 0x34,
12214 J32 = 0x35,
12215 BGTZC = 0x35,
12216 BLTZC = 0x35,
12217 BLTC = 0x35,
12218 SD32 = 0x36, /* MIPS64 */
12219 LD32 = 0x37, /* MIPS64 */
12221 /* 0x39 is reserved */
12222 RES_39 = 0x39,
12223 BGTZALC = 0x38,
12224 BLTZALC = 0x38,
12225 BLTUC = 0x38,
12226 SW16 = 0x3a,
12227 LI16 = 0x3b,
12228 JALX32 = 0x3c,
12229 JAL32 = 0x3d,
12230 BLEZC = 0x3d,
12231 BGEZC = 0x3d,
12232 BGEC = 0x3d,
12233 SW32 = 0x3e,
12234 LW32 = 0x3f
12237 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12238 enum {
12239 ADDIUPC_00 = 0x00,
12240 ADDIUPC_07 = 0x07,
12241 AUIPC = 0x1e,
12242 ALUIPC = 0x1f,
12243 LWPC_08 = 0x08,
12244 LWPC_0F = 0x0F,
12247 /* POOL32A encoding of minor opcode field */
12249 enum {
12250 /* These opcodes are distinguished only by bits 9..6; those bits are
12251 * what are recorded below. */
12252 SLL32 = 0x0,
12253 SRL32 = 0x1,
12254 SRA = 0x2,
12255 ROTR = 0x3,
12256 SELEQZ = 0x5,
12257 SELNEZ = 0x6,
12258 R6_RDHWR = 0x7,
12260 SLLV = 0x0,
12261 SRLV = 0x1,
12262 SRAV = 0x2,
12263 ROTRV = 0x3,
12264 ADD = 0x4,
12265 ADDU32 = 0x5,
12266 SUB = 0x6,
12267 SUBU32 = 0x7,
12268 MUL = 0x8,
12269 AND = 0x9,
12270 OR32 = 0xa,
12271 NOR = 0xb,
12272 XOR32 = 0xc,
12273 SLT = 0xd,
12274 SLTU = 0xe,
12276 MOVN = 0x0,
12277 R6_MUL = 0x0,
12278 MOVZ = 0x1,
12279 MUH = 0x1,
12280 MULU = 0x2,
12281 MUHU = 0x3,
12282 LWXS = 0x4,
12283 R6_DIV = 0x4,
12284 MOD = 0x5,
12285 R6_DIVU = 0x6,
12286 MODU = 0x7,
12288 /* The following can be distinguished by their lower 6 bits. */
12289 BREAK32 = 0x07,
12290 INS = 0x0c,
12291 LSA = 0x0f,
12292 ALIGN = 0x1f,
12293 EXT = 0x2c,
12294 POOL32AXF = 0x3c,
12295 SIGRIE = 0x3f
12298 /* POOL32AXF encoding of minor opcode field extension */
12301 * 1. MIPS Architecture for Programmers Volume II-B:
12302 * The microMIPS32 Instruction Set (Revision 3.05)
12304 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12306 * 2. MIPS Architecture for Programmers VolumeIV-e:
12307 * The MIPS DSP Application-Specific Extension
12308 * to the microMIPS32 Architecture (Revision 2.34)
12310 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12313 enum {
12314 /* bits 11..6 */
12315 TEQ = 0x00,
12316 TGE = 0x08,
12317 TGEU = 0x10,
12318 TLT = 0x20,
12319 TLTU = 0x28,
12320 TNE = 0x30,
12322 MFC0 = 0x03,
12323 MTC0 = 0x0b,
12325 /* begin of microMIPS32 DSP */
12327 /* bits 13..12 for 0x01 */
12328 MFHI_ACC = 0x0,
12329 MFLO_ACC = 0x1,
12330 MTHI_ACC = 0x2,
12331 MTLO_ACC = 0x3,
12333 /* bits 13..12 for 0x2a */
12334 MADD_ACC = 0x0,
12335 MADDU_ACC = 0x1,
12336 MSUB_ACC = 0x2,
12337 MSUBU_ACC = 0x3,
12339 /* bits 13..12 for 0x32 */
12340 MULT_ACC = 0x0,
12341 MULTU_ACC = 0x1,
12343 /* end of microMIPS32 DSP */
12345 /* bits 15..12 for 0x2c */
12346 BITSWAP = 0x0,
12347 SEB = 0x2,
12348 SEH = 0x3,
12349 CLO = 0x4,
12350 CLZ = 0x5,
12351 RDHWR = 0x6,
12352 WSBH = 0x7,
12353 MULT = 0x8,
12354 MULTU = 0x9,
12355 DIV = 0xa,
12356 DIVU = 0xb,
12357 MADD = 0xc,
12358 MADDU = 0xd,
12359 MSUB = 0xe,
12360 MSUBU = 0xf,
12362 /* bits 15..12 for 0x34 */
12363 MFC2 = 0x4,
12364 MTC2 = 0x5,
12365 MFHC2 = 0x8,
12366 MTHC2 = 0x9,
12367 CFC2 = 0xc,
12368 CTC2 = 0xd,
12370 /* bits 15..12 for 0x3c */
12371 JALR = 0x0,
12372 JR = 0x0, /* alias */
12373 JALRC = 0x0,
12374 JRC = 0x0,
12375 JALR_HB = 0x1,
12376 JALRC_HB = 0x1,
12377 JALRS = 0x4,
12378 JALRS_HB = 0x5,
12380 /* bits 15..12 for 0x05 */
12381 RDPGPR = 0xe,
12382 WRPGPR = 0xf,
12384 /* bits 15..12 for 0x0d */
12385 TLBP = 0x0,
12386 TLBR = 0x1,
12387 TLBWI = 0x2,
12388 TLBWR = 0x3,
12389 TLBINV = 0x4,
12390 TLBINVF = 0x5,
12391 WAIT = 0x9,
12392 IRET = 0xd,
12393 DERET = 0xe,
12394 ERET = 0xf,
12396 /* bits 15..12 for 0x15 */
12397 DMT = 0x0,
12398 DVPE = 0x1,
12399 EMT = 0x2,
12400 EVPE = 0x3,
12402 /* bits 15..12 for 0x1d */
12403 DI = 0x4,
12404 EI = 0x5,
12406 /* bits 15..12 for 0x2d */
12407 SYNC = 0x6,
12408 SYSCALL = 0x8,
12409 SDBBP = 0xd,
12411 /* bits 15..12 for 0x35 */
12412 MFHI32 = 0x0,
12413 MFLO32 = 0x1,
12414 MTHI32 = 0x2,
12415 MTLO32 = 0x3,
12418 /* POOL32B encoding of minor opcode field (bits 15..12) */
12420 enum {
12421 LWC2 = 0x0,
12422 LWP = 0x1,
12423 LDP = 0x4,
12424 LWM32 = 0x5,
12425 CACHE = 0x6,
12426 LDM = 0x7,
12427 SWC2 = 0x8,
12428 SWP = 0x9,
12429 SDP = 0xc,
12430 SWM32 = 0xd,
12431 SDM = 0xf
12434 /* POOL32C encoding of minor opcode field (bits 15..12) */
12436 enum {
12437 LWL = 0x0,
12438 SWL = 0x8,
12439 LWR = 0x1,
12440 SWR = 0x9,
12441 PREF = 0x2,
12442 /* 0xa is reserved */
12443 LL = 0x3,
12444 SC = 0xb,
12445 LDL = 0x4,
12446 SDL = 0xc,
12447 LDR = 0x5,
12448 SDR = 0xd,
12449 /* 0x6 is reserved */
12450 LWU = 0xe,
12451 LLD = 0x7,
12452 SCD = 0xf
12455 /* POOL32F encoding of minor opcode field (bits 5..0) */
12457 enum {
12458 /* These are the bit 7..6 values */
12459 ADD_FMT = 0x0,
12461 SUB_FMT = 0x1,
12463 MUL_FMT = 0x2,
12465 DIV_FMT = 0x3,
12467 /* These are the bit 8..6 values */
12468 MOVN_FMT = 0x0,
12469 RSQRT2_FMT = 0x0,
12470 MOVF_FMT = 0x0,
12471 RINT_FMT = 0x0,
12472 SELNEZ_FMT = 0x0,
12474 MOVZ_FMT = 0x1,
12475 LWXC1 = 0x1,
12476 MOVT_FMT = 0x1,
12477 CLASS_FMT = 0x1,
12478 SELEQZ_FMT = 0x1,
12480 PLL_PS = 0x2,
12481 SWXC1 = 0x2,
12482 SEL_FMT = 0x2,
12484 PLU_PS = 0x3,
12485 LDXC1 = 0x3,
12487 MOVN_FMT_04 = 0x4,
12488 PUL_PS = 0x4,
12489 SDXC1 = 0x4,
12490 RECIP2_FMT = 0x4,
12492 MOVZ_FMT_05 = 0x05,
12493 PUU_PS = 0x5,
12494 LUXC1 = 0x5,
12496 CVT_PS_S = 0x6,
12497 SUXC1 = 0x6,
12498 ADDR_PS = 0x6,
12499 PREFX = 0x6,
12500 MADDF_FMT = 0x6,
12502 MULR_PS = 0x7,
12503 MSUBF_FMT = 0x7,
12505 MADD_S = 0x01,
12506 MADD_D = 0x09,
12507 MADD_PS = 0x11,
12508 ALNV_PS = 0x19,
12509 MSUB_S = 0x21,
12510 MSUB_D = 0x29,
12511 MSUB_PS = 0x31,
12513 NMADD_S = 0x02,
12514 NMADD_D = 0x0a,
12515 NMADD_PS = 0x12,
12516 NMSUB_S = 0x22,
12517 NMSUB_D = 0x2a,
12518 NMSUB_PS = 0x32,
12520 MIN_FMT = 0x3,
12521 MAX_FMT = 0xb,
12522 MINA_FMT = 0x23,
12523 MAXA_FMT = 0x2b,
12524 POOL32FXF = 0x3b,
12526 CABS_COND_FMT = 0x1c, /* MIPS3D */
12527 C_COND_FMT = 0x3c,
12529 CMP_CONDN_S = 0x5,
12530 CMP_CONDN_D = 0x15
12533 /* POOL32Fxf encoding of minor opcode extension field */
12535 enum {
12536 CVT_L = 0x04,
12537 RSQRT_FMT = 0x08,
12538 FLOOR_L = 0x0c,
12539 CVT_PW_PS = 0x1c,
12540 CVT_W = 0x24,
12541 SQRT_FMT = 0x28,
12542 FLOOR_W = 0x2c,
12543 CVT_PS_PW = 0x3c,
12544 CFC1 = 0x40,
12545 RECIP_FMT = 0x48,
12546 CEIL_L = 0x4c,
12547 CTC1 = 0x60,
12548 CEIL_W = 0x6c,
12549 MFC1 = 0x80,
12550 CVT_S_PL = 0x84,
12551 TRUNC_L = 0x8c,
12552 MTC1 = 0xa0,
12553 CVT_S_PU = 0xa4,
12554 TRUNC_W = 0xac,
12555 MFHC1 = 0xc0,
12556 ROUND_L = 0xcc,
12557 MTHC1 = 0xe0,
12558 ROUND_W = 0xec,
12560 MOV_FMT = 0x01,
12561 MOVF = 0x05,
12562 ABS_FMT = 0x0d,
12563 RSQRT1_FMT = 0x1d,
12564 MOVT = 0x25,
12565 NEG_FMT = 0x2d,
12566 CVT_D = 0x4d,
12567 RECIP1_FMT = 0x5d,
12568 CVT_S = 0x6d
12571 /* POOL32I encoding of minor opcode field (bits 25..21) */
12573 enum {
12574 BLTZ = 0x00,
12575 BLTZAL = 0x01,
12576 BGEZ = 0x02,
12577 BGEZAL = 0x03,
12578 BLEZ = 0x04,
12579 BNEZC = 0x05,
12580 BGTZ = 0x06,
12581 BEQZC = 0x07,
12582 TLTI = 0x08,
12583 BC1EQZC = 0x08,
12584 TGEI = 0x09,
12585 BC1NEZC = 0x09,
12586 TLTIU = 0x0a,
12587 BC2EQZC = 0x0a,
12588 TGEIU = 0x0b,
12589 BC2NEZC = 0x0a,
12590 TNEI = 0x0c,
12591 R6_SYNCI = 0x0c,
12592 LUI = 0x0d,
12593 TEQI = 0x0e,
12594 SYNCI = 0x10,
12595 BLTZALS = 0x11,
12596 BGEZALS = 0x13,
12597 BC2F = 0x14,
12598 BC2T = 0x15,
12599 BPOSGE64 = 0x1a,
12600 BPOSGE32 = 0x1b,
12601 /* These overlap and are distinguished by bit16 of the instruction */
12602 BC1F = 0x1c,
12603 BC1T = 0x1d,
12604 BC1ANY2F = 0x1c,
12605 BC1ANY2T = 0x1d,
12606 BC1ANY4F = 0x1e,
12607 BC1ANY4T = 0x1f
12610 /* POOL16A encoding of minor opcode field */
12612 enum {
12613 ADDU16 = 0x0,
12614 SUBU16 = 0x1
12617 /* POOL16B encoding of minor opcode field */
12619 enum {
12620 SLL16 = 0x0,
12621 SRL16 = 0x1
12624 /* POOL16C encoding of minor opcode field */
12626 enum {
12627 NOT16 = 0x00,
12628 XOR16 = 0x04,
12629 AND16 = 0x08,
12630 OR16 = 0x0c,
12631 LWM16 = 0x10,
12632 SWM16 = 0x14,
12633 JR16 = 0x18,
12634 JRC16 = 0x1a,
12635 JALR16 = 0x1c,
12636 JALR16S = 0x1e,
12637 MFHI16 = 0x20,
12638 MFLO16 = 0x24,
12639 BREAK16 = 0x28,
12640 SDBBP16 = 0x2c,
12641 JRADDIUSP = 0x30
12644 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
12646 enum {
12647 R6_NOT16 = 0x00,
12648 R6_AND16 = 0x01,
12649 R6_LWM16 = 0x02,
12650 R6_JRC16 = 0x03,
12651 MOVEP = 0x04,
12652 MOVEP_07 = 0x07,
12653 R6_XOR16 = 0x08,
12654 R6_OR16 = 0x09,
12655 R6_SWM16 = 0x0a,
12656 JALRC16 = 0x0b,
12657 MOVEP_0C = 0x0c,
12658 MOVEP_0F = 0x0f,
12659 JRCADDIUSP = 0x13,
12660 R6_BREAK16 = 0x1b,
12661 R6_SDBBP16 = 0x3b
12664 /* POOL16D encoding of minor opcode field */
12666 enum {
12667 ADDIUS5 = 0x0,
12668 ADDIUSP = 0x1
12671 /* POOL16E encoding of minor opcode field */
12673 enum {
12674 ADDIUR2 = 0x0,
12675 ADDIUR1SP = 0x1
12678 static int mmreg (int r)
12680 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12682 return map[r];
12685 /* Used for 16-bit store instructions. */
12686 static int mmreg2 (int r)
12688 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12690 return map[r];
12693 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12694 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12695 #define uMIPS_RS2(op) uMIPS_RS(op)
12696 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12697 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12698 #define uMIPS_RS5(op) (op & 0x1f)
12700 /* Signed immediate */
12701 #define SIMM(op, start, width) \
12702 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12703 << (32-width)) \
12704 >> (32-width))
12705 /* Zero-extended immediate */
12706 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12708 static void gen_addiur1sp(DisasContext *ctx)
12710 int rd = mmreg(uMIPS_RD(ctx->opcode));
12712 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12715 static void gen_addiur2(DisasContext *ctx)
12717 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12718 int rd = mmreg(uMIPS_RD(ctx->opcode));
12719 int rs = mmreg(uMIPS_RS(ctx->opcode));
12721 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12724 static void gen_addiusp(DisasContext *ctx)
12726 int encoded = ZIMM(ctx->opcode, 1, 9);
12727 int decoded;
12729 if (encoded <= 1) {
12730 decoded = 256 + encoded;
12731 } else if (encoded <= 255) {
12732 decoded = encoded;
12733 } else if (encoded <= 509) {
12734 decoded = encoded - 512;
12735 } else {
12736 decoded = encoded - 768;
12739 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
12742 static void gen_addius5(DisasContext *ctx)
12744 int imm = SIMM(ctx->opcode, 1, 4);
12745 int rd = (ctx->opcode >> 5) & 0x1f;
12747 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
12750 static void gen_andi16(DisasContext *ctx)
12752 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
12753 31, 32, 63, 64, 255, 32768, 65535 };
12754 int rd = mmreg(uMIPS_RD(ctx->opcode));
12755 int rs = mmreg(uMIPS_RS(ctx->opcode));
12756 int encoded = ZIMM(ctx->opcode, 0, 4);
12758 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
12761 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
12762 int base, int16_t offset)
12764 TCGv t0, t1;
12765 TCGv_i32 t2;
12767 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12768 generate_exception_end(ctx, EXCP_RI);
12769 return;
12772 t0 = tcg_temp_new();
12774 gen_base_offset_addr(ctx, t0, base, offset);
12776 t1 = tcg_const_tl(reglist);
12777 t2 = tcg_const_i32(ctx->mem_idx);
12779 save_cpu_state(ctx, 1);
12780 switch (opc) {
12781 case LWM32:
12782 gen_helper_lwm(cpu_env, t0, t1, t2);
12783 break;
12784 case SWM32:
12785 gen_helper_swm(cpu_env, t0, t1, t2);
12786 break;
12787 #ifdef TARGET_MIPS64
12788 case LDM:
12789 gen_helper_ldm(cpu_env, t0, t1, t2);
12790 break;
12791 case SDM:
12792 gen_helper_sdm(cpu_env, t0, t1, t2);
12793 break;
12794 #endif
12796 tcg_temp_free(t0);
12797 tcg_temp_free(t1);
12798 tcg_temp_free_i32(t2);
12802 static void gen_pool16c_insn(DisasContext *ctx)
12804 int rd = mmreg((ctx->opcode >> 3) & 0x7);
12805 int rs = mmreg(ctx->opcode & 0x7);
12807 switch (((ctx->opcode) >> 4) & 0x3f) {
12808 case NOT16 + 0:
12809 case NOT16 + 1:
12810 case NOT16 + 2:
12811 case NOT16 + 3:
12812 gen_logic(ctx, OPC_NOR, rd, rs, 0);
12813 break;
12814 case XOR16 + 0:
12815 case XOR16 + 1:
12816 case XOR16 + 2:
12817 case XOR16 + 3:
12818 gen_logic(ctx, OPC_XOR, rd, rd, rs);
12819 break;
12820 case AND16 + 0:
12821 case AND16 + 1:
12822 case AND16 + 2:
12823 case AND16 + 3:
12824 gen_logic(ctx, OPC_AND, rd, rd, rs);
12825 break;
12826 case OR16 + 0:
12827 case OR16 + 1:
12828 case OR16 + 2:
12829 case OR16 + 3:
12830 gen_logic(ctx, OPC_OR, rd, rd, rs);
12831 break;
12832 case LWM16 + 0:
12833 case LWM16 + 1:
12834 case LWM16 + 2:
12835 case LWM16 + 3:
12837 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12838 int offset = ZIMM(ctx->opcode, 0, 4);
12840 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
12841 29, offset << 2);
12843 break;
12844 case SWM16 + 0:
12845 case SWM16 + 1:
12846 case SWM16 + 2:
12847 case SWM16 + 3:
12849 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12850 int offset = ZIMM(ctx->opcode, 0, 4);
12852 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
12853 29, offset << 2);
12855 break;
12856 case JR16 + 0:
12857 case JR16 + 1:
12859 int reg = ctx->opcode & 0x1f;
12861 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
12863 break;
12864 case JRC16 + 0:
12865 case JRC16 + 1:
12867 int reg = ctx->opcode & 0x1f;
12868 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
12869 /* Let normal delay slot handling in our caller take us
12870 to the branch target. */
12872 break;
12873 case JALR16 + 0:
12874 case JALR16 + 1:
12875 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
12876 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12877 break;
12878 case JALR16S + 0:
12879 case JALR16S + 1:
12880 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
12881 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12882 break;
12883 case MFHI16 + 0:
12884 case MFHI16 + 1:
12885 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
12886 break;
12887 case MFLO16 + 0:
12888 case MFLO16 + 1:
12889 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
12890 break;
12891 case BREAK16:
12892 generate_exception_end(ctx, EXCP_BREAK);
12893 break;
12894 case SDBBP16:
12895 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
12896 gen_helper_do_semihosting(cpu_env);
12897 } else {
12898 /* XXX: not clear which exception should be raised
12899 * when in debug mode...
12901 check_insn(ctx, ISA_MIPS32);
12902 generate_exception_end(ctx, EXCP_DBp);
12904 break;
12905 case JRADDIUSP + 0:
12906 case JRADDIUSP + 1:
12908 int imm = ZIMM(ctx->opcode, 0, 5);
12909 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12910 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12911 /* Let normal delay slot handling in our caller take us
12912 to the branch target. */
12914 break;
12915 default:
12916 generate_exception_end(ctx, EXCP_RI);
12917 break;
12921 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
12922 int enc_rs)
12924 int rd, rs, re, rt;
12925 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
12926 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
12927 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
12928 rd = rd_enc[enc_dest];
12929 re = re_enc[enc_dest];
12930 rs = rs_rt_enc[enc_rs];
12931 rt = rs_rt_enc[enc_rt];
12932 if (rs) {
12933 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
12934 } else {
12935 tcg_gen_movi_tl(cpu_gpr[rd], 0);
12937 if (rt) {
12938 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
12939 } else {
12940 tcg_gen_movi_tl(cpu_gpr[re], 0);
12944 static void gen_pool16c_r6_insn(DisasContext *ctx)
12946 int rt = mmreg((ctx->opcode >> 7) & 0x7);
12947 int rs = mmreg((ctx->opcode >> 4) & 0x7);
12949 switch (ctx->opcode & 0xf) {
12950 case R6_NOT16:
12951 gen_logic(ctx, OPC_NOR, rt, rs, 0);
12952 break;
12953 case R6_AND16:
12954 gen_logic(ctx, OPC_AND, rt, rt, rs);
12955 break;
12956 case R6_LWM16:
12958 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
12959 int offset = extract32(ctx->opcode, 4, 4);
12960 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
12962 break;
12963 case R6_JRC16: /* JRCADDIUSP */
12964 if ((ctx->opcode >> 4) & 1) {
12965 /* JRCADDIUSP */
12966 int imm = extract32(ctx->opcode, 5, 5);
12967 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12968 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12969 } else {
12970 /* JRC16 */
12971 int rs = extract32(ctx->opcode, 5, 5);
12972 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
12974 break;
12975 case MOVEP ... MOVEP_07:
12976 case MOVEP_0C ... MOVEP_0F:
12978 int enc_dest = uMIPS_RD(ctx->opcode);
12979 int enc_rt = uMIPS_RS2(ctx->opcode);
12980 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
12981 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
12983 break;
12984 case R6_XOR16:
12985 gen_logic(ctx, OPC_XOR, rt, rt, rs);
12986 break;
12987 case R6_OR16:
12988 gen_logic(ctx, OPC_OR, rt, rt, rs);
12989 break;
12990 case R6_SWM16:
12992 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
12993 int offset = extract32(ctx->opcode, 4, 4);
12994 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
12996 break;
12997 case JALRC16: /* BREAK16, SDBBP16 */
12998 switch (ctx->opcode & 0x3f) {
12999 case JALRC16:
13000 case JALRC16 + 0x20:
13001 /* JALRC16 */
13002 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
13003 31, 0, 0);
13004 break;
13005 case R6_BREAK16:
13006 /* BREAK16 */
13007 generate_exception(ctx, EXCP_BREAK);
13008 break;
13009 case R6_SDBBP16:
13010 /* SDBBP16 */
13011 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
13012 gen_helper_do_semihosting(cpu_env);
13013 } else {
13014 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13015 generate_exception(ctx, EXCP_RI);
13016 } else {
13017 generate_exception(ctx, EXCP_DBp);
13020 break;
13022 break;
13023 default:
13024 generate_exception(ctx, EXCP_RI);
13025 break;
13029 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
13031 TCGv t0 = tcg_temp_new();
13032 TCGv t1 = tcg_temp_new();
13034 gen_load_gpr(t0, base);
13036 if (index != 0) {
13037 gen_load_gpr(t1, index);
13038 tcg_gen_shli_tl(t1, t1, 2);
13039 gen_op_addr_add(ctx, t0, t1, t0);
13042 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13043 gen_store_gpr(t1, rd);
13045 tcg_temp_free(t0);
13046 tcg_temp_free(t1);
13049 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
13050 int base, int16_t offset)
13052 TCGv t0, t1;
13054 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
13055 generate_exception_end(ctx, EXCP_RI);
13056 return;
13059 t0 = tcg_temp_new();
13060 t1 = tcg_temp_new();
13062 gen_base_offset_addr(ctx, t0, base, offset);
13064 switch (opc) {
13065 case LWP:
13066 if (rd == base) {
13067 generate_exception_end(ctx, EXCP_RI);
13068 return;
13070 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13071 gen_store_gpr(t1, rd);
13072 tcg_gen_movi_tl(t1, 4);
13073 gen_op_addr_add(ctx, t0, t0, t1);
13074 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13075 gen_store_gpr(t1, rd+1);
13076 break;
13077 case SWP:
13078 gen_load_gpr(t1, rd);
13079 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13080 tcg_gen_movi_tl(t1, 4);
13081 gen_op_addr_add(ctx, t0, t0, t1);
13082 gen_load_gpr(t1, rd+1);
13083 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13084 break;
13085 #ifdef TARGET_MIPS64
13086 case LDP:
13087 if (rd == base) {
13088 generate_exception_end(ctx, EXCP_RI);
13089 return;
13091 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13092 gen_store_gpr(t1, rd);
13093 tcg_gen_movi_tl(t1, 8);
13094 gen_op_addr_add(ctx, t0, t0, t1);
13095 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13096 gen_store_gpr(t1, rd+1);
13097 break;
13098 case SDP:
13099 gen_load_gpr(t1, rd);
13100 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13101 tcg_gen_movi_tl(t1, 8);
13102 gen_op_addr_add(ctx, t0, t0, t1);
13103 gen_load_gpr(t1, rd+1);
13104 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13105 break;
13106 #endif
13108 tcg_temp_free(t0);
13109 tcg_temp_free(t1);
13112 static void gen_sync(int stype)
13114 TCGBar tcg_mo = TCG_BAR_SC;
13116 switch (stype) {
13117 case 0x4: /* SYNC_WMB */
13118 tcg_mo |= TCG_MO_ST_ST;
13119 break;
13120 case 0x10: /* SYNC_MB */
13121 tcg_mo |= TCG_MO_ALL;
13122 break;
13123 case 0x11: /* SYNC_ACQUIRE */
13124 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
13125 break;
13126 case 0x12: /* SYNC_RELEASE */
13127 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
13128 break;
13129 case 0x13: /* SYNC_RMB */
13130 tcg_mo |= TCG_MO_LD_LD;
13131 break;
13132 default:
13133 tcg_mo |= TCG_MO_ALL;
13134 break;
13137 tcg_gen_mb(tcg_mo);
13140 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
13142 int extension = (ctx->opcode >> 6) & 0x3f;
13143 int minor = (ctx->opcode >> 12) & 0xf;
13144 uint32_t mips32_op;
13146 switch (extension) {
13147 case TEQ:
13148 mips32_op = OPC_TEQ;
13149 goto do_trap;
13150 case TGE:
13151 mips32_op = OPC_TGE;
13152 goto do_trap;
13153 case TGEU:
13154 mips32_op = OPC_TGEU;
13155 goto do_trap;
13156 case TLT:
13157 mips32_op = OPC_TLT;
13158 goto do_trap;
13159 case TLTU:
13160 mips32_op = OPC_TLTU;
13161 goto do_trap;
13162 case TNE:
13163 mips32_op = OPC_TNE;
13164 do_trap:
13165 gen_trap(ctx, mips32_op, rs, rt, -1);
13166 break;
13167 #ifndef CONFIG_USER_ONLY
13168 case MFC0:
13169 case MFC0 + 32:
13170 check_cp0_enabled(ctx);
13171 if (rt == 0) {
13172 /* Treat as NOP. */
13173 break;
13175 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
13176 break;
13177 case MTC0:
13178 case MTC0 + 32:
13179 check_cp0_enabled(ctx);
13181 TCGv t0 = tcg_temp_new();
13183 gen_load_gpr(t0, rt);
13184 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
13185 tcg_temp_free(t0);
13187 break;
13188 #endif
13189 case 0x2a:
13190 switch (minor & 3) {
13191 case MADD_ACC:
13192 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
13193 break;
13194 case MADDU_ACC:
13195 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
13196 break;
13197 case MSUB_ACC:
13198 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
13199 break;
13200 case MSUBU_ACC:
13201 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
13202 break;
13203 default:
13204 goto pool32axf_invalid;
13206 break;
13207 case 0x32:
13208 switch (minor & 3) {
13209 case MULT_ACC:
13210 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
13211 break;
13212 case MULTU_ACC:
13213 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
13214 break;
13215 default:
13216 goto pool32axf_invalid;
13218 break;
13219 case 0x2c:
13220 switch (minor) {
13221 case BITSWAP:
13222 check_insn(ctx, ISA_MIPS32R6);
13223 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
13224 break;
13225 case SEB:
13226 gen_bshfl(ctx, OPC_SEB, rs, rt);
13227 break;
13228 case SEH:
13229 gen_bshfl(ctx, OPC_SEH, rs, rt);
13230 break;
13231 case CLO:
13232 mips32_op = OPC_CLO;
13233 goto do_cl;
13234 case CLZ:
13235 mips32_op = OPC_CLZ;
13236 do_cl:
13237 check_insn(ctx, ISA_MIPS32);
13238 gen_cl(ctx, mips32_op, rt, rs);
13239 break;
13240 case RDHWR:
13241 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13242 gen_rdhwr(ctx, rt, rs, 0);
13243 break;
13244 case WSBH:
13245 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13246 break;
13247 case MULT:
13248 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13249 mips32_op = OPC_MULT;
13250 goto do_mul;
13251 case MULTU:
13252 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13253 mips32_op = OPC_MULTU;
13254 goto do_mul;
13255 case DIV:
13256 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13257 mips32_op = OPC_DIV;
13258 goto do_div;
13259 case DIVU:
13260 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13261 mips32_op = OPC_DIVU;
13262 goto do_div;
13263 do_div:
13264 check_insn(ctx, ISA_MIPS32);
13265 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13266 break;
13267 case MADD:
13268 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13269 mips32_op = OPC_MADD;
13270 goto do_mul;
13271 case MADDU:
13272 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13273 mips32_op = OPC_MADDU;
13274 goto do_mul;
13275 case MSUB:
13276 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13277 mips32_op = OPC_MSUB;
13278 goto do_mul;
13279 case MSUBU:
13280 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13281 mips32_op = OPC_MSUBU;
13282 do_mul:
13283 check_insn(ctx, ISA_MIPS32);
13284 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13285 break;
13286 default:
13287 goto pool32axf_invalid;
13289 break;
13290 case 0x34:
13291 switch (minor) {
13292 case MFC2:
13293 case MTC2:
13294 case MFHC2:
13295 case MTHC2:
13296 case CFC2:
13297 case CTC2:
13298 generate_exception_err(ctx, EXCP_CpU, 2);
13299 break;
13300 default:
13301 goto pool32axf_invalid;
13303 break;
13304 case 0x3c:
13305 switch (minor) {
13306 case JALR: /* JALRC */
13307 case JALR_HB: /* JALRC_HB */
13308 if (ctx->insn_flags & ISA_MIPS32R6) {
13309 /* JALRC, JALRC_HB */
13310 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13311 } else {
13312 /* JALR, JALR_HB */
13313 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13314 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13316 break;
13317 case JALRS:
13318 case JALRS_HB:
13319 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13320 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13321 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13322 break;
13323 default:
13324 goto pool32axf_invalid;
13326 break;
13327 case 0x05:
13328 switch (minor) {
13329 case RDPGPR:
13330 check_cp0_enabled(ctx);
13331 check_insn(ctx, ISA_MIPS32R2);
13332 gen_load_srsgpr(rs, rt);
13333 break;
13334 case WRPGPR:
13335 check_cp0_enabled(ctx);
13336 check_insn(ctx, ISA_MIPS32R2);
13337 gen_store_srsgpr(rs, rt);
13338 break;
13339 default:
13340 goto pool32axf_invalid;
13342 break;
13343 #ifndef CONFIG_USER_ONLY
13344 case 0x0d:
13345 switch (minor) {
13346 case TLBP:
13347 mips32_op = OPC_TLBP;
13348 goto do_cp0;
13349 case TLBR:
13350 mips32_op = OPC_TLBR;
13351 goto do_cp0;
13352 case TLBWI:
13353 mips32_op = OPC_TLBWI;
13354 goto do_cp0;
13355 case TLBWR:
13356 mips32_op = OPC_TLBWR;
13357 goto do_cp0;
13358 case TLBINV:
13359 mips32_op = OPC_TLBINV;
13360 goto do_cp0;
13361 case TLBINVF:
13362 mips32_op = OPC_TLBINVF;
13363 goto do_cp0;
13364 case WAIT:
13365 mips32_op = OPC_WAIT;
13366 goto do_cp0;
13367 case DERET:
13368 mips32_op = OPC_DERET;
13369 goto do_cp0;
13370 case ERET:
13371 mips32_op = OPC_ERET;
13372 do_cp0:
13373 gen_cp0(env, ctx, mips32_op, rt, rs);
13374 break;
13375 default:
13376 goto pool32axf_invalid;
13378 break;
13379 case 0x1d:
13380 switch (minor) {
13381 case DI:
13382 check_cp0_enabled(ctx);
13384 TCGv t0 = tcg_temp_new();
13386 save_cpu_state(ctx, 1);
13387 gen_helper_di(t0, cpu_env);
13388 gen_store_gpr(t0, rs);
13389 /* Stop translation as we may have switched the execution mode */
13390 ctx->bstate = BS_STOP;
13391 tcg_temp_free(t0);
13393 break;
13394 case EI:
13395 check_cp0_enabled(ctx);
13397 TCGv t0 = tcg_temp_new();
13399 save_cpu_state(ctx, 1);
13400 gen_helper_ei(t0, cpu_env);
13401 gen_store_gpr(t0, rs);
13402 /* Stop translation as we may have switched the execution mode */
13403 ctx->bstate = BS_STOP;
13404 tcg_temp_free(t0);
13406 break;
13407 default:
13408 goto pool32axf_invalid;
13410 break;
13411 #endif
13412 case 0x2d:
13413 switch (minor) {
13414 case SYNC:
13415 gen_sync(extract32(ctx->opcode, 16, 5));
13416 break;
13417 case SYSCALL:
13418 generate_exception_end(ctx, EXCP_SYSCALL);
13419 break;
13420 case SDBBP:
13421 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
13422 gen_helper_do_semihosting(cpu_env);
13423 } else {
13424 check_insn(ctx, ISA_MIPS32);
13425 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13426 generate_exception_end(ctx, EXCP_RI);
13427 } else {
13428 generate_exception_end(ctx, EXCP_DBp);
13431 break;
13432 default:
13433 goto pool32axf_invalid;
13435 break;
13436 case 0x01:
13437 switch (minor & 3) {
13438 case MFHI_ACC:
13439 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
13440 break;
13441 case MFLO_ACC:
13442 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
13443 break;
13444 case MTHI_ACC:
13445 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
13446 break;
13447 case MTLO_ACC:
13448 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
13449 break;
13450 default:
13451 goto pool32axf_invalid;
13453 break;
13454 case 0x35:
13455 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13456 switch (minor) {
13457 case MFHI32:
13458 gen_HILO(ctx, OPC_MFHI, 0, rs);
13459 break;
13460 case MFLO32:
13461 gen_HILO(ctx, OPC_MFLO, 0, rs);
13462 break;
13463 case MTHI32:
13464 gen_HILO(ctx, OPC_MTHI, 0, rs);
13465 break;
13466 case MTLO32:
13467 gen_HILO(ctx, OPC_MTLO, 0, rs);
13468 break;
13469 default:
13470 goto pool32axf_invalid;
13472 break;
13473 default:
13474 pool32axf_invalid:
13475 MIPS_INVAL("pool32axf");
13476 generate_exception_end(ctx, EXCP_RI);
13477 break;
13481 /* Values for microMIPS fmt field. Variable-width, depending on which
13482 formats the instruction supports. */
13484 enum {
13485 FMT_SD_S = 0,
13486 FMT_SD_D = 1,
13488 FMT_SDPS_S = 0,
13489 FMT_SDPS_D = 1,
13490 FMT_SDPS_PS = 2,
13492 FMT_SWL_S = 0,
13493 FMT_SWL_W = 1,
13494 FMT_SWL_L = 2,
13496 FMT_DWL_D = 0,
13497 FMT_DWL_W = 1,
13498 FMT_DWL_L = 2
13501 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
13503 int extension = (ctx->opcode >> 6) & 0x3ff;
13504 uint32_t mips32_op;
13506 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
13507 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
13508 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
13510 switch (extension) {
13511 case FLOAT_1BIT_FMT(CFC1, 0):
13512 mips32_op = OPC_CFC1;
13513 goto do_cp1;
13514 case FLOAT_1BIT_FMT(CTC1, 0):
13515 mips32_op = OPC_CTC1;
13516 goto do_cp1;
13517 case FLOAT_1BIT_FMT(MFC1, 0):
13518 mips32_op = OPC_MFC1;
13519 goto do_cp1;
13520 case FLOAT_1BIT_FMT(MTC1, 0):
13521 mips32_op = OPC_MTC1;
13522 goto do_cp1;
13523 case FLOAT_1BIT_FMT(MFHC1, 0):
13524 mips32_op = OPC_MFHC1;
13525 goto do_cp1;
13526 case FLOAT_1BIT_FMT(MTHC1, 0):
13527 mips32_op = OPC_MTHC1;
13528 do_cp1:
13529 gen_cp1(ctx, mips32_op, rt, rs);
13530 break;
13532 /* Reciprocal square root */
13533 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
13534 mips32_op = OPC_RSQRT_S;
13535 goto do_unaryfp;
13536 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
13537 mips32_op = OPC_RSQRT_D;
13538 goto do_unaryfp;
13540 /* Square root */
13541 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
13542 mips32_op = OPC_SQRT_S;
13543 goto do_unaryfp;
13544 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
13545 mips32_op = OPC_SQRT_D;
13546 goto do_unaryfp;
13548 /* Reciprocal */
13549 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
13550 mips32_op = OPC_RECIP_S;
13551 goto do_unaryfp;
13552 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
13553 mips32_op = OPC_RECIP_D;
13554 goto do_unaryfp;
13556 /* Floor */
13557 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
13558 mips32_op = OPC_FLOOR_L_S;
13559 goto do_unaryfp;
13560 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
13561 mips32_op = OPC_FLOOR_L_D;
13562 goto do_unaryfp;
13563 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
13564 mips32_op = OPC_FLOOR_W_S;
13565 goto do_unaryfp;
13566 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
13567 mips32_op = OPC_FLOOR_W_D;
13568 goto do_unaryfp;
13570 /* Ceiling */
13571 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
13572 mips32_op = OPC_CEIL_L_S;
13573 goto do_unaryfp;
13574 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
13575 mips32_op = OPC_CEIL_L_D;
13576 goto do_unaryfp;
13577 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
13578 mips32_op = OPC_CEIL_W_S;
13579 goto do_unaryfp;
13580 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
13581 mips32_op = OPC_CEIL_W_D;
13582 goto do_unaryfp;
13584 /* Truncation */
13585 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
13586 mips32_op = OPC_TRUNC_L_S;
13587 goto do_unaryfp;
13588 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
13589 mips32_op = OPC_TRUNC_L_D;
13590 goto do_unaryfp;
13591 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
13592 mips32_op = OPC_TRUNC_W_S;
13593 goto do_unaryfp;
13594 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
13595 mips32_op = OPC_TRUNC_W_D;
13596 goto do_unaryfp;
13598 /* Round */
13599 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
13600 mips32_op = OPC_ROUND_L_S;
13601 goto do_unaryfp;
13602 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
13603 mips32_op = OPC_ROUND_L_D;
13604 goto do_unaryfp;
13605 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
13606 mips32_op = OPC_ROUND_W_S;
13607 goto do_unaryfp;
13608 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
13609 mips32_op = OPC_ROUND_W_D;
13610 goto do_unaryfp;
13612 /* Integer to floating-point conversion */
13613 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
13614 mips32_op = OPC_CVT_L_S;
13615 goto do_unaryfp;
13616 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
13617 mips32_op = OPC_CVT_L_D;
13618 goto do_unaryfp;
13619 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
13620 mips32_op = OPC_CVT_W_S;
13621 goto do_unaryfp;
13622 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
13623 mips32_op = OPC_CVT_W_D;
13624 goto do_unaryfp;
13626 /* Paired-foo conversions */
13627 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
13628 mips32_op = OPC_CVT_S_PL;
13629 goto do_unaryfp;
13630 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13631 mips32_op = OPC_CVT_S_PU;
13632 goto do_unaryfp;
13633 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13634 mips32_op = OPC_CVT_PW_PS;
13635 goto do_unaryfp;
13636 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13637 mips32_op = OPC_CVT_PS_PW;
13638 goto do_unaryfp;
13640 /* Floating-point moves */
13641 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13642 mips32_op = OPC_MOV_S;
13643 goto do_unaryfp;
13644 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13645 mips32_op = OPC_MOV_D;
13646 goto do_unaryfp;
13647 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13648 mips32_op = OPC_MOV_PS;
13649 goto do_unaryfp;
13651 /* Absolute value */
13652 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13653 mips32_op = OPC_ABS_S;
13654 goto do_unaryfp;
13655 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13656 mips32_op = OPC_ABS_D;
13657 goto do_unaryfp;
13658 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13659 mips32_op = OPC_ABS_PS;
13660 goto do_unaryfp;
13662 /* Negation */
13663 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13664 mips32_op = OPC_NEG_S;
13665 goto do_unaryfp;
13666 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13667 mips32_op = OPC_NEG_D;
13668 goto do_unaryfp;
13669 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13670 mips32_op = OPC_NEG_PS;
13671 goto do_unaryfp;
13673 /* Reciprocal square root step */
13674 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13675 mips32_op = OPC_RSQRT1_S;
13676 goto do_unaryfp;
13677 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13678 mips32_op = OPC_RSQRT1_D;
13679 goto do_unaryfp;
13680 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13681 mips32_op = OPC_RSQRT1_PS;
13682 goto do_unaryfp;
13684 /* Reciprocal step */
13685 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13686 mips32_op = OPC_RECIP1_S;
13687 goto do_unaryfp;
13688 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13689 mips32_op = OPC_RECIP1_S;
13690 goto do_unaryfp;
13691 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13692 mips32_op = OPC_RECIP1_PS;
13693 goto do_unaryfp;
13695 /* Conversions from double */
13696 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13697 mips32_op = OPC_CVT_D_S;
13698 goto do_unaryfp;
13699 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13700 mips32_op = OPC_CVT_D_W;
13701 goto do_unaryfp;
13702 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13703 mips32_op = OPC_CVT_D_L;
13704 goto do_unaryfp;
13706 /* Conversions from single */
13707 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13708 mips32_op = OPC_CVT_S_D;
13709 goto do_unaryfp;
13710 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13711 mips32_op = OPC_CVT_S_W;
13712 goto do_unaryfp;
13713 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13714 mips32_op = OPC_CVT_S_L;
13715 do_unaryfp:
13716 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13717 break;
13719 /* Conditional moves on floating-point codes */
13720 case COND_FLOAT_MOV(MOVT, 0):
13721 case COND_FLOAT_MOV(MOVT, 1):
13722 case COND_FLOAT_MOV(MOVT, 2):
13723 case COND_FLOAT_MOV(MOVT, 3):
13724 case COND_FLOAT_MOV(MOVT, 4):
13725 case COND_FLOAT_MOV(MOVT, 5):
13726 case COND_FLOAT_MOV(MOVT, 6):
13727 case COND_FLOAT_MOV(MOVT, 7):
13728 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13729 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13730 break;
13731 case COND_FLOAT_MOV(MOVF, 0):
13732 case COND_FLOAT_MOV(MOVF, 1):
13733 case COND_FLOAT_MOV(MOVF, 2):
13734 case COND_FLOAT_MOV(MOVF, 3):
13735 case COND_FLOAT_MOV(MOVF, 4):
13736 case COND_FLOAT_MOV(MOVF, 5):
13737 case COND_FLOAT_MOV(MOVF, 6):
13738 case COND_FLOAT_MOV(MOVF, 7):
13739 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13740 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13741 break;
13742 default:
13743 MIPS_INVAL("pool32fxf");
13744 generate_exception_end(ctx, EXCP_RI);
13745 break;
13749 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
13751 int32_t offset;
13752 uint16_t insn;
13753 int rt, rs, rd, rr;
13754 int16_t imm;
13755 uint32_t op, minor, mips32_op;
13756 uint32_t cond, fmt, cc;
13758 insn = cpu_lduw_code(env, ctx->pc + 2);
13759 ctx->opcode = (ctx->opcode << 16) | insn;
13761 rt = (ctx->opcode >> 21) & 0x1f;
13762 rs = (ctx->opcode >> 16) & 0x1f;
13763 rd = (ctx->opcode >> 11) & 0x1f;
13764 rr = (ctx->opcode >> 6) & 0x1f;
13765 imm = (int16_t) ctx->opcode;
13767 op = (ctx->opcode >> 26) & 0x3f;
13768 switch (op) {
13769 case POOL32A:
13770 minor = ctx->opcode & 0x3f;
13771 switch (minor) {
13772 case 0x00:
13773 minor = (ctx->opcode >> 6) & 0xf;
13774 switch (minor) {
13775 case SLL32:
13776 mips32_op = OPC_SLL;
13777 goto do_shifti;
13778 case SRA:
13779 mips32_op = OPC_SRA;
13780 goto do_shifti;
13781 case SRL32:
13782 mips32_op = OPC_SRL;
13783 goto do_shifti;
13784 case ROTR:
13785 mips32_op = OPC_ROTR;
13786 do_shifti:
13787 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
13788 break;
13789 case SELEQZ:
13790 check_insn(ctx, ISA_MIPS32R6);
13791 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
13792 break;
13793 case SELNEZ:
13794 check_insn(ctx, ISA_MIPS32R6);
13795 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
13796 break;
13797 case R6_RDHWR:
13798 check_insn(ctx, ISA_MIPS32R6);
13799 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
13800 break;
13801 default:
13802 goto pool32a_invalid;
13804 break;
13805 case 0x10:
13806 minor = (ctx->opcode >> 6) & 0xf;
13807 switch (minor) {
13808 /* Arithmetic */
13809 case ADD:
13810 mips32_op = OPC_ADD;
13811 goto do_arith;
13812 case ADDU32:
13813 mips32_op = OPC_ADDU;
13814 goto do_arith;
13815 case SUB:
13816 mips32_op = OPC_SUB;
13817 goto do_arith;
13818 case SUBU32:
13819 mips32_op = OPC_SUBU;
13820 goto do_arith;
13821 case MUL:
13822 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13823 mips32_op = OPC_MUL;
13824 do_arith:
13825 gen_arith(ctx, mips32_op, rd, rs, rt);
13826 break;
13827 /* Shifts */
13828 case SLLV:
13829 mips32_op = OPC_SLLV;
13830 goto do_shift;
13831 case SRLV:
13832 mips32_op = OPC_SRLV;
13833 goto do_shift;
13834 case SRAV:
13835 mips32_op = OPC_SRAV;
13836 goto do_shift;
13837 case ROTRV:
13838 mips32_op = OPC_ROTRV;
13839 do_shift:
13840 gen_shift(ctx, mips32_op, rd, rs, rt);
13841 break;
13842 /* Logical operations */
13843 case AND:
13844 mips32_op = OPC_AND;
13845 goto do_logic;
13846 case OR32:
13847 mips32_op = OPC_OR;
13848 goto do_logic;
13849 case NOR:
13850 mips32_op = OPC_NOR;
13851 goto do_logic;
13852 case XOR32:
13853 mips32_op = OPC_XOR;
13854 do_logic:
13855 gen_logic(ctx, mips32_op, rd, rs, rt);
13856 break;
13857 /* Set less than */
13858 case SLT:
13859 mips32_op = OPC_SLT;
13860 goto do_slt;
13861 case SLTU:
13862 mips32_op = OPC_SLTU;
13863 do_slt:
13864 gen_slt(ctx, mips32_op, rd, rs, rt);
13865 break;
13866 default:
13867 goto pool32a_invalid;
13869 break;
13870 case 0x18:
13871 minor = (ctx->opcode >> 6) & 0xf;
13872 switch (minor) {
13873 /* Conditional moves */
13874 case MOVN: /* MUL */
13875 if (ctx->insn_flags & ISA_MIPS32R6) {
13876 /* MUL */
13877 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
13878 } else {
13879 /* MOVN */
13880 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
13882 break;
13883 case MOVZ: /* MUH */
13884 if (ctx->insn_flags & ISA_MIPS32R6) {
13885 /* MUH */
13886 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
13887 } else {
13888 /* MOVZ */
13889 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
13891 break;
13892 case MULU:
13893 check_insn(ctx, ISA_MIPS32R6);
13894 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
13895 break;
13896 case MUHU:
13897 check_insn(ctx, ISA_MIPS32R6);
13898 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
13899 break;
13900 case LWXS: /* DIV */
13901 if (ctx->insn_flags & ISA_MIPS32R6) {
13902 /* DIV */
13903 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
13904 } else {
13905 /* LWXS */
13906 gen_ldxs(ctx, rs, rt, rd);
13908 break;
13909 case MOD:
13910 check_insn(ctx, ISA_MIPS32R6);
13911 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
13912 break;
13913 case R6_DIVU:
13914 check_insn(ctx, ISA_MIPS32R6);
13915 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
13916 break;
13917 case MODU:
13918 check_insn(ctx, ISA_MIPS32R6);
13919 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
13920 break;
13921 default:
13922 goto pool32a_invalid;
13924 break;
13925 case INS:
13926 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
13927 return;
13928 case LSA:
13929 check_insn(ctx, ISA_MIPS32R6);
13930 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
13931 extract32(ctx->opcode, 9, 2));
13932 break;
13933 case ALIGN:
13934 check_insn(ctx, ISA_MIPS32R6);
13935 gen_align(ctx, OPC_ALIGN, rd, rs, rt,
13936 extract32(ctx->opcode, 9, 2));
13937 break;
13938 case EXT:
13939 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
13940 return;
13941 case POOL32AXF:
13942 gen_pool32axf(env, ctx, rt, rs);
13943 break;
13944 case BREAK32:
13945 generate_exception_end(ctx, EXCP_BREAK);
13946 break;
13947 case SIGRIE:
13948 check_insn(ctx, ISA_MIPS32R6);
13949 generate_exception_end(ctx, EXCP_RI);
13950 break;
13951 default:
13952 pool32a_invalid:
13953 MIPS_INVAL("pool32a");
13954 generate_exception_end(ctx, EXCP_RI);
13955 break;
13957 break;
13958 case POOL32B:
13959 minor = (ctx->opcode >> 12) & 0xf;
13960 switch (minor) {
13961 case CACHE:
13962 check_cp0_enabled(ctx);
13963 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
13964 gen_cache_operation(ctx, rt, rs, imm);
13966 break;
13967 case LWC2:
13968 case SWC2:
13969 /* COP2: Not implemented. */
13970 generate_exception_err(ctx, EXCP_CpU, 2);
13971 break;
13972 #ifdef TARGET_MIPS64
13973 case LDP:
13974 case SDP:
13975 check_insn(ctx, ISA_MIPS3);
13976 check_mips_64(ctx);
13977 /* Fallthrough */
13978 #endif
13979 case LWP:
13980 case SWP:
13981 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13982 break;
13983 #ifdef TARGET_MIPS64
13984 case LDM:
13985 case SDM:
13986 check_insn(ctx, ISA_MIPS3);
13987 check_mips_64(ctx);
13988 /* Fallthrough */
13989 #endif
13990 case LWM32:
13991 case SWM32:
13992 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13993 break;
13994 default:
13995 MIPS_INVAL("pool32b");
13996 generate_exception_end(ctx, EXCP_RI);
13997 break;
13999 break;
14000 case POOL32F:
14001 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14002 minor = ctx->opcode & 0x3f;
14003 check_cp1_enabled(ctx);
14004 switch (minor) {
14005 case ALNV_PS:
14006 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14007 mips32_op = OPC_ALNV_PS;
14008 goto do_madd;
14009 case MADD_S:
14010 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14011 mips32_op = OPC_MADD_S;
14012 goto do_madd;
14013 case MADD_D:
14014 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14015 mips32_op = OPC_MADD_D;
14016 goto do_madd;
14017 case MADD_PS:
14018 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14019 mips32_op = OPC_MADD_PS;
14020 goto do_madd;
14021 case MSUB_S:
14022 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14023 mips32_op = OPC_MSUB_S;
14024 goto do_madd;
14025 case MSUB_D:
14026 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14027 mips32_op = OPC_MSUB_D;
14028 goto do_madd;
14029 case MSUB_PS:
14030 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14031 mips32_op = OPC_MSUB_PS;
14032 goto do_madd;
14033 case NMADD_S:
14034 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14035 mips32_op = OPC_NMADD_S;
14036 goto do_madd;
14037 case NMADD_D:
14038 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14039 mips32_op = OPC_NMADD_D;
14040 goto do_madd;
14041 case NMADD_PS:
14042 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14043 mips32_op = OPC_NMADD_PS;
14044 goto do_madd;
14045 case NMSUB_S:
14046 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14047 mips32_op = OPC_NMSUB_S;
14048 goto do_madd;
14049 case NMSUB_D:
14050 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14051 mips32_op = OPC_NMSUB_D;
14052 goto do_madd;
14053 case NMSUB_PS:
14054 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14055 mips32_op = OPC_NMSUB_PS;
14056 do_madd:
14057 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
14058 break;
14059 case CABS_COND_FMT:
14060 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14061 cond = (ctx->opcode >> 6) & 0xf;
14062 cc = (ctx->opcode >> 13) & 0x7;
14063 fmt = (ctx->opcode >> 10) & 0x3;
14064 switch (fmt) {
14065 case 0x0:
14066 gen_cmpabs_s(ctx, cond, rt, rs, cc);
14067 break;
14068 case 0x1:
14069 gen_cmpabs_d(ctx, cond, rt, rs, cc);
14070 break;
14071 case 0x2:
14072 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
14073 break;
14074 default:
14075 goto pool32f_invalid;
14077 break;
14078 case C_COND_FMT:
14079 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14080 cond = (ctx->opcode >> 6) & 0xf;
14081 cc = (ctx->opcode >> 13) & 0x7;
14082 fmt = (ctx->opcode >> 10) & 0x3;
14083 switch (fmt) {
14084 case 0x0:
14085 gen_cmp_s(ctx, cond, rt, rs, cc);
14086 break;
14087 case 0x1:
14088 gen_cmp_d(ctx, cond, rt, rs, cc);
14089 break;
14090 case 0x2:
14091 gen_cmp_ps(ctx, cond, rt, rs, cc);
14092 break;
14093 default:
14094 goto pool32f_invalid;
14096 break;
14097 case CMP_CONDN_S:
14098 check_insn(ctx, ISA_MIPS32R6);
14099 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14100 break;
14101 case CMP_CONDN_D:
14102 check_insn(ctx, ISA_MIPS32R6);
14103 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14104 break;
14105 case POOL32FXF:
14106 gen_pool32fxf(ctx, rt, rs);
14107 break;
14108 case 0x00:
14109 /* PLL foo */
14110 switch ((ctx->opcode >> 6) & 0x7) {
14111 case PLL_PS:
14112 mips32_op = OPC_PLL_PS;
14113 goto do_ps;
14114 case PLU_PS:
14115 mips32_op = OPC_PLU_PS;
14116 goto do_ps;
14117 case PUL_PS:
14118 mips32_op = OPC_PUL_PS;
14119 goto do_ps;
14120 case PUU_PS:
14121 mips32_op = OPC_PUU_PS;
14122 goto do_ps;
14123 case CVT_PS_S:
14124 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14125 mips32_op = OPC_CVT_PS_S;
14126 do_ps:
14127 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14128 break;
14129 default:
14130 goto pool32f_invalid;
14132 break;
14133 case MIN_FMT:
14134 check_insn(ctx, ISA_MIPS32R6);
14135 switch ((ctx->opcode >> 9) & 0x3) {
14136 case FMT_SDPS_S:
14137 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
14138 break;
14139 case FMT_SDPS_D:
14140 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
14141 break;
14142 default:
14143 goto pool32f_invalid;
14145 break;
14146 case 0x08:
14147 /* [LS][WDU]XC1 */
14148 switch ((ctx->opcode >> 6) & 0x7) {
14149 case LWXC1:
14150 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14151 mips32_op = OPC_LWXC1;
14152 goto do_ldst_cp1;
14153 case SWXC1:
14154 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14155 mips32_op = OPC_SWXC1;
14156 goto do_ldst_cp1;
14157 case LDXC1:
14158 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14159 mips32_op = OPC_LDXC1;
14160 goto do_ldst_cp1;
14161 case SDXC1:
14162 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14163 mips32_op = OPC_SDXC1;
14164 goto do_ldst_cp1;
14165 case LUXC1:
14166 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14167 mips32_op = OPC_LUXC1;
14168 goto do_ldst_cp1;
14169 case SUXC1:
14170 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14171 mips32_op = OPC_SUXC1;
14172 do_ldst_cp1:
14173 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
14174 break;
14175 default:
14176 goto pool32f_invalid;
14178 break;
14179 case MAX_FMT:
14180 check_insn(ctx, ISA_MIPS32R6);
14181 switch ((ctx->opcode >> 9) & 0x3) {
14182 case FMT_SDPS_S:
14183 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
14184 break;
14185 case FMT_SDPS_D:
14186 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
14187 break;
14188 default:
14189 goto pool32f_invalid;
14191 break;
14192 case 0x18:
14193 /* 3D insns */
14194 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14195 fmt = (ctx->opcode >> 9) & 0x3;
14196 switch ((ctx->opcode >> 6) & 0x7) {
14197 case RSQRT2_FMT:
14198 switch (fmt) {
14199 case FMT_SDPS_S:
14200 mips32_op = OPC_RSQRT2_S;
14201 goto do_3d;
14202 case FMT_SDPS_D:
14203 mips32_op = OPC_RSQRT2_D;
14204 goto do_3d;
14205 case FMT_SDPS_PS:
14206 mips32_op = OPC_RSQRT2_PS;
14207 goto do_3d;
14208 default:
14209 goto pool32f_invalid;
14211 break;
14212 case RECIP2_FMT:
14213 switch (fmt) {
14214 case FMT_SDPS_S:
14215 mips32_op = OPC_RECIP2_S;
14216 goto do_3d;
14217 case FMT_SDPS_D:
14218 mips32_op = OPC_RECIP2_D;
14219 goto do_3d;
14220 case FMT_SDPS_PS:
14221 mips32_op = OPC_RECIP2_PS;
14222 goto do_3d;
14223 default:
14224 goto pool32f_invalid;
14226 break;
14227 case ADDR_PS:
14228 mips32_op = OPC_ADDR_PS;
14229 goto do_3d;
14230 case MULR_PS:
14231 mips32_op = OPC_MULR_PS;
14232 do_3d:
14233 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14234 break;
14235 default:
14236 goto pool32f_invalid;
14238 break;
14239 case 0x20:
14240 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
14241 cc = (ctx->opcode >> 13) & 0x7;
14242 fmt = (ctx->opcode >> 9) & 0x3;
14243 switch ((ctx->opcode >> 6) & 0x7) {
14244 case MOVF_FMT: /* RINT_FMT */
14245 if (ctx->insn_flags & ISA_MIPS32R6) {
14246 /* RINT_FMT */
14247 switch (fmt) {
14248 case FMT_SDPS_S:
14249 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14250 break;
14251 case FMT_SDPS_D:
14252 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14253 break;
14254 default:
14255 goto pool32f_invalid;
14257 } else {
14258 /* MOVF_FMT */
14259 switch (fmt) {
14260 case FMT_SDPS_S:
14261 gen_movcf_s(ctx, rs, rt, cc, 0);
14262 break;
14263 case FMT_SDPS_D:
14264 gen_movcf_d(ctx, rs, rt, cc, 0);
14265 break;
14266 case FMT_SDPS_PS:
14267 check_ps(ctx);
14268 gen_movcf_ps(ctx, rs, rt, cc, 0);
14269 break;
14270 default:
14271 goto pool32f_invalid;
14274 break;
14275 case MOVT_FMT: /* CLASS_FMT */
14276 if (ctx->insn_flags & ISA_MIPS32R6) {
14277 /* CLASS_FMT */
14278 switch (fmt) {
14279 case FMT_SDPS_S:
14280 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14281 break;
14282 case FMT_SDPS_D:
14283 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14284 break;
14285 default:
14286 goto pool32f_invalid;
14288 } else {
14289 /* MOVT_FMT */
14290 switch (fmt) {
14291 case FMT_SDPS_S:
14292 gen_movcf_s(ctx, rs, rt, cc, 1);
14293 break;
14294 case FMT_SDPS_D:
14295 gen_movcf_d(ctx, rs, rt, cc, 1);
14296 break;
14297 case FMT_SDPS_PS:
14298 check_ps(ctx);
14299 gen_movcf_ps(ctx, rs, rt, cc, 1);
14300 break;
14301 default:
14302 goto pool32f_invalid;
14305 break;
14306 case PREFX:
14307 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14308 break;
14309 default:
14310 goto pool32f_invalid;
14312 break;
14313 #define FINSN_3ARG_SDPS(prfx) \
14314 switch ((ctx->opcode >> 8) & 0x3) { \
14315 case FMT_SDPS_S: \
14316 mips32_op = OPC_##prfx##_S; \
14317 goto do_fpop; \
14318 case FMT_SDPS_D: \
14319 mips32_op = OPC_##prfx##_D; \
14320 goto do_fpop; \
14321 case FMT_SDPS_PS: \
14322 check_ps(ctx); \
14323 mips32_op = OPC_##prfx##_PS; \
14324 goto do_fpop; \
14325 default: \
14326 goto pool32f_invalid; \
14328 case MINA_FMT:
14329 check_insn(ctx, ISA_MIPS32R6);
14330 switch ((ctx->opcode >> 9) & 0x3) {
14331 case FMT_SDPS_S:
14332 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14333 break;
14334 case FMT_SDPS_D:
14335 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14336 break;
14337 default:
14338 goto pool32f_invalid;
14340 break;
14341 case MAXA_FMT:
14342 check_insn(ctx, ISA_MIPS32R6);
14343 switch ((ctx->opcode >> 9) & 0x3) {
14344 case FMT_SDPS_S:
14345 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14346 break;
14347 case FMT_SDPS_D:
14348 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14349 break;
14350 default:
14351 goto pool32f_invalid;
14353 break;
14354 case 0x30:
14355 /* regular FP ops */
14356 switch ((ctx->opcode >> 6) & 0x3) {
14357 case ADD_FMT:
14358 FINSN_3ARG_SDPS(ADD);
14359 break;
14360 case SUB_FMT:
14361 FINSN_3ARG_SDPS(SUB);
14362 break;
14363 case MUL_FMT:
14364 FINSN_3ARG_SDPS(MUL);
14365 break;
14366 case DIV_FMT:
14367 fmt = (ctx->opcode >> 8) & 0x3;
14368 if (fmt == 1) {
14369 mips32_op = OPC_DIV_D;
14370 } else if (fmt == 0) {
14371 mips32_op = OPC_DIV_S;
14372 } else {
14373 goto pool32f_invalid;
14375 goto do_fpop;
14376 default:
14377 goto pool32f_invalid;
14379 break;
14380 case 0x38:
14381 /* cmovs */
14382 switch ((ctx->opcode >> 6) & 0x7) {
14383 case MOVN_FMT: /* SELNEZ_FMT */
14384 if (ctx->insn_flags & ISA_MIPS32R6) {
14385 /* SELNEZ_FMT */
14386 switch ((ctx->opcode >> 9) & 0x3) {
14387 case FMT_SDPS_S:
14388 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14389 break;
14390 case FMT_SDPS_D:
14391 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
14392 break;
14393 default:
14394 goto pool32f_invalid;
14396 } else {
14397 /* MOVN_FMT */
14398 FINSN_3ARG_SDPS(MOVN);
14400 break;
14401 case MOVN_FMT_04:
14402 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14403 FINSN_3ARG_SDPS(MOVN);
14404 break;
14405 case MOVZ_FMT: /* SELEQZ_FMT */
14406 if (ctx->insn_flags & ISA_MIPS32R6) {
14407 /* SELEQZ_FMT */
14408 switch ((ctx->opcode >> 9) & 0x3) {
14409 case FMT_SDPS_S:
14410 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
14411 break;
14412 case FMT_SDPS_D:
14413 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
14414 break;
14415 default:
14416 goto pool32f_invalid;
14418 } else {
14419 /* MOVZ_FMT */
14420 FINSN_3ARG_SDPS(MOVZ);
14422 break;
14423 case MOVZ_FMT_05:
14424 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14425 FINSN_3ARG_SDPS(MOVZ);
14426 break;
14427 case SEL_FMT:
14428 check_insn(ctx, ISA_MIPS32R6);
14429 switch ((ctx->opcode >> 9) & 0x3) {
14430 case FMT_SDPS_S:
14431 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
14432 break;
14433 case FMT_SDPS_D:
14434 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
14435 break;
14436 default:
14437 goto pool32f_invalid;
14439 break;
14440 case MADDF_FMT:
14441 check_insn(ctx, ISA_MIPS32R6);
14442 switch ((ctx->opcode >> 9) & 0x3) {
14443 case FMT_SDPS_S:
14444 mips32_op = OPC_MADDF_S;
14445 goto do_fpop;
14446 case FMT_SDPS_D:
14447 mips32_op = OPC_MADDF_D;
14448 goto do_fpop;
14449 default:
14450 goto pool32f_invalid;
14452 break;
14453 case MSUBF_FMT:
14454 check_insn(ctx, ISA_MIPS32R6);
14455 switch ((ctx->opcode >> 9) & 0x3) {
14456 case FMT_SDPS_S:
14457 mips32_op = OPC_MSUBF_S;
14458 goto do_fpop;
14459 case FMT_SDPS_D:
14460 mips32_op = OPC_MSUBF_D;
14461 goto do_fpop;
14462 default:
14463 goto pool32f_invalid;
14465 break;
14466 default:
14467 goto pool32f_invalid;
14469 break;
14470 do_fpop:
14471 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14472 break;
14473 default:
14474 pool32f_invalid:
14475 MIPS_INVAL("pool32f");
14476 generate_exception_end(ctx, EXCP_RI);
14477 break;
14479 } else {
14480 generate_exception_err(ctx, EXCP_CpU, 1);
14482 break;
14483 case POOL32I:
14484 minor = (ctx->opcode >> 21) & 0x1f;
14485 switch (minor) {
14486 case BLTZ:
14487 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14488 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
14489 break;
14490 case BLTZAL:
14491 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14492 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
14493 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14494 break;
14495 case BLTZALS:
14496 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14497 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
14498 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14499 break;
14500 case BGEZ:
14501 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14502 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
14503 break;
14504 case BGEZAL:
14505 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14506 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
14507 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14508 break;
14509 case BGEZALS:
14510 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14511 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
14512 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14513 break;
14514 case BLEZ:
14515 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14516 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
14517 break;
14518 case BGTZ:
14519 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14520 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
14521 break;
14523 /* Traps */
14524 case TLTI: /* BC1EQZC */
14525 if (ctx->insn_flags & ISA_MIPS32R6) {
14526 /* BC1EQZC */
14527 check_cp1_enabled(ctx);
14528 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
14529 } else {
14530 /* TLTI */
14531 mips32_op = OPC_TLTI;
14532 goto do_trapi;
14534 break;
14535 case TGEI: /* BC1NEZC */
14536 if (ctx->insn_flags & ISA_MIPS32R6) {
14537 /* BC1NEZC */
14538 check_cp1_enabled(ctx);
14539 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
14540 } else {
14541 /* TGEI */
14542 mips32_op = OPC_TGEI;
14543 goto do_trapi;
14545 break;
14546 case TLTIU:
14547 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14548 mips32_op = OPC_TLTIU;
14549 goto do_trapi;
14550 case TGEIU:
14551 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14552 mips32_op = OPC_TGEIU;
14553 goto do_trapi;
14554 case TNEI: /* SYNCI */
14555 if (ctx->insn_flags & ISA_MIPS32R6) {
14556 /* SYNCI */
14557 /* Break the TB to be able to sync copied instructions
14558 immediately */
14559 ctx->bstate = BS_STOP;
14560 } else {
14561 /* TNEI */
14562 mips32_op = OPC_TNEI;
14563 goto do_trapi;
14565 break;
14566 case TEQI:
14567 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14568 mips32_op = OPC_TEQI;
14569 do_trapi:
14570 gen_trap(ctx, mips32_op, rs, -1, imm);
14571 break;
14573 case BNEZC:
14574 case BEQZC:
14575 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14576 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
14577 4, rs, 0, imm << 1, 0);
14578 /* Compact branches don't have a delay slot, so just let
14579 the normal delay slot handling take us to the branch
14580 target. */
14581 break;
14582 case LUI:
14583 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14584 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
14585 break;
14586 case SYNCI:
14587 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14588 /* Break the TB to be able to sync copied instructions
14589 immediately */
14590 ctx->bstate = BS_STOP;
14591 break;
14592 case BC2F:
14593 case BC2T:
14594 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14595 /* COP2: Not implemented. */
14596 generate_exception_err(ctx, EXCP_CpU, 2);
14597 break;
14598 case BC1F:
14599 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14600 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
14601 goto do_cp1branch;
14602 case BC1T:
14603 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14604 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
14605 goto do_cp1branch;
14606 case BC1ANY4F:
14607 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14608 mips32_op = OPC_BC1FANY4;
14609 goto do_cp1mips3d;
14610 case BC1ANY4T:
14611 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14612 mips32_op = OPC_BC1TANY4;
14613 do_cp1mips3d:
14614 check_cop1x(ctx);
14615 check_insn(ctx, ASE_MIPS3D);
14616 /* Fall through */
14617 do_cp1branch:
14618 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14619 check_cp1_enabled(ctx);
14620 gen_compute_branch1(ctx, mips32_op,
14621 (ctx->opcode >> 18) & 0x7, imm << 1);
14622 } else {
14623 generate_exception_err(ctx, EXCP_CpU, 1);
14625 break;
14626 case BPOSGE64:
14627 case BPOSGE32:
14628 /* MIPS DSP: not implemented */
14629 /* Fall through */
14630 default:
14631 MIPS_INVAL("pool32i");
14632 generate_exception_end(ctx, EXCP_RI);
14633 break;
14635 break;
14636 case POOL32C:
14637 minor = (ctx->opcode >> 12) & 0xf;
14638 offset = sextract32(ctx->opcode, 0,
14639 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
14640 switch (minor) {
14641 case LWL:
14642 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14643 mips32_op = OPC_LWL;
14644 goto do_ld_lr;
14645 case SWL:
14646 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14647 mips32_op = OPC_SWL;
14648 goto do_st_lr;
14649 case LWR:
14650 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14651 mips32_op = OPC_LWR;
14652 goto do_ld_lr;
14653 case SWR:
14654 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14655 mips32_op = OPC_SWR;
14656 goto do_st_lr;
14657 #if defined(TARGET_MIPS64)
14658 case LDL:
14659 check_insn(ctx, ISA_MIPS3);
14660 check_mips_64(ctx);
14661 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14662 mips32_op = OPC_LDL;
14663 goto do_ld_lr;
14664 case SDL:
14665 check_insn(ctx, ISA_MIPS3);
14666 check_mips_64(ctx);
14667 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14668 mips32_op = OPC_SDL;
14669 goto do_st_lr;
14670 case LDR:
14671 check_insn(ctx, ISA_MIPS3);
14672 check_mips_64(ctx);
14673 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14674 mips32_op = OPC_LDR;
14675 goto do_ld_lr;
14676 case SDR:
14677 check_insn(ctx, ISA_MIPS3);
14678 check_mips_64(ctx);
14679 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14680 mips32_op = OPC_SDR;
14681 goto do_st_lr;
14682 case LWU:
14683 check_insn(ctx, ISA_MIPS3);
14684 check_mips_64(ctx);
14685 mips32_op = OPC_LWU;
14686 goto do_ld_lr;
14687 case LLD:
14688 check_insn(ctx, ISA_MIPS3);
14689 check_mips_64(ctx);
14690 mips32_op = OPC_LLD;
14691 goto do_ld_lr;
14692 #endif
14693 case LL:
14694 mips32_op = OPC_LL;
14695 goto do_ld_lr;
14696 do_ld_lr:
14697 gen_ld(ctx, mips32_op, rt, rs, offset);
14698 break;
14699 do_st_lr:
14700 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
14701 break;
14702 case SC:
14703 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
14704 break;
14705 #if defined(TARGET_MIPS64)
14706 case SCD:
14707 check_insn(ctx, ISA_MIPS3);
14708 check_mips_64(ctx);
14709 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
14710 break;
14711 #endif
14712 case PREF:
14713 /* Treat as no-op */
14714 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
14715 /* hint codes 24-31 are reserved and signal RI */
14716 generate_exception(ctx, EXCP_RI);
14718 break;
14719 default:
14720 MIPS_INVAL("pool32c");
14721 generate_exception_end(ctx, EXCP_RI);
14722 break;
14724 break;
14725 case ADDI32: /* AUI, LUI */
14726 if (ctx->insn_flags & ISA_MIPS32R6) {
14727 /* AUI, LUI */
14728 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
14729 } else {
14730 /* ADDI32 */
14731 mips32_op = OPC_ADDI;
14732 goto do_addi;
14734 break;
14735 case ADDIU32:
14736 mips32_op = OPC_ADDIU;
14737 do_addi:
14738 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
14739 break;
14741 /* Logical operations */
14742 case ORI32:
14743 mips32_op = OPC_ORI;
14744 goto do_logici;
14745 case XORI32:
14746 mips32_op = OPC_XORI;
14747 goto do_logici;
14748 case ANDI32:
14749 mips32_op = OPC_ANDI;
14750 do_logici:
14751 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
14752 break;
14754 /* Set less than immediate */
14755 case SLTI32:
14756 mips32_op = OPC_SLTI;
14757 goto do_slti;
14758 case SLTIU32:
14759 mips32_op = OPC_SLTIU;
14760 do_slti:
14761 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
14762 break;
14763 case JALX32:
14764 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14765 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14766 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
14767 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14768 break;
14769 case JALS32: /* BOVC, BEQC, BEQZALC */
14770 if (ctx->insn_flags & ISA_MIPS32R6) {
14771 if (rs >= rt) {
14772 /* BOVC */
14773 mips32_op = OPC_BOVC;
14774 } else if (rs < rt && rs == 0) {
14775 /* BEQZALC */
14776 mips32_op = OPC_BEQZALC;
14777 } else {
14778 /* BEQC */
14779 mips32_op = OPC_BEQC;
14781 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14782 } else {
14783 /* JALS32 */
14784 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
14785 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
14786 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14788 break;
14789 case BEQ32: /* BC */
14790 if (ctx->insn_flags & ISA_MIPS32R6) {
14791 /* BC */
14792 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
14793 sextract32(ctx->opcode << 1, 0, 27));
14794 } else {
14795 /* BEQ32 */
14796 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
14798 break;
14799 case BNE32: /* BALC */
14800 if (ctx->insn_flags & ISA_MIPS32R6) {
14801 /* BALC */
14802 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
14803 sextract32(ctx->opcode << 1, 0, 27));
14804 } else {
14805 /* BNE32 */
14806 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
14808 break;
14809 case J32: /* BGTZC, BLTZC, BLTC */
14810 if (ctx->insn_flags & ISA_MIPS32R6) {
14811 if (rs == 0 && rt != 0) {
14812 /* BGTZC */
14813 mips32_op = OPC_BGTZC;
14814 } else if (rs != 0 && rt != 0 && rs == rt) {
14815 /* BLTZC */
14816 mips32_op = OPC_BLTZC;
14817 } else {
14818 /* BLTC */
14819 mips32_op = OPC_BLTC;
14821 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14822 } else {
14823 /* J32 */
14824 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
14825 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14827 break;
14828 case JAL32: /* BLEZC, BGEZC, BGEC */
14829 if (ctx->insn_flags & ISA_MIPS32R6) {
14830 if (rs == 0 && rt != 0) {
14831 /* BLEZC */
14832 mips32_op = OPC_BLEZC;
14833 } else if (rs != 0 && rt != 0 && rs == rt) {
14834 /* BGEZC */
14835 mips32_op = OPC_BGEZC;
14836 } else {
14837 /* BGEC */
14838 mips32_op = OPC_BGEC;
14840 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14841 } else {
14842 /* JAL32 */
14843 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
14844 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14845 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14847 break;
14848 /* Floating point (COP1) */
14849 case LWC132:
14850 mips32_op = OPC_LWC1;
14851 goto do_cop1;
14852 case LDC132:
14853 mips32_op = OPC_LDC1;
14854 goto do_cop1;
14855 case SWC132:
14856 mips32_op = OPC_SWC1;
14857 goto do_cop1;
14858 case SDC132:
14859 mips32_op = OPC_SDC1;
14860 do_cop1:
14861 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
14862 break;
14863 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14864 if (ctx->insn_flags & ISA_MIPS32R6) {
14865 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14866 switch ((ctx->opcode >> 16) & 0x1f) {
14867 case ADDIUPC_00 ... ADDIUPC_07:
14868 gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
14869 break;
14870 case AUIPC:
14871 gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
14872 break;
14873 case ALUIPC:
14874 gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
14875 break;
14876 case LWPC_08 ... LWPC_0F:
14877 gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
14878 break;
14879 default:
14880 generate_exception(ctx, EXCP_RI);
14881 break;
14883 } else {
14884 /* ADDIUPC */
14885 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
14886 int offset = SIMM(ctx->opcode, 0, 23) << 2;
14888 gen_addiupc(ctx, reg, offset, 0, 0);
14890 break;
14891 case BNVC: /* BNEC, BNEZALC */
14892 check_insn(ctx, ISA_MIPS32R6);
14893 if (rs >= rt) {
14894 /* BNVC */
14895 mips32_op = OPC_BNVC;
14896 } else if (rs < rt && rs == 0) {
14897 /* BNEZALC */
14898 mips32_op = OPC_BNEZALC;
14899 } else {
14900 /* BNEC */
14901 mips32_op = OPC_BNEC;
14903 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14904 break;
14905 case R6_BNEZC: /* JIALC */
14906 check_insn(ctx, ISA_MIPS32R6);
14907 if (rt != 0) {
14908 /* BNEZC */
14909 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
14910 sextract32(ctx->opcode << 1, 0, 22));
14911 } else {
14912 /* JIALC */
14913 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
14915 break;
14916 case R6_BEQZC: /* JIC */
14917 check_insn(ctx, ISA_MIPS32R6);
14918 if (rt != 0) {
14919 /* BEQZC */
14920 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
14921 sextract32(ctx->opcode << 1, 0, 22));
14922 } else {
14923 /* JIC */
14924 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
14926 break;
14927 case BLEZALC: /* BGEZALC, BGEUC */
14928 check_insn(ctx, ISA_MIPS32R6);
14929 if (rs == 0 && rt != 0) {
14930 /* BLEZALC */
14931 mips32_op = OPC_BLEZALC;
14932 } else if (rs != 0 && rt != 0 && rs == rt) {
14933 /* BGEZALC */
14934 mips32_op = OPC_BGEZALC;
14935 } else {
14936 /* BGEUC */
14937 mips32_op = OPC_BGEUC;
14939 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14940 break;
14941 case BGTZALC: /* BLTZALC, BLTUC */
14942 check_insn(ctx, ISA_MIPS32R6);
14943 if (rs == 0 && rt != 0) {
14944 /* BGTZALC */
14945 mips32_op = OPC_BGTZALC;
14946 } else if (rs != 0 && rt != 0 && rs == rt) {
14947 /* BLTZALC */
14948 mips32_op = OPC_BLTZALC;
14949 } else {
14950 /* BLTUC */
14951 mips32_op = OPC_BLTUC;
14953 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14954 break;
14955 /* Loads and stores */
14956 case LB32:
14957 mips32_op = OPC_LB;
14958 goto do_ld;
14959 case LBU32:
14960 mips32_op = OPC_LBU;
14961 goto do_ld;
14962 case LH32:
14963 mips32_op = OPC_LH;
14964 goto do_ld;
14965 case LHU32:
14966 mips32_op = OPC_LHU;
14967 goto do_ld;
14968 case LW32:
14969 mips32_op = OPC_LW;
14970 goto do_ld;
14971 #ifdef TARGET_MIPS64
14972 case LD32:
14973 check_insn(ctx, ISA_MIPS3);
14974 check_mips_64(ctx);
14975 mips32_op = OPC_LD;
14976 goto do_ld;
14977 case SD32:
14978 check_insn(ctx, ISA_MIPS3);
14979 check_mips_64(ctx);
14980 mips32_op = OPC_SD;
14981 goto do_st;
14982 #endif
14983 case SB32:
14984 mips32_op = OPC_SB;
14985 goto do_st;
14986 case SH32:
14987 mips32_op = OPC_SH;
14988 goto do_st;
14989 case SW32:
14990 mips32_op = OPC_SW;
14991 goto do_st;
14992 do_ld:
14993 gen_ld(ctx, mips32_op, rt, rs, imm);
14994 break;
14995 do_st:
14996 gen_st(ctx, mips32_op, rt, rs, imm);
14997 break;
14998 default:
14999 generate_exception_end(ctx, EXCP_RI);
15000 break;
15004 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
15006 uint32_t op;
15008 /* make sure instructions are on a halfword boundary */
15009 if (ctx->pc & 0x1) {
15010 env->CP0_BadVAddr = ctx->pc;
15011 generate_exception_end(ctx, EXCP_AdEL);
15012 return 2;
15015 op = (ctx->opcode >> 10) & 0x3f;
15016 /* Enforce properly-sized instructions in a delay slot */
15017 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
15018 switch (op & 0x7) { /* MSB-3..MSB-5 */
15019 case 0:
15020 /* POOL32A, POOL32B, POOL32I, POOL32C */
15021 case 4:
15022 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
15023 case 5:
15024 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
15025 case 6:
15026 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
15027 case 7:
15028 /* LB32, LH32, LWC132, LDC132, LW32 */
15029 if (ctx->hflags & MIPS_HFLAG_BDS16) {
15030 generate_exception_end(ctx, EXCP_RI);
15031 return 2;
15033 break;
15034 case 1:
15035 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
15036 case 2:
15037 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
15038 case 3:
15039 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
15040 if (ctx->hflags & MIPS_HFLAG_BDS32) {
15041 generate_exception_end(ctx, EXCP_RI);
15042 return 2;
15044 break;
15048 switch (op) {
15049 case POOL16A:
15051 int rd = mmreg(uMIPS_RD(ctx->opcode));
15052 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
15053 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
15054 uint32_t opc = 0;
15056 switch (ctx->opcode & 0x1) {
15057 case ADDU16:
15058 opc = OPC_ADDU;
15059 break;
15060 case SUBU16:
15061 opc = OPC_SUBU;
15062 break;
15064 if (ctx->insn_flags & ISA_MIPS32R6) {
15065 /* In the Release 6 the register number location in
15066 * the instruction encoding has changed.
15068 gen_arith(ctx, opc, rs1, rd, rs2);
15069 } else {
15070 gen_arith(ctx, opc, rd, rs1, rs2);
15073 break;
15074 case POOL16B:
15076 int rd = mmreg(uMIPS_RD(ctx->opcode));
15077 int rs = mmreg(uMIPS_RS(ctx->opcode));
15078 int amount = (ctx->opcode >> 1) & 0x7;
15079 uint32_t opc = 0;
15080 amount = amount == 0 ? 8 : amount;
15082 switch (ctx->opcode & 0x1) {
15083 case SLL16:
15084 opc = OPC_SLL;
15085 break;
15086 case SRL16:
15087 opc = OPC_SRL;
15088 break;
15091 gen_shift_imm(ctx, opc, rd, rs, amount);
15093 break;
15094 case POOL16C:
15095 if (ctx->insn_flags & ISA_MIPS32R6) {
15096 gen_pool16c_r6_insn(ctx);
15097 } else {
15098 gen_pool16c_insn(ctx);
15100 break;
15101 case LWGP16:
15103 int rd = mmreg(uMIPS_RD(ctx->opcode));
15104 int rb = 28; /* GP */
15105 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
15107 gen_ld(ctx, OPC_LW, rd, rb, offset);
15109 break;
15110 case POOL16F:
15111 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15112 if (ctx->opcode & 1) {
15113 generate_exception_end(ctx, EXCP_RI);
15114 } else {
15115 /* MOVEP */
15116 int enc_dest = uMIPS_RD(ctx->opcode);
15117 int enc_rt = uMIPS_RS2(ctx->opcode);
15118 int enc_rs = uMIPS_RS1(ctx->opcode);
15119 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15121 break;
15122 case LBU16:
15124 int rd = mmreg(uMIPS_RD(ctx->opcode));
15125 int rb = mmreg(uMIPS_RS(ctx->opcode));
15126 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15127 offset = (offset == 0xf ? -1 : offset);
15129 gen_ld(ctx, OPC_LBU, rd, rb, offset);
15131 break;
15132 case LHU16:
15134 int rd = mmreg(uMIPS_RD(ctx->opcode));
15135 int rb = mmreg(uMIPS_RS(ctx->opcode));
15136 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15138 gen_ld(ctx, OPC_LHU, rd, rb, offset);
15140 break;
15141 case LWSP16:
15143 int rd = (ctx->opcode >> 5) & 0x1f;
15144 int rb = 29; /* SP */
15145 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15147 gen_ld(ctx, OPC_LW, rd, rb, offset);
15149 break;
15150 case LW16:
15152 int rd = mmreg(uMIPS_RD(ctx->opcode));
15153 int rb = mmreg(uMIPS_RS(ctx->opcode));
15154 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15156 gen_ld(ctx, OPC_LW, rd, rb, offset);
15158 break;
15159 case SB16:
15161 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15162 int rb = mmreg(uMIPS_RS(ctx->opcode));
15163 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15165 gen_st(ctx, OPC_SB, rd, rb, offset);
15167 break;
15168 case SH16:
15170 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15171 int rb = mmreg(uMIPS_RS(ctx->opcode));
15172 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15174 gen_st(ctx, OPC_SH, rd, rb, offset);
15176 break;
15177 case SWSP16:
15179 int rd = (ctx->opcode >> 5) & 0x1f;
15180 int rb = 29; /* SP */
15181 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15183 gen_st(ctx, OPC_SW, rd, rb, offset);
15185 break;
15186 case SW16:
15188 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15189 int rb = mmreg(uMIPS_RS(ctx->opcode));
15190 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15192 gen_st(ctx, OPC_SW, rd, rb, offset);
15194 break;
15195 case MOVE16:
15197 int rd = uMIPS_RD5(ctx->opcode);
15198 int rs = uMIPS_RS5(ctx->opcode);
15200 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
15202 break;
15203 case ANDI16:
15204 gen_andi16(ctx);
15205 break;
15206 case POOL16D:
15207 switch (ctx->opcode & 0x1) {
15208 case ADDIUS5:
15209 gen_addius5(ctx);
15210 break;
15211 case ADDIUSP:
15212 gen_addiusp(ctx);
15213 break;
15215 break;
15216 case POOL16E:
15217 switch (ctx->opcode & 0x1) {
15218 case ADDIUR2:
15219 gen_addiur2(ctx);
15220 break;
15221 case ADDIUR1SP:
15222 gen_addiur1sp(ctx);
15223 break;
15225 break;
15226 case B16: /* BC16 */
15227 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
15228 sextract32(ctx->opcode, 0, 10) << 1,
15229 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15230 break;
15231 case BNEZ16: /* BNEZC16 */
15232 case BEQZ16: /* BEQZC16 */
15233 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
15234 mmreg(uMIPS_RD(ctx->opcode)),
15235 0, sextract32(ctx->opcode, 0, 7) << 1,
15236 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15238 break;
15239 case LI16:
15241 int reg = mmreg(uMIPS_RD(ctx->opcode));
15242 int imm = ZIMM(ctx->opcode, 0, 7);
15244 imm = (imm == 0x7f ? -1 : imm);
15245 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15247 break;
15248 case RES_29:
15249 case RES_31:
15250 case RES_39:
15251 generate_exception_end(ctx, EXCP_RI);
15252 break;
15253 default:
15254 decode_micromips32_opc(env, ctx);
15255 return 4;
15258 return 2;
15261 /* SmartMIPS extension to MIPS32 */
15263 #if defined(TARGET_MIPS64)
15265 /* MDMX extension to MIPS64 */
15267 #endif
15269 /* MIPSDSP functions. */
15270 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
15271 int rd, int base, int offset)
15273 TCGv t0;
15275 check_dsp(ctx);
15276 t0 = tcg_temp_new();
15278 if (base == 0) {
15279 gen_load_gpr(t0, offset);
15280 } else if (offset == 0) {
15281 gen_load_gpr(t0, base);
15282 } else {
15283 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
15286 switch (opc) {
15287 case OPC_LBUX:
15288 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
15289 gen_store_gpr(t0, rd);
15290 break;
15291 case OPC_LHX:
15292 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
15293 gen_store_gpr(t0, rd);
15294 break;
15295 case OPC_LWX:
15296 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
15297 gen_store_gpr(t0, rd);
15298 break;
15299 #if defined(TARGET_MIPS64)
15300 case OPC_LDX:
15301 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
15302 gen_store_gpr(t0, rd);
15303 break;
15304 #endif
15306 tcg_temp_free(t0);
15309 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
15310 int ret, int v1, int v2)
15312 TCGv v1_t;
15313 TCGv v2_t;
15315 if (ret == 0) {
15316 /* Treat as NOP. */
15317 return;
15320 v1_t = tcg_temp_new();
15321 v2_t = tcg_temp_new();
15323 gen_load_gpr(v1_t, v1);
15324 gen_load_gpr(v2_t, v2);
15326 switch (op1) {
15327 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
15328 case OPC_MULT_G_2E:
15329 check_dspr2(ctx);
15330 switch (op2) {
15331 case OPC_ADDUH_QB:
15332 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
15333 break;
15334 case OPC_ADDUH_R_QB:
15335 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15336 break;
15337 case OPC_ADDQH_PH:
15338 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
15339 break;
15340 case OPC_ADDQH_R_PH:
15341 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15342 break;
15343 case OPC_ADDQH_W:
15344 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
15345 break;
15346 case OPC_ADDQH_R_W:
15347 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15348 break;
15349 case OPC_SUBUH_QB:
15350 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
15351 break;
15352 case OPC_SUBUH_R_QB:
15353 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15354 break;
15355 case OPC_SUBQH_PH:
15356 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
15357 break;
15358 case OPC_SUBQH_R_PH:
15359 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15360 break;
15361 case OPC_SUBQH_W:
15362 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
15363 break;
15364 case OPC_SUBQH_R_W:
15365 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15366 break;
15368 break;
15369 case OPC_ABSQ_S_PH_DSP:
15370 switch (op2) {
15371 case OPC_ABSQ_S_QB:
15372 check_dspr2(ctx);
15373 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
15374 break;
15375 case OPC_ABSQ_S_PH:
15376 check_dsp(ctx);
15377 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
15378 break;
15379 case OPC_ABSQ_S_W:
15380 check_dsp(ctx);
15381 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
15382 break;
15383 case OPC_PRECEQ_W_PHL:
15384 check_dsp(ctx);
15385 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
15386 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15387 break;
15388 case OPC_PRECEQ_W_PHR:
15389 check_dsp(ctx);
15390 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
15391 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
15392 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15393 break;
15394 case OPC_PRECEQU_PH_QBL:
15395 check_dsp(ctx);
15396 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
15397 break;
15398 case OPC_PRECEQU_PH_QBR:
15399 check_dsp(ctx);
15400 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
15401 break;
15402 case OPC_PRECEQU_PH_QBLA:
15403 check_dsp(ctx);
15404 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
15405 break;
15406 case OPC_PRECEQU_PH_QBRA:
15407 check_dsp(ctx);
15408 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
15409 break;
15410 case OPC_PRECEU_PH_QBL:
15411 check_dsp(ctx);
15412 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
15413 break;
15414 case OPC_PRECEU_PH_QBR:
15415 check_dsp(ctx);
15416 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
15417 break;
15418 case OPC_PRECEU_PH_QBLA:
15419 check_dsp(ctx);
15420 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
15421 break;
15422 case OPC_PRECEU_PH_QBRA:
15423 check_dsp(ctx);
15424 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
15425 break;
15427 break;
15428 case OPC_ADDU_QB_DSP:
15429 switch (op2) {
15430 case OPC_ADDQ_PH:
15431 check_dsp(ctx);
15432 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15433 break;
15434 case OPC_ADDQ_S_PH:
15435 check_dsp(ctx);
15436 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15437 break;
15438 case OPC_ADDQ_S_W:
15439 check_dsp(ctx);
15440 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15441 break;
15442 case OPC_ADDU_QB:
15443 check_dsp(ctx);
15444 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15445 break;
15446 case OPC_ADDU_S_QB:
15447 check_dsp(ctx);
15448 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15449 break;
15450 case OPC_ADDU_PH:
15451 check_dspr2(ctx);
15452 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15453 break;
15454 case OPC_ADDU_S_PH:
15455 check_dspr2(ctx);
15456 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15457 break;
15458 case OPC_SUBQ_PH:
15459 check_dsp(ctx);
15460 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15461 break;
15462 case OPC_SUBQ_S_PH:
15463 check_dsp(ctx);
15464 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15465 break;
15466 case OPC_SUBQ_S_W:
15467 check_dsp(ctx);
15468 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15469 break;
15470 case OPC_SUBU_QB:
15471 check_dsp(ctx);
15472 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15473 break;
15474 case OPC_SUBU_S_QB:
15475 check_dsp(ctx);
15476 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15477 break;
15478 case OPC_SUBU_PH:
15479 check_dspr2(ctx);
15480 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15481 break;
15482 case OPC_SUBU_S_PH:
15483 check_dspr2(ctx);
15484 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15485 break;
15486 case OPC_ADDSC:
15487 check_dsp(ctx);
15488 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15489 break;
15490 case OPC_ADDWC:
15491 check_dsp(ctx);
15492 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15493 break;
15494 case OPC_MODSUB:
15495 check_dsp(ctx);
15496 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
15497 break;
15498 case OPC_RADDU_W_QB:
15499 check_dsp(ctx);
15500 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
15501 break;
15503 break;
15504 case OPC_CMPU_EQ_QB_DSP:
15505 switch (op2) {
15506 case OPC_PRECR_QB_PH:
15507 check_dspr2(ctx);
15508 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15509 break;
15510 case OPC_PRECRQ_QB_PH:
15511 check_dsp(ctx);
15512 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15513 break;
15514 case OPC_PRECR_SRA_PH_W:
15515 check_dspr2(ctx);
15517 TCGv_i32 sa_t = tcg_const_i32(v2);
15518 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
15519 cpu_gpr[ret]);
15520 tcg_temp_free_i32(sa_t);
15521 break;
15523 case OPC_PRECR_SRA_R_PH_W:
15524 check_dspr2(ctx);
15526 TCGv_i32 sa_t = tcg_const_i32(v2);
15527 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
15528 cpu_gpr[ret]);
15529 tcg_temp_free_i32(sa_t);
15530 break;
15532 case OPC_PRECRQ_PH_W:
15533 check_dsp(ctx);
15534 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
15535 break;
15536 case OPC_PRECRQ_RS_PH_W:
15537 check_dsp(ctx);
15538 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15539 break;
15540 case OPC_PRECRQU_S_QB_PH:
15541 check_dsp(ctx);
15542 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15543 break;
15545 break;
15546 #ifdef TARGET_MIPS64
15547 case OPC_ABSQ_S_QH_DSP:
15548 switch (op2) {
15549 case OPC_PRECEQ_L_PWL:
15550 check_dsp(ctx);
15551 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
15552 break;
15553 case OPC_PRECEQ_L_PWR:
15554 check_dsp(ctx);
15555 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
15556 break;
15557 case OPC_PRECEQ_PW_QHL:
15558 check_dsp(ctx);
15559 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
15560 break;
15561 case OPC_PRECEQ_PW_QHR:
15562 check_dsp(ctx);
15563 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
15564 break;
15565 case OPC_PRECEQ_PW_QHLA:
15566 check_dsp(ctx);
15567 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
15568 break;
15569 case OPC_PRECEQ_PW_QHRA:
15570 check_dsp(ctx);
15571 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
15572 break;
15573 case OPC_PRECEQU_QH_OBL:
15574 check_dsp(ctx);
15575 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
15576 break;
15577 case OPC_PRECEQU_QH_OBR:
15578 check_dsp(ctx);
15579 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
15580 break;
15581 case OPC_PRECEQU_QH_OBLA:
15582 check_dsp(ctx);
15583 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
15584 break;
15585 case OPC_PRECEQU_QH_OBRA:
15586 check_dsp(ctx);
15587 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
15588 break;
15589 case OPC_PRECEU_QH_OBL:
15590 check_dsp(ctx);
15591 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
15592 break;
15593 case OPC_PRECEU_QH_OBR:
15594 check_dsp(ctx);
15595 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
15596 break;
15597 case OPC_PRECEU_QH_OBLA:
15598 check_dsp(ctx);
15599 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
15600 break;
15601 case OPC_PRECEU_QH_OBRA:
15602 check_dsp(ctx);
15603 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
15604 break;
15605 case OPC_ABSQ_S_OB:
15606 check_dspr2(ctx);
15607 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
15608 break;
15609 case OPC_ABSQ_S_PW:
15610 check_dsp(ctx);
15611 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
15612 break;
15613 case OPC_ABSQ_S_QH:
15614 check_dsp(ctx);
15615 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
15616 break;
15618 break;
15619 case OPC_ADDU_OB_DSP:
15620 switch (op2) {
15621 case OPC_RADDU_L_OB:
15622 check_dsp(ctx);
15623 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
15624 break;
15625 case OPC_SUBQ_PW:
15626 check_dsp(ctx);
15627 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15628 break;
15629 case OPC_SUBQ_S_PW:
15630 check_dsp(ctx);
15631 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15632 break;
15633 case OPC_SUBQ_QH:
15634 check_dsp(ctx);
15635 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15636 break;
15637 case OPC_SUBQ_S_QH:
15638 check_dsp(ctx);
15639 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15640 break;
15641 case OPC_SUBU_OB:
15642 check_dsp(ctx);
15643 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15644 break;
15645 case OPC_SUBU_S_OB:
15646 check_dsp(ctx);
15647 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15648 break;
15649 case OPC_SUBU_QH:
15650 check_dspr2(ctx);
15651 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15652 break;
15653 case OPC_SUBU_S_QH:
15654 check_dspr2(ctx);
15655 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15656 break;
15657 case OPC_SUBUH_OB:
15658 check_dspr2(ctx);
15659 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
15660 break;
15661 case OPC_SUBUH_R_OB:
15662 check_dspr2(ctx);
15663 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15664 break;
15665 case OPC_ADDQ_PW:
15666 check_dsp(ctx);
15667 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15668 break;
15669 case OPC_ADDQ_S_PW:
15670 check_dsp(ctx);
15671 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15672 break;
15673 case OPC_ADDQ_QH:
15674 check_dsp(ctx);
15675 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15676 break;
15677 case OPC_ADDQ_S_QH:
15678 check_dsp(ctx);
15679 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15680 break;
15681 case OPC_ADDU_OB:
15682 check_dsp(ctx);
15683 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15684 break;
15685 case OPC_ADDU_S_OB:
15686 check_dsp(ctx);
15687 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15688 break;
15689 case OPC_ADDU_QH:
15690 check_dspr2(ctx);
15691 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15692 break;
15693 case OPC_ADDU_S_QH:
15694 check_dspr2(ctx);
15695 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15696 break;
15697 case OPC_ADDUH_OB:
15698 check_dspr2(ctx);
15699 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
15700 break;
15701 case OPC_ADDUH_R_OB:
15702 check_dspr2(ctx);
15703 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15704 break;
15706 break;
15707 case OPC_CMPU_EQ_OB_DSP:
15708 switch (op2) {
15709 case OPC_PRECR_OB_QH:
15710 check_dspr2(ctx);
15711 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15712 break;
15713 case OPC_PRECR_SRA_QH_PW:
15714 check_dspr2(ctx);
15716 TCGv_i32 ret_t = tcg_const_i32(ret);
15717 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
15718 tcg_temp_free_i32(ret_t);
15719 break;
15721 case OPC_PRECR_SRA_R_QH_PW:
15722 check_dspr2(ctx);
15724 TCGv_i32 sa_v = tcg_const_i32(ret);
15725 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
15726 tcg_temp_free_i32(sa_v);
15727 break;
15729 case OPC_PRECRQ_OB_QH:
15730 check_dsp(ctx);
15731 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15732 break;
15733 case OPC_PRECRQ_PW_L:
15734 check_dsp(ctx);
15735 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
15736 break;
15737 case OPC_PRECRQ_QH_PW:
15738 check_dsp(ctx);
15739 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
15740 break;
15741 case OPC_PRECRQ_RS_QH_PW:
15742 check_dsp(ctx);
15743 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15744 break;
15745 case OPC_PRECRQU_S_OB_QH:
15746 check_dsp(ctx);
15747 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15748 break;
15750 break;
15751 #endif
15754 tcg_temp_free(v1_t);
15755 tcg_temp_free(v2_t);
15758 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
15759 int ret, int v1, int v2)
15761 uint32_t op2;
15762 TCGv t0;
15763 TCGv v1_t;
15764 TCGv v2_t;
15766 if (ret == 0) {
15767 /* Treat as NOP. */
15768 return;
15771 t0 = tcg_temp_new();
15772 v1_t = tcg_temp_new();
15773 v2_t = tcg_temp_new();
15775 tcg_gen_movi_tl(t0, v1);
15776 gen_load_gpr(v1_t, v1);
15777 gen_load_gpr(v2_t, v2);
15779 switch (opc) {
15780 case OPC_SHLL_QB_DSP:
15782 op2 = MASK_SHLL_QB(ctx->opcode);
15783 switch (op2) {
15784 case OPC_SHLL_QB:
15785 check_dsp(ctx);
15786 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
15787 break;
15788 case OPC_SHLLV_QB:
15789 check_dsp(ctx);
15790 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15791 break;
15792 case OPC_SHLL_PH:
15793 check_dsp(ctx);
15794 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15795 break;
15796 case OPC_SHLLV_PH:
15797 check_dsp(ctx);
15798 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15799 break;
15800 case OPC_SHLL_S_PH:
15801 check_dsp(ctx);
15802 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15803 break;
15804 case OPC_SHLLV_S_PH:
15805 check_dsp(ctx);
15806 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15807 break;
15808 case OPC_SHLL_S_W:
15809 check_dsp(ctx);
15810 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
15811 break;
15812 case OPC_SHLLV_S_W:
15813 check_dsp(ctx);
15814 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15815 break;
15816 case OPC_SHRL_QB:
15817 check_dsp(ctx);
15818 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
15819 break;
15820 case OPC_SHRLV_QB:
15821 check_dsp(ctx);
15822 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
15823 break;
15824 case OPC_SHRL_PH:
15825 check_dspr2(ctx);
15826 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
15827 break;
15828 case OPC_SHRLV_PH:
15829 check_dspr2(ctx);
15830 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
15831 break;
15832 case OPC_SHRA_QB:
15833 check_dspr2(ctx);
15834 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
15835 break;
15836 case OPC_SHRA_R_QB:
15837 check_dspr2(ctx);
15838 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
15839 break;
15840 case OPC_SHRAV_QB:
15841 check_dspr2(ctx);
15842 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
15843 break;
15844 case OPC_SHRAV_R_QB:
15845 check_dspr2(ctx);
15846 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
15847 break;
15848 case OPC_SHRA_PH:
15849 check_dsp(ctx);
15850 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
15851 break;
15852 case OPC_SHRA_R_PH:
15853 check_dsp(ctx);
15854 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
15855 break;
15856 case OPC_SHRAV_PH:
15857 check_dsp(ctx);
15858 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
15859 break;
15860 case OPC_SHRAV_R_PH:
15861 check_dsp(ctx);
15862 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
15863 break;
15864 case OPC_SHRA_R_W:
15865 check_dsp(ctx);
15866 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
15867 break;
15868 case OPC_SHRAV_R_W:
15869 check_dsp(ctx);
15870 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
15871 break;
15872 default: /* Invalid */
15873 MIPS_INVAL("MASK SHLL.QB");
15874 generate_exception_end(ctx, EXCP_RI);
15875 break;
15877 break;
15879 #ifdef TARGET_MIPS64
15880 case OPC_SHLL_OB_DSP:
15881 op2 = MASK_SHLL_OB(ctx->opcode);
15882 switch (op2) {
15883 case OPC_SHLL_PW:
15884 check_dsp(ctx);
15885 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15886 break;
15887 case OPC_SHLLV_PW:
15888 check_dsp(ctx);
15889 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15890 break;
15891 case OPC_SHLL_S_PW:
15892 check_dsp(ctx);
15893 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15894 break;
15895 case OPC_SHLLV_S_PW:
15896 check_dsp(ctx);
15897 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15898 break;
15899 case OPC_SHLL_OB:
15900 check_dsp(ctx);
15901 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
15902 break;
15903 case OPC_SHLLV_OB:
15904 check_dsp(ctx);
15905 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15906 break;
15907 case OPC_SHLL_QH:
15908 check_dsp(ctx);
15909 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15910 break;
15911 case OPC_SHLLV_QH:
15912 check_dsp(ctx);
15913 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15914 break;
15915 case OPC_SHLL_S_QH:
15916 check_dsp(ctx);
15917 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15918 break;
15919 case OPC_SHLLV_S_QH:
15920 check_dsp(ctx);
15921 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15922 break;
15923 case OPC_SHRA_OB:
15924 check_dspr2(ctx);
15925 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
15926 break;
15927 case OPC_SHRAV_OB:
15928 check_dspr2(ctx);
15929 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
15930 break;
15931 case OPC_SHRA_R_OB:
15932 check_dspr2(ctx);
15933 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
15934 break;
15935 case OPC_SHRAV_R_OB:
15936 check_dspr2(ctx);
15937 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
15938 break;
15939 case OPC_SHRA_PW:
15940 check_dsp(ctx);
15941 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
15942 break;
15943 case OPC_SHRAV_PW:
15944 check_dsp(ctx);
15945 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
15946 break;
15947 case OPC_SHRA_R_PW:
15948 check_dsp(ctx);
15949 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
15950 break;
15951 case OPC_SHRAV_R_PW:
15952 check_dsp(ctx);
15953 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
15954 break;
15955 case OPC_SHRA_QH:
15956 check_dsp(ctx);
15957 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
15958 break;
15959 case OPC_SHRAV_QH:
15960 check_dsp(ctx);
15961 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
15962 break;
15963 case OPC_SHRA_R_QH:
15964 check_dsp(ctx);
15965 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
15966 break;
15967 case OPC_SHRAV_R_QH:
15968 check_dsp(ctx);
15969 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
15970 break;
15971 case OPC_SHRL_OB:
15972 check_dsp(ctx);
15973 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
15974 break;
15975 case OPC_SHRLV_OB:
15976 check_dsp(ctx);
15977 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
15978 break;
15979 case OPC_SHRL_QH:
15980 check_dspr2(ctx);
15981 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
15982 break;
15983 case OPC_SHRLV_QH:
15984 check_dspr2(ctx);
15985 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
15986 break;
15987 default: /* Invalid */
15988 MIPS_INVAL("MASK SHLL.OB");
15989 generate_exception_end(ctx, EXCP_RI);
15990 break;
15992 break;
15993 #endif
15996 tcg_temp_free(t0);
15997 tcg_temp_free(v1_t);
15998 tcg_temp_free(v2_t);
16001 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
16002 int ret, int v1, int v2, int check_ret)
16004 TCGv_i32 t0;
16005 TCGv v1_t;
16006 TCGv v2_t;
16008 if ((ret == 0) && (check_ret == 1)) {
16009 /* Treat as NOP. */
16010 return;
16013 t0 = tcg_temp_new_i32();
16014 v1_t = tcg_temp_new();
16015 v2_t = tcg_temp_new();
16017 tcg_gen_movi_i32(t0, ret);
16018 gen_load_gpr(v1_t, v1);
16019 gen_load_gpr(v2_t, v2);
16021 switch (op1) {
16022 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
16023 * the same mask and op1. */
16024 case OPC_MULT_G_2E:
16025 check_dspr2(ctx);
16026 switch (op2) {
16027 case OPC_MUL_PH:
16028 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16029 break;
16030 case OPC_MUL_S_PH:
16031 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16032 break;
16033 case OPC_MULQ_S_W:
16034 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16035 break;
16036 case OPC_MULQ_RS_W:
16037 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16038 break;
16040 break;
16041 case OPC_DPA_W_PH_DSP:
16042 switch (op2) {
16043 case OPC_DPAU_H_QBL:
16044 check_dsp(ctx);
16045 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
16046 break;
16047 case OPC_DPAU_H_QBR:
16048 check_dsp(ctx);
16049 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
16050 break;
16051 case OPC_DPSU_H_QBL:
16052 check_dsp(ctx);
16053 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
16054 break;
16055 case OPC_DPSU_H_QBR:
16056 check_dsp(ctx);
16057 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
16058 break;
16059 case OPC_DPA_W_PH:
16060 check_dspr2(ctx);
16061 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
16062 break;
16063 case OPC_DPAX_W_PH:
16064 check_dspr2(ctx);
16065 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
16066 break;
16067 case OPC_DPAQ_S_W_PH:
16068 check_dsp(ctx);
16069 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16070 break;
16071 case OPC_DPAQX_S_W_PH:
16072 check_dspr2(ctx);
16073 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16074 break;
16075 case OPC_DPAQX_SA_W_PH:
16076 check_dspr2(ctx);
16077 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16078 break;
16079 case OPC_DPS_W_PH:
16080 check_dspr2(ctx);
16081 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
16082 break;
16083 case OPC_DPSX_W_PH:
16084 check_dspr2(ctx);
16085 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
16086 break;
16087 case OPC_DPSQ_S_W_PH:
16088 check_dsp(ctx);
16089 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16090 break;
16091 case OPC_DPSQX_S_W_PH:
16092 check_dspr2(ctx);
16093 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16094 break;
16095 case OPC_DPSQX_SA_W_PH:
16096 check_dspr2(ctx);
16097 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16098 break;
16099 case OPC_MULSAQ_S_W_PH:
16100 check_dsp(ctx);
16101 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16102 break;
16103 case OPC_DPAQ_SA_L_W:
16104 check_dsp(ctx);
16105 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16106 break;
16107 case OPC_DPSQ_SA_L_W:
16108 check_dsp(ctx);
16109 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16110 break;
16111 case OPC_MAQ_S_W_PHL:
16112 check_dsp(ctx);
16113 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
16114 break;
16115 case OPC_MAQ_S_W_PHR:
16116 check_dsp(ctx);
16117 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
16118 break;
16119 case OPC_MAQ_SA_W_PHL:
16120 check_dsp(ctx);
16121 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
16122 break;
16123 case OPC_MAQ_SA_W_PHR:
16124 check_dsp(ctx);
16125 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
16126 break;
16127 case OPC_MULSA_W_PH:
16128 check_dspr2(ctx);
16129 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
16130 break;
16132 break;
16133 #ifdef TARGET_MIPS64
16134 case OPC_DPAQ_W_QH_DSP:
16136 int ac = ret & 0x03;
16137 tcg_gen_movi_i32(t0, ac);
16139 switch (op2) {
16140 case OPC_DMADD:
16141 check_dsp(ctx);
16142 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
16143 break;
16144 case OPC_DMADDU:
16145 check_dsp(ctx);
16146 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
16147 break;
16148 case OPC_DMSUB:
16149 check_dsp(ctx);
16150 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
16151 break;
16152 case OPC_DMSUBU:
16153 check_dsp(ctx);
16154 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
16155 break;
16156 case OPC_DPA_W_QH:
16157 check_dspr2(ctx);
16158 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
16159 break;
16160 case OPC_DPAQ_S_W_QH:
16161 check_dsp(ctx);
16162 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16163 break;
16164 case OPC_DPAQ_SA_L_PW:
16165 check_dsp(ctx);
16166 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16167 break;
16168 case OPC_DPAU_H_OBL:
16169 check_dsp(ctx);
16170 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
16171 break;
16172 case OPC_DPAU_H_OBR:
16173 check_dsp(ctx);
16174 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
16175 break;
16176 case OPC_DPS_W_QH:
16177 check_dspr2(ctx);
16178 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
16179 break;
16180 case OPC_DPSQ_S_W_QH:
16181 check_dsp(ctx);
16182 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16183 break;
16184 case OPC_DPSQ_SA_L_PW:
16185 check_dsp(ctx);
16186 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16187 break;
16188 case OPC_DPSU_H_OBL:
16189 check_dsp(ctx);
16190 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
16191 break;
16192 case OPC_DPSU_H_OBR:
16193 check_dsp(ctx);
16194 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
16195 break;
16196 case OPC_MAQ_S_L_PWL:
16197 check_dsp(ctx);
16198 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
16199 break;
16200 case OPC_MAQ_S_L_PWR:
16201 check_dsp(ctx);
16202 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
16203 break;
16204 case OPC_MAQ_S_W_QHLL:
16205 check_dsp(ctx);
16206 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
16207 break;
16208 case OPC_MAQ_SA_W_QHLL:
16209 check_dsp(ctx);
16210 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
16211 break;
16212 case OPC_MAQ_S_W_QHLR:
16213 check_dsp(ctx);
16214 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
16215 break;
16216 case OPC_MAQ_SA_W_QHLR:
16217 check_dsp(ctx);
16218 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
16219 break;
16220 case OPC_MAQ_S_W_QHRL:
16221 check_dsp(ctx);
16222 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
16223 break;
16224 case OPC_MAQ_SA_W_QHRL:
16225 check_dsp(ctx);
16226 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
16227 break;
16228 case OPC_MAQ_S_W_QHRR:
16229 check_dsp(ctx);
16230 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
16231 break;
16232 case OPC_MAQ_SA_W_QHRR:
16233 check_dsp(ctx);
16234 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
16235 break;
16236 case OPC_MULSAQ_S_L_PW:
16237 check_dsp(ctx);
16238 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
16239 break;
16240 case OPC_MULSAQ_S_W_QH:
16241 check_dsp(ctx);
16242 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16243 break;
16246 break;
16247 #endif
16248 case OPC_ADDU_QB_DSP:
16249 switch (op2) {
16250 case OPC_MULEU_S_PH_QBL:
16251 check_dsp(ctx);
16252 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16253 break;
16254 case OPC_MULEU_S_PH_QBR:
16255 check_dsp(ctx);
16256 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16257 break;
16258 case OPC_MULQ_RS_PH:
16259 check_dsp(ctx);
16260 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16261 break;
16262 case OPC_MULEQ_S_W_PHL:
16263 check_dsp(ctx);
16264 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16265 break;
16266 case OPC_MULEQ_S_W_PHR:
16267 check_dsp(ctx);
16268 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16269 break;
16270 case OPC_MULQ_S_PH:
16271 check_dspr2(ctx);
16272 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16273 break;
16275 break;
16276 #ifdef TARGET_MIPS64
16277 case OPC_ADDU_OB_DSP:
16278 switch (op2) {
16279 case OPC_MULEQ_S_PW_QHL:
16280 check_dsp(ctx);
16281 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16282 break;
16283 case OPC_MULEQ_S_PW_QHR:
16284 check_dsp(ctx);
16285 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16286 break;
16287 case OPC_MULEU_S_QH_OBL:
16288 check_dsp(ctx);
16289 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16290 break;
16291 case OPC_MULEU_S_QH_OBR:
16292 check_dsp(ctx);
16293 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16294 break;
16295 case OPC_MULQ_RS_QH:
16296 check_dsp(ctx);
16297 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16298 break;
16300 break;
16301 #endif
16304 tcg_temp_free_i32(t0);
16305 tcg_temp_free(v1_t);
16306 tcg_temp_free(v2_t);
16309 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16310 int ret, int val)
16312 int16_t imm;
16313 TCGv t0;
16314 TCGv val_t;
16316 if (ret == 0) {
16317 /* Treat as NOP. */
16318 return;
16321 t0 = tcg_temp_new();
16322 val_t = tcg_temp_new();
16323 gen_load_gpr(val_t, val);
16325 switch (op1) {
16326 case OPC_ABSQ_S_PH_DSP:
16327 switch (op2) {
16328 case OPC_BITREV:
16329 check_dsp(ctx);
16330 gen_helper_bitrev(cpu_gpr[ret], val_t);
16331 break;
16332 case OPC_REPL_QB:
16333 check_dsp(ctx);
16335 target_long result;
16336 imm = (ctx->opcode >> 16) & 0xFF;
16337 result = (uint32_t)imm << 24 |
16338 (uint32_t)imm << 16 |
16339 (uint32_t)imm << 8 |
16340 (uint32_t)imm;
16341 result = (int32_t)result;
16342 tcg_gen_movi_tl(cpu_gpr[ret], result);
16344 break;
16345 case OPC_REPLV_QB:
16346 check_dsp(ctx);
16347 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16348 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16349 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16350 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16351 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16352 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16353 break;
16354 case OPC_REPL_PH:
16355 check_dsp(ctx);
16357 imm = (ctx->opcode >> 16) & 0x03FF;
16358 imm = (int16_t)(imm << 6) >> 6;
16359 tcg_gen_movi_tl(cpu_gpr[ret], \
16360 (target_long)((int32_t)imm << 16 | \
16361 (uint16_t)imm));
16363 break;
16364 case OPC_REPLV_PH:
16365 check_dsp(ctx);
16366 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16367 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16368 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16369 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16370 break;
16372 break;
16373 #ifdef TARGET_MIPS64
16374 case OPC_ABSQ_S_QH_DSP:
16375 switch (op2) {
16376 case OPC_REPL_OB:
16377 check_dsp(ctx);
16379 target_long temp;
16381 imm = (ctx->opcode >> 16) & 0xFF;
16382 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
16383 temp = (temp << 16) | temp;
16384 temp = (temp << 32) | temp;
16385 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16386 break;
16388 case OPC_REPL_PW:
16389 check_dsp(ctx);
16391 target_long temp;
16393 imm = (ctx->opcode >> 16) & 0x03FF;
16394 imm = (int16_t)(imm << 6) >> 6;
16395 temp = ((target_long)imm << 32) \
16396 | ((target_long)imm & 0xFFFFFFFF);
16397 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16398 break;
16400 case OPC_REPL_QH:
16401 check_dsp(ctx);
16403 target_long temp;
16405 imm = (ctx->opcode >> 16) & 0x03FF;
16406 imm = (int16_t)(imm << 6) >> 6;
16408 temp = ((uint64_t)(uint16_t)imm << 48) |
16409 ((uint64_t)(uint16_t)imm << 32) |
16410 ((uint64_t)(uint16_t)imm << 16) |
16411 (uint64_t)(uint16_t)imm;
16412 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16413 break;
16415 case OPC_REPLV_OB:
16416 check_dsp(ctx);
16417 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16418 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16419 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16420 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16421 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16422 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16423 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16424 break;
16425 case OPC_REPLV_PW:
16426 check_dsp(ctx);
16427 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
16428 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16429 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16430 break;
16431 case OPC_REPLV_QH:
16432 check_dsp(ctx);
16433 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16434 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16435 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16436 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16437 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16438 break;
16440 break;
16441 #endif
16443 tcg_temp_free(t0);
16444 tcg_temp_free(val_t);
16447 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
16448 uint32_t op1, uint32_t op2,
16449 int ret, int v1, int v2, int check_ret)
16451 TCGv t1;
16452 TCGv v1_t;
16453 TCGv v2_t;
16455 if ((ret == 0) && (check_ret == 1)) {
16456 /* Treat as NOP. */
16457 return;
16460 t1 = tcg_temp_new();
16461 v1_t = tcg_temp_new();
16462 v2_t = tcg_temp_new();
16464 gen_load_gpr(v1_t, v1);
16465 gen_load_gpr(v2_t, v2);
16467 switch (op1) {
16468 case OPC_CMPU_EQ_QB_DSP:
16469 switch (op2) {
16470 case OPC_CMPU_EQ_QB:
16471 check_dsp(ctx);
16472 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
16473 break;
16474 case OPC_CMPU_LT_QB:
16475 check_dsp(ctx);
16476 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
16477 break;
16478 case OPC_CMPU_LE_QB:
16479 check_dsp(ctx);
16480 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
16481 break;
16482 case OPC_CMPGU_EQ_QB:
16483 check_dsp(ctx);
16484 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
16485 break;
16486 case OPC_CMPGU_LT_QB:
16487 check_dsp(ctx);
16488 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
16489 break;
16490 case OPC_CMPGU_LE_QB:
16491 check_dsp(ctx);
16492 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
16493 break;
16494 case OPC_CMPGDU_EQ_QB:
16495 check_dspr2(ctx);
16496 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
16497 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16498 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16499 tcg_gen_shli_tl(t1, t1, 24);
16500 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16501 break;
16502 case OPC_CMPGDU_LT_QB:
16503 check_dspr2(ctx);
16504 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
16505 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16506 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16507 tcg_gen_shli_tl(t1, t1, 24);
16508 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16509 break;
16510 case OPC_CMPGDU_LE_QB:
16511 check_dspr2(ctx);
16512 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
16513 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16514 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16515 tcg_gen_shli_tl(t1, t1, 24);
16516 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16517 break;
16518 case OPC_CMP_EQ_PH:
16519 check_dsp(ctx);
16520 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
16521 break;
16522 case OPC_CMP_LT_PH:
16523 check_dsp(ctx);
16524 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
16525 break;
16526 case OPC_CMP_LE_PH:
16527 check_dsp(ctx);
16528 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
16529 break;
16530 case OPC_PICK_QB:
16531 check_dsp(ctx);
16532 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16533 break;
16534 case OPC_PICK_PH:
16535 check_dsp(ctx);
16536 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16537 break;
16538 case OPC_PACKRL_PH:
16539 check_dsp(ctx);
16540 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
16541 break;
16543 break;
16544 #ifdef TARGET_MIPS64
16545 case OPC_CMPU_EQ_OB_DSP:
16546 switch (op2) {
16547 case OPC_CMP_EQ_PW:
16548 check_dsp(ctx);
16549 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
16550 break;
16551 case OPC_CMP_LT_PW:
16552 check_dsp(ctx);
16553 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
16554 break;
16555 case OPC_CMP_LE_PW:
16556 check_dsp(ctx);
16557 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
16558 break;
16559 case OPC_CMP_EQ_QH:
16560 check_dsp(ctx);
16561 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
16562 break;
16563 case OPC_CMP_LT_QH:
16564 check_dsp(ctx);
16565 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
16566 break;
16567 case OPC_CMP_LE_QH:
16568 check_dsp(ctx);
16569 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
16570 break;
16571 case OPC_CMPGDU_EQ_OB:
16572 check_dspr2(ctx);
16573 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16574 break;
16575 case OPC_CMPGDU_LT_OB:
16576 check_dspr2(ctx);
16577 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16578 break;
16579 case OPC_CMPGDU_LE_OB:
16580 check_dspr2(ctx);
16581 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16582 break;
16583 case OPC_CMPGU_EQ_OB:
16584 check_dsp(ctx);
16585 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
16586 break;
16587 case OPC_CMPGU_LT_OB:
16588 check_dsp(ctx);
16589 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
16590 break;
16591 case OPC_CMPGU_LE_OB:
16592 check_dsp(ctx);
16593 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
16594 break;
16595 case OPC_CMPU_EQ_OB:
16596 check_dsp(ctx);
16597 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
16598 break;
16599 case OPC_CMPU_LT_OB:
16600 check_dsp(ctx);
16601 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
16602 break;
16603 case OPC_CMPU_LE_OB:
16604 check_dsp(ctx);
16605 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
16606 break;
16607 case OPC_PACKRL_PW:
16608 check_dsp(ctx);
16609 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
16610 break;
16611 case OPC_PICK_OB:
16612 check_dsp(ctx);
16613 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16614 break;
16615 case OPC_PICK_PW:
16616 check_dsp(ctx);
16617 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16618 break;
16619 case OPC_PICK_QH:
16620 check_dsp(ctx);
16621 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16622 break;
16624 break;
16625 #endif
16628 tcg_temp_free(t1);
16629 tcg_temp_free(v1_t);
16630 tcg_temp_free(v2_t);
16633 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
16634 uint32_t op1, int rt, int rs, int sa)
16636 TCGv t0;
16638 check_dspr2(ctx);
16640 if (rt == 0) {
16641 /* Treat as NOP. */
16642 return;
16645 t0 = tcg_temp_new();
16646 gen_load_gpr(t0, rs);
16648 switch (op1) {
16649 case OPC_APPEND_DSP:
16650 switch (MASK_APPEND(ctx->opcode)) {
16651 case OPC_APPEND:
16652 if (sa != 0) {
16653 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
16655 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16656 break;
16657 case OPC_PREPEND:
16658 if (sa != 0) {
16659 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
16660 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16661 tcg_gen_shli_tl(t0, t0, 32 - sa);
16662 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16664 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16665 break;
16666 case OPC_BALIGN:
16667 sa &= 3;
16668 if (sa != 0 && sa != 2) {
16669 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16670 tcg_gen_ext32u_tl(t0, t0);
16671 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
16672 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16674 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16675 break;
16676 default: /* Invalid */
16677 MIPS_INVAL("MASK APPEND");
16678 generate_exception_end(ctx, EXCP_RI);
16679 break;
16681 break;
16682 #ifdef TARGET_MIPS64
16683 case OPC_DAPPEND_DSP:
16684 switch (MASK_DAPPEND(ctx->opcode)) {
16685 case OPC_DAPPEND:
16686 if (sa != 0) {
16687 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
16689 break;
16690 case OPC_PREPENDD:
16691 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
16692 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
16693 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
16694 break;
16695 case OPC_PREPENDW:
16696 if (sa != 0) {
16697 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16698 tcg_gen_shli_tl(t0, t0, 64 - sa);
16699 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16701 break;
16702 case OPC_DBALIGN:
16703 sa &= 7;
16704 if (sa != 0 && sa != 2 && sa != 4) {
16705 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16706 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
16707 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16709 break;
16710 default: /* Invalid */
16711 MIPS_INVAL("MASK DAPPEND");
16712 generate_exception_end(ctx, EXCP_RI);
16713 break;
16715 break;
16716 #endif
16718 tcg_temp_free(t0);
16721 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16722 int ret, int v1, int v2, int check_ret)
16725 TCGv t0;
16726 TCGv t1;
16727 TCGv v1_t;
16728 TCGv v2_t;
16729 int16_t imm;
16731 if ((ret == 0) && (check_ret == 1)) {
16732 /* Treat as NOP. */
16733 return;
16736 t0 = tcg_temp_new();
16737 t1 = tcg_temp_new();
16738 v1_t = tcg_temp_new();
16739 v2_t = tcg_temp_new();
16741 gen_load_gpr(v1_t, v1);
16742 gen_load_gpr(v2_t, v2);
16744 switch (op1) {
16745 case OPC_EXTR_W_DSP:
16746 check_dsp(ctx);
16747 switch (op2) {
16748 case OPC_EXTR_W:
16749 tcg_gen_movi_tl(t0, v2);
16750 tcg_gen_movi_tl(t1, v1);
16751 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
16752 break;
16753 case OPC_EXTR_R_W:
16754 tcg_gen_movi_tl(t0, v2);
16755 tcg_gen_movi_tl(t1, v1);
16756 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16757 break;
16758 case OPC_EXTR_RS_W:
16759 tcg_gen_movi_tl(t0, v2);
16760 tcg_gen_movi_tl(t1, v1);
16761 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16762 break;
16763 case OPC_EXTR_S_H:
16764 tcg_gen_movi_tl(t0, v2);
16765 tcg_gen_movi_tl(t1, v1);
16766 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16767 break;
16768 case OPC_EXTRV_S_H:
16769 tcg_gen_movi_tl(t0, v2);
16770 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
16771 break;
16772 case OPC_EXTRV_W:
16773 tcg_gen_movi_tl(t0, v2);
16774 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16775 break;
16776 case OPC_EXTRV_R_W:
16777 tcg_gen_movi_tl(t0, v2);
16778 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16779 break;
16780 case OPC_EXTRV_RS_W:
16781 tcg_gen_movi_tl(t0, v2);
16782 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16783 break;
16784 case OPC_EXTP:
16785 tcg_gen_movi_tl(t0, v2);
16786 tcg_gen_movi_tl(t1, v1);
16787 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
16788 break;
16789 case OPC_EXTPV:
16790 tcg_gen_movi_tl(t0, v2);
16791 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
16792 break;
16793 case OPC_EXTPDP:
16794 tcg_gen_movi_tl(t0, v2);
16795 tcg_gen_movi_tl(t1, v1);
16796 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
16797 break;
16798 case OPC_EXTPDPV:
16799 tcg_gen_movi_tl(t0, v2);
16800 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16801 break;
16802 case OPC_SHILO:
16803 imm = (ctx->opcode >> 20) & 0x3F;
16804 tcg_gen_movi_tl(t0, ret);
16805 tcg_gen_movi_tl(t1, imm);
16806 gen_helper_shilo(t0, t1, cpu_env);
16807 break;
16808 case OPC_SHILOV:
16809 tcg_gen_movi_tl(t0, ret);
16810 gen_helper_shilo(t0, v1_t, cpu_env);
16811 break;
16812 case OPC_MTHLIP:
16813 tcg_gen_movi_tl(t0, ret);
16814 gen_helper_mthlip(t0, v1_t, cpu_env);
16815 break;
16816 case OPC_WRDSP:
16817 imm = (ctx->opcode >> 11) & 0x3FF;
16818 tcg_gen_movi_tl(t0, imm);
16819 gen_helper_wrdsp(v1_t, t0, cpu_env);
16820 break;
16821 case OPC_RDDSP:
16822 imm = (ctx->opcode >> 16) & 0x03FF;
16823 tcg_gen_movi_tl(t0, imm);
16824 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
16825 break;
16827 break;
16828 #ifdef TARGET_MIPS64
16829 case OPC_DEXTR_W_DSP:
16830 check_dsp(ctx);
16831 switch (op2) {
16832 case OPC_DMTHLIP:
16833 tcg_gen_movi_tl(t0, ret);
16834 gen_helper_dmthlip(v1_t, t0, cpu_env);
16835 break;
16836 case OPC_DSHILO:
16838 int shift = (ctx->opcode >> 19) & 0x7F;
16839 int ac = (ctx->opcode >> 11) & 0x03;
16840 tcg_gen_movi_tl(t0, shift);
16841 tcg_gen_movi_tl(t1, ac);
16842 gen_helper_dshilo(t0, t1, cpu_env);
16843 break;
16845 case OPC_DSHILOV:
16847 int ac = (ctx->opcode >> 11) & 0x03;
16848 tcg_gen_movi_tl(t0, ac);
16849 gen_helper_dshilo(v1_t, t0, cpu_env);
16850 break;
16852 case OPC_DEXTP:
16853 tcg_gen_movi_tl(t0, v2);
16854 tcg_gen_movi_tl(t1, v1);
16856 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
16857 break;
16858 case OPC_DEXTPV:
16859 tcg_gen_movi_tl(t0, v2);
16860 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
16861 break;
16862 case OPC_DEXTPDP:
16863 tcg_gen_movi_tl(t0, v2);
16864 tcg_gen_movi_tl(t1, v1);
16865 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
16866 break;
16867 case OPC_DEXTPDPV:
16868 tcg_gen_movi_tl(t0, v2);
16869 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16870 break;
16871 case OPC_DEXTR_L:
16872 tcg_gen_movi_tl(t0, v2);
16873 tcg_gen_movi_tl(t1, v1);
16874 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
16875 break;
16876 case OPC_DEXTR_R_L:
16877 tcg_gen_movi_tl(t0, v2);
16878 tcg_gen_movi_tl(t1, v1);
16879 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
16880 break;
16881 case OPC_DEXTR_RS_L:
16882 tcg_gen_movi_tl(t0, v2);
16883 tcg_gen_movi_tl(t1, v1);
16884 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
16885 break;
16886 case OPC_DEXTR_W:
16887 tcg_gen_movi_tl(t0, v2);
16888 tcg_gen_movi_tl(t1, v1);
16889 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
16890 break;
16891 case OPC_DEXTR_R_W:
16892 tcg_gen_movi_tl(t0, v2);
16893 tcg_gen_movi_tl(t1, v1);
16894 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16895 break;
16896 case OPC_DEXTR_RS_W:
16897 tcg_gen_movi_tl(t0, v2);
16898 tcg_gen_movi_tl(t1, v1);
16899 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16900 break;
16901 case OPC_DEXTR_S_H:
16902 tcg_gen_movi_tl(t0, v2);
16903 tcg_gen_movi_tl(t1, v1);
16904 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16905 break;
16906 case OPC_DEXTRV_S_H:
16907 tcg_gen_movi_tl(t0, v2);
16908 tcg_gen_movi_tl(t1, v1);
16909 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16910 break;
16911 case OPC_DEXTRV_L:
16912 tcg_gen_movi_tl(t0, v2);
16913 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16914 break;
16915 case OPC_DEXTRV_R_L:
16916 tcg_gen_movi_tl(t0, v2);
16917 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16918 break;
16919 case OPC_DEXTRV_RS_L:
16920 tcg_gen_movi_tl(t0, v2);
16921 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16922 break;
16923 case OPC_DEXTRV_W:
16924 tcg_gen_movi_tl(t0, v2);
16925 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16926 break;
16927 case OPC_DEXTRV_R_W:
16928 tcg_gen_movi_tl(t0, v2);
16929 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16930 break;
16931 case OPC_DEXTRV_RS_W:
16932 tcg_gen_movi_tl(t0, v2);
16933 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16934 break;
16936 break;
16937 #endif
16940 tcg_temp_free(t0);
16941 tcg_temp_free(t1);
16942 tcg_temp_free(v1_t);
16943 tcg_temp_free(v2_t);
16946 /* End MIPSDSP functions. */
16948 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
16950 int rs, rt, rd, sa;
16951 uint32_t op1, op2;
16953 rs = (ctx->opcode >> 21) & 0x1f;
16954 rt = (ctx->opcode >> 16) & 0x1f;
16955 rd = (ctx->opcode >> 11) & 0x1f;
16956 sa = (ctx->opcode >> 6) & 0x1f;
16958 op1 = MASK_SPECIAL(ctx->opcode);
16959 switch (op1) {
16960 case OPC_LSA:
16961 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
16962 break;
16963 case OPC_MULT ... OPC_DIVU:
16964 op2 = MASK_R6_MULDIV(ctx->opcode);
16965 switch (op2) {
16966 case R6_OPC_MUL:
16967 case R6_OPC_MUH:
16968 case R6_OPC_MULU:
16969 case R6_OPC_MUHU:
16970 case R6_OPC_DIV:
16971 case R6_OPC_MOD:
16972 case R6_OPC_DIVU:
16973 case R6_OPC_MODU:
16974 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16975 break;
16976 default:
16977 MIPS_INVAL("special_r6 muldiv");
16978 generate_exception_end(ctx, EXCP_RI);
16979 break;
16981 break;
16982 case OPC_SELEQZ:
16983 case OPC_SELNEZ:
16984 gen_cond_move(ctx, op1, rd, rs, rt);
16985 break;
16986 case R6_OPC_CLO:
16987 case R6_OPC_CLZ:
16988 if (rt == 0 && sa == 1) {
16989 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16990 We need additionally to check other fields */
16991 gen_cl(ctx, op1, rd, rs);
16992 } else {
16993 generate_exception_end(ctx, EXCP_RI);
16995 break;
16996 case R6_OPC_SDBBP:
16997 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
16998 gen_helper_do_semihosting(cpu_env);
16999 } else {
17000 if (ctx->hflags & MIPS_HFLAG_SBRI) {
17001 generate_exception_end(ctx, EXCP_RI);
17002 } else {
17003 generate_exception_end(ctx, EXCP_DBp);
17006 break;
17007 #if defined(TARGET_MIPS64)
17008 case OPC_DLSA:
17009 check_mips_64(ctx);
17010 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
17011 break;
17012 case R6_OPC_DCLO:
17013 case R6_OPC_DCLZ:
17014 if (rt == 0 && sa == 1) {
17015 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17016 We need additionally to check other fields */
17017 check_mips_64(ctx);
17018 gen_cl(ctx, op1, rd, rs);
17019 } else {
17020 generate_exception_end(ctx, EXCP_RI);
17022 break;
17023 case OPC_DMULT ... OPC_DDIVU:
17024 op2 = MASK_R6_MULDIV(ctx->opcode);
17025 switch (op2) {
17026 case R6_OPC_DMUL:
17027 case R6_OPC_DMUH:
17028 case R6_OPC_DMULU:
17029 case R6_OPC_DMUHU:
17030 case R6_OPC_DDIV:
17031 case R6_OPC_DMOD:
17032 case R6_OPC_DDIVU:
17033 case R6_OPC_DMODU:
17034 check_mips_64(ctx);
17035 gen_r6_muldiv(ctx, op2, rd, rs, rt);
17036 break;
17037 default:
17038 MIPS_INVAL("special_r6 muldiv");
17039 generate_exception_end(ctx, EXCP_RI);
17040 break;
17042 break;
17043 #endif
17044 default: /* Invalid */
17045 MIPS_INVAL("special_r6");
17046 generate_exception_end(ctx, EXCP_RI);
17047 break;
17051 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
17053 int rs, rt, rd, sa;
17054 uint32_t op1;
17056 rs = (ctx->opcode >> 21) & 0x1f;
17057 rt = (ctx->opcode >> 16) & 0x1f;
17058 rd = (ctx->opcode >> 11) & 0x1f;
17059 sa = (ctx->opcode >> 6) & 0x1f;
17061 op1 = MASK_SPECIAL(ctx->opcode);
17062 switch (op1) {
17063 case OPC_MOVN: /* Conditional move */
17064 case OPC_MOVZ:
17065 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
17066 INSN_LOONGSON2E | INSN_LOONGSON2F);
17067 gen_cond_move(ctx, op1, rd, rs, rt);
17068 break;
17069 case OPC_MFHI: /* Move from HI/LO */
17070 case OPC_MFLO:
17071 gen_HILO(ctx, op1, rs & 3, rd);
17072 break;
17073 case OPC_MTHI:
17074 case OPC_MTLO: /* Move to HI/LO */
17075 gen_HILO(ctx, op1, rd & 3, rs);
17076 break;
17077 case OPC_MOVCI:
17078 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
17079 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17080 check_cp1_enabled(ctx);
17081 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
17082 (ctx->opcode >> 16) & 1);
17083 } else {
17084 generate_exception_err(ctx, EXCP_CpU, 1);
17086 break;
17087 case OPC_MULT:
17088 case OPC_MULTU:
17089 if (sa) {
17090 check_insn(ctx, INSN_VR54XX);
17091 op1 = MASK_MUL_VR54XX(ctx->opcode);
17092 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
17093 } else {
17094 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17096 break;
17097 case OPC_DIV:
17098 case OPC_DIVU:
17099 gen_muldiv(ctx, op1, 0, rs, rt);
17100 break;
17101 #if defined(TARGET_MIPS64)
17102 case OPC_DMULT ... OPC_DDIVU:
17103 check_insn(ctx, ISA_MIPS3);
17104 check_mips_64(ctx);
17105 gen_muldiv(ctx, op1, 0, rs, rt);
17106 break;
17107 #endif
17108 case OPC_JR:
17109 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17110 break;
17111 case OPC_SPIM:
17112 #ifdef MIPS_STRICT_STANDARD
17113 MIPS_INVAL("SPIM");
17114 generate_exception_end(ctx, EXCP_RI);
17115 #else
17116 /* Implemented as RI exception for now. */
17117 MIPS_INVAL("spim (unofficial)");
17118 generate_exception_end(ctx, EXCP_RI);
17119 #endif
17120 break;
17121 default: /* Invalid */
17122 MIPS_INVAL("special_legacy");
17123 generate_exception_end(ctx, EXCP_RI);
17124 break;
17128 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
17130 int rs, rt, rd, sa;
17131 uint32_t op1;
17133 rs = (ctx->opcode >> 21) & 0x1f;
17134 rt = (ctx->opcode >> 16) & 0x1f;
17135 rd = (ctx->opcode >> 11) & 0x1f;
17136 sa = (ctx->opcode >> 6) & 0x1f;
17138 op1 = MASK_SPECIAL(ctx->opcode);
17139 switch (op1) {
17140 case OPC_SLL: /* Shift with immediate */
17141 if (sa == 5 && rd == 0 &&
17142 rs == 0 && rt == 0) { /* PAUSE */
17143 if ((ctx->insn_flags & ISA_MIPS32R6) &&
17144 (ctx->hflags & MIPS_HFLAG_BMASK)) {
17145 generate_exception_end(ctx, EXCP_RI);
17146 break;
17149 /* Fallthrough */
17150 case OPC_SRA:
17151 gen_shift_imm(ctx, op1, rd, rt, sa);
17152 break;
17153 case OPC_SRL:
17154 switch ((ctx->opcode >> 21) & 0x1f) {
17155 case 1:
17156 /* rotr is decoded as srl on non-R2 CPUs */
17157 if (ctx->insn_flags & ISA_MIPS32R2) {
17158 op1 = OPC_ROTR;
17160 /* Fallthrough */
17161 case 0:
17162 gen_shift_imm(ctx, op1, rd, rt, sa);
17163 break;
17164 default:
17165 generate_exception_end(ctx, EXCP_RI);
17166 break;
17168 break;
17169 case OPC_ADD ... OPC_SUBU:
17170 gen_arith(ctx, op1, rd, rs, rt);
17171 break;
17172 case OPC_SLLV: /* Shifts */
17173 case OPC_SRAV:
17174 gen_shift(ctx, op1, rd, rs, rt);
17175 break;
17176 case OPC_SRLV:
17177 switch ((ctx->opcode >> 6) & 0x1f) {
17178 case 1:
17179 /* rotrv is decoded as srlv on non-R2 CPUs */
17180 if (ctx->insn_flags & ISA_MIPS32R2) {
17181 op1 = OPC_ROTRV;
17183 /* Fallthrough */
17184 case 0:
17185 gen_shift(ctx, op1, rd, rs, rt);
17186 break;
17187 default:
17188 generate_exception_end(ctx, EXCP_RI);
17189 break;
17191 break;
17192 case OPC_SLT: /* Set on less than */
17193 case OPC_SLTU:
17194 gen_slt(ctx, op1, rd, rs, rt);
17195 break;
17196 case OPC_AND: /* Logic*/
17197 case OPC_OR:
17198 case OPC_NOR:
17199 case OPC_XOR:
17200 gen_logic(ctx, op1, rd, rs, rt);
17201 break;
17202 case OPC_JALR:
17203 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17204 break;
17205 case OPC_TGE ... OPC_TEQ: /* Traps */
17206 case OPC_TNE:
17207 check_insn(ctx, ISA_MIPS2);
17208 gen_trap(ctx, op1, rs, rt, -1);
17209 break;
17210 case OPC_LSA: /* OPC_PMON */
17211 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17212 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17213 decode_opc_special_r6(env, ctx);
17214 } else {
17215 /* Pmon entry point, also R4010 selsl */
17216 #ifdef MIPS_STRICT_STANDARD
17217 MIPS_INVAL("PMON / selsl");
17218 generate_exception_end(ctx, EXCP_RI);
17219 #else
17220 gen_helper_0e0i(pmon, sa);
17221 #endif
17223 break;
17224 case OPC_SYSCALL:
17225 generate_exception_end(ctx, EXCP_SYSCALL);
17226 break;
17227 case OPC_BREAK:
17228 generate_exception_end(ctx, EXCP_BREAK);
17229 break;
17230 case OPC_SYNC:
17231 check_insn(ctx, ISA_MIPS2);
17232 gen_sync(extract32(ctx->opcode, 6, 5));
17233 break;
17235 #if defined(TARGET_MIPS64)
17236 /* MIPS64 specific opcodes */
17237 case OPC_DSLL:
17238 case OPC_DSRA:
17239 case OPC_DSLL32:
17240 case OPC_DSRA32:
17241 check_insn(ctx, ISA_MIPS3);
17242 check_mips_64(ctx);
17243 gen_shift_imm(ctx, op1, rd, rt, sa);
17244 break;
17245 case OPC_DSRL:
17246 switch ((ctx->opcode >> 21) & 0x1f) {
17247 case 1:
17248 /* drotr is decoded as dsrl on non-R2 CPUs */
17249 if (ctx->insn_flags & ISA_MIPS32R2) {
17250 op1 = OPC_DROTR;
17252 /* Fallthrough */
17253 case 0:
17254 check_insn(ctx, ISA_MIPS3);
17255 check_mips_64(ctx);
17256 gen_shift_imm(ctx, op1, rd, rt, sa);
17257 break;
17258 default:
17259 generate_exception_end(ctx, EXCP_RI);
17260 break;
17262 break;
17263 case OPC_DSRL32:
17264 switch ((ctx->opcode >> 21) & 0x1f) {
17265 case 1:
17266 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
17267 if (ctx->insn_flags & ISA_MIPS32R2) {
17268 op1 = OPC_DROTR32;
17270 /* Fallthrough */
17271 case 0:
17272 check_insn(ctx, ISA_MIPS3);
17273 check_mips_64(ctx);
17274 gen_shift_imm(ctx, op1, rd, rt, sa);
17275 break;
17276 default:
17277 generate_exception_end(ctx, EXCP_RI);
17278 break;
17280 break;
17281 case OPC_DADD ... OPC_DSUBU:
17282 check_insn(ctx, ISA_MIPS3);
17283 check_mips_64(ctx);
17284 gen_arith(ctx, op1, rd, rs, rt);
17285 break;
17286 case OPC_DSLLV:
17287 case OPC_DSRAV:
17288 check_insn(ctx, ISA_MIPS3);
17289 check_mips_64(ctx);
17290 gen_shift(ctx, op1, rd, rs, rt);
17291 break;
17292 case OPC_DSRLV:
17293 switch ((ctx->opcode >> 6) & 0x1f) {
17294 case 1:
17295 /* drotrv is decoded as dsrlv on non-R2 CPUs */
17296 if (ctx->insn_flags & ISA_MIPS32R2) {
17297 op1 = OPC_DROTRV;
17299 /* Fallthrough */
17300 case 0:
17301 check_insn(ctx, ISA_MIPS3);
17302 check_mips_64(ctx);
17303 gen_shift(ctx, op1, rd, rs, rt);
17304 break;
17305 default:
17306 generate_exception_end(ctx, EXCP_RI);
17307 break;
17309 break;
17310 case OPC_DLSA:
17311 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17312 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17313 decode_opc_special_r6(env, ctx);
17315 break;
17316 #endif
17317 default:
17318 if (ctx->insn_flags & ISA_MIPS32R6) {
17319 decode_opc_special_r6(env, ctx);
17320 } else {
17321 decode_opc_special_legacy(env, ctx);
17326 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
17328 int rs, rt, rd;
17329 uint32_t op1;
17331 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17333 rs = (ctx->opcode >> 21) & 0x1f;
17334 rt = (ctx->opcode >> 16) & 0x1f;
17335 rd = (ctx->opcode >> 11) & 0x1f;
17337 op1 = MASK_SPECIAL2(ctx->opcode);
17338 switch (op1) {
17339 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
17340 case OPC_MSUB ... OPC_MSUBU:
17341 check_insn(ctx, ISA_MIPS32);
17342 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17343 break;
17344 case OPC_MUL:
17345 gen_arith(ctx, op1, rd, rs, rt);
17346 break;
17347 case OPC_DIV_G_2F:
17348 case OPC_DIVU_G_2F:
17349 case OPC_MULT_G_2F:
17350 case OPC_MULTU_G_2F:
17351 case OPC_MOD_G_2F:
17352 case OPC_MODU_G_2F:
17353 check_insn(ctx, INSN_LOONGSON2F);
17354 gen_loongson_integer(ctx, op1, rd, rs, rt);
17355 break;
17356 case OPC_CLO:
17357 case OPC_CLZ:
17358 check_insn(ctx, ISA_MIPS32);
17359 gen_cl(ctx, op1, rd, rs);
17360 break;
17361 case OPC_SDBBP:
17362 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17363 gen_helper_do_semihosting(cpu_env);
17364 } else {
17365 /* XXX: not clear which exception should be raised
17366 * when in debug mode...
17368 check_insn(ctx, ISA_MIPS32);
17369 generate_exception_end(ctx, EXCP_DBp);
17371 break;
17372 #if defined(TARGET_MIPS64)
17373 case OPC_DCLO:
17374 case OPC_DCLZ:
17375 check_insn(ctx, ISA_MIPS64);
17376 check_mips_64(ctx);
17377 gen_cl(ctx, op1, rd, rs);
17378 break;
17379 case OPC_DMULT_G_2F:
17380 case OPC_DMULTU_G_2F:
17381 case OPC_DDIV_G_2F:
17382 case OPC_DDIVU_G_2F:
17383 case OPC_DMOD_G_2F:
17384 case OPC_DMODU_G_2F:
17385 check_insn(ctx, INSN_LOONGSON2F);
17386 gen_loongson_integer(ctx, op1, rd, rs, rt);
17387 break;
17388 #endif
17389 default: /* Invalid */
17390 MIPS_INVAL("special2_legacy");
17391 generate_exception_end(ctx, EXCP_RI);
17392 break;
17396 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
17398 int rs, rt, rd, sa;
17399 uint32_t op1, op2;
17400 int16_t imm;
17402 rs = (ctx->opcode >> 21) & 0x1f;
17403 rt = (ctx->opcode >> 16) & 0x1f;
17404 rd = (ctx->opcode >> 11) & 0x1f;
17405 sa = (ctx->opcode >> 6) & 0x1f;
17406 imm = (int16_t)ctx->opcode >> 7;
17408 op1 = MASK_SPECIAL3(ctx->opcode);
17409 switch (op1) {
17410 case R6_OPC_PREF:
17411 if (rt >= 24) {
17412 /* hint codes 24-31 are reserved and signal RI */
17413 generate_exception_end(ctx, EXCP_RI);
17415 /* Treat as NOP. */
17416 break;
17417 case R6_OPC_CACHE:
17418 check_cp0_enabled(ctx);
17419 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17420 gen_cache_operation(ctx, rt, rs, imm);
17422 break;
17423 case R6_OPC_SC:
17424 gen_st_cond(ctx, op1, rt, rs, imm);
17425 break;
17426 case R6_OPC_LL:
17427 gen_ld(ctx, op1, rt, rs, imm);
17428 break;
17429 case OPC_BSHFL:
17431 if (rd == 0) {
17432 /* Treat as NOP. */
17433 break;
17435 op2 = MASK_BSHFL(ctx->opcode);
17436 switch (op2) {
17437 case OPC_ALIGN ... OPC_ALIGN_END:
17438 gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3);
17439 break;
17440 case OPC_BITSWAP:
17441 gen_bitswap(ctx, op2, rd, rt);
17442 break;
17445 break;
17446 #if defined(TARGET_MIPS64)
17447 case R6_OPC_SCD:
17448 gen_st_cond(ctx, op1, rt, rs, imm);
17449 break;
17450 case R6_OPC_LLD:
17451 gen_ld(ctx, op1, rt, rs, imm);
17452 break;
17453 case OPC_DBSHFL:
17454 check_mips_64(ctx);
17456 if (rd == 0) {
17457 /* Treat as NOP. */
17458 break;
17460 op2 = MASK_DBSHFL(ctx->opcode);
17461 switch (op2) {
17462 case OPC_DALIGN ... OPC_DALIGN_END:
17463 gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7);
17464 break;
17465 case OPC_DBITSWAP:
17466 gen_bitswap(ctx, op2, rd, rt);
17467 break;
17471 break;
17472 #endif
17473 default: /* Invalid */
17474 MIPS_INVAL("special3_r6");
17475 generate_exception_end(ctx, EXCP_RI);
17476 break;
17480 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
17482 int rs, rt, rd;
17483 uint32_t op1, op2;
17485 rs = (ctx->opcode >> 21) & 0x1f;
17486 rt = (ctx->opcode >> 16) & 0x1f;
17487 rd = (ctx->opcode >> 11) & 0x1f;
17489 op1 = MASK_SPECIAL3(ctx->opcode);
17490 switch (op1) {
17491 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
17492 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
17493 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
17494 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
17495 * the same mask and op1. */
17496 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
17497 op2 = MASK_ADDUH_QB(ctx->opcode);
17498 switch (op2) {
17499 case OPC_ADDUH_QB:
17500 case OPC_ADDUH_R_QB:
17501 case OPC_ADDQH_PH:
17502 case OPC_ADDQH_R_PH:
17503 case OPC_ADDQH_W:
17504 case OPC_ADDQH_R_W:
17505 case OPC_SUBUH_QB:
17506 case OPC_SUBUH_R_QB:
17507 case OPC_SUBQH_PH:
17508 case OPC_SUBQH_R_PH:
17509 case OPC_SUBQH_W:
17510 case OPC_SUBQH_R_W:
17511 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17512 break;
17513 case OPC_MUL_PH:
17514 case OPC_MUL_S_PH:
17515 case OPC_MULQ_S_W:
17516 case OPC_MULQ_RS_W:
17517 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17518 break;
17519 default:
17520 MIPS_INVAL("MASK ADDUH.QB");
17521 generate_exception_end(ctx, EXCP_RI);
17522 break;
17524 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
17525 gen_loongson_integer(ctx, op1, rd, rs, rt);
17526 } else {
17527 generate_exception_end(ctx, EXCP_RI);
17529 break;
17530 case OPC_LX_DSP:
17531 op2 = MASK_LX(ctx->opcode);
17532 switch (op2) {
17533 #if defined(TARGET_MIPS64)
17534 case OPC_LDX:
17535 #endif
17536 case OPC_LBUX:
17537 case OPC_LHX:
17538 case OPC_LWX:
17539 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
17540 break;
17541 default: /* Invalid */
17542 MIPS_INVAL("MASK LX");
17543 generate_exception_end(ctx, EXCP_RI);
17544 break;
17546 break;
17547 case OPC_ABSQ_S_PH_DSP:
17548 op2 = MASK_ABSQ_S_PH(ctx->opcode);
17549 switch (op2) {
17550 case OPC_ABSQ_S_QB:
17551 case OPC_ABSQ_S_PH:
17552 case OPC_ABSQ_S_W:
17553 case OPC_PRECEQ_W_PHL:
17554 case OPC_PRECEQ_W_PHR:
17555 case OPC_PRECEQU_PH_QBL:
17556 case OPC_PRECEQU_PH_QBR:
17557 case OPC_PRECEQU_PH_QBLA:
17558 case OPC_PRECEQU_PH_QBRA:
17559 case OPC_PRECEU_PH_QBL:
17560 case OPC_PRECEU_PH_QBR:
17561 case OPC_PRECEU_PH_QBLA:
17562 case OPC_PRECEU_PH_QBRA:
17563 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17564 break;
17565 case OPC_BITREV:
17566 case OPC_REPL_QB:
17567 case OPC_REPLV_QB:
17568 case OPC_REPL_PH:
17569 case OPC_REPLV_PH:
17570 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17571 break;
17572 default:
17573 MIPS_INVAL("MASK ABSQ_S.PH");
17574 generate_exception_end(ctx, EXCP_RI);
17575 break;
17577 break;
17578 case OPC_ADDU_QB_DSP:
17579 op2 = MASK_ADDU_QB(ctx->opcode);
17580 switch (op2) {
17581 case OPC_ADDQ_PH:
17582 case OPC_ADDQ_S_PH:
17583 case OPC_ADDQ_S_W:
17584 case OPC_ADDU_QB:
17585 case OPC_ADDU_S_QB:
17586 case OPC_ADDU_PH:
17587 case OPC_ADDU_S_PH:
17588 case OPC_SUBQ_PH:
17589 case OPC_SUBQ_S_PH:
17590 case OPC_SUBQ_S_W:
17591 case OPC_SUBU_QB:
17592 case OPC_SUBU_S_QB:
17593 case OPC_SUBU_PH:
17594 case OPC_SUBU_S_PH:
17595 case OPC_ADDSC:
17596 case OPC_ADDWC:
17597 case OPC_MODSUB:
17598 case OPC_RADDU_W_QB:
17599 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17600 break;
17601 case OPC_MULEU_S_PH_QBL:
17602 case OPC_MULEU_S_PH_QBR:
17603 case OPC_MULQ_RS_PH:
17604 case OPC_MULEQ_S_W_PHL:
17605 case OPC_MULEQ_S_W_PHR:
17606 case OPC_MULQ_S_PH:
17607 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17608 break;
17609 default: /* Invalid */
17610 MIPS_INVAL("MASK ADDU.QB");
17611 generate_exception_end(ctx, EXCP_RI);
17612 break;
17615 break;
17616 case OPC_CMPU_EQ_QB_DSP:
17617 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
17618 switch (op2) {
17619 case OPC_PRECR_SRA_PH_W:
17620 case OPC_PRECR_SRA_R_PH_W:
17621 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17622 break;
17623 case OPC_PRECR_QB_PH:
17624 case OPC_PRECRQ_QB_PH:
17625 case OPC_PRECRQ_PH_W:
17626 case OPC_PRECRQ_RS_PH_W:
17627 case OPC_PRECRQU_S_QB_PH:
17628 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17629 break;
17630 case OPC_CMPU_EQ_QB:
17631 case OPC_CMPU_LT_QB:
17632 case OPC_CMPU_LE_QB:
17633 case OPC_CMP_EQ_PH:
17634 case OPC_CMP_LT_PH:
17635 case OPC_CMP_LE_PH:
17636 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17637 break;
17638 case OPC_CMPGU_EQ_QB:
17639 case OPC_CMPGU_LT_QB:
17640 case OPC_CMPGU_LE_QB:
17641 case OPC_CMPGDU_EQ_QB:
17642 case OPC_CMPGDU_LT_QB:
17643 case OPC_CMPGDU_LE_QB:
17644 case OPC_PICK_QB:
17645 case OPC_PICK_PH:
17646 case OPC_PACKRL_PH:
17647 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17648 break;
17649 default: /* Invalid */
17650 MIPS_INVAL("MASK CMPU.EQ.QB");
17651 generate_exception_end(ctx, EXCP_RI);
17652 break;
17654 break;
17655 case OPC_SHLL_QB_DSP:
17656 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17657 break;
17658 case OPC_DPA_W_PH_DSP:
17659 op2 = MASK_DPA_W_PH(ctx->opcode);
17660 switch (op2) {
17661 case OPC_DPAU_H_QBL:
17662 case OPC_DPAU_H_QBR:
17663 case OPC_DPSU_H_QBL:
17664 case OPC_DPSU_H_QBR:
17665 case OPC_DPA_W_PH:
17666 case OPC_DPAX_W_PH:
17667 case OPC_DPAQ_S_W_PH:
17668 case OPC_DPAQX_S_W_PH:
17669 case OPC_DPAQX_SA_W_PH:
17670 case OPC_DPS_W_PH:
17671 case OPC_DPSX_W_PH:
17672 case OPC_DPSQ_S_W_PH:
17673 case OPC_DPSQX_S_W_PH:
17674 case OPC_DPSQX_SA_W_PH:
17675 case OPC_MULSAQ_S_W_PH:
17676 case OPC_DPAQ_SA_L_W:
17677 case OPC_DPSQ_SA_L_W:
17678 case OPC_MAQ_S_W_PHL:
17679 case OPC_MAQ_S_W_PHR:
17680 case OPC_MAQ_SA_W_PHL:
17681 case OPC_MAQ_SA_W_PHR:
17682 case OPC_MULSA_W_PH:
17683 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17684 break;
17685 default: /* Invalid */
17686 MIPS_INVAL("MASK DPAW.PH");
17687 generate_exception_end(ctx, EXCP_RI);
17688 break;
17690 break;
17691 case OPC_INSV_DSP:
17692 op2 = MASK_INSV(ctx->opcode);
17693 switch (op2) {
17694 case OPC_INSV:
17695 check_dsp(ctx);
17697 TCGv t0, t1;
17699 if (rt == 0) {
17700 break;
17703 t0 = tcg_temp_new();
17704 t1 = tcg_temp_new();
17706 gen_load_gpr(t0, rt);
17707 gen_load_gpr(t1, rs);
17709 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
17711 tcg_temp_free(t0);
17712 tcg_temp_free(t1);
17713 break;
17715 default: /* Invalid */
17716 MIPS_INVAL("MASK INSV");
17717 generate_exception_end(ctx, EXCP_RI);
17718 break;
17720 break;
17721 case OPC_APPEND_DSP:
17722 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17723 break;
17724 case OPC_EXTR_W_DSP:
17725 op2 = MASK_EXTR_W(ctx->opcode);
17726 switch (op2) {
17727 case OPC_EXTR_W:
17728 case OPC_EXTR_R_W:
17729 case OPC_EXTR_RS_W:
17730 case OPC_EXTR_S_H:
17731 case OPC_EXTRV_S_H:
17732 case OPC_EXTRV_W:
17733 case OPC_EXTRV_R_W:
17734 case OPC_EXTRV_RS_W:
17735 case OPC_EXTP:
17736 case OPC_EXTPV:
17737 case OPC_EXTPDP:
17738 case OPC_EXTPDPV:
17739 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17740 break;
17741 case OPC_RDDSP:
17742 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
17743 break;
17744 case OPC_SHILO:
17745 case OPC_SHILOV:
17746 case OPC_MTHLIP:
17747 case OPC_WRDSP:
17748 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17749 break;
17750 default: /* Invalid */
17751 MIPS_INVAL("MASK EXTR.W");
17752 generate_exception_end(ctx, EXCP_RI);
17753 break;
17755 break;
17756 #if defined(TARGET_MIPS64)
17757 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
17758 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
17759 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
17760 check_insn(ctx, INSN_LOONGSON2E);
17761 gen_loongson_integer(ctx, op1, rd, rs, rt);
17762 break;
17763 case OPC_ABSQ_S_QH_DSP:
17764 op2 = MASK_ABSQ_S_QH(ctx->opcode);
17765 switch (op2) {
17766 case OPC_PRECEQ_L_PWL:
17767 case OPC_PRECEQ_L_PWR:
17768 case OPC_PRECEQ_PW_QHL:
17769 case OPC_PRECEQ_PW_QHR:
17770 case OPC_PRECEQ_PW_QHLA:
17771 case OPC_PRECEQ_PW_QHRA:
17772 case OPC_PRECEQU_QH_OBL:
17773 case OPC_PRECEQU_QH_OBR:
17774 case OPC_PRECEQU_QH_OBLA:
17775 case OPC_PRECEQU_QH_OBRA:
17776 case OPC_PRECEU_QH_OBL:
17777 case OPC_PRECEU_QH_OBR:
17778 case OPC_PRECEU_QH_OBLA:
17779 case OPC_PRECEU_QH_OBRA:
17780 case OPC_ABSQ_S_OB:
17781 case OPC_ABSQ_S_PW:
17782 case OPC_ABSQ_S_QH:
17783 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17784 break;
17785 case OPC_REPL_OB:
17786 case OPC_REPL_PW:
17787 case OPC_REPL_QH:
17788 case OPC_REPLV_OB:
17789 case OPC_REPLV_PW:
17790 case OPC_REPLV_QH:
17791 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17792 break;
17793 default: /* Invalid */
17794 MIPS_INVAL("MASK ABSQ_S.QH");
17795 generate_exception_end(ctx, EXCP_RI);
17796 break;
17798 break;
17799 case OPC_ADDU_OB_DSP:
17800 op2 = MASK_ADDU_OB(ctx->opcode);
17801 switch (op2) {
17802 case OPC_RADDU_L_OB:
17803 case OPC_SUBQ_PW:
17804 case OPC_SUBQ_S_PW:
17805 case OPC_SUBQ_QH:
17806 case OPC_SUBQ_S_QH:
17807 case OPC_SUBU_OB:
17808 case OPC_SUBU_S_OB:
17809 case OPC_SUBU_QH:
17810 case OPC_SUBU_S_QH:
17811 case OPC_SUBUH_OB:
17812 case OPC_SUBUH_R_OB:
17813 case OPC_ADDQ_PW:
17814 case OPC_ADDQ_S_PW:
17815 case OPC_ADDQ_QH:
17816 case OPC_ADDQ_S_QH:
17817 case OPC_ADDU_OB:
17818 case OPC_ADDU_S_OB:
17819 case OPC_ADDU_QH:
17820 case OPC_ADDU_S_QH:
17821 case OPC_ADDUH_OB:
17822 case OPC_ADDUH_R_OB:
17823 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17824 break;
17825 case OPC_MULEQ_S_PW_QHL:
17826 case OPC_MULEQ_S_PW_QHR:
17827 case OPC_MULEU_S_QH_OBL:
17828 case OPC_MULEU_S_QH_OBR:
17829 case OPC_MULQ_RS_QH:
17830 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17831 break;
17832 default: /* Invalid */
17833 MIPS_INVAL("MASK ADDU.OB");
17834 generate_exception_end(ctx, EXCP_RI);
17835 break;
17837 break;
17838 case OPC_CMPU_EQ_OB_DSP:
17839 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
17840 switch (op2) {
17841 case OPC_PRECR_SRA_QH_PW:
17842 case OPC_PRECR_SRA_R_QH_PW:
17843 /* Return value is rt. */
17844 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17845 break;
17846 case OPC_PRECR_OB_QH:
17847 case OPC_PRECRQ_OB_QH:
17848 case OPC_PRECRQ_PW_L:
17849 case OPC_PRECRQ_QH_PW:
17850 case OPC_PRECRQ_RS_QH_PW:
17851 case OPC_PRECRQU_S_OB_QH:
17852 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17853 break;
17854 case OPC_CMPU_EQ_OB:
17855 case OPC_CMPU_LT_OB:
17856 case OPC_CMPU_LE_OB:
17857 case OPC_CMP_EQ_QH:
17858 case OPC_CMP_LT_QH:
17859 case OPC_CMP_LE_QH:
17860 case OPC_CMP_EQ_PW:
17861 case OPC_CMP_LT_PW:
17862 case OPC_CMP_LE_PW:
17863 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17864 break;
17865 case OPC_CMPGDU_EQ_OB:
17866 case OPC_CMPGDU_LT_OB:
17867 case OPC_CMPGDU_LE_OB:
17868 case OPC_CMPGU_EQ_OB:
17869 case OPC_CMPGU_LT_OB:
17870 case OPC_CMPGU_LE_OB:
17871 case OPC_PACKRL_PW:
17872 case OPC_PICK_OB:
17873 case OPC_PICK_PW:
17874 case OPC_PICK_QH:
17875 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17876 break;
17877 default: /* Invalid */
17878 MIPS_INVAL("MASK CMPU_EQ.OB");
17879 generate_exception_end(ctx, EXCP_RI);
17880 break;
17882 break;
17883 case OPC_DAPPEND_DSP:
17884 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17885 break;
17886 case OPC_DEXTR_W_DSP:
17887 op2 = MASK_DEXTR_W(ctx->opcode);
17888 switch (op2) {
17889 case OPC_DEXTP:
17890 case OPC_DEXTPDP:
17891 case OPC_DEXTPDPV:
17892 case OPC_DEXTPV:
17893 case OPC_DEXTR_L:
17894 case OPC_DEXTR_R_L:
17895 case OPC_DEXTR_RS_L:
17896 case OPC_DEXTR_W:
17897 case OPC_DEXTR_R_W:
17898 case OPC_DEXTR_RS_W:
17899 case OPC_DEXTR_S_H:
17900 case OPC_DEXTRV_L:
17901 case OPC_DEXTRV_R_L:
17902 case OPC_DEXTRV_RS_L:
17903 case OPC_DEXTRV_S_H:
17904 case OPC_DEXTRV_W:
17905 case OPC_DEXTRV_R_W:
17906 case OPC_DEXTRV_RS_W:
17907 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17908 break;
17909 case OPC_DMTHLIP:
17910 case OPC_DSHILO:
17911 case OPC_DSHILOV:
17912 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17913 break;
17914 default: /* Invalid */
17915 MIPS_INVAL("MASK EXTR.W");
17916 generate_exception_end(ctx, EXCP_RI);
17917 break;
17919 break;
17920 case OPC_DPAQ_W_QH_DSP:
17921 op2 = MASK_DPAQ_W_QH(ctx->opcode);
17922 switch (op2) {
17923 case OPC_DPAU_H_OBL:
17924 case OPC_DPAU_H_OBR:
17925 case OPC_DPSU_H_OBL:
17926 case OPC_DPSU_H_OBR:
17927 case OPC_DPA_W_QH:
17928 case OPC_DPAQ_S_W_QH:
17929 case OPC_DPS_W_QH:
17930 case OPC_DPSQ_S_W_QH:
17931 case OPC_MULSAQ_S_W_QH:
17932 case OPC_DPAQ_SA_L_PW:
17933 case OPC_DPSQ_SA_L_PW:
17934 case OPC_MULSAQ_S_L_PW:
17935 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17936 break;
17937 case OPC_MAQ_S_W_QHLL:
17938 case OPC_MAQ_S_W_QHLR:
17939 case OPC_MAQ_S_W_QHRL:
17940 case OPC_MAQ_S_W_QHRR:
17941 case OPC_MAQ_SA_W_QHLL:
17942 case OPC_MAQ_SA_W_QHLR:
17943 case OPC_MAQ_SA_W_QHRL:
17944 case OPC_MAQ_SA_W_QHRR:
17945 case OPC_MAQ_S_L_PWL:
17946 case OPC_MAQ_S_L_PWR:
17947 case OPC_DMADD:
17948 case OPC_DMADDU:
17949 case OPC_DMSUB:
17950 case OPC_DMSUBU:
17951 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17952 break;
17953 default: /* Invalid */
17954 MIPS_INVAL("MASK DPAQ.W.QH");
17955 generate_exception_end(ctx, EXCP_RI);
17956 break;
17958 break;
17959 case OPC_DINSV_DSP:
17960 op2 = MASK_INSV(ctx->opcode);
17961 switch (op2) {
17962 case OPC_DINSV:
17964 TCGv t0, t1;
17966 if (rt == 0) {
17967 break;
17969 check_dsp(ctx);
17971 t0 = tcg_temp_new();
17972 t1 = tcg_temp_new();
17974 gen_load_gpr(t0, rt);
17975 gen_load_gpr(t1, rs);
17977 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
17979 tcg_temp_free(t0);
17980 tcg_temp_free(t1);
17981 break;
17983 default: /* Invalid */
17984 MIPS_INVAL("MASK DINSV");
17985 generate_exception_end(ctx, EXCP_RI);
17986 break;
17988 break;
17989 case OPC_SHLL_OB_DSP:
17990 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17991 break;
17992 #endif
17993 default: /* Invalid */
17994 MIPS_INVAL("special3_legacy");
17995 generate_exception_end(ctx, EXCP_RI);
17996 break;
18000 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
18002 int rs, rt, rd, sa;
18003 uint32_t op1, op2;
18005 rs = (ctx->opcode >> 21) & 0x1f;
18006 rt = (ctx->opcode >> 16) & 0x1f;
18007 rd = (ctx->opcode >> 11) & 0x1f;
18008 sa = (ctx->opcode >> 6) & 0x1f;
18010 op1 = MASK_SPECIAL3(ctx->opcode);
18011 switch (op1) {
18012 case OPC_EXT:
18013 case OPC_INS:
18014 check_insn(ctx, ISA_MIPS32R2);
18015 gen_bitops(ctx, op1, rt, rs, sa, rd);
18016 break;
18017 case OPC_BSHFL:
18018 op2 = MASK_BSHFL(ctx->opcode);
18019 switch (op2) {
18020 case OPC_ALIGN ... OPC_ALIGN_END:
18021 case OPC_BITSWAP:
18022 check_insn(ctx, ISA_MIPS32R6);
18023 decode_opc_special3_r6(env, ctx);
18024 break;
18025 default:
18026 check_insn(ctx, ISA_MIPS32R2);
18027 gen_bshfl(ctx, op2, rt, rd);
18028 break;
18030 break;
18031 #if defined(TARGET_MIPS64)
18032 case OPC_DEXTM ... OPC_DEXT:
18033 case OPC_DINSM ... OPC_DINS:
18034 check_insn(ctx, ISA_MIPS64R2);
18035 check_mips_64(ctx);
18036 gen_bitops(ctx, op1, rt, rs, sa, rd);
18037 break;
18038 case OPC_DBSHFL:
18039 op2 = MASK_DBSHFL(ctx->opcode);
18040 switch (op2) {
18041 case OPC_DALIGN ... OPC_DALIGN_END:
18042 case OPC_DBITSWAP:
18043 check_insn(ctx, ISA_MIPS32R6);
18044 decode_opc_special3_r6(env, ctx);
18045 break;
18046 default:
18047 check_insn(ctx, ISA_MIPS64R2);
18048 check_mips_64(ctx);
18049 op2 = MASK_DBSHFL(ctx->opcode);
18050 gen_bshfl(ctx, op2, rt, rd);
18051 break;
18053 break;
18054 #endif
18055 case OPC_RDHWR:
18056 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
18057 break;
18058 case OPC_FORK:
18059 check_insn(ctx, ASE_MT);
18061 TCGv t0 = tcg_temp_new();
18062 TCGv t1 = tcg_temp_new();
18064 gen_load_gpr(t0, rt);
18065 gen_load_gpr(t1, rs);
18066 gen_helper_fork(t0, t1);
18067 tcg_temp_free(t0);
18068 tcg_temp_free(t1);
18070 break;
18071 case OPC_YIELD:
18072 check_insn(ctx, ASE_MT);
18074 TCGv t0 = tcg_temp_new();
18076 gen_load_gpr(t0, rs);
18077 gen_helper_yield(t0, cpu_env, t0);
18078 gen_store_gpr(t0, rd);
18079 tcg_temp_free(t0);
18081 break;
18082 default:
18083 if (ctx->insn_flags & ISA_MIPS32R6) {
18084 decode_opc_special3_r6(env, ctx);
18085 } else {
18086 decode_opc_special3_legacy(env, ctx);
18091 /* MIPS SIMD Architecture (MSA) */
18092 static inline int check_msa_access(DisasContext *ctx)
18094 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
18095 !(ctx->hflags & MIPS_HFLAG_F64))) {
18096 generate_exception_end(ctx, EXCP_RI);
18097 return 0;
18100 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
18101 if (ctx->insn_flags & ASE_MSA) {
18102 generate_exception_end(ctx, EXCP_MSADIS);
18103 return 0;
18104 } else {
18105 generate_exception_end(ctx, EXCP_RI);
18106 return 0;
18109 return 1;
18112 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
18114 /* generates tcg ops to check if any element is 0 */
18115 /* Note this function only works with MSA_WRLEN = 128 */
18116 uint64_t eval_zero_or_big = 0;
18117 uint64_t eval_big = 0;
18118 TCGv_i64 t0 = tcg_temp_new_i64();
18119 TCGv_i64 t1 = tcg_temp_new_i64();
18120 switch (df) {
18121 case DF_BYTE:
18122 eval_zero_or_big = 0x0101010101010101ULL;
18123 eval_big = 0x8080808080808080ULL;
18124 break;
18125 case DF_HALF:
18126 eval_zero_or_big = 0x0001000100010001ULL;
18127 eval_big = 0x8000800080008000ULL;
18128 break;
18129 case DF_WORD:
18130 eval_zero_or_big = 0x0000000100000001ULL;
18131 eval_big = 0x8000000080000000ULL;
18132 break;
18133 case DF_DOUBLE:
18134 eval_zero_or_big = 0x0000000000000001ULL;
18135 eval_big = 0x8000000000000000ULL;
18136 break;
18138 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
18139 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
18140 tcg_gen_andi_i64(t0, t0, eval_big);
18141 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
18142 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
18143 tcg_gen_andi_i64(t1, t1, eval_big);
18144 tcg_gen_or_i64(t0, t0, t1);
18145 /* if all bits are zero then all elements are not zero */
18146 /* if some bit is non-zero then some element is zero */
18147 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
18148 tcg_gen_trunc_i64_tl(tresult, t0);
18149 tcg_temp_free_i64(t0);
18150 tcg_temp_free_i64(t1);
18153 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
18155 uint8_t df = (ctx->opcode >> 21) & 0x3;
18156 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18157 int64_t s16 = (int16_t)ctx->opcode;
18159 check_msa_access(ctx);
18161 if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
18162 generate_exception_end(ctx, EXCP_RI);
18163 return;
18165 switch (op1) {
18166 case OPC_BZ_V:
18167 case OPC_BNZ_V:
18169 TCGv_i64 t0 = tcg_temp_new_i64();
18170 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
18171 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
18172 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
18173 tcg_gen_trunc_i64_tl(bcond, t0);
18174 tcg_temp_free_i64(t0);
18176 break;
18177 case OPC_BZ_B:
18178 case OPC_BZ_H:
18179 case OPC_BZ_W:
18180 case OPC_BZ_D:
18181 gen_check_zero_element(bcond, df, wt);
18182 break;
18183 case OPC_BNZ_B:
18184 case OPC_BNZ_H:
18185 case OPC_BNZ_W:
18186 case OPC_BNZ_D:
18187 gen_check_zero_element(bcond, df, wt);
18188 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
18189 break;
18192 ctx->btarget = ctx->pc + (s16 << 2) + 4;
18194 ctx->hflags |= MIPS_HFLAG_BC;
18195 ctx->hflags |= MIPS_HFLAG_BDS32;
18198 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
18200 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
18201 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
18202 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18203 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18205 TCGv_i32 twd = tcg_const_i32(wd);
18206 TCGv_i32 tws = tcg_const_i32(ws);
18207 TCGv_i32 ti8 = tcg_const_i32(i8);
18209 switch (MASK_MSA_I8(ctx->opcode)) {
18210 case OPC_ANDI_B:
18211 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
18212 break;
18213 case OPC_ORI_B:
18214 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
18215 break;
18216 case OPC_NORI_B:
18217 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
18218 break;
18219 case OPC_XORI_B:
18220 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
18221 break;
18222 case OPC_BMNZI_B:
18223 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
18224 break;
18225 case OPC_BMZI_B:
18226 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
18227 break;
18228 case OPC_BSELI_B:
18229 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
18230 break;
18231 case OPC_SHF_B:
18232 case OPC_SHF_H:
18233 case OPC_SHF_W:
18235 uint8_t df = (ctx->opcode >> 24) & 0x3;
18236 if (df == DF_DOUBLE) {
18237 generate_exception_end(ctx, EXCP_RI);
18238 } else {
18239 TCGv_i32 tdf = tcg_const_i32(df);
18240 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
18241 tcg_temp_free_i32(tdf);
18244 break;
18245 default:
18246 MIPS_INVAL("MSA instruction");
18247 generate_exception_end(ctx, EXCP_RI);
18248 break;
18251 tcg_temp_free_i32(twd);
18252 tcg_temp_free_i32(tws);
18253 tcg_temp_free_i32(ti8);
18256 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
18258 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18259 uint8_t df = (ctx->opcode >> 21) & 0x3;
18260 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
18261 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
18262 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18263 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18265 TCGv_i32 tdf = tcg_const_i32(df);
18266 TCGv_i32 twd = tcg_const_i32(wd);
18267 TCGv_i32 tws = tcg_const_i32(ws);
18268 TCGv_i32 timm = tcg_temp_new_i32();
18269 tcg_gen_movi_i32(timm, u5);
18271 switch (MASK_MSA_I5(ctx->opcode)) {
18272 case OPC_ADDVI_df:
18273 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
18274 break;
18275 case OPC_SUBVI_df:
18276 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
18277 break;
18278 case OPC_MAXI_S_df:
18279 tcg_gen_movi_i32(timm, s5);
18280 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
18281 break;
18282 case OPC_MAXI_U_df:
18283 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
18284 break;
18285 case OPC_MINI_S_df:
18286 tcg_gen_movi_i32(timm, s5);
18287 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
18288 break;
18289 case OPC_MINI_U_df:
18290 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
18291 break;
18292 case OPC_CEQI_df:
18293 tcg_gen_movi_i32(timm, s5);
18294 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
18295 break;
18296 case OPC_CLTI_S_df:
18297 tcg_gen_movi_i32(timm, s5);
18298 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
18299 break;
18300 case OPC_CLTI_U_df:
18301 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
18302 break;
18303 case OPC_CLEI_S_df:
18304 tcg_gen_movi_i32(timm, s5);
18305 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
18306 break;
18307 case OPC_CLEI_U_df:
18308 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
18309 break;
18310 case OPC_LDI_df:
18312 int32_t s10 = sextract32(ctx->opcode, 11, 10);
18313 tcg_gen_movi_i32(timm, s10);
18314 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
18316 break;
18317 default:
18318 MIPS_INVAL("MSA instruction");
18319 generate_exception_end(ctx, EXCP_RI);
18320 break;
18323 tcg_temp_free_i32(tdf);
18324 tcg_temp_free_i32(twd);
18325 tcg_temp_free_i32(tws);
18326 tcg_temp_free_i32(timm);
18329 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
18331 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18332 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
18333 uint32_t df = 0, m = 0;
18334 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18335 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18337 TCGv_i32 tdf;
18338 TCGv_i32 tm;
18339 TCGv_i32 twd;
18340 TCGv_i32 tws;
18342 if ((dfm & 0x40) == 0x00) {
18343 m = dfm & 0x3f;
18344 df = DF_DOUBLE;
18345 } else if ((dfm & 0x60) == 0x40) {
18346 m = dfm & 0x1f;
18347 df = DF_WORD;
18348 } else if ((dfm & 0x70) == 0x60) {
18349 m = dfm & 0x0f;
18350 df = DF_HALF;
18351 } else if ((dfm & 0x78) == 0x70) {
18352 m = dfm & 0x7;
18353 df = DF_BYTE;
18354 } else {
18355 generate_exception_end(ctx, EXCP_RI);
18356 return;
18359 tdf = tcg_const_i32(df);
18360 tm = tcg_const_i32(m);
18361 twd = tcg_const_i32(wd);
18362 tws = tcg_const_i32(ws);
18364 switch (MASK_MSA_BIT(ctx->opcode)) {
18365 case OPC_SLLI_df:
18366 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
18367 break;
18368 case OPC_SRAI_df:
18369 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
18370 break;
18371 case OPC_SRLI_df:
18372 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
18373 break;
18374 case OPC_BCLRI_df:
18375 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
18376 break;
18377 case OPC_BSETI_df:
18378 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
18379 break;
18380 case OPC_BNEGI_df:
18381 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
18382 break;
18383 case OPC_BINSLI_df:
18384 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
18385 break;
18386 case OPC_BINSRI_df:
18387 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
18388 break;
18389 case OPC_SAT_S_df:
18390 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
18391 break;
18392 case OPC_SAT_U_df:
18393 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
18394 break;
18395 case OPC_SRARI_df:
18396 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
18397 break;
18398 case OPC_SRLRI_df:
18399 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
18400 break;
18401 default:
18402 MIPS_INVAL("MSA instruction");
18403 generate_exception_end(ctx, EXCP_RI);
18404 break;
18407 tcg_temp_free_i32(tdf);
18408 tcg_temp_free_i32(tm);
18409 tcg_temp_free_i32(twd);
18410 tcg_temp_free_i32(tws);
18413 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
18415 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18416 uint8_t df = (ctx->opcode >> 21) & 0x3;
18417 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18418 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18419 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18421 TCGv_i32 tdf = tcg_const_i32(df);
18422 TCGv_i32 twd = tcg_const_i32(wd);
18423 TCGv_i32 tws = tcg_const_i32(ws);
18424 TCGv_i32 twt = tcg_const_i32(wt);
18426 switch (MASK_MSA_3R(ctx->opcode)) {
18427 case OPC_SLL_df:
18428 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
18429 break;
18430 case OPC_ADDV_df:
18431 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
18432 break;
18433 case OPC_CEQ_df:
18434 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
18435 break;
18436 case OPC_ADD_A_df:
18437 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
18438 break;
18439 case OPC_SUBS_S_df:
18440 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
18441 break;
18442 case OPC_MULV_df:
18443 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
18444 break;
18445 case OPC_SLD_df:
18446 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
18447 break;
18448 case OPC_VSHF_df:
18449 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
18450 break;
18451 case OPC_SRA_df:
18452 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
18453 break;
18454 case OPC_SUBV_df:
18455 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
18456 break;
18457 case OPC_ADDS_A_df:
18458 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
18459 break;
18460 case OPC_SUBS_U_df:
18461 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
18462 break;
18463 case OPC_MADDV_df:
18464 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
18465 break;
18466 case OPC_SPLAT_df:
18467 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
18468 break;
18469 case OPC_SRAR_df:
18470 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
18471 break;
18472 case OPC_SRL_df:
18473 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
18474 break;
18475 case OPC_MAX_S_df:
18476 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
18477 break;
18478 case OPC_CLT_S_df:
18479 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
18480 break;
18481 case OPC_ADDS_S_df:
18482 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
18483 break;
18484 case OPC_SUBSUS_U_df:
18485 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
18486 break;
18487 case OPC_MSUBV_df:
18488 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
18489 break;
18490 case OPC_PCKEV_df:
18491 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
18492 break;
18493 case OPC_SRLR_df:
18494 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
18495 break;
18496 case OPC_BCLR_df:
18497 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
18498 break;
18499 case OPC_MAX_U_df:
18500 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
18501 break;
18502 case OPC_CLT_U_df:
18503 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
18504 break;
18505 case OPC_ADDS_U_df:
18506 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
18507 break;
18508 case OPC_SUBSUU_S_df:
18509 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
18510 break;
18511 case OPC_PCKOD_df:
18512 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
18513 break;
18514 case OPC_BSET_df:
18515 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
18516 break;
18517 case OPC_MIN_S_df:
18518 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
18519 break;
18520 case OPC_CLE_S_df:
18521 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
18522 break;
18523 case OPC_AVE_S_df:
18524 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
18525 break;
18526 case OPC_ASUB_S_df:
18527 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
18528 break;
18529 case OPC_DIV_S_df:
18530 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
18531 break;
18532 case OPC_ILVL_df:
18533 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
18534 break;
18535 case OPC_BNEG_df:
18536 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
18537 break;
18538 case OPC_MIN_U_df:
18539 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
18540 break;
18541 case OPC_CLE_U_df:
18542 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
18543 break;
18544 case OPC_AVE_U_df:
18545 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
18546 break;
18547 case OPC_ASUB_U_df:
18548 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
18549 break;
18550 case OPC_DIV_U_df:
18551 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
18552 break;
18553 case OPC_ILVR_df:
18554 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
18555 break;
18556 case OPC_BINSL_df:
18557 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
18558 break;
18559 case OPC_MAX_A_df:
18560 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
18561 break;
18562 case OPC_AVER_S_df:
18563 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
18564 break;
18565 case OPC_MOD_S_df:
18566 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
18567 break;
18568 case OPC_ILVEV_df:
18569 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
18570 break;
18571 case OPC_BINSR_df:
18572 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
18573 break;
18574 case OPC_MIN_A_df:
18575 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
18576 break;
18577 case OPC_AVER_U_df:
18578 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
18579 break;
18580 case OPC_MOD_U_df:
18581 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
18582 break;
18583 case OPC_ILVOD_df:
18584 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
18585 break;
18587 case OPC_DOTP_S_df:
18588 case OPC_DOTP_U_df:
18589 case OPC_DPADD_S_df:
18590 case OPC_DPADD_U_df:
18591 case OPC_DPSUB_S_df:
18592 case OPC_HADD_S_df:
18593 case OPC_DPSUB_U_df:
18594 case OPC_HADD_U_df:
18595 case OPC_HSUB_S_df:
18596 case OPC_HSUB_U_df:
18597 if (df == DF_BYTE) {
18598 generate_exception_end(ctx, EXCP_RI);
18599 break;
18601 switch (MASK_MSA_3R(ctx->opcode)) {
18602 case OPC_DOTP_S_df:
18603 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
18604 break;
18605 case OPC_DOTP_U_df:
18606 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
18607 break;
18608 case OPC_DPADD_S_df:
18609 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
18610 break;
18611 case OPC_DPADD_U_df:
18612 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
18613 break;
18614 case OPC_DPSUB_S_df:
18615 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
18616 break;
18617 case OPC_HADD_S_df:
18618 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
18619 break;
18620 case OPC_DPSUB_U_df:
18621 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
18622 break;
18623 case OPC_HADD_U_df:
18624 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
18625 break;
18626 case OPC_HSUB_S_df:
18627 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
18628 break;
18629 case OPC_HSUB_U_df:
18630 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
18631 break;
18633 break;
18634 default:
18635 MIPS_INVAL("MSA instruction");
18636 generate_exception_end(ctx, EXCP_RI);
18637 break;
18639 tcg_temp_free_i32(twd);
18640 tcg_temp_free_i32(tws);
18641 tcg_temp_free_i32(twt);
18642 tcg_temp_free_i32(tdf);
18645 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
18647 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
18648 uint8_t source = (ctx->opcode >> 11) & 0x1f;
18649 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
18650 TCGv telm = tcg_temp_new();
18651 TCGv_i32 tsr = tcg_const_i32(source);
18652 TCGv_i32 tdt = tcg_const_i32(dest);
18654 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
18655 case OPC_CTCMSA:
18656 gen_load_gpr(telm, source);
18657 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
18658 break;
18659 case OPC_CFCMSA:
18660 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
18661 gen_store_gpr(telm, dest);
18662 break;
18663 case OPC_MOVE_V:
18664 gen_helper_msa_move_v(cpu_env, tdt, tsr);
18665 break;
18666 default:
18667 MIPS_INVAL("MSA instruction");
18668 generate_exception_end(ctx, EXCP_RI);
18669 break;
18672 tcg_temp_free(telm);
18673 tcg_temp_free_i32(tdt);
18674 tcg_temp_free_i32(tsr);
18677 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
18678 uint32_t n)
18680 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18681 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18682 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18684 TCGv_i32 tws = tcg_const_i32(ws);
18685 TCGv_i32 twd = tcg_const_i32(wd);
18686 TCGv_i32 tn = tcg_const_i32(n);
18687 TCGv_i32 tdf = tcg_const_i32(df);
18689 switch (MASK_MSA_ELM(ctx->opcode)) {
18690 case OPC_SLDI_df:
18691 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
18692 break;
18693 case OPC_SPLATI_df:
18694 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
18695 break;
18696 case OPC_INSVE_df:
18697 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
18698 break;
18699 case OPC_COPY_S_df:
18700 case OPC_COPY_U_df:
18701 case OPC_INSERT_df:
18702 #if !defined(TARGET_MIPS64)
18703 /* Double format valid only for MIPS64 */
18704 if (df == DF_DOUBLE) {
18705 generate_exception_end(ctx, EXCP_RI);
18706 break;
18708 #endif
18709 switch (MASK_MSA_ELM(ctx->opcode)) {
18710 case OPC_COPY_S_df:
18711 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
18712 break;
18713 case OPC_COPY_U_df:
18714 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
18715 break;
18716 case OPC_INSERT_df:
18717 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
18718 break;
18720 break;
18721 default:
18722 MIPS_INVAL("MSA instruction");
18723 generate_exception_end(ctx, EXCP_RI);
18725 tcg_temp_free_i32(twd);
18726 tcg_temp_free_i32(tws);
18727 tcg_temp_free_i32(tn);
18728 tcg_temp_free_i32(tdf);
18731 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
18733 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
18734 uint32_t df = 0, n = 0;
18736 if ((dfn & 0x30) == 0x00) {
18737 n = dfn & 0x0f;
18738 df = DF_BYTE;
18739 } else if ((dfn & 0x38) == 0x20) {
18740 n = dfn & 0x07;
18741 df = DF_HALF;
18742 } else if ((dfn & 0x3c) == 0x30) {
18743 n = dfn & 0x03;
18744 df = DF_WORD;
18745 } else if ((dfn & 0x3e) == 0x38) {
18746 n = dfn & 0x01;
18747 df = DF_DOUBLE;
18748 } else if (dfn == 0x3E) {
18749 /* CTCMSA, CFCMSA, MOVE.V */
18750 gen_msa_elm_3e(env, ctx);
18751 return;
18752 } else {
18753 generate_exception_end(ctx, EXCP_RI);
18754 return;
18757 gen_msa_elm_df(env, ctx, df, n);
18760 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
18762 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18763 uint8_t df = (ctx->opcode >> 21) & 0x1;
18764 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18765 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18766 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18768 TCGv_i32 twd = tcg_const_i32(wd);
18769 TCGv_i32 tws = tcg_const_i32(ws);
18770 TCGv_i32 twt = tcg_const_i32(wt);
18771 TCGv_i32 tdf = tcg_temp_new_i32();
18773 /* adjust df value for floating-point instruction */
18774 tcg_gen_movi_i32(tdf, df + 2);
18776 switch (MASK_MSA_3RF(ctx->opcode)) {
18777 case OPC_FCAF_df:
18778 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
18779 break;
18780 case OPC_FADD_df:
18781 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
18782 break;
18783 case OPC_FCUN_df:
18784 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
18785 break;
18786 case OPC_FSUB_df:
18787 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
18788 break;
18789 case OPC_FCOR_df:
18790 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
18791 break;
18792 case OPC_FCEQ_df:
18793 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
18794 break;
18795 case OPC_FMUL_df:
18796 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
18797 break;
18798 case OPC_FCUNE_df:
18799 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
18800 break;
18801 case OPC_FCUEQ_df:
18802 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
18803 break;
18804 case OPC_FDIV_df:
18805 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
18806 break;
18807 case OPC_FCNE_df:
18808 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
18809 break;
18810 case OPC_FCLT_df:
18811 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
18812 break;
18813 case OPC_FMADD_df:
18814 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
18815 break;
18816 case OPC_MUL_Q_df:
18817 tcg_gen_movi_i32(tdf, df + 1);
18818 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
18819 break;
18820 case OPC_FCULT_df:
18821 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
18822 break;
18823 case OPC_FMSUB_df:
18824 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
18825 break;
18826 case OPC_MADD_Q_df:
18827 tcg_gen_movi_i32(tdf, df + 1);
18828 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
18829 break;
18830 case OPC_FCLE_df:
18831 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
18832 break;
18833 case OPC_MSUB_Q_df:
18834 tcg_gen_movi_i32(tdf, df + 1);
18835 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
18836 break;
18837 case OPC_FCULE_df:
18838 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
18839 break;
18840 case OPC_FEXP2_df:
18841 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
18842 break;
18843 case OPC_FSAF_df:
18844 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
18845 break;
18846 case OPC_FEXDO_df:
18847 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
18848 break;
18849 case OPC_FSUN_df:
18850 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
18851 break;
18852 case OPC_FSOR_df:
18853 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
18854 break;
18855 case OPC_FSEQ_df:
18856 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
18857 break;
18858 case OPC_FTQ_df:
18859 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
18860 break;
18861 case OPC_FSUNE_df:
18862 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
18863 break;
18864 case OPC_FSUEQ_df:
18865 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
18866 break;
18867 case OPC_FSNE_df:
18868 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
18869 break;
18870 case OPC_FSLT_df:
18871 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
18872 break;
18873 case OPC_FMIN_df:
18874 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
18875 break;
18876 case OPC_MULR_Q_df:
18877 tcg_gen_movi_i32(tdf, df + 1);
18878 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
18879 break;
18880 case OPC_FSULT_df:
18881 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
18882 break;
18883 case OPC_FMIN_A_df:
18884 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
18885 break;
18886 case OPC_MADDR_Q_df:
18887 tcg_gen_movi_i32(tdf, df + 1);
18888 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
18889 break;
18890 case OPC_FSLE_df:
18891 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
18892 break;
18893 case OPC_FMAX_df:
18894 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
18895 break;
18896 case OPC_MSUBR_Q_df:
18897 tcg_gen_movi_i32(tdf, df + 1);
18898 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
18899 break;
18900 case OPC_FSULE_df:
18901 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
18902 break;
18903 case OPC_FMAX_A_df:
18904 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
18905 break;
18906 default:
18907 MIPS_INVAL("MSA instruction");
18908 generate_exception_end(ctx, EXCP_RI);
18909 break;
18912 tcg_temp_free_i32(twd);
18913 tcg_temp_free_i32(tws);
18914 tcg_temp_free_i32(twt);
18915 tcg_temp_free_i32(tdf);
18918 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
18920 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18921 (op & (0x7 << 18)))
18922 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18923 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18924 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18925 uint8_t df = (ctx->opcode >> 16) & 0x3;
18926 TCGv_i32 twd = tcg_const_i32(wd);
18927 TCGv_i32 tws = tcg_const_i32(ws);
18928 TCGv_i32 twt = tcg_const_i32(wt);
18929 TCGv_i32 tdf = tcg_const_i32(df);
18931 switch (MASK_MSA_2R(ctx->opcode)) {
18932 case OPC_FILL_df:
18933 #if !defined(TARGET_MIPS64)
18934 /* Double format valid only for MIPS64 */
18935 if (df == DF_DOUBLE) {
18936 generate_exception_end(ctx, EXCP_RI);
18937 break;
18939 #endif
18940 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
18941 break;
18942 case OPC_PCNT_df:
18943 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
18944 break;
18945 case OPC_NLOC_df:
18946 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
18947 break;
18948 case OPC_NLZC_df:
18949 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
18950 break;
18951 default:
18952 MIPS_INVAL("MSA instruction");
18953 generate_exception_end(ctx, EXCP_RI);
18954 break;
18957 tcg_temp_free_i32(twd);
18958 tcg_temp_free_i32(tws);
18959 tcg_temp_free_i32(twt);
18960 tcg_temp_free_i32(tdf);
18963 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
18965 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18966 (op & (0xf << 17)))
18967 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18968 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18969 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18970 uint8_t df = (ctx->opcode >> 16) & 0x1;
18971 TCGv_i32 twd = tcg_const_i32(wd);
18972 TCGv_i32 tws = tcg_const_i32(ws);
18973 TCGv_i32 twt = tcg_const_i32(wt);
18974 /* adjust df value for floating-point instruction */
18975 TCGv_i32 tdf = tcg_const_i32(df + 2);
18977 switch (MASK_MSA_2RF(ctx->opcode)) {
18978 case OPC_FCLASS_df:
18979 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
18980 break;
18981 case OPC_FTRUNC_S_df:
18982 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
18983 break;
18984 case OPC_FTRUNC_U_df:
18985 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
18986 break;
18987 case OPC_FSQRT_df:
18988 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
18989 break;
18990 case OPC_FRSQRT_df:
18991 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
18992 break;
18993 case OPC_FRCP_df:
18994 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
18995 break;
18996 case OPC_FRINT_df:
18997 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
18998 break;
18999 case OPC_FLOG2_df:
19000 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
19001 break;
19002 case OPC_FEXUPL_df:
19003 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
19004 break;
19005 case OPC_FEXUPR_df:
19006 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
19007 break;
19008 case OPC_FFQL_df:
19009 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
19010 break;
19011 case OPC_FFQR_df:
19012 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
19013 break;
19014 case OPC_FTINT_S_df:
19015 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
19016 break;
19017 case OPC_FTINT_U_df:
19018 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
19019 break;
19020 case OPC_FFINT_S_df:
19021 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
19022 break;
19023 case OPC_FFINT_U_df:
19024 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
19025 break;
19028 tcg_temp_free_i32(twd);
19029 tcg_temp_free_i32(tws);
19030 tcg_temp_free_i32(twt);
19031 tcg_temp_free_i32(tdf);
19034 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
19036 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
19037 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19038 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19039 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19040 TCGv_i32 twd = tcg_const_i32(wd);
19041 TCGv_i32 tws = tcg_const_i32(ws);
19042 TCGv_i32 twt = tcg_const_i32(wt);
19044 switch (MASK_MSA_VEC(ctx->opcode)) {
19045 case OPC_AND_V:
19046 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
19047 break;
19048 case OPC_OR_V:
19049 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
19050 break;
19051 case OPC_NOR_V:
19052 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
19053 break;
19054 case OPC_XOR_V:
19055 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
19056 break;
19057 case OPC_BMNZ_V:
19058 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
19059 break;
19060 case OPC_BMZ_V:
19061 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
19062 break;
19063 case OPC_BSEL_V:
19064 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
19065 break;
19066 default:
19067 MIPS_INVAL("MSA instruction");
19068 generate_exception_end(ctx, EXCP_RI);
19069 break;
19072 tcg_temp_free_i32(twd);
19073 tcg_temp_free_i32(tws);
19074 tcg_temp_free_i32(twt);
19077 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
19079 switch (MASK_MSA_VEC(ctx->opcode)) {
19080 case OPC_AND_V:
19081 case OPC_OR_V:
19082 case OPC_NOR_V:
19083 case OPC_XOR_V:
19084 case OPC_BMNZ_V:
19085 case OPC_BMZ_V:
19086 case OPC_BSEL_V:
19087 gen_msa_vec_v(env, ctx);
19088 break;
19089 case OPC_MSA_2R:
19090 gen_msa_2r(env, ctx);
19091 break;
19092 case OPC_MSA_2RF:
19093 gen_msa_2rf(env, ctx);
19094 break;
19095 default:
19096 MIPS_INVAL("MSA instruction");
19097 generate_exception_end(ctx, EXCP_RI);
19098 break;
19102 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
19104 uint32_t opcode = ctx->opcode;
19105 check_insn(ctx, ASE_MSA);
19106 check_msa_access(ctx);
19108 switch (MASK_MSA_MINOR(opcode)) {
19109 case OPC_MSA_I8_00:
19110 case OPC_MSA_I8_01:
19111 case OPC_MSA_I8_02:
19112 gen_msa_i8(env, ctx);
19113 break;
19114 case OPC_MSA_I5_06:
19115 case OPC_MSA_I5_07:
19116 gen_msa_i5(env, ctx);
19117 break;
19118 case OPC_MSA_BIT_09:
19119 case OPC_MSA_BIT_0A:
19120 gen_msa_bit(env, ctx);
19121 break;
19122 case OPC_MSA_3R_0D:
19123 case OPC_MSA_3R_0E:
19124 case OPC_MSA_3R_0F:
19125 case OPC_MSA_3R_10:
19126 case OPC_MSA_3R_11:
19127 case OPC_MSA_3R_12:
19128 case OPC_MSA_3R_13:
19129 case OPC_MSA_3R_14:
19130 case OPC_MSA_3R_15:
19131 gen_msa_3r(env, ctx);
19132 break;
19133 case OPC_MSA_ELM:
19134 gen_msa_elm(env, ctx);
19135 break;
19136 case OPC_MSA_3RF_1A:
19137 case OPC_MSA_3RF_1B:
19138 case OPC_MSA_3RF_1C:
19139 gen_msa_3rf(env, ctx);
19140 break;
19141 case OPC_MSA_VEC:
19142 gen_msa_vec(env, ctx);
19143 break;
19144 case OPC_LD_B:
19145 case OPC_LD_H:
19146 case OPC_LD_W:
19147 case OPC_LD_D:
19148 case OPC_ST_B:
19149 case OPC_ST_H:
19150 case OPC_ST_W:
19151 case OPC_ST_D:
19153 int32_t s10 = sextract32(ctx->opcode, 16, 10);
19154 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
19155 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19156 uint8_t df = (ctx->opcode >> 0) & 0x3;
19158 TCGv_i32 twd = tcg_const_i32(wd);
19159 TCGv taddr = tcg_temp_new();
19160 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
19162 switch (MASK_MSA_MINOR(opcode)) {
19163 case OPC_LD_B:
19164 gen_helper_msa_ld_b(cpu_env, twd, taddr);
19165 break;
19166 case OPC_LD_H:
19167 gen_helper_msa_ld_h(cpu_env, twd, taddr);
19168 break;
19169 case OPC_LD_W:
19170 gen_helper_msa_ld_w(cpu_env, twd, taddr);
19171 break;
19172 case OPC_LD_D:
19173 gen_helper_msa_ld_d(cpu_env, twd, taddr);
19174 break;
19175 case OPC_ST_B:
19176 gen_helper_msa_st_b(cpu_env, twd, taddr);
19177 break;
19178 case OPC_ST_H:
19179 gen_helper_msa_st_h(cpu_env, twd, taddr);
19180 break;
19181 case OPC_ST_W:
19182 gen_helper_msa_st_w(cpu_env, twd, taddr);
19183 break;
19184 case OPC_ST_D:
19185 gen_helper_msa_st_d(cpu_env, twd, taddr);
19186 break;
19189 tcg_temp_free_i32(twd);
19190 tcg_temp_free(taddr);
19192 break;
19193 default:
19194 MIPS_INVAL("MSA instruction");
19195 generate_exception_end(ctx, EXCP_RI);
19196 break;
19201 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
19203 int32_t offset;
19204 int rs, rt, rd, sa;
19205 uint32_t op, op1;
19206 int16_t imm;
19208 /* make sure instructions are on a word boundary */
19209 if (ctx->pc & 0x3) {
19210 env->CP0_BadVAddr = ctx->pc;
19211 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
19212 return;
19215 /* Handle blikely not taken case */
19216 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
19217 TCGLabel *l1 = gen_new_label();
19219 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
19220 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
19221 gen_goto_tb(ctx, 1, ctx->pc + 4);
19222 gen_set_label(l1);
19225 op = MASK_OP_MAJOR(ctx->opcode);
19226 rs = (ctx->opcode >> 21) & 0x1f;
19227 rt = (ctx->opcode >> 16) & 0x1f;
19228 rd = (ctx->opcode >> 11) & 0x1f;
19229 sa = (ctx->opcode >> 6) & 0x1f;
19230 imm = (int16_t)ctx->opcode;
19231 switch (op) {
19232 case OPC_SPECIAL:
19233 decode_opc_special(env, ctx);
19234 break;
19235 case OPC_SPECIAL2:
19236 decode_opc_special2_legacy(env, ctx);
19237 break;
19238 case OPC_SPECIAL3:
19239 decode_opc_special3(env, ctx);
19240 break;
19241 case OPC_REGIMM:
19242 op1 = MASK_REGIMM(ctx->opcode);
19243 switch (op1) {
19244 case OPC_BLTZL: /* REGIMM branches */
19245 case OPC_BGEZL:
19246 case OPC_BLTZALL:
19247 case OPC_BGEZALL:
19248 check_insn(ctx, ISA_MIPS2);
19249 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19250 /* Fallthrough */
19251 case OPC_BLTZ:
19252 case OPC_BGEZ:
19253 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19254 break;
19255 case OPC_BLTZAL:
19256 case OPC_BGEZAL:
19257 if (ctx->insn_flags & ISA_MIPS32R6) {
19258 if (rs == 0) {
19259 /* OPC_NAL, OPC_BAL */
19260 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
19261 } else {
19262 generate_exception_end(ctx, EXCP_RI);
19264 } else {
19265 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19267 break;
19268 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
19269 case OPC_TNEI:
19270 check_insn(ctx, ISA_MIPS2);
19271 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19272 gen_trap(ctx, op1, rs, -1, imm);
19273 break;
19274 case OPC_SIGRIE:
19275 check_insn(ctx, ISA_MIPS32R6);
19276 generate_exception_end(ctx, EXCP_RI);
19277 break;
19278 case OPC_SYNCI:
19279 check_insn(ctx, ISA_MIPS32R2);
19280 /* Break the TB to be able to sync copied instructions
19281 immediately */
19282 ctx->bstate = BS_STOP;
19283 break;
19284 case OPC_BPOSGE32: /* MIPS DSP branch */
19285 #if defined(TARGET_MIPS64)
19286 case OPC_BPOSGE64:
19287 #endif
19288 check_dsp(ctx);
19289 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
19290 break;
19291 #if defined(TARGET_MIPS64)
19292 case OPC_DAHI:
19293 check_insn(ctx, ISA_MIPS32R6);
19294 check_mips_64(ctx);
19295 if (rs != 0) {
19296 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
19298 break;
19299 case OPC_DATI:
19300 check_insn(ctx, ISA_MIPS32R6);
19301 check_mips_64(ctx);
19302 if (rs != 0) {
19303 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
19305 break;
19306 #endif
19307 default: /* Invalid */
19308 MIPS_INVAL("regimm");
19309 generate_exception_end(ctx, EXCP_RI);
19310 break;
19312 break;
19313 case OPC_CP0:
19314 check_cp0_enabled(ctx);
19315 op1 = MASK_CP0(ctx->opcode);
19316 switch (op1) {
19317 case OPC_MFC0:
19318 case OPC_MTC0:
19319 case OPC_MFTR:
19320 case OPC_MTTR:
19321 case OPC_MFHC0:
19322 case OPC_MTHC0:
19323 #if defined(TARGET_MIPS64)
19324 case OPC_DMFC0:
19325 case OPC_DMTC0:
19326 #endif
19327 #ifndef CONFIG_USER_ONLY
19328 gen_cp0(env, ctx, op1, rt, rd);
19329 #endif /* !CONFIG_USER_ONLY */
19330 break;
19331 case OPC_C0_FIRST ... OPC_C0_LAST:
19332 #ifndef CONFIG_USER_ONLY
19333 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
19334 #endif /* !CONFIG_USER_ONLY */
19335 break;
19336 case OPC_MFMC0:
19337 #ifndef CONFIG_USER_ONLY
19339 uint32_t op2;
19340 TCGv t0 = tcg_temp_new();
19342 op2 = MASK_MFMC0(ctx->opcode);
19343 switch (op2) {
19344 case OPC_DMT:
19345 check_insn(ctx, ASE_MT);
19346 gen_helper_dmt(t0);
19347 gen_store_gpr(t0, rt);
19348 break;
19349 case OPC_EMT:
19350 check_insn(ctx, ASE_MT);
19351 gen_helper_emt(t0);
19352 gen_store_gpr(t0, rt);
19353 break;
19354 case OPC_DVPE:
19355 check_insn(ctx, ASE_MT);
19356 gen_helper_dvpe(t0, cpu_env);
19357 gen_store_gpr(t0, rt);
19358 break;
19359 case OPC_EVPE:
19360 check_insn(ctx, ASE_MT);
19361 gen_helper_evpe(t0, cpu_env);
19362 gen_store_gpr(t0, rt);
19363 break;
19364 case OPC_DVP:
19365 check_insn(ctx, ISA_MIPS32R6);
19366 if (ctx->vp) {
19367 gen_helper_dvp(t0, cpu_env);
19368 gen_store_gpr(t0, rt);
19370 break;
19371 case OPC_EVP:
19372 check_insn(ctx, ISA_MIPS32R6);
19373 if (ctx->vp) {
19374 gen_helper_evp(t0, cpu_env);
19375 gen_store_gpr(t0, rt);
19377 break;
19378 case OPC_DI:
19379 check_insn(ctx, ISA_MIPS32R2);
19380 save_cpu_state(ctx, 1);
19381 gen_helper_di(t0, cpu_env);
19382 gen_store_gpr(t0, rt);
19383 /* Stop translation as we may have switched
19384 the execution mode. */
19385 ctx->bstate = BS_STOP;
19386 break;
19387 case OPC_EI:
19388 check_insn(ctx, ISA_MIPS32R2);
19389 save_cpu_state(ctx, 1);
19390 gen_helper_ei(t0, cpu_env);
19391 gen_store_gpr(t0, rt);
19392 /* Stop translation as we may have switched
19393 the execution mode. */
19394 ctx->bstate = BS_STOP;
19395 break;
19396 default: /* Invalid */
19397 MIPS_INVAL("mfmc0");
19398 generate_exception_end(ctx, EXCP_RI);
19399 break;
19401 tcg_temp_free(t0);
19403 #endif /* !CONFIG_USER_ONLY */
19404 break;
19405 case OPC_RDPGPR:
19406 check_insn(ctx, ISA_MIPS32R2);
19407 gen_load_srsgpr(rt, rd);
19408 break;
19409 case OPC_WRPGPR:
19410 check_insn(ctx, ISA_MIPS32R2);
19411 gen_store_srsgpr(rt, rd);
19412 break;
19413 default:
19414 MIPS_INVAL("cp0");
19415 generate_exception_end(ctx, EXCP_RI);
19416 break;
19418 break;
19419 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
19420 if (ctx->insn_flags & ISA_MIPS32R6) {
19421 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
19422 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19423 } else {
19424 /* OPC_ADDI */
19425 /* Arithmetic with immediate opcode */
19426 gen_arith_imm(ctx, op, rt, rs, imm);
19428 break;
19429 case OPC_ADDIU:
19430 gen_arith_imm(ctx, op, rt, rs, imm);
19431 break;
19432 case OPC_SLTI: /* Set on less than with immediate opcode */
19433 case OPC_SLTIU:
19434 gen_slt_imm(ctx, op, rt, rs, imm);
19435 break;
19436 case OPC_ANDI: /* Arithmetic with immediate opcode */
19437 case OPC_LUI: /* OPC_AUI */
19438 case OPC_ORI:
19439 case OPC_XORI:
19440 gen_logic_imm(ctx, op, rt, rs, imm);
19441 break;
19442 case OPC_J ... OPC_JAL: /* Jump */
19443 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19444 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19445 break;
19446 /* Branch */
19447 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
19448 if (ctx->insn_flags & ISA_MIPS32R6) {
19449 if (rt == 0) {
19450 generate_exception_end(ctx, EXCP_RI);
19451 break;
19453 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
19454 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19455 } else {
19456 /* OPC_BLEZL */
19457 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19459 break;
19460 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
19461 if (ctx->insn_flags & ISA_MIPS32R6) {
19462 if (rt == 0) {
19463 generate_exception_end(ctx, EXCP_RI);
19464 break;
19466 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
19467 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19468 } else {
19469 /* OPC_BGTZL */
19470 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19472 break;
19473 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
19474 if (rt == 0) {
19475 /* OPC_BLEZ */
19476 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19477 } else {
19478 check_insn(ctx, ISA_MIPS32R6);
19479 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
19480 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19482 break;
19483 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
19484 if (rt == 0) {
19485 /* OPC_BGTZ */
19486 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19487 } else {
19488 check_insn(ctx, ISA_MIPS32R6);
19489 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
19490 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19492 break;
19493 case OPC_BEQL:
19494 case OPC_BNEL:
19495 check_insn(ctx, ISA_MIPS2);
19496 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19497 /* Fallthrough */
19498 case OPC_BEQ:
19499 case OPC_BNE:
19500 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19501 break;
19502 case OPC_LL: /* Load and stores */
19503 check_insn(ctx, ISA_MIPS2);
19504 /* Fallthrough */
19505 case OPC_LWL:
19506 case OPC_LWR:
19507 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19508 /* Fallthrough */
19509 case OPC_LB ... OPC_LH:
19510 case OPC_LW ... OPC_LHU:
19511 gen_ld(ctx, op, rt, rs, imm);
19512 break;
19513 case OPC_SWL:
19514 case OPC_SWR:
19515 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19516 /* fall through */
19517 case OPC_SB ... OPC_SH:
19518 case OPC_SW:
19519 gen_st(ctx, op, rt, rs, imm);
19520 break;
19521 case OPC_SC:
19522 check_insn(ctx, ISA_MIPS2);
19523 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19524 gen_st_cond(ctx, op, rt, rs, imm);
19525 break;
19526 case OPC_CACHE:
19527 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19528 check_cp0_enabled(ctx);
19529 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
19530 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
19531 gen_cache_operation(ctx, rt, rs, imm);
19533 /* Treat as NOP. */
19534 break;
19535 case OPC_PREF:
19536 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19537 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
19538 /* Treat as NOP. */
19539 break;
19541 /* Floating point (COP1). */
19542 case OPC_LWC1:
19543 case OPC_LDC1:
19544 case OPC_SWC1:
19545 case OPC_SDC1:
19546 gen_cop1_ldst(ctx, op, rt, rs, imm);
19547 break;
19549 case OPC_CP1:
19550 op1 = MASK_CP1(ctx->opcode);
19552 switch (op1) {
19553 case OPC_MFHC1:
19554 case OPC_MTHC1:
19555 check_cp1_enabled(ctx);
19556 check_insn(ctx, ISA_MIPS32R2);
19557 case OPC_MFC1:
19558 case OPC_CFC1:
19559 case OPC_MTC1:
19560 case OPC_CTC1:
19561 check_cp1_enabled(ctx);
19562 gen_cp1(ctx, op1, rt, rd);
19563 break;
19564 #if defined(TARGET_MIPS64)
19565 case OPC_DMFC1:
19566 case OPC_DMTC1:
19567 check_cp1_enabled(ctx);
19568 check_insn(ctx, ISA_MIPS3);
19569 check_mips_64(ctx);
19570 gen_cp1(ctx, op1, rt, rd);
19571 break;
19572 #endif
19573 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
19574 check_cp1_enabled(ctx);
19575 if (ctx->insn_flags & ISA_MIPS32R6) {
19576 /* OPC_BC1EQZ */
19577 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19578 rt, imm << 2, 4);
19579 } else {
19580 /* OPC_BC1ANY2 */
19581 check_cop1x(ctx);
19582 check_insn(ctx, ASE_MIPS3D);
19583 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19584 (rt >> 2) & 0x7, imm << 2);
19586 break;
19587 case OPC_BC1NEZ:
19588 check_cp1_enabled(ctx);
19589 check_insn(ctx, ISA_MIPS32R6);
19590 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19591 rt, imm << 2, 4);
19592 break;
19593 case OPC_BC1ANY4:
19594 check_cp1_enabled(ctx);
19595 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19596 check_cop1x(ctx);
19597 check_insn(ctx, ASE_MIPS3D);
19598 /* fall through */
19599 case OPC_BC1:
19600 check_cp1_enabled(ctx);
19601 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19602 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19603 (rt >> 2) & 0x7, imm << 2);
19604 break;
19605 case OPC_PS_FMT:
19606 check_ps(ctx);
19607 /* fall through */
19608 case OPC_S_FMT:
19609 case OPC_D_FMT:
19610 check_cp1_enabled(ctx);
19611 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19612 (imm >> 8) & 0x7);
19613 break;
19614 case OPC_W_FMT:
19615 case OPC_L_FMT:
19617 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
19618 check_cp1_enabled(ctx);
19619 if (ctx->insn_flags & ISA_MIPS32R6) {
19620 switch (r6_op) {
19621 case R6_OPC_CMP_AF_S:
19622 case R6_OPC_CMP_UN_S:
19623 case R6_OPC_CMP_EQ_S:
19624 case R6_OPC_CMP_UEQ_S:
19625 case R6_OPC_CMP_LT_S:
19626 case R6_OPC_CMP_ULT_S:
19627 case R6_OPC_CMP_LE_S:
19628 case R6_OPC_CMP_ULE_S:
19629 case R6_OPC_CMP_SAF_S:
19630 case R6_OPC_CMP_SUN_S:
19631 case R6_OPC_CMP_SEQ_S:
19632 case R6_OPC_CMP_SEUQ_S:
19633 case R6_OPC_CMP_SLT_S:
19634 case R6_OPC_CMP_SULT_S:
19635 case R6_OPC_CMP_SLE_S:
19636 case R6_OPC_CMP_SULE_S:
19637 case R6_OPC_CMP_OR_S:
19638 case R6_OPC_CMP_UNE_S:
19639 case R6_OPC_CMP_NE_S:
19640 case R6_OPC_CMP_SOR_S:
19641 case R6_OPC_CMP_SUNE_S:
19642 case R6_OPC_CMP_SNE_S:
19643 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19644 break;
19645 case R6_OPC_CMP_AF_D:
19646 case R6_OPC_CMP_UN_D:
19647 case R6_OPC_CMP_EQ_D:
19648 case R6_OPC_CMP_UEQ_D:
19649 case R6_OPC_CMP_LT_D:
19650 case R6_OPC_CMP_ULT_D:
19651 case R6_OPC_CMP_LE_D:
19652 case R6_OPC_CMP_ULE_D:
19653 case R6_OPC_CMP_SAF_D:
19654 case R6_OPC_CMP_SUN_D:
19655 case R6_OPC_CMP_SEQ_D:
19656 case R6_OPC_CMP_SEUQ_D:
19657 case R6_OPC_CMP_SLT_D:
19658 case R6_OPC_CMP_SULT_D:
19659 case R6_OPC_CMP_SLE_D:
19660 case R6_OPC_CMP_SULE_D:
19661 case R6_OPC_CMP_OR_D:
19662 case R6_OPC_CMP_UNE_D:
19663 case R6_OPC_CMP_NE_D:
19664 case R6_OPC_CMP_SOR_D:
19665 case R6_OPC_CMP_SUNE_D:
19666 case R6_OPC_CMP_SNE_D:
19667 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19668 break;
19669 default:
19670 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
19671 rt, rd, sa, (imm >> 8) & 0x7);
19673 break;
19675 } else {
19676 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19677 (imm >> 8) & 0x7);
19679 break;
19681 case OPC_BZ_V:
19682 case OPC_BNZ_V:
19683 case OPC_BZ_B:
19684 case OPC_BZ_H:
19685 case OPC_BZ_W:
19686 case OPC_BZ_D:
19687 case OPC_BNZ_B:
19688 case OPC_BNZ_H:
19689 case OPC_BNZ_W:
19690 case OPC_BNZ_D:
19691 check_insn(ctx, ASE_MSA);
19692 gen_msa_branch(env, ctx, op1);
19693 break;
19694 default:
19695 MIPS_INVAL("cp1");
19696 generate_exception_end(ctx, EXCP_RI);
19697 break;
19699 break;
19701 /* Compact branches [R6] and COP2 [non-R6] */
19702 case OPC_BC: /* OPC_LWC2 */
19703 case OPC_BALC: /* OPC_SWC2 */
19704 if (ctx->insn_flags & ISA_MIPS32R6) {
19705 /* OPC_BC, OPC_BALC */
19706 gen_compute_compact_branch(ctx, op, 0, 0,
19707 sextract32(ctx->opcode << 2, 0, 28));
19708 } else {
19709 /* OPC_LWC2, OPC_SWC2 */
19710 /* COP2: Not implemented. */
19711 generate_exception_err(ctx, EXCP_CpU, 2);
19713 break;
19714 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
19715 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
19716 if (ctx->insn_flags & ISA_MIPS32R6) {
19717 if (rs != 0) {
19718 /* OPC_BEQZC, OPC_BNEZC */
19719 gen_compute_compact_branch(ctx, op, rs, 0,
19720 sextract32(ctx->opcode << 2, 0, 23));
19721 } else {
19722 /* OPC_JIC, OPC_JIALC */
19723 gen_compute_compact_branch(ctx, op, 0, rt, imm);
19725 } else {
19726 /* OPC_LWC2, OPC_SWC2 */
19727 /* COP2: Not implemented. */
19728 generate_exception_err(ctx, EXCP_CpU, 2);
19730 break;
19731 case OPC_CP2:
19732 check_insn(ctx, INSN_LOONGSON2F);
19733 /* Note that these instructions use different fields. */
19734 gen_loongson_multimedia(ctx, sa, rd, rt);
19735 break;
19737 case OPC_CP3:
19738 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19739 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19740 check_cp1_enabled(ctx);
19741 op1 = MASK_CP3(ctx->opcode);
19742 switch (op1) {
19743 case OPC_LUXC1:
19744 case OPC_SUXC1:
19745 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19746 /* Fallthrough */
19747 case OPC_LWXC1:
19748 case OPC_LDXC1:
19749 case OPC_SWXC1:
19750 case OPC_SDXC1:
19751 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19752 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
19753 break;
19754 case OPC_PREFX:
19755 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19756 /* Treat as NOP. */
19757 break;
19758 case OPC_ALNV_PS:
19759 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19760 /* Fallthrough */
19761 case OPC_MADD_S:
19762 case OPC_MADD_D:
19763 case OPC_MADD_PS:
19764 case OPC_MSUB_S:
19765 case OPC_MSUB_D:
19766 case OPC_MSUB_PS:
19767 case OPC_NMADD_S:
19768 case OPC_NMADD_D:
19769 case OPC_NMADD_PS:
19770 case OPC_NMSUB_S:
19771 case OPC_NMSUB_D:
19772 case OPC_NMSUB_PS:
19773 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19774 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
19775 break;
19776 default:
19777 MIPS_INVAL("cp3");
19778 generate_exception_end(ctx, EXCP_RI);
19779 break;
19781 } else {
19782 generate_exception_err(ctx, EXCP_CpU, 1);
19784 break;
19786 #if defined(TARGET_MIPS64)
19787 /* MIPS64 opcodes */
19788 case OPC_LDL ... OPC_LDR:
19789 case OPC_LLD:
19790 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19791 /* fall through */
19792 case OPC_LWU:
19793 case OPC_LD:
19794 check_insn(ctx, ISA_MIPS3);
19795 check_mips_64(ctx);
19796 gen_ld(ctx, op, rt, rs, imm);
19797 break;
19798 case OPC_SDL ... OPC_SDR:
19799 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19800 /* fall through */
19801 case OPC_SD:
19802 check_insn(ctx, ISA_MIPS3);
19803 check_mips_64(ctx);
19804 gen_st(ctx, op, rt, rs, imm);
19805 break;
19806 case OPC_SCD:
19807 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19808 check_insn(ctx, ISA_MIPS3);
19809 check_mips_64(ctx);
19810 gen_st_cond(ctx, op, rt, rs, imm);
19811 break;
19812 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
19813 if (ctx->insn_flags & ISA_MIPS32R6) {
19814 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
19815 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19816 } else {
19817 /* OPC_DADDI */
19818 check_insn(ctx, ISA_MIPS3);
19819 check_mips_64(ctx);
19820 gen_arith_imm(ctx, op, rt, rs, imm);
19822 break;
19823 case OPC_DADDIU:
19824 check_insn(ctx, ISA_MIPS3);
19825 check_mips_64(ctx);
19826 gen_arith_imm(ctx, op, rt, rs, imm);
19827 break;
19828 #else
19829 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
19830 if (ctx->insn_flags & ISA_MIPS32R6) {
19831 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19832 } else {
19833 MIPS_INVAL("major opcode");
19834 generate_exception_end(ctx, EXCP_RI);
19836 break;
19837 #endif
19838 case OPC_DAUI: /* OPC_JALX */
19839 if (ctx->insn_flags & ISA_MIPS32R6) {
19840 #if defined(TARGET_MIPS64)
19841 /* OPC_DAUI */
19842 check_mips_64(ctx);
19843 if (rs == 0) {
19844 generate_exception(ctx, EXCP_RI);
19845 } else if (rt != 0) {
19846 TCGv t0 = tcg_temp_new();
19847 gen_load_gpr(t0, rs);
19848 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
19849 tcg_temp_free(t0);
19851 #else
19852 generate_exception_end(ctx, EXCP_RI);
19853 MIPS_INVAL("major opcode");
19854 #endif
19855 } else {
19856 /* OPC_JALX */
19857 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
19858 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19859 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19861 break;
19862 case OPC_MSA: /* OPC_MDMX */
19863 /* MDMX: Not implemented. */
19864 gen_msa(env, ctx);
19865 break;
19866 case OPC_PCREL:
19867 check_insn(ctx, ISA_MIPS32R6);
19868 gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
19869 break;
19870 default: /* Invalid */
19871 MIPS_INVAL("major opcode");
19872 generate_exception_end(ctx, EXCP_RI);
19873 break;
19877 void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
19879 MIPSCPU *cpu = mips_env_get_cpu(env);
19880 CPUState *cs = CPU(cpu);
19881 DisasContext ctx;
19882 target_ulong pc_start;
19883 target_ulong next_page_start;
19884 int num_insns;
19885 int max_insns;
19886 int insn_bytes;
19887 int is_slot;
19889 pc_start = tb->pc;
19890 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
19891 ctx.pc = pc_start;
19892 ctx.saved_pc = -1;
19893 ctx.singlestep_enabled = cs->singlestep_enabled;
19894 ctx.insn_flags = env->insn_flags;
19895 ctx.CP0_Config1 = env->CP0_Config1;
19896 ctx.tb = tb;
19897 ctx.bstate = BS_NONE;
19898 ctx.btarget = 0;
19899 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
19900 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
19901 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
19902 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
19903 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
19904 ctx.PAMask = env->PAMask;
19905 ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
19906 ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
19907 ctx.cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
19908 /* Restore delay slot state from the tb context. */
19909 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
19910 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
19911 ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
19912 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
19913 ctx.vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
19914 ctx.mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
19915 ctx.nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
19916 ctx.abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
19917 restore_cpu_state(env, &ctx);
19918 #ifdef CONFIG_USER_ONLY
19919 ctx.mem_idx = MIPS_HFLAG_UM;
19920 #else
19921 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
19922 #endif
19923 ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
19924 MO_UNALN : MO_ALIGN;
19925 num_insns = 0;
19926 max_insns = tb->cflags & CF_COUNT_MASK;
19927 if (max_insns == 0) {
19928 max_insns = CF_COUNT_MASK;
19930 if (max_insns > TCG_MAX_INSNS) {
19931 max_insns = TCG_MAX_INSNS;
19934 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
19935 gen_tb_start(tb);
19936 while (ctx.bstate == BS_NONE) {
19937 tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
19938 num_insns++;
19940 if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
19941 save_cpu_state(&ctx, 1);
19942 ctx.bstate = BS_BRANCH;
19943 gen_helper_raise_exception_debug(cpu_env);
19944 /* The address covered by the breakpoint must be included in
19945 [tb->pc, tb->pc + tb->size) in order to for it to be
19946 properly cleared -- thus we increment the PC here so that
19947 the logic setting tb->size below does the right thing. */
19948 ctx.pc += 4;
19949 goto done_generating;
19952 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
19953 gen_io_start();
19956 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
19957 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
19958 ctx.opcode = cpu_ldl_code(env, ctx.pc);
19959 insn_bytes = 4;
19960 decode_opc(env, &ctx);
19961 } else if (ctx.insn_flags & ASE_MICROMIPS) {
19962 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19963 insn_bytes = decode_micromips_opc(env, &ctx);
19964 } else if (ctx.insn_flags & ASE_MIPS16) {
19965 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19966 insn_bytes = decode_mips16_opc(env, &ctx);
19967 } else {
19968 generate_exception_end(&ctx, EXCP_RI);
19969 break;
19972 if (ctx.hflags & MIPS_HFLAG_BMASK) {
19973 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
19974 MIPS_HFLAG_FBNSLOT))) {
19975 /* force to generate branch as there is neither delay nor
19976 forbidden slot */
19977 is_slot = 1;
19979 if ((ctx.hflags & MIPS_HFLAG_M16) &&
19980 (ctx.hflags & MIPS_HFLAG_FBNSLOT)) {
19981 /* Force to generate branch as microMIPS R6 doesn't restrict
19982 branches in the forbidden slot. */
19983 is_slot = 1;
19986 if (is_slot) {
19987 gen_branch(&ctx, insn_bytes);
19989 ctx.pc += insn_bytes;
19991 /* Execute a branch and its delay slot as a single instruction.
19992 This is what GDB expects and is consistent with what the
19993 hardware does (e.g. if a delay slot instruction faults, the
19994 reported PC is the PC of the branch). */
19995 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
19996 break;
19999 if (ctx.pc >= next_page_start) {
20000 break;
20003 if (tcg_op_buf_full()) {
20004 break;
20007 if (num_insns >= max_insns)
20008 break;
20010 if (singlestep)
20011 break;
20013 if (tb->cflags & CF_LAST_IO) {
20014 gen_io_end();
20016 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
20017 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
20018 gen_helper_raise_exception_debug(cpu_env);
20019 } else {
20020 switch (ctx.bstate) {
20021 case BS_STOP:
20022 gen_goto_tb(&ctx, 0, ctx.pc);
20023 break;
20024 case BS_NONE:
20025 save_cpu_state(&ctx, 0);
20026 gen_goto_tb(&ctx, 0, ctx.pc);
20027 break;
20028 case BS_EXCP:
20029 tcg_gen_exit_tb(0);
20030 break;
20031 case BS_BRANCH:
20032 default:
20033 break;
20036 done_generating:
20037 gen_tb_end(tb, num_insns);
20039 tb->size = ctx.pc - pc_start;
20040 tb->icount = num_insns;
20042 #ifdef DEBUG_DISAS
20043 LOG_DISAS("\n");
20044 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
20045 && qemu_log_in_addr_range(pc_start)) {
20046 qemu_log("IN: %s\n", lookup_symbol(pc_start));
20047 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
20048 qemu_log("\n");
20050 #endif
20053 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
20054 int flags)
20056 int i;
20057 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
20059 #define printfpr(fp) \
20060 do { \
20061 if (is_fpu64) \
20062 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20063 " fd:%13g fs:%13g psu: %13g\n", \
20064 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
20065 (double)(fp)->fd, \
20066 (double)(fp)->fs[FP_ENDIAN_IDX], \
20067 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
20068 else { \
20069 fpr_t tmp; \
20070 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
20071 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
20072 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20073 " fd:%13g fs:%13g psu:%13g\n", \
20074 tmp.w[FP_ENDIAN_IDX], tmp.d, \
20075 (double)tmp.fd, \
20076 (double)tmp.fs[FP_ENDIAN_IDX], \
20077 (double)tmp.fs[!FP_ENDIAN_IDX]); \
20079 } while(0)
20082 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
20083 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
20084 get_float_exception_flags(&env->active_fpu.fp_status));
20085 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
20086 fpu_fprintf(f, "%3s: ", fregnames[i]);
20087 printfpr(&env->active_fpu.fpr[i]);
20090 #undef printfpr
20093 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
20094 int flags)
20096 MIPSCPU *cpu = MIPS_CPU(cs);
20097 CPUMIPSState *env = &cpu->env;
20098 int i;
20100 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
20101 " LO=0x" TARGET_FMT_lx " ds %04x "
20102 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
20103 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
20104 env->hflags, env->btarget, env->bcond);
20105 for (i = 0; i < 32; i++) {
20106 if ((i & 3) == 0)
20107 cpu_fprintf(f, "GPR%02d:", i);
20108 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
20109 if ((i & 3) == 3)
20110 cpu_fprintf(f, "\n");
20113 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
20114 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
20115 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
20116 PRIx64 "\n",
20117 env->CP0_Config0, env->CP0_Config1, env->lladdr);
20118 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
20119 env->CP0_Config2, env->CP0_Config3);
20120 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
20121 env->CP0_Config4, env->CP0_Config5);
20122 if (env->hflags & MIPS_HFLAG_FPU)
20123 fpu_dump_state(env, f, cpu_fprintf, flags);
20126 void mips_tcg_init(void)
20128 int i;
20129 static int inited;
20131 /* Initialize various static tables. */
20132 if (inited)
20133 return;
20135 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
20136 tcg_ctx.tcg_env = cpu_env;
20138 TCGV_UNUSED(cpu_gpr[0]);
20139 for (i = 1; i < 32; i++)
20140 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
20141 offsetof(CPUMIPSState, active_tc.gpr[i]),
20142 regnames[i]);
20144 for (i = 0; i < 32; i++) {
20145 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
20146 msa_wr_d[i * 2] =
20147 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
20148 /* The scalar floating-point unit (FPU) registers are mapped on
20149 * the MSA vector registers. */
20150 fpu_f64[i] = msa_wr_d[i * 2];
20151 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
20152 msa_wr_d[i * 2 + 1] =
20153 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
20156 cpu_PC = tcg_global_mem_new(cpu_env,
20157 offsetof(CPUMIPSState, active_tc.PC), "PC");
20158 for (i = 0; i < MIPS_DSP_ACC; i++) {
20159 cpu_HI[i] = tcg_global_mem_new(cpu_env,
20160 offsetof(CPUMIPSState, active_tc.HI[i]),
20161 regnames_HI[i]);
20162 cpu_LO[i] = tcg_global_mem_new(cpu_env,
20163 offsetof(CPUMIPSState, active_tc.LO[i]),
20164 regnames_LO[i]);
20166 cpu_dspctrl = tcg_global_mem_new(cpu_env,
20167 offsetof(CPUMIPSState, active_tc.DSPControl),
20168 "DSPControl");
20169 bcond = tcg_global_mem_new(cpu_env,
20170 offsetof(CPUMIPSState, bcond), "bcond");
20171 btarget = tcg_global_mem_new(cpu_env,
20172 offsetof(CPUMIPSState, btarget), "btarget");
20173 hflags = tcg_global_mem_new_i32(cpu_env,
20174 offsetof(CPUMIPSState, hflags), "hflags");
20176 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
20177 offsetof(CPUMIPSState, active_fpu.fcr0),
20178 "fcr0");
20179 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
20180 offsetof(CPUMIPSState, active_fpu.fcr31),
20181 "fcr31");
20183 inited = 1;
20186 #include "translate_init.c"
20188 MIPSCPU *cpu_mips_init(const char *cpu_model)
20190 MIPSCPU *cpu;
20191 CPUMIPSState *env;
20192 const mips_def_t *def;
20194 def = cpu_mips_find_by_name(cpu_model);
20195 if (!def)
20196 return NULL;
20197 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
20198 env = &cpu->env;
20199 env->cpu_model = def;
20200 env->exception_base = (int32_t)0xBFC00000;
20202 #ifndef CONFIG_USER_ONLY
20203 mmu_init(env, def);
20204 #endif
20205 fpu_init(env, def);
20206 mvp_init(env, def);
20208 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
20210 return cpu;
20213 bool cpu_supports_cps_smp(const char *cpu_model)
20215 const mips_def_t *def = cpu_mips_find_by_name(cpu_model);
20216 if (!def) {
20217 return false;
20220 return (def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
20223 void cpu_set_exception_base(int vp_index, target_ulong address)
20225 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
20226 vp->env.exception_base = address;
20229 void cpu_state_reset(CPUMIPSState *env)
20231 MIPSCPU *cpu = mips_env_get_cpu(env);
20232 CPUState *cs = CPU(cpu);
20234 /* Reset registers to their default values */
20235 env->CP0_PRid = env->cpu_model->CP0_PRid;
20236 env->CP0_Config0 = env->cpu_model->CP0_Config0;
20237 #ifdef TARGET_WORDS_BIGENDIAN
20238 env->CP0_Config0 |= (1 << CP0C0_BE);
20239 #endif
20240 env->CP0_Config1 = env->cpu_model->CP0_Config1;
20241 env->CP0_Config2 = env->cpu_model->CP0_Config2;
20242 env->CP0_Config3 = env->cpu_model->CP0_Config3;
20243 env->CP0_Config4 = env->cpu_model->CP0_Config4;
20244 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
20245 env->CP0_Config5 = env->cpu_model->CP0_Config5;
20246 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
20247 env->CP0_Config6 = env->cpu_model->CP0_Config6;
20248 env->CP0_Config7 = env->cpu_model->CP0_Config7;
20249 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
20250 << env->cpu_model->CP0_LLAddr_shift;
20251 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
20252 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
20253 env->CCRes = env->cpu_model->CCRes;
20254 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
20255 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
20256 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
20257 env->current_tc = 0;
20258 env->SEGBITS = env->cpu_model->SEGBITS;
20259 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
20260 #if defined(TARGET_MIPS64)
20261 if (env->cpu_model->insn_flags & ISA_MIPS3) {
20262 env->SEGMask |= 3ULL << 62;
20264 #endif
20265 env->PABITS = env->cpu_model->PABITS;
20266 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
20267 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
20268 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
20269 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
20270 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
20271 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
20272 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
20273 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
20274 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
20275 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
20276 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
20277 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
20278 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
20279 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
20280 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
20281 env->msair = env->cpu_model->MSAIR;
20282 env->insn_flags = env->cpu_model->insn_flags;
20284 #if defined(CONFIG_USER_ONLY)
20285 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
20286 # ifdef TARGET_MIPS64
20287 /* Enable 64-bit register mode. */
20288 env->CP0_Status |= (1 << CP0St_PX);
20289 # endif
20290 # ifdef TARGET_ABI_MIPSN64
20291 /* Enable 64-bit address mode. */
20292 env->CP0_Status |= (1 << CP0St_UX);
20293 # endif
20294 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
20295 hardware registers. */
20296 env->CP0_HWREna |= 0x0000000F;
20297 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
20298 env->CP0_Status |= (1 << CP0St_CU1);
20300 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
20301 env->CP0_Status |= (1 << CP0St_MX);
20303 # if defined(TARGET_MIPS64)
20304 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
20305 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
20306 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
20307 env->CP0_Status |= (1 << CP0St_FR);
20309 # endif
20310 #else
20311 if (env->hflags & MIPS_HFLAG_BMASK) {
20312 /* If the exception was raised from a delay slot,
20313 come back to the jump. */
20314 env->CP0_ErrorEPC = (env->active_tc.PC
20315 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
20316 } else {
20317 env->CP0_ErrorEPC = env->active_tc.PC;
20319 env->active_tc.PC = env->exception_base;
20320 env->CP0_Random = env->tlb->nb_tlb - 1;
20321 env->tlb->tlb_in_use = env->tlb->nb_tlb;
20322 env->CP0_Wired = 0;
20323 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
20324 env->CP0_EBase = (cs->cpu_index & 0x3FF);
20325 if (kvm_enabled()) {
20326 env->CP0_EBase |= 0x40000000;
20327 } else {
20328 env->CP0_EBase |= 0x80000000;
20330 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
20331 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
20333 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
20334 0x3ff : 0xff;
20335 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
20336 /* vectored interrupts not implemented, timer on int 7,
20337 no performance counters. */
20338 env->CP0_IntCtl = 0xe0000000;
20340 int i;
20342 for (i = 0; i < 7; i++) {
20343 env->CP0_WatchLo[i] = 0;
20344 env->CP0_WatchHi[i] = 0x80000000;
20346 env->CP0_WatchLo[7] = 0;
20347 env->CP0_WatchHi[7] = 0;
20349 /* Count register increments in debug mode, EJTAG version 1 */
20350 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
20352 cpu_mips_store_count(env, 1);
20354 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
20355 int i;
20357 /* Only TC0 on VPE 0 starts as active. */
20358 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
20359 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
20360 env->tcs[i].CP0_TCHalt = 1;
20362 env->active_tc.CP0_TCHalt = 1;
20363 cs->halted = 1;
20365 if (cs->cpu_index == 0) {
20366 /* VPE0 starts up enabled. */
20367 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
20368 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
20370 /* TC0 starts up unhalted. */
20371 cs->halted = 0;
20372 env->active_tc.CP0_TCHalt = 0;
20373 env->tcs[0].CP0_TCHalt = 0;
20374 /* With thread 0 active. */
20375 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
20376 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
20379 #endif
20380 if ((env->insn_flags & ISA_MIPS32R6) &&
20381 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
20382 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
20383 env->CP0_Status |= (1 << CP0St_FR);
20386 /* MSA */
20387 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
20388 msa_reset(env);
20391 compute_hflags(env);
20392 restore_fp_status(env);
20393 restore_pamask(env);
20394 cs->exception_index = EXCP_NONE;
20396 if (semihosting_get_argc()) {
20397 /* UHI interface can be used to obtain argc and argv */
20398 env->active_tc.gpr[4] = -1;
20402 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
20403 target_ulong *data)
20405 env->active_tc.PC = data[0];
20406 env->hflags &= ~MIPS_HFLAG_BMASK;
20407 env->hflags |= data[1];
20408 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
20409 case MIPS_HFLAG_BR:
20410 break;
20411 case MIPS_HFLAG_BC:
20412 case MIPS_HFLAG_BL:
20413 case MIPS_HFLAG_B:
20414 env->btarget = data[2];
20415 break;