MAINTAINERS: add ACPI entry
[qemu/cris-port.git] / target-mips / translate.c
blob1d128eef02fcd16a3e1fe3ca178d567ac9668bf1
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 "cpu.h"
25 #include "disas/disas.h"
26 #include "tcg-op.h"
27 #include "exec/cpu_ldst.h"
29 #include "exec/helper-proto.h"
30 #include "exec/helper-gen.h"
31 #include "sysemu/kvm.h"
33 #include "trace-tcg.h"
36 #define MIPS_DEBUG_DISAS 0
37 //#define MIPS_DEBUG_SIGN_EXTENSIONS
39 /* MIPS major opcodes */
40 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
42 enum {
43 /* indirect opcode tables */
44 OPC_SPECIAL = (0x00 << 26),
45 OPC_REGIMM = (0x01 << 26),
46 OPC_CP0 = (0x10 << 26),
47 OPC_CP1 = (0x11 << 26),
48 OPC_CP2 = (0x12 << 26),
49 OPC_CP3 = (0x13 << 26),
50 OPC_SPECIAL2 = (0x1C << 26),
51 OPC_SPECIAL3 = (0x1F << 26),
52 /* arithmetic with immediate */
53 OPC_ADDI = (0x08 << 26),
54 OPC_ADDIU = (0x09 << 26),
55 OPC_SLTI = (0x0A << 26),
56 OPC_SLTIU = (0x0B << 26),
57 /* logic with immediate */
58 OPC_ANDI = (0x0C << 26),
59 OPC_ORI = (0x0D << 26),
60 OPC_XORI = (0x0E << 26),
61 OPC_LUI = (0x0F << 26),
62 /* arithmetic with immediate */
63 OPC_DADDI = (0x18 << 26),
64 OPC_DADDIU = (0x19 << 26),
65 /* Jump and branches */
66 OPC_J = (0x02 << 26),
67 OPC_JAL = (0x03 << 26),
68 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
69 OPC_BEQL = (0x14 << 26),
70 OPC_BNE = (0x05 << 26),
71 OPC_BNEL = (0x15 << 26),
72 OPC_BLEZ = (0x06 << 26),
73 OPC_BLEZL = (0x16 << 26),
74 OPC_BGTZ = (0x07 << 26),
75 OPC_BGTZL = (0x17 << 26),
76 OPC_JALX = (0x1D << 26),
77 OPC_DAUI = (0x1D << 26),
78 /* Load and stores */
79 OPC_LDL = (0x1A << 26),
80 OPC_LDR = (0x1B << 26),
81 OPC_LB = (0x20 << 26),
82 OPC_LH = (0x21 << 26),
83 OPC_LWL = (0x22 << 26),
84 OPC_LW = (0x23 << 26),
85 OPC_LWPC = OPC_LW | 0x5,
86 OPC_LBU = (0x24 << 26),
87 OPC_LHU = (0x25 << 26),
88 OPC_LWR = (0x26 << 26),
89 OPC_LWU = (0x27 << 26),
90 OPC_SB = (0x28 << 26),
91 OPC_SH = (0x29 << 26),
92 OPC_SWL = (0x2A << 26),
93 OPC_SW = (0x2B << 26),
94 OPC_SDL = (0x2C << 26),
95 OPC_SDR = (0x2D << 26),
96 OPC_SWR = (0x2E << 26),
97 OPC_LL = (0x30 << 26),
98 OPC_LLD = (0x34 << 26),
99 OPC_LD = (0x37 << 26),
100 OPC_LDPC = OPC_LD | 0x5,
101 OPC_SC = (0x38 << 26),
102 OPC_SCD = (0x3C << 26),
103 OPC_SD = (0x3F << 26),
104 /* Floating point load/store */
105 OPC_LWC1 = (0x31 << 26),
106 OPC_LWC2 = (0x32 << 26),
107 OPC_LDC1 = (0x35 << 26),
108 OPC_LDC2 = (0x36 << 26),
109 OPC_SWC1 = (0x39 << 26),
110 OPC_SWC2 = (0x3A << 26),
111 OPC_SDC1 = (0x3D << 26),
112 OPC_SDC2 = (0x3E << 26),
113 /* Compact Branches */
114 OPC_BLEZALC = (0x06 << 26),
115 OPC_BGEZALC = (0x06 << 26),
116 OPC_BGEUC = (0x06 << 26),
117 OPC_BGTZALC = (0x07 << 26),
118 OPC_BLTZALC = (0x07 << 26),
119 OPC_BLTUC = (0x07 << 26),
120 OPC_BOVC = (0x08 << 26),
121 OPC_BEQZALC = (0x08 << 26),
122 OPC_BEQC = (0x08 << 26),
123 OPC_BLEZC = (0x16 << 26),
124 OPC_BGEZC = (0x16 << 26),
125 OPC_BGEC = (0x16 << 26),
126 OPC_BGTZC = (0x17 << 26),
127 OPC_BLTZC = (0x17 << 26),
128 OPC_BLTC = (0x17 << 26),
129 OPC_BNVC = (0x18 << 26),
130 OPC_BNEZALC = (0x18 << 26),
131 OPC_BNEC = (0x18 << 26),
132 OPC_BC = (0x32 << 26),
133 OPC_BEQZC = (0x36 << 26),
134 OPC_JIC = (0x36 << 26),
135 OPC_BALC = (0x3A << 26),
136 OPC_BNEZC = (0x3E << 26),
137 OPC_JIALC = (0x3E << 26),
138 /* MDMX ASE specific */
139 OPC_MDMX = (0x1E << 26),
140 /* MSA ASE, same as MDMX */
141 OPC_MSA = OPC_MDMX,
142 /* Cache and prefetch */
143 OPC_CACHE = (0x2F << 26),
144 OPC_PREF = (0x33 << 26),
145 /* PC-relative address computation / loads */
146 OPC_PCREL = (0x3B << 26),
149 /* PC-relative address computation / loads */
150 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
151 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
152 enum {
153 /* Instructions determined by bits 19 and 20 */
154 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
155 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
156 OPC_LWUPC = OPC_PCREL | (2 << 19),
158 /* Instructions determined by bits 16 ... 20 */
159 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
160 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
162 /* Other */
163 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
166 /* MIPS special opcodes */
167 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
169 enum {
170 /* Shifts */
171 OPC_SLL = 0x00 | OPC_SPECIAL,
172 /* NOP is SLL r0, r0, 0 */
173 /* SSNOP is SLL r0, r0, 1 */
174 /* EHB is SLL r0, r0, 3 */
175 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
176 OPC_ROTR = OPC_SRL | (1 << 21),
177 OPC_SRA = 0x03 | OPC_SPECIAL,
178 OPC_SLLV = 0x04 | OPC_SPECIAL,
179 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
180 OPC_ROTRV = OPC_SRLV | (1 << 6),
181 OPC_SRAV = 0x07 | OPC_SPECIAL,
182 OPC_DSLLV = 0x14 | OPC_SPECIAL,
183 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
184 OPC_DROTRV = OPC_DSRLV | (1 << 6),
185 OPC_DSRAV = 0x17 | OPC_SPECIAL,
186 OPC_DSLL = 0x38 | OPC_SPECIAL,
187 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
188 OPC_DROTR = OPC_DSRL | (1 << 21),
189 OPC_DSRA = 0x3B | OPC_SPECIAL,
190 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
191 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
192 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
193 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
194 /* Multiplication / division */
195 OPC_MULT = 0x18 | OPC_SPECIAL,
196 OPC_MULTU = 0x19 | OPC_SPECIAL,
197 OPC_DIV = 0x1A | OPC_SPECIAL,
198 OPC_DIVU = 0x1B | OPC_SPECIAL,
199 OPC_DMULT = 0x1C | OPC_SPECIAL,
200 OPC_DMULTU = 0x1D | OPC_SPECIAL,
201 OPC_DDIV = 0x1E | OPC_SPECIAL,
202 OPC_DDIVU = 0x1F | OPC_SPECIAL,
204 /* 2 registers arithmetic / logic */
205 OPC_ADD = 0x20 | OPC_SPECIAL,
206 OPC_ADDU = 0x21 | OPC_SPECIAL,
207 OPC_SUB = 0x22 | OPC_SPECIAL,
208 OPC_SUBU = 0x23 | OPC_SPECIAL,
209 OPC_AND = 0x24 | OPC_SPECIAL,
210 OPC_OR = 0x25 | OPC_SPECIAL,
211 OPC_XOR = 0x26 | OPC_SPECIAL,
212 OPC_NOR = 0x27 | OPC_SPECIAL,
213 OPC_SLT = 0x2A | OPC_SPECIAL,
214 OPC_SLTU = 0x2B | OPC_SPECIAL,
215 OPC_DADD = 0x2C | OPC_SPECIAL,
216 OPC_DADDU = 0x2D | OPC_SPECIAL,
217 OPC_DSUB = 0x2E | OPC_SPECIAL,
218 OPC_DSUBU = 0x2F | OPC_SPECIAL,
219 /* Jumps */
220 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
221 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
222 /* Traps */
223 OPC_TGE = 0x30 | OPC_SPECIAL,
224 OPC_TGEU = 0x31 | OPC_SPECIAL,
225 OPC_TLT = 0x32 | OPC_SPECIAL,
226 OPC_TLTU = 0x33 | OPC_SPECIAL,
227 OPC_TEQ = 0x34 | OPC_SPECIAL,
228 OPC_TNE = 0x36 | OPC_SPECIAL,
229 /* HI / LO registers load & stores */
230 OPC_MFHI = 0x10 | OPC_SPECIAL,
231 OPC_MTHI = 0x11 | OPC_SPECIAL,
232 OPC_MFLO = 0x12 | OPC_SPECIAL,
233 OPC_MTLO = 0x13 | OPC_SPECIAL,
234 /* Conditional moves */
235 OPC_MOVZ = 0x0A | OPC_SPECIAL,
236 OPC_MOVN = 0x0B | OPC_SPECIAL,
238 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
239 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
241 OPC_MOVCI = 0x01 | OPC_SPECIAL,
243 /* Special */
244 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
245 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
246 OPC_BREAK = 0x0D | OPC_SPECIAL,
247 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
248 OPC_SYNC = 0x0F | OPC_SPECIAL,
250 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
251 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
252 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
253 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
256 /* R6 Multiply and Divide instructions have the same Opcode
257 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
258 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
260 enum {
261 R6_OPC_MUL = OPC_MULT | (2 << 6),
262 R6_OPC_MUH = OPC_MULT | (3 << 6),
263 R6_OPC_MULU = OPC_MULTU | (2 << 6),
264 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
265 R6_OPC_DIV = OPC_DIV | (2 << 6),
266 R6_OPC_MOD = OPC_DIV | (3 << 6),
267 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
268 R6_OPC_MODU = OPC_DIVU | (3 << 6),
270 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
271 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
272 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
273 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
274 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
275 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
276 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
277 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
279 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
280 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
281 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
282 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
283 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
285 OPC_LSA = 0x05 | OPC_SPECIAL,
286 OPC_DLSA = 0x15 | OPC_SPECIAL,
289 /* Multiplication variants of the vr54xx. */
290 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
292 enum {
293 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
294 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
295 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
296 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
297 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
298 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
299 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
300 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
301 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
302 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
303 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
304 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
305 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
306 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
309 /* REGIMM (rt field) opcodes */
310 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
312 enum {
313 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
314 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
315 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
316 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
317 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
318 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
319 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
320 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
321 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
322 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
323 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
324 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
325 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
326 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
327 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
329 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
330 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
333 /* Special2 opcodes */
334 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
336 enum {
337 /* Multiply & xxx operations */
338 OPC_MADD = 0x00 | OPC_SPECIAL2,
339 OPC_MADDU = 0x01 | OPC_SPECIAL2,
340 OPC_MUL = 0x02 | OPC_SPECIAL2,
341 OPC_MSUB = 0x04 | OPC_SPECIAL2,
342 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
343 /* Loongson 2F */
344 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
345 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
346 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
347 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
348 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
349 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
350 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
351 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
352 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
353 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
354 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
355 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
356 /* Misc */
357 OPC_CLZ = 0x20 | OPC_SPECIAL2,
358 OPC_CLO = 0x21 | OPC_SPECIAL2,
359 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
360 OPC_DCLO = 0x25 | OPC_SPECIAL2,
361 /* Special */
362 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
365 /* Special3 opcodes */
366 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
368 enum {
369 OPC_EXT = 0x00 | OPC_SPECIAL3,
370 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
371 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
372 OPC_DEXT = 0x03 | OPC_SPECIAL3,
373 OPC_INS = 0x04 | OPC_SPECIAL3,
374 OPC_DINSM = 0x05 | OPC_SPECIAL3,
375 OPC_DINSU = 0x06 | OPC_SPECIAL3,
376 OPC_DINS = 0x07 | OPC_SPECIAL3,
377 OPC_FORK = 0x08 | OPC_SPECIAL3,
378 OPC_YIELD = 0x09 | OPC_SPECIAL3,
379 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
380 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
381 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
383 /* Loongson 2E */
384 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
385 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
386 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
387 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
388 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
389 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
390 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
391 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
392 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
393 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
394 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
395 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
397 /* MIPS DSP Load */
398 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
399 /* MIPS DSP Arithmetic */
400 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
401 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
402 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
403 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
404 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
405 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
406 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
407 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
408 /* MIPS DSP GPR-Based Shift Sub-class */
409 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
410 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
411 /* MIPS DSP Multiply Sub-class insns */
412 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
413 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
414 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
415 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
416 /* DSP Bit/Manipulation Sub-class */
417 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
418 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
419 /* MIPS DSP Append Sub-class */
420 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
421 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
422 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
423 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
424 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
426 /* R6 */
427 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
428 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
429 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
430 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
431 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
432 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
435 /* BSHFL opcodes */
436 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
438 enum {
439 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
440 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
441 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
442 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
443 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
444 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
447 /* DBSHFL opcodes */
448 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
450 enum {
451 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
452 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
453 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
454 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
455 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
458 /* MIPS DSP REGIMM opcodes */
459 enum {
460 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
461 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
464 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
465 /* MIPS DSP Load */
466 enum {
467 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
468 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
469 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
470 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
473 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
474 enum {
475 /* MIPS DSP Arithmetic Sub-class */
476 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
477 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
478 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
479 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
480 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
481 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
482 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
483 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
484 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
485 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
486 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
487 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
488 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
489 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
490 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
491 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
492 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
493 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
494 /* MIPS DSP Multiply Sub-class insns */
495 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
496 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
497 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
498 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
499 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
500 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
503 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
504 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
505 enum {
506 /* MIPS DSP Arithmetic Sub-class */
507 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
508 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
509 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
510 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
511 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
512 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
513 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
514 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
515 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
516 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
517 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
518 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
519 /* MIPS DSP Multiply Sub-class insns */
520 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
521 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
522 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
523 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
526 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
527 enum {
528 /* MIPS DSP Arithmetic Sub-class */
529 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
530 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
531 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
532 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
533 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
534 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
535 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
536 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
537 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
538 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
539 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
540 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
541 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
542 /* DSP Bit/Manipulation Sub-class */
543 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
544 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
545 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
546 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
547 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
550 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
551 enum {
552 /* MIPS DSP Arithmetic Sub-class */
553 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
554 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
555 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
556 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
557 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
558 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
559 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
560 /* DSP Compare-Pick Sub-class */
561 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
562 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
563 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
564 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
565 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
566 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
567 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
568 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
569 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
570 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
571 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
572 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
573 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
574 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
575 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
578 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
579 enum {
580 /* MIPS DSP GPR-Based Shift Sub-class */
581 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
582 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
583 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
584 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
585 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
586 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
587 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
588 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
589 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
590 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
591 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
592 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
593 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
594 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
595 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
596 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
597 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
598 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
599 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
600 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
601 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
602 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
605 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
606 enum {
607 /* MIPS DSP Multiply Sub-class insns */
608 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
609 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
610 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
611 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
612 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
613 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
614 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
615 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
616 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
617 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
618 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
619 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
620 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
621 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
622 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
623 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
624 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
625 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
626 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
627 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
628 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
629 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
632 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
633 enum {
634 /* DSP Bit/Manipulation Sub-class */
635 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
638 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
639 enum {
640 /* MIPS DSP Append Sub-class */
641 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
642 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
643 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
646 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
647 enum {
648 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
649 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
650 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
651 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
652 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
653 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
654 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
655 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
656 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
657 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
658 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
659 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
660 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
661 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
662 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
663 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
664 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
665 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
668 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
669 enum {
670 /* MIPS DSP Arithmetic Sub-class */
671 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
672 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
673 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
674 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
675 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
676 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
677 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
678 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
679 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
680 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
681 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
682 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
683 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
684 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
685 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
686 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
687 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
688 /* DSP Bit/Manipulation Sub-class */
689 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
690 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
691 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
692 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
693 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
694 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
697 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
698 enum {
699 /* MIPS DSP Multiply Sub-class insns */
700 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
701 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
702 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
703 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
704 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
705 /* MIPS DSP Arithmetic Sub-class */
706 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
707 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
708 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
709 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
710 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
711 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
712 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
713 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
714 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
715 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
716 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
717 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
718 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
719 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
720 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
721 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
722 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
723 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
724 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
725 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
726 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
729 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
730 enum {
731 /* DSP Compare-Pick Sub-class */
732 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
733 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
734 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
735 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
736 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
737 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
738 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
739 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
740 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
741 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
742 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
743 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
744 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
745 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
746 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
747 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
748 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
749 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
750 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
751 /* MIPS DSP Arithmetic Sub-class */
752 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
753 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
754 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
755 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
756 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
762 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
763 enum {
764 /* DSP Append Sub-class */
765 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
766 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
767 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
768 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
771 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
772 enum {
773 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
774 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
775 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
776 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
777 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
778 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
779 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
780 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
781 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
782 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
783 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
784 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
785 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
786 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
787 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
788 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
789 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
790 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
791 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
792 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
793 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
794 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
797 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
798 enum {
799 /* DSP Bit/Manipulation Sub-class */
800 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
803 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
804 enum {
805 /* MIPS DSP Multiply Sub-class insns */
806 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
807 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
808 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
809 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
810 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
811 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
812 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
813 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
814 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
815 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
816 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
817 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
818 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
819 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
820 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
821 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
822 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
823 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
824 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
825 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
826 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
827 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
828 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
829 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
830 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
834 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
835 enum {
836 /* MIPS DSP GPR-Based Shift Sub-class */
837 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
838 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
839 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
840 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
841 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
842 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
843 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
844 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
845 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
846 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
847 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
848 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
849 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
850 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
851 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
852 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
853 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
854 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
855 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
856 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
857 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
858 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
859 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
860 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
861 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
865 /* Coprocessor 0 (rs field) */
866 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
868 enum {
869 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
870 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
871 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
872 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
873 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
874 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
875 OPC_MFTR = (0x08 << 21) | OPC_CP0,
876 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
877 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
878 OPC_MTTR = (0x0C << 21) | OPC_CP0,
879 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
880 OPC_C0 = (0x10 << 21) | OPC_CP0,
881 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
882 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
885 /* MFMC0 opcodes */
886 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
888 enum {
889 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
890 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
891 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
892 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
893 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
894 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
897 /* Coprocessor 0 (with rs == C0) */
898 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
900 enum {
901 OPC_TLBR = 0x01 | OPC_C0,
902 OPC_TLBWI = 0x02 | OPC_C0,
903 OPC_TLBINV = 0x03 | OPC_C0,
904 OPC_TLBINVF = 0x04 | OPC_C0,
905 OPC_TLBWR = 0x06 | OPC_C0,
906 OPC_TLBP = 0x08 | OPC_C0,
907 OPC_RFE = 0x10 | OPC_C0,
908 OPC_ERET = 0x18 | OPC_C0,
909 OPC_DERET = 0x1F | OPC_C0,
910 OPC_WAIT = 0x20 | OPC_C0,
913 /* Coprocessor 1 (rs field) */
914 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
916 /* Values for the fmt field in FP instructions */
917 enum {
918 /* 0 - 15 are reserved */
919 FMT_S = 16, /* single fp */
920 FMT_D = 17, /* double fp */
921 FMT_E = 18, /* extended fp */
922 FMT_Q = 19, /* quad fp */
923 FMT_W = 20, /* 32-bit fixed */
924 FMT_L = 21, /* 64-bit fixed */
925 FMT_PS = 22, /* paired single fp */
926 /* 23 - 31 are reserved */
929 enum {
930 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
931 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
932 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
933 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
934 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
935 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
936 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
937 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
938 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
939 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
940 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
941 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
942 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
943 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
944 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
945 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
946 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
947 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
948 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
949 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
950 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
951 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
952 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
953 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
954 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
955 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
956 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
957 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
958 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
959 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
962 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
963 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
965 enum {
966 OPC_BC1F = (0x00 << 16) | OPC_BC1,
967 OPC_BC1T = (0x01 << 16) | OPC_BC1,
968 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
969 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
972 enum {
973 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
974 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
977 enum {
978 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
979 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
982 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
984 enum {
985 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
986 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
987 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
988 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
989 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
990 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
991 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
992 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
993 OPC_BC2 = (0x08 << 21) | OPC_CP2,
994 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
995 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
998 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1000 enum {
1001 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1002 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1003 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1004 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1005 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1006 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1007 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1008 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1010 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1011 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1012 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1013 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1014 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1015 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1016 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1019 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1020 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1021 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1022 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1023 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1024 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1025 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1026 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1028 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1029 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1030 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1031 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1032 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1033 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1034 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1035 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1037 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1038 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1039 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1040 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1041 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1042 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1044 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1045 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1046 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1047 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1048 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1049 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1051 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1052 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1053 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1054 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1055 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1056 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1058 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1059 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1060 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1061 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1062 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1063 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1065 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1066 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1067 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1068 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1069 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1070 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1072 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1073 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1074 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1075 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1076 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1077 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1079 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1080 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1081 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1082 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1083 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1084 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1086 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1087 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1088 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1089 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1090 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1091 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1095 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1097 enum {
1098 OPC_LWXC1 = 0x00 | OPC_CP3,
1099 OPC_LDXC1 = 0x01 | OPC_CP3,
1100 OPC_LUXC1 = 0x05 | OPC_CP3,
1101 OPC_SWXC1 = 0x08 | OPC_CP3,
1102 OPC_SDXC1 = 0x09 | OPC_CP3,
1103 OPC_SUXC1 = 0x0D | OPC_CP3,
1104 OPC_PREFX = 0x0F | OPC_CP3,
1105 OPC_ALNV_PS = 0x1E | OPC_CP3,
1106 OPC_MADD_S = 0x20 | OPC_CP3,
1107 OPC_MADD_D = 0x21 | OPC_CP3,
1108 OPC_MADD_PS = 0x26 | OPC_CP3,
1109 OPC_MSUB_S = 0x28 | OPC_CP3,
1110 OPC_MSUB_D = 0x29 | OPC_CP3,
1111 OPC_MSUB_PS = 0x2E | OPC_CP3,
1112 OPC_NMADD_S = 0x30 | OPC_CP3,
1113 OPC_NMADD_D = 0x31 | OPC_CP3,
1114 OPC_NMADD_PS= 0x36 | OPC_CP3,
1115 OPC_NMSUB_S = 0x38 | OPC_CP3,
1116 OPC_NMSUB_D = 0x39 | OPC_CP3,
1117 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1120 /* MSA Opcodes */
1121 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1122 enum {
1123 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1124 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1125 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1126 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1127 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1128 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1129 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1130 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1131 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1132 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1133 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1134 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1135 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1136 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1137 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1138 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1139 OPC_MSA_ELM = 0x19 | OPC_MSA,
1140 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1141 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1142 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1143 OPC_MSA_VEC = 0x1E | OPC_MSA,
1145 /* MI10 instruction */
1146 OPC_LD_B = (0x20) | OPC_MSA,
1147 OPC_LD_H = (0x21) | OPC_MSA,
1148 OPC_LD_W = (0x22) | OPC_MSA,
1149 OPC_LD_D = (0x23) | OPC_MSA,
1150 OPC_ST_B = (0x24) | OPC_MSA,
1151 OPC_ST_H = (0x25) | OPC_MSA,
1152 OPC_ST_W = (0x26) | OPC_MSA,
1153 OPC_ST_D = (0x27) | OPC_MSA,
1156 enum {
1157 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1158 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1159 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1160 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1161 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1162 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1163 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1164 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1165 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1166 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1167 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1168 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1169 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1171 /* I8 instruction */
1172 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1173 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1174 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1175 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1176 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1177 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1178 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1179 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1180 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1181 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1183 /* VEC/2R/2RF instruction */
1184 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1185 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1186 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1187 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1188 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1189 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1190 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1192 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1193 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1195 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1196 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1197 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1198 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1199 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1201 /* 2RF instruction df(bit 16) = _w, _d */
1202 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1203 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1204 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1205 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1206 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1207 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1208 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1209 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1210 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1211 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1212 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1213 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1214 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1215 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1216 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1217 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1219 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1220 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1221 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1222 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1223 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1224 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1225 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1226 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1227 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1228 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1229 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1230 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1231 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1232 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1233 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1234 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1235 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1236 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1237 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1238 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1239 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1240 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1241 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1242 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1243 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1244 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1245 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1246 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1247 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1248 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1249 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1250 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1251 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1252 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1253 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1254 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1255 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1256 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1257 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1258 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1259 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1260 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1261 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1262 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1263 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1264 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1265 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1266 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1267 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1268 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1269 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1270 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1271 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1272 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1273 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1274 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1275 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1276 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1277 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1278 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1279 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1280 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1281 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1282 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1284 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1285 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1286 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1287 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1288 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1289 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1290 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1291 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1292 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1293 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1295 /* 3RF instruction _df(bit 21) = _w, _d */
1296 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1297 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1298 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1299 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1300 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1301 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1302 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1303 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1304 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1305 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1306 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1307 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1308 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1309 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1310 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1311 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1312 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1313 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1314 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1315 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1316 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1317 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1318 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1319 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1320 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1321 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1322 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1323 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1324 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1325 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1326 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1327 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1328 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1329 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1330 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1331 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1332 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1333 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1334 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1335 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1336 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1338 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1339 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1340 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1341 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1342 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1343 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1344 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1345 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1346 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1347 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1348 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1349 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1350 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1353 /* global register indices */
1354 static TCGv_ptr cpu_env;
1355 static TCGv cpu_gpr[32], cpu_PC;
1356 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1357 static TCGv cpu_dspctrl, btarget, bcond;
1358 static TCGv_i32 hflags;
1359 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1360 static TCGv_i64 fpu_f64[32];
1361 static TCGv_i64 msa_wr_d[64];
1363 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
1364 static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
1366 #include "exec/gen-icount.h"
1368 #define gen_helper_0e0i(name, arg) do { \
1369 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1370 gen_helper_##name(cpu_env, helper_tmp); \
1371 tcg_temp_free_i32(helper_tmp); \
1372 } while(0)
1374 #define gen_helper_0e1i(name, arg1, arg2) do { \
1375 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1376 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1377 tcg_temp_free_i32(helper_tmp); \
1378 } while(0)
1380 #define gen_helper_1e0i(name, ret, arg1) do { \
1381 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1382 gen_helper_##name(ret, cpu_env, helper_tmp); \
1383 tcg_temp_free_i32(helper_tmp); \
1384 } while(0)
1386 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1387 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1388 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1389 tcg_temp_free_i32(helper_tmp); \
1390 } while(0)
1392 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1393 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1394 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1395 tcg_temp_free_i32(helper_tmp); \
1396 } while(0)
1398 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1399 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1400 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1401 tcg_temp_free_i32(helper_tmp); \
1402 } while(0)
1404 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1405 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1406 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1407 tcg_temp_free_i32(helper_tmp); \
1408 } while(0)
1410 typedef struct DisasContext {
1411 struct TranslationBlock *tb;
1412 target_ulong pc, saved_pc;
1413 uint32_t opcode;
1414 int singlestep_enabled;
1415 int insn_flags;
1416 int32_t CP0_Config1;
1417 /* Routine used to access memory */
1418 int mem_idx;
1419 TCGMemOp default_tcg_memop_mask;
1420 uint32_t hflags, saved_hflags;
1421 int bstate;
1422 target_ulong btarget;
1423 bool ulri;
1424 int kscrexist;
1425 bool rxi;
1426 int ie;
1427 bool bi;
1428 bool bp;
1429 uint64_t PAMask;
1430 bool mvh;
1431 int CP0_LLAddr_shift;
1432 } DisasContext;
1434 enum {
1435 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1436 * exception condition */
1437 BS_STOP = 1, /* We want to stop translation for any reason */
1438 BS_BRANCH = 2, /* We reached a branch condition */
1439 BS_EXCP = 3, /* We reached an exception condition */
1442 static const char * const regnames[] = {
1443 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1444 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1445 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1446 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1449 static const char * const regnames_HI[] = {
1450 "HI0", "HI1", "HI2", "HI3",
1453 static const char * const regnames_LO[] = {
1454 "LO0", "LO1", "LO2", "LO3",
1457 static const char * const fregnames[] = {
1458 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1459 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1460 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1461 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1464 static const char * const msaregnames[] = {
1465 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1466 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1467 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1468 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1469 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1470 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1471 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1472 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1473 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1474 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1475 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1476 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1477 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1478 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1479 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1480 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1483 #define MIPS_DEBUG(fmt, ...) \
1484 do { \
1485 if (MIPS_DEBUG_DISAS) { \
1486 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1487 TARGET_FMT_lx ": %08x " fmt "\n", \
1488 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
1490 } while (0)
1492 #define LOG_DISAS(...) \
1493 do { \
1494 if (MIPS_DEBUG_DISAS) { \
1495 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1497 } while (0)
1499 #define MIPS_INVAL(op) \
1500 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
1501 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
1503 /* General purpose registers moves. */
1504 static inline void gen_load_gpr (TCGv t, int reg)
1506 if (reg == 0)
1507 tcg_gen_movi_tl(t, 0);
1508 else
1509 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1512 static inline void gen_store_gpr (TCGv t, int reg)
1514 if (reg != 0)
1515 tcg_gen_mov_tl(cpu_gpr[reg], t);
1518 /* Moves to/from shadow registers. */
1519 static inline void gen_load_srsgpr (int from, int to)
1521 TCGv t0 = tcg_temp_new();
1523 if (from == 0)
1524 tcg_gen_movi_tl(t0, 0);
1525 else {
1526 TCGv_i32 t2 = tcg_temp_new_i32();
1527 TCGv_ptr addr = tcg_temp_new_ptr();
1529 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1530 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1531 tcg_gen_andi_i32(t2, t2, 0xf);
1532 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1533 tcg_gen_ext_i32_ptr(addr, t2);
1534 tcg_gen_add_ptr(addr, cpu_env, addr);
1536 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1537 tcg_temp_free_ptr(addr);
1538 tcg_temp_free_i32(t2);
1540 gen_store_gpr(t0, to);
1541 tcg_temp_free(t0);
1544 static inline void gen_store_srsgpr (int from, int to)
1546 if (to != 0) {
1547 TCGv t0 = tcg_temp_new();
1548 TCGv_i32 t2 = tcg_temp_new_i32();
1549 TCGv_ptr addr = tcg_temp_new_ptr();
1551 gen_load_gpr(t0, from);
1552 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1553 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1554 tcg_gen_andi_i32(t2, t2, 0xf);
1555 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1556 tcg_gen_ext_i32_ptr(addr, t2);
1557 tcg_gen_add_ptr(addr, cpu_env, addr);
1559 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1560 tcg_temp_free_ptr(addr);
1561 tcg_temp_free_i32(t2);
1562 tcg_temp_free(t0);
1566 /* Tests */
1567 static inline void gen_save_pc(target_ulong pc)
1569 tcg_gen_movi_tl(cpu_PC, pc);
1572 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1574 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1575 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1576 gen_save_pc(ctx->pc);
1577 ctx->saved_pc = ctx->pc;
1579 if (ctx->hflags != ctx->saved_hflags) {
1580 tcg_gen_movi_i32(hflags, ctx->hflags);
1581 ctx->saved_hflags = ctx->hflags;
1582 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1583 case MIPS_HFLAG_BR:
1584 break;
1585 case MIPS_HFLAG_BC:
1586 case MIPS_HFLAG_BL:
1587 case MIPS_HFLAG_B:
1588 tcg_gen_movi_tl(btarget, ctx->btarget);
1589 break;
1594 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1596 ctx->saved_hflags = ctx->hflags;
1597 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1598 case MIPS_HFLAG_BR:
1599 break;
1600 case MIPS_HFLAG_BC:
1601 case MIPS_HFLAG_BL:
1602 case MIPS_HFLAG_B:
1603 ctx->btarget = env->btarget;
1604 break;
1608 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1610 TCGv_i32 texcp = tcg_const_i32(excp);
1611 TCGv_i32 terr = tcg_const_i32(err);
1612 save_cpu_state(ctx, 1);
1613 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1614 tcg_temp_free_i32(terr);
1615 tcg_temp_free_i32(texcp);
1618 static inline void generate_exception(DisasContext *ctx, int excp)
1620 save_cpu_state(ctx, 1);
1621 gen_helper_0e0i(raise_exception, excp);
1624 /* Floating point register moves. */
1625 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1627 if (ctx->hflags & MIPS_HFLAG_FRE) {
1628 generate_exception(ctx, EXCP_RI);
1630 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
1633 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1635 TCGv_i64 t64;
1636 if (ctx->hflags & MIPS_HFLAG_FRE) {
1637 generate_exception(ctx, EXCP_RI);
1639 t64 = tcg_temp_new_i64();
1640 tcg_gen_extu_i32_i64(t64, t);
1641 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1642 tcg_temp_free_i64(t64);
1645 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1647 if (ctx->hflags & MIPS_HFLAG_F64) {
1648 TCGv_i64 t64 = tcg_temp_new_i64();
1649 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
1650 tcg_gen_trunc_i64_i32(t, t64);
1651 tcg_temp_free_i64(t64);
1652 } else {
1653 gen_load_fpr32(ctx, t, reg | 1);
1657 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1659 if (ctx->hflags & MIPS_HFLAG_F64) {
1660 TCGv_i64 t64 = tcg_temp_new_i64();
1661 tcg_gen_extu_i32_i64(t64, t);
1662 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1663 tcg_temp_free_i64(t64);
1664 } else {
1665 gen_store_fpr32(ctx, t, reg | 1);
1669 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1671 if (ctx->hflags & MIPS_HFLAG_F64) {
1672 tcg_gen_mov_i64(t, fpu_f64[reg]);
1673 } else {
1674 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1678 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1680 if (ctx->hflags & MIPS_HFLAG_F64) {
1681 tcg_gen_mov_i64(fpu_f64[reg], t);
1682 } else {
1683 TCGv_i64 t0;
1684 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1685 t0 = tcg_temp_new_i64();
1686 tcg_gen_shri_i64(t0, t, 32);
1687 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1688 tcg_temp_free_i64(t0);
1692 static inline int get_fp_bit (int cc)
1694 if (cc)
1695 return 24 + cc;
1696 else
1697 return 23;
1700 /* Addresses computation */
1701 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1703 tcg_gen_add_tl(ret, arg0, arg1);
1705 #if defined(TARGET_MIPS64)
1706 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1707 tcg_gen_ext32s_i64(ret, ret);
1709 #endif
1712 /* Addresses computation (translation time) */
1713 static target_long addr_add(DisasContext *ctx, target_long base,
1714 target_long offset)
1716 target_long sum = base + offset;
1718 #if defined(TARGET_MIPS64)
1719 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1720 sum = (int32_t)sum;
1722 #endif
1723 return sum;
1726 static inline void check_cp0_enabled(DisasContext *ctx)
1728 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1729 generate_exception_err(ctx, EXCP_CpU, 0);
1732 static inline void check_cp1_enabled(DisasContext *ctx)
1734 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1735 generate_exception_err(ctx, EXCP_CpU, 1);
1738 /* Verify that the processor is running with COP1X instructions enabled.
1739 This is associated with the nabla symbol in the MIPS32 and MIPS64
1740 opcode tables. */
1742 static inline void check_cop1x(DisasContext *ctx)
1744 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1745 generate_exception(ctx, EXCP_RI);
1748 /* Verify that the processor is running with 64-bit floating-point
1749 operations enabled. */
1751 static inline void check_cp1_64bitmode(DisasContext *ctx)
1753 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1754 generate_exception(ctx, EXCP_RI);
1758 * Verify if floating point register is valid; an operation is not defined
1759 * if bit 0 of any register specification is set and the FR bit in the
1760 * Status register equals zero, since the register numbers specify an
1761 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1762 * in the Status register equals one, both even and odd register numbers
1763 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1765 * Multiple 64 bit wide registers can be checked by calling
1766 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1768 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1770 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1771 generate_exception(ctx, EXCP_RI);
1774 /* Verify that the processor is running with DSP instructions enabled.
1775 This is enabled by CP0 Status register MX(24) bit.
1778 static inline void check_dsp(DisasContext *ctx)
1780 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1781 if (ctx->insn_flags & ASE_DSP) {
1782 generate_exception(ctx, EXCP_DSPDIS);
1783 } else {
1784 generate_exception(ctx, EXCP_RI);
1789 static inline void check_dspr2(DisasContext *ctx)
1791 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1792 if (ctx->insn_flags & ASE_DSP) {
1793 generate_exception(ctx, EXCP_DSPDIS);
1794 } else {
1795 generate_exception(ctx, EXCP_RI);
1800 /* This code generates a "reserved instruction" exception if the
1801 CPU does not support the instruction set corresponding to flags. */
1802 static inline void check_insn(DisasContext *ctx, int flags)
1804 if (unlikely(!(ctx->insn_flags & flags))) {
1805 generate_exception(ctx, EXCP_RI);
1809 /* This code generates a "reserved instruction" exception if the
1810 CPU has corresponding flag set which indicates that the instruction
1811 has been removed. */
1812 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1814 if (unlikely(ctx->insn_flags & flags)) {
1815 generate_exception(ctx, EXCP_RI);
1819 #ifdef TARGET_MIPS64
1820 /* This code generates a "reserved instruction" exception if 64-bit
1821 instructions are not enabled. */
1822 static inline void check_mips_64(DisasContext *ctx)
1824 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1825 generate_exception(ctx, EXCP_RI);
1827 #endif
1829 #ifndef CONFIG_USER_ONLY
1830 static inline void check_mvh(DisasContext *ctx)
1832 if (unlikely(!ctx->mvh)) {
1833 generate_exception(ctx, EXCP_RI);
1836 #endif
1838 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1839 calling interface for 32 and 64-bit FPRs. No sense in changing
1840 all callers for gen_load_fpr32 when we need the CTX parameter for
1841 this one use. */
1842 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1843 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1844 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1845 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1846 int ft, int fs, int cc) \
1848 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1849 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1850 switch (ifmt) { \
1851 case FMT_PS: \
1852 check_cp1_64bitmode(ctx); \
1853 break; \
1854 case FMT_D: \
1855 if (abs) { \
1856 check_cop1x(ctx); \
1858 check_cp1_registers(ctx, fs | ft); \
1859 break; \
1860 case FMT_S: \
1861 if (abs) { \
1862 check_cop1x(ctx); \
1864 break; \
1866 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1867 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1868 switch (n) { \
1869 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1870 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1871 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1872 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1873 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1874 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1875 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1876 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1877 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1878 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1879 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1880 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1881 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1882 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1883 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1884 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1885 default: abort(); \
1887 tcg_temp_free_i##bits (fp0); \
1888 tcg_temp_free_i##bits (fp1); \
1891 FOP_CONDS(, 0, d, FMT_D, 64)
1892 FOP_CONDS(abs, 1, d, FMT_D, 64)
1893 FOP_CONDS(, 0, s, FMT_S, 32)
1894 FOP_CONDS(abs, 1, s, FMT_S, 32)
1895 FOP_CONDS(, 0, ps, FMT_PS, 64)
1896 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1897 #undef FOP_CONDS
1899 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1900 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1901 int ft, int fs, int fd) \
1903 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1904 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1905 if (ifmt == FMT_D) { \
1906 check_cp1_registers(ctx, fs | ft | fd); \
1908 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1909 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1910 switch (n) { \
1911 case 0: \
1912 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1913 break; \
1914 case 1: \
1915 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1916 break; \
1917 case 2: \
1918 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1919 break; \
1920 case 3: \
1921 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1922 break; \
1923 case 4: \
1924 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1925 break; \
1926 case 5: \
1927 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1928 break; \
1929 case 6: \
1930 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1931 break; \
1932 case 7: \
1933 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1934 break; \
1935 case 8: \
1936 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1937 break; \
1938 case 9: \
1939 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1940 break; \
1941 case 10: \
1942 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1943 break; \
1944 case 11: \
1945 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1946 break; \
1947 case 12: \
1948 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1949 break; \
1950 case 13: \
1951 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1952 break; \
1953 case 14: \
1954 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1955 break; \
1956 case 15: \
1957 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1958 break; \
1959 case 17: \
1960 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1961 break; \
1962 case 18: \
1963 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1964 break; \
1965 case 19: \
1966 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1967 break; \
1968 case 25: \
1969 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1970 break; \
1971 case 26: \
1972 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
1973 break; \
1974 case 27: \
1975 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
1976 break; \
1977 default: \
1978 abort(); \
1980 STORE; \
1981 tcg_temp_free_i ## bits (fp0); \
1982 tcg_temp_free_i ## bits (fp1); \
1985 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
1986 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
1987 #undef FOP_CONDNS
1988 #undef gen_ldcmp_fpr32
1989 #undef gen_ldcmp_fpr64
1991 /* load/store instructions. */
1992 #ifdef CONFIG_USER_ONLY
1993 #define OP_LD_ATOMIC(insn,fname) \
1994 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1996 TCGv t0 = tcg_temp_new(); \
1997 tcg_gen_mov_tl(t0, arg1); \
1998 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1999 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2000 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2001 tcg_temp_free(t0); \
2003 #else
2004 #define OP_LD_ATOMIC(insn,fname) \
2005 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2007 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
2009 #endif
2010 OP_LD_ATOMIC(ll,ld32s);
2011 #if defined(TARGET_MIPS64)
2012 OP_LD_ATOMIC(lld,ld64);
2013 #endif
2014 #undef OP_LD_ATOMIC
2016 #ifdef CONFIG_USER_ONLY
2017 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2018 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2020 TCGv t0 = tcg_temp_new(); \
2021 TCGLabel *l1 = gen_new_label(); \
2022 TCGLabel *l2 = gen_new_label(); \
2024 tcg_gen_andi_tl(t0, arg2, almask); \
2025 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2026 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2027 generate_exception(ctx, EXCP_AdES); \
2028 gen_set_label(l1); \
2029 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2030 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2031 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2032 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2033 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2034 gen_helper_0e0i(raise_exception, EXCP_SC); \
2035 gen_set_label(l2); \
2036 tcg_gen_movi_tl(t0, 0); \
2037 gen_store_gpr(t0, rt); \
2038 tcg_temp_free(t0); \
2040 #else
2041 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2042 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2044 TCGv t0 = tcg_temp_new(); \
2045 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
2046 gen_store_gpr(t0, rt); \
2047 tcg_temp_free(t0); \
2049 #endif
2050 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2051 #if defined(TARGET_MIPS64)
2052 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2053 #endif
2054 #undef OP_ST_ATOMIC
2056 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2057 int base, int16_t offset)
2059 if (base == 0) {
2060 tcg_gen_movi_tl(addr, offset);
2061 } else if (offset == 0) {
2062 gen_load_gpr(addr, base);
2063 } else {
2064 tcg_gen_movi_tl(addr, offset);
2065 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2069 static target_ulong pc_relative_pc (DisasContext *ctx)
2071 target_ulong pc = ctx->pc;
2073 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2074 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2076 pc -= branch_bytes;
2079 pc &= ~(target_ulong)3;
2080 return pc;
2083 /* Load */
2084 static void gen_ld(DisasContext *ctx, uint32_t opc,
2085 int rt, int base, int16_t offset)
2087 const char *opn = "ld";
2088 TCGv t0, t1, t2;
2090 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2091 /* Loongson CPU uses a load to zero register for prefetch.
2092 We emulate it as a NOP. On other CPU we must perform the
2093 actual memory access. */
2094 MIPS_DEBUG("NOP");
2095 return;
2098 t0 = tcg_temp_new();
2099 gen_base_offset_addr(ctx, t0, base, offset);
2101 switch (opc) {
2102 #if defined(TARGET_MIPS64)
2103 case OPC_LWU:
2104 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL |
2105 ctx->default_tcg_memop_mask);
2106 gen_store_gpr(t0, rt);
2107 opn = "lwu";
2108 break;
2109 case OPC_LD:
2110 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
2111 ctx->default_tcg_memop_mask);
2112 gen_store_gpr(t0, rt);
2113 opn = "ld";
2114 break;
2115 case OPC_LLD:
2116 case R6_OPC_LLD:
2117 save_cpu_state(ctx, 1);
2118 op_ld_lld(t0, t0, ctx);
2119 gen_store_gpr(t0, rt);
2120 opn = "lld";
2121 break;
2122 case OPC_LDL:
2123 t1 = tcg_temp_new();
2124 tcg_gen_andi_tl(t1, t0, 7);
2125 #ifndef TARGET_WORDS_BIGENDIAN
2126 tcg_gen_xori_tl(t1, t1, 7);
2127 #endif
2128 tcg_gen_shli_tl(t1, t1, 3);
2129 tcg_gen_andi_tl(t0, t0, ~7);
2130 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2131 tcg_gen_shl_tl(t0, t0, t1);
2132 tcg_gen_xori_tl(t1, t1, 63);
2133 t2 = tcg_const_tl(0x7fffffffffffffffull);
2134 tcg_gen_shr_tl(t2, t2, t1);
2135 gen_load_gpr(t1, rt);
2136 tcg_gen_and_tl(t1, t1, t2);
2137 tcg_temp_free(t2);
2138 tcg_gen_or_tl(t0, t0, t1);
2139 tcg_temp_free(t1);
2140 gen_store_gpr(t0, rt);
2141 opn = "ldl";
2142 break;
2143 case OPC_LDR:
2144 t1 = tcg_temp_new();
2145 tcg_gen_andi_tl(t1, t0, 7);
2146 #ifdef TARGET_WORDS_BIGENDIAN
2147 tcg_gen_xori_tl(t1, t1, 7);
2148 #endif
2149 tcg_gen_shli_tl(t1, t1, 3);
2150 tcg_gen_andi_tl(t0, t0, ~7);
2151 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2152 tcg_gen_shr_tl(t0, t0, t1);
2153 tcg_gen_xori_tl(t1, t1, 63);
2154 t2 = tcg_const_tl(0xfffffffffffffffeull);
2155 tcg_gen_shl_tl(t2, t2, t1);
2156 gen_load_gpr(t1, rt);
2157 tcg_gen_and_tl(t1, t1, t2);
2158 tcg_temp_free(t2);
2159 tcg_gen_or_tl(t0, t0, t1);
2160 tcg_temp_free(t1);
2161 gen_store_gpr(t0, rt);
2162 opn = "ldr";
2163 break;
2164 case OPC_LDPC:
2165 t1 = tcg_const_tl(pc_relative_pc(ctx));
2166 gen_op_addr_add(ctx, t0, t0, t1);
2167 tcg_temp_free(t1);
2168 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2169 gen_store_gpr(t0, rt);
2170 opn = "ldpc";
2171 break;
2172 #endif
2173 case OPC_LWPC:
2174 t1 = tcg_const_tl(pc_relative_pc(ctx));
2175 gen_op_addr_add(ctx, t0, t0, t1);
2176 tcg_temp_free(t1);
2177 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2178 gen_store_gpr(t0, rt);
2179 opn = "lwpc";
2180 break;
2181 case OPC_LW:
2182 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
2183 ctx->default_tcg_memop_mask);
2184 gen_store_gpr(t0, rt);
2185 opn = "lw";
2186 break;
2187 case OPC_LH:
2188 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
2189 ctx->default_tcg_memop_mask);
2190 gen_store_gpr(t0, rt);
2191 opn = "lh";
2192 break;
2193 case OPC_LHU:
2194 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW |
2195 ctx->default_tcg_memop_mask);
2196 gen_store_gpr(t0, rt);
2197 opn = "lhu";
2198 break;
2199 case OPC_LB:
2200 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
2201 gen_store_gpr(t0, rt);
2202 opn = "lb";
2203 break;
2204 case OPC_LBU:
2205 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
2206 gen_store_gpr(t0, rt);
2207 opn = "lbu";
2208 break;
2209 case OPC_LWL:
2210 t1 = tcg_temp_new();
2211 tcg_gen_andi_tl(t1, t0, 3);
2212 #ifndef TARGET_WORDS_BIGENDIAN
2213 tcg_gen_xori_tl(t1, t1, 3);
2214 #endif
2215 tcg_gen_shli_tl(t1, t1, 3);
2216 tcg_gen_andi_tl(t0, t0, ~3);
2217 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2218 tcg_gen_shl_tl(t0, t0, t1);
2219 tcg_gen_xori_tl(t1, t1, 31);
2220 t2 = tcg_const_tl(0x7fffffffull);
2221 tcg_gen_shr_tl(t2, t2, t1);
2222 gen_load_gpr(t1, rt);
2223 tcg_gen_and_tl(t1, t1, t2);
2224 tcg_temp_free(t2);
2225 tcg_gen_or_tl(t0, t0, t1);
2226 tcg_temp_free(t1);
2227 tcg_gen_ext32s_tl(t0, t0);
2228 gen_store_gpr(t0, rt);
2229 opn = "lwl";
2230 break;
2231 case OPC_LWR:
2232 t1 = tcg_temp_new();
2233 tcg_gen_andi_tl(t1, t0, 3);
2234 #ifdef TARGET_WORDS_BIGENDIAN
2235 tcg_gen_xori_tl(t1, t1, 3);
2236 #endif
2237 tcg_gen_shli_tl(t1, t1, 3);
2238 tcg_gen_andi_tl(t0, t0, ~3);
2239 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2240 tcg_gen_shr_tl(t0, t0, t1);
2241 tcg_gen_xori_tl(t1, t1, 31);
2242 t2 = tcg_const_tl(0xfffffffeull);
2243 tcg_gen_shl_tl(t2, t2, t1);
2244 gen_load_gpr(t1, rt);
2245 tcg_gen_and_tl(t1, t1, t2);
2246 tcg_temp_free(t2);
2247 tcg_gen_or_tl(t0, t0, t1);
2248 tcg_temp_free(t1);
2249 tcg_gen_ext32s_tl(t0, t0);
2250 gen_store_gpr(t0, rt);
2251 opn = "lwr";
2252 break;
2253 case OPC_LL:
2254 case R6_OPC_LL:
2255 save_cpu_state(ctx, 1);
2256 op_ld_ll(t0, t0, ctx);
2257 gen_store_gpr(t0, rt);
2258 opn = "ll";
2259 break;
2261 (void)opn; /* avoid a compiler warning */
2262 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2263 tcg_temp_free(t0);
2266 /* Store */
2267 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2268 int base, int16_t offset)
2270 const char *opn = "st";
2271 TCGv t0 = tcg_temp_new();
2272 TCGv t1 = tcg_temp_new();
2274 gen_base_offset_addr(ctx, t0, base, offset);
2275 gen_load_gpr(t1, rt);
2276 switch (opc) {
2277 #if defined(TARGET_MIPS64)
2278 case OPC_SD:
2279 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
2280 ctx->default_tcg_memop_mask);
2281 opn = "sd";
2282 break;
2283 case OPC_SDL:
2284 save_cpu_state(ctx, 1);
2285 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
2286 opn = "sdl";
2287 break;
2288 case OPC_SDR:
2289 save_cpu_state(ctx, 1);
2290 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2291 opn = "sdr";
2292 break;
2293 #endif
2294 case OPC_SW:
2295 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
2296 ctx->default_tcg_memop_mask);
2297 opn = "sw";
2298 break;
2299 case OPC_SH:
2300 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
2301 ctx->default_tcg_memop_mask);
2302 opn = "sh";
2303 break;
2304 case OPC_SB:
2305 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2306 opn = "sb";
2307 break;
2308 case OPC_SWL:
2309 save_cpu_state(ctx, 1);
2310 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2311 opn = "swl";
2312 break;
2313 case OPC_SWR:
2314 save_cpu_state(ctx, 1);
2315 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2316 opn = "swr";
2317 break;
2319 (void)opn; /* avoid a compiler warning */
2320 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2321 tcg_temp_free(t0);
2322 tcg_temp_free(t1);
2326 /* Store conditional */
2327 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2328 int base, int16_t offset)
2330 const char *opn = "st_cond";
2331 TCGv t0, t1;
2333 #ifdef CONFIG_USER_ONLY
2334 t0 = tcg_temp_local_new();
2335 t1 = tcg_temp_local_new();
2336 #else
2337 t0 = tcg_temp_new();
2338 t1 = tcg_temp_new();
2339 #endif
2340 gen_base_offset_addr(ctx, t0, base, offset);
2341 gen_load_gpr(t1, rt);
2342 switch (opc) {
2343 #if defined(TARGET_MIPS64)
2344 case OPC_SCD:
2345 case R6_OPC_SCD:
2346 save_cpu_state(ctx, 1);
2347 op_st_scd(t1, t0, rt, ctx);
2348 opn = "scd";
2349 break;
2350 #endif
2351 case OPC_SC:
2352 case R6_OPC_SC:
2353 save_cpu_state(ctx, 1);
2354 op_st_sc(t1, t0, rt, ctx);
2355 opn = "sc";
2356 break;
2358 (void)opn; /* avoid a compiler warning */
2359 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2360 tcg_temp_free(t1);
2361 tcg_temp_free(t0);
2364 /* Load and store */
2365 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2366 int base, int16_t offset)
2368 const char *opn = "flt_ldst";
2369 TCGv t0 = tcg_temp_new();
2371 gen_base_offset_addr(ctx, t0, base, offset);
2372 /* Don't do NOP if destination is zero: we must perform the actual
2373 memory access. */
2374 switch (opc) {
2375 case OPC_LWC1:
2377 TCGv_i32 fp0 = tcg_temp_new_i32();
2378 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2379 ctx->default_tcg_memop_mask);
2380 gen_store_fpr32(ctx, fp0, ft);
2381 tcg_temp_free_i32(fp0);
2383 opn = "lwc1";
2384 break;
2385 case OPC_SWC1:
2387 TCGv_i32 fp0 = tcg_temp_new_i32();
2388 gen_load_fpr32(ctx, fp0, ft);
2389 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2390 ctx->default_tcg_memop_mask);
2391 tcg_temp_free_i32(fp0);
2393 opn = "swc1";
2394 break;
2395 case OPC_LDC1:
2397 TCGv_i64 fp0 = tcg_temp_new_i64();
2398 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2399 ctx->default_tcg_memop_mask);
2400 gen_store_fpr64(ctx, fp0, ft);
2401 tcg_temp_free_i64(fp0);
2403 opn = "ldc1";
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 opn = "sdc1";
2414 break;
2415 default:
2416 MIPS_INVAL(opn);
2417 generate_exception(ctx, EXCP_RI);
2418 goto out;
2420 (void)opn; /* avoid a compiler warning */
2421 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
2422 out:
2423 tcg_temp_free(t0);
2426 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2427 int rs, int16_t imm)
2429 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2430 check_cp1_enabled(ctx);
2431 switch (op) {
2432 case OPC_LDC1:
2433 case OPC_SDC1:
2434 check_insn(ctx, ISA_MIPS2);
2435 /* Fallthrough */
2436 default:
2437 gen_flt_ldst(ctx, op, rt, rs, imm);
2439 } else {
2440 generate_exception_err(ctx, EXCP_CpU, 1);
2444 /* Arithmetic with immediate operand */
2445 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2446 int rt, int rs, int16_t imm)
2448 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2449 const char *opn = "imm arith";
2451 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2452 /* If no destination, treat it as a NOP.
2453 For addi, we must generate the overflow exception when needed. */
2454 MIPS_DEBUG("NOP");
2455 return;
2457 switch (opc) {
2458 case OPC_ADDI:
2460 TCGv t0 = tcg_temp_local_new();
2461 TCGv t1 = tcg_temp_new();
2462 TCGv t2 = tcg_temp_new();
2463 TCGLabel *l1 = gen_new_label();
2465 gen_load_gpr(t1, rs);
2466 tcg_gen_addi_tl(t0, t1, uimm);
2467 tcg_gen_ext32s_tl(t0, t0);
2469 tcg_gen_xori_tl(t1, t1, ~uimm);
2470 tcg_gen_xori_tl(t2, t0, uimm);
2471 tcg_gen_and_tl(t1, t1, t2);
2472 tcg_temp_free(t2);
2473 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2474 tcg_temp_free(t1);
2475 /* operands of same sign, result different sign */
2476 generate_exception(ctx, EXCP_OVERFLOW);
2477 gen_set_label(l1);
2478 tcg_gen_ext32s_tl(t0, t0);
2479 gen_store_gpr(t0, rt);
2480 tcg_temp_free(t0);
2482 opn = "addi";
2483 break;
2484 case OPC_ADDIU:
2485 if (rs != 0) {
2486 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2487 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2488 } else {
2489 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2491 opn = "addiu";
2492 break;
2493 #if defined(TARGET_MIPS64)
2494 case OPC_DADDI:
2496 TCGv t0 = tcg_temp_local_new();
2497 TCGv t1 = tcg_temp_new();
2498 TCGv t2 = tcg_temp_new();
2499 TCGLabel *l1 = gen_new_label();
2501 gen_load_gpr(t1, rs);
2502 tcg_gen_addi_tl(t0, t1, uimm);
2504 tcg_gen_xori_tl(t1, t1, ~uimm);
2505 tcg_gen_xori_tl(t2, t0, uimm);
2506 tcg_gen_and_tl(t1, t1, t2);
2507 tcg_temp_free(t2);
2508 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2509 tcg_temp_free(t1);
2510 /* operands of same sign, result different sign */
2511 generate_exception(ctx, EXCP_OVERFLOW);
2512 gen_set_label(l1);
2513 gen_store_gpr(t0, rt);
2514 tcg_temp_free(t0);
2516 opn = "daddi";
2517 break;
2518 case OPC_DADDIU:
2519 if (rs != 0) {
2520 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2521 } else {
2522 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2524 opn = "daddiu";
2525 break;
2526 #endif
2528 (void)opn; /* avoid a compiler warning */
2529 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2532 /* Logic with immediate operand */
2533 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2534 int rt, int rs, int16_t imm)
2536 target_ulong uimm;
2538 if (rt == 0) {
2539 /* If no destination, treat it as a NOP. */
2540 MIPS_DEBUG("NOP");
2541 return;
2543 uimm = (uint16_t)imm;
2544 switch (opc) {
2545 case OPC_ANDI:
2546 if (likely(rs != 0))
2547 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2548 else
2549 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2550 MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
2551 regnames[rs], uimm);
2552 break;
2553 case OPC_ORI:
2554 if (rs != 0)
2555 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2556 else
2557 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2558 MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
2559 regnames[rs], uimm);
2560 break;
2561 case OPC_XORI:
2562 if (likely(rs != 0))
2563 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2564 else
2565 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2566 MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
2567 regnames[rs], uimm);
2568 break;
2569 case OPC_LUI:
2570 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2571 /* OPC_AUI */
2572 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2573 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2574 MIPS_DEBUG("aui %s, %s, %04x", regnames[rt], regnames[rs], imm);
2575 } else {
2576 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2577 MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
2579 break;
2581 default:
2582 MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
2583 break;
2587 /* Set on less than with immediate operand */
2588 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2589 int rt, int rs, int16_t imm)
2591 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2592 const char *opn = "imm arith";
2593 TCGv t0;
2595 if (rt == 0) {
2596 /* If no destination, treat it as a NOP. */
2597 MIPS_DEBUG("NOP");
2598 return;
2600 t0 = tcg_temp_new();
2601 gen_load_gpr(t0, rs);
2602 switch (opc) {
2603 case OPC_SLTI:
2604 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2605 opn = "slti";
2606 break;
2607 case OPC_SLTIU:
2608 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2609 opn = "sltiu";
2610 break;
2612 (void)opn; /* avoid a compiler warning */
2613 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2614 tcg_temp_free(t0);
2617 /* Shifts with immediate operand */
2618 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2619 int rt, int rs, int16_t imm)
2621 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2622 const char *opn = "imm shift";
2623 TCGv t0;
2625 if (rt == 0) {
2626 /* If no destination, treat it as a NOP. */
2627 MIPS_DEBUG("NOP");
2628 return;
2631 t0 = tcg_temp_new();
2632 gen_load_gpr(t0, rs);
2633 switch (opc) {
2634 case OPC_SLL:
2635 tcg_gen_shli_tl(t0, t0, uimm);
2636 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2637 opn = "sll";
2638 break;
2639 case OPC_SRA:
2640 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2641 opn = "sra";
2642 break;
2643 case OPC_SRL:
2644 if (uimm != 0) {
2645 tcg_gen_ext32u_tl(t0, t0);
2646 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2647 } else {
2648 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2650 opn = "srl";
2651 break;
2652 case OPC_ROTR:
2653 if (uimm != 0) {
2654 TCGv_i32 t1 = tcg_temp_new_i32();
2656 tcg_gen_trunc_tl_i32(t1, t0);
2657 tcg_gen_rotri_i32(t1, t1, uimm);
2658 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2659 tcg_temp_free_i32(t1);
2660 } else {
2661 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2663 opn = "rotr";
2664 break;
2665 #if defined(TARGET_MIPS64)
2666 case OPC_DSLL:
2667 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2668 opn = "dsll";
2669 break;
2670 case OPC_DSRA:
2671 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2672 opn = "dsra";
2673 break;
2674 case OPC_DSRL:
2675 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2676 opn = "dsrl";
2677 break;
2678 case OPC_DROTR:
2679 if (uimm != 0) {
2680 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2681 } else {
2682 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2684 opn = "drotr";
2685 break;
2686 case OPC_DSLL32:
2687 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2688 opn = "dsll32";
2689 break;
2690 case OPC_DSRA32:
2691 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2692 opn = "dsra32";
2693 break;
2694 case OPC_DSRL32:
2695 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2696 opn = "dsrl32";
2697 break;
2698 case OPC_DROTR32:
2699 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2700 opn = "drotr32";
2701 break;
2702 #endif
2704 (void)opn; /* avoid a compiler warning */
2705 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2706 tcg_temp_free(t0);
2709 /* Arithmetic */
2710 static void gen_arith(DisasContext *ctx, uint32_t opc,
2711 int rd, int rs, int rt)
2713 const char *opn = "arith";
2715 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2716 && opc != OPC_DADD && opc != OPC_DSUB) {
2717 /* If no destination, treat it as a NOP.
2718 For add & sub, we must generate the overflow exception when needed. */
2719 MIPS_DEBUG("NOP");
2720 return;
2723 switch (opc) {
2724 case OPC_ADD:
2726 TCGv t0 = tcg_temp_local_new();
2727 TCGv t1 = tcg_temp_new();
2728 TCGv t2 = tcg_temp_new();
2729 TCGLabel *l1 = gen_new_label();
2731 gen_load_gpr(t1, rs);
2732 gen_load_gpr(t2, rt);
2733 tcg_gen_add_tl(t0, t1, t2);
2734 tcg_gen_ext32s_tl(t0, t0);
2735 tcg_gen_xor_tl(t1, t1, t2);
2736 tcg_gen_xor_tl(t2, t0, t2);
2737 tcg_gen_andc_tl(t1, t2, t1);
2738 tcg_temp_free(t2);
2739 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2740 tcg_temp_free(t1);
2741 /* operands of same sign, result different sign */
2742 generate_exception(ctx, EXCP_OVERFLOW);
2743 gen_set_label(l1);
2744 gen_store_gpr(t0, rd);
2745 tcg_temp_free(t0);
2747 opn = "add";
2748 break;
2749 case OPC_ADDU:
2750 if (rs != 0 && rt != 0) {
2751 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2752 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2753 } else if (rs == 0 && rt != 0) {
2754 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2755 } else if (rs != 0 && rt == 0) {
2756 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2757 } else {
2758 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2760 opn = "addu";
2761 break;
2762 case OPC_SUB:
2764 TCGv t0 = tcg_temp_local_new();
2765 TCGv t1 = tcg_temp_new();
2766 TCGv t2 = tcg_temp_new();
2767 TCGLabel *l1 = gen_new_label();
2769 gen_load_gpr(t1, rs);
2770 gen_load_gpr(t2, rt);
2771 tcg_gen_sub_tl(t0, t1, t2);
2772 tcg_gen_ext32s_tl(t0, t0);
2773 tcg_gen_xor_tl(t2, t1, t2);
2774 tcg_gen_xor_tl(t1, t0, t1);
2775 tcg_gen_and_tl(t1, t1, t2);
2776 tcg_temp_free(t2);
2777 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2778 tcg_temp_free(t1);
2779 /* operands of different sign, first operand and result different sign */
2780 generate_exception(ctx, EXCP_OVERFLOW);
2781 gen_set_label(l1);
2782 gen_store_gpr(t0, rd);
2783 tcg_temp_free(t0);
2785 opn = "sub";
2786 break;
2787 case OPC_SUBU:
2788 if (rs != 0 && rt != 0) {
2789 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2790 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2791 } else if (rs == 0 && rt != 0) {
2792 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2793 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2794 } else if (rs != 0 && rt == 0) {
2795 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2796 } else {
2797 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2799 opn = "subu";
2800 break;
2801 #if defined(TARGET_MIPS64)
2802 case OPC_DADD:
2804 TCGv t0 = tcg_temp_local_new();
2805 TCGv t1 = tcg_temp_new();
2806 TCGv t2 = tcg_temp_new();
2807 TCGLabel *l1 = gen_new_label();
2809 gen_load_gpr(t1, rs);
2810 gen_load_gpr(t2, rt);
2811 tcg_gen_add_tl(t0, t1, t2);
2812 tcg_gen_xor_tl(t1, t1, t2);
2813 tcg_gen_xor_tl(t2, t0, t2);
2814 tcg_gen_andc_tl(t1, t2, t1);
2815 tcg_temp_free(t2);
2816 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2817 tcg_temp_free(t1);
2818 /* operands of same sign, result different sign */
2819 generate_exception(ctx, EXCP_OVERFLOW);
2820 gen_set_label(l1);
2821 gen_store_gpr(t0, rd);
2822 tcg_temp_free(t0);
2824 opn = "dadd";
2825 break;
2826 case OPC_DADDU:
2827 if (rs != 0 && rt != 0) {
2828 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2829 } else if (rs == 0 && rt != 0) {
2830 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2831 } else if (rs != 0 && rt == 0) {
2832 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2833 } else {
2834 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2836 opn = "daddu";
2837 break;
2838 case OPC_DSUB:
2840 TCGv t0 = tcg_temp_local_new();
2841 TCGv t1 = tcg_temp_new();
2842 TCGv t2 = tcg_temp_new();
2843 TCGLabel *l1 = gen_new_label();
2845 gen_load_gpr(t1, rs);
2846 gen_load_gpr(t2, rt);
2847 tcg_gen_sub_tl(t0, t1, t2);
2848 tcg_gen_xor_tl(t2, t1, t2);
2849 tcg_gen_xor_tl(t1, t0, t1);
2850 tcg_gen_and_tl(t1, t1, t2);
2851 tcg_temp_free(t2);
2852 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2853 tcg_temp_free(t1);
2854 /* operands of different sign, first operand and result different sign */
2855 generate_exception(ctx, EXCP_OVERFLOW);
2856 gen_set_label(l1);
2857 gen_store_gpr(t0, rd);
2858 tcg_temp_free(t0);
2860 opn = "dsub";
2861 break;
2862 case OPC_DSUBU:
2863 if (rs != 0 && rt != 0) {
2864 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2865 } else if (rs == 0 && rt != 0) {
2866 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2867 } else if (rs != 0 && rt == 0) {
2868 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2869 } else {
2870 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2872 opn = "dsubu";
2873 break;
2874 #endif
2875 case OPC_MUL:
2876 if (likely(rs != 0 && rt != 0)) {
2877 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2878 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2879 } else {
2880 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2882 opn = "mul";
2883 break;
2885 (void)opn; /* avoid a compiler warning */
2886 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2889 /* Conditional move */
2890 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2891 int rd, int rs, int rt)
2893 const char *opn = "cond move";
2894 TCGv t0, t1, t2;
2896 if (rd == 0) {
2897 /* If no destination, treat it as a NOP. */
2898 MIPS_DEBUG("NOP");
2899 return;
2902 t0 = tcg_temp_new();
2903 gen_load_gpr(t0, rt);
2904 t1 = tcg_const_tl(0);
2905 t2 = tcg_temp_new();
2906 gen_load_gpr(t2, rs);
2907 switch (opc) {
2908 case OPC_MOVN:
2909 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2910 opn = "movn";
2911 break;
2912 case OPC_MOVZ:
2913 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2914 opn = "movz";
2915 break;
2916 case OPC_SELNEZ:
2917 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2918 opn = "selnez";
2919 break;
2920 case OPC_SELEQZ:
2921 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2922 opn = "seleqz";
2923 break;
2925 tcg_temp_free(t2);
2926 tcg_temp_free(t1);
2927 tcg_temp_free(t0);
2929 (void)opn; /* avoid a compiler warning */
2930 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2933 /* Logic */
2934 static void gen_logic(DisasContext *ctx, uint32_t opc,
2935 int rd, int rs, int rt)
2937 const char *opn = "logic";
2939 if (rd == 0) {
2940 /* If no destination, treat it as a NOP. */
2941 MIPS_DEBUG("NOP");
2942 return;
2945 switch (opc) {
2946 case OPC_AND:
2947 if (likely(rs != 0 && rt != 0)) {
2948 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2949 } else {
2950 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2952 opn = "and";
2953 break;
2954 case OPC_NOR:
2955 if (rs != 0 && rt != 0) {
2956 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2957 } else if (rs == 0 && rt != 0) {
2958 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2959 } else if (rs != 0 && rt == 0) {
2960 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2961 } else {
2962 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2964 opn = "nor";
2965 break;
2966 case OPC_OR:
2967 if (likely(rs != 0 && rt != 0)) {
2968 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2969 } else if (rs == 0 && rt != 0) {
2970 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2971 } else if (rs != 0 && rt == 0) {
2972 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2973 } else {
2974 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2976 opn = "or";
2977 break;
2978 case OPC_XOR:
2979 if (likely(rs != 0 && rt != 0)) {
2980 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2981 } else if (rs == 0 && rt != 0) {
2982 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2983 } else if (rs != 0 && rt == 0) {
2984 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2985 } else {
2986 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2988 opn = "xor";
2989 break;
2991 (void)opn; /* avoid a compiler warning */
2992 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2995 /* Set on lower than */
2996 static void gen_slt(DisasContext *ctx, uint32_t opc,
2997 int rd, int rs, int rt)
2999 const char *opn = "slt";
3000 TCGv t0, t1;
3002 if (rd == 0) {
3003 /* If no destination, treat it as a NOP. */
3004 MIPS_DEBUG("NOP");
3005 return;
3008 t0 = tcg_temp_new();
3009 t1 = tcg_temp_new();
3010 gen_load_gpr(t0, rs);
3011 gen_load_gpr(t1, rt);
3012 switch (opc) {
3013 case OPC_SLT:
3014 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3015 opn = "slt";
3016 break;
3017 case OPC_SLTU:
3018 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3019 opn = "sltu";
3020 break;
3022 (void)opn; /* avoid a compiler warning */
3023 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3024 tcg_temp_free(t0);
3025 tcg_temp_free(t1);
3028 /* Shifts */
3029 static void gen_shift(DisasContext *ctx, uint32_t opc,
3030 int rd, int rs, int rt)
3032 const char *opn = "shifts";
3033 TCGv t0, t1;
3035 if (rd == 0) {
3036 /* If no destination, treat it as a NOP.
3037 For add & sub, we must generate the overflow exception when needed. */
3038 MIPS_DEBUG("NOP");
3039 return;
3042 t0 = tcg_temp_new();
3043 t1 = tcg_temp_new();
3044 gen_load_gpr(t0, rs);
3045 gen_load_gpr(t1, rt);
3046 switch (opc) {
3047 case OPC_SLLV:
3048 tcg_gen_andi_tl(t0, t0, 0x1f);
3049 tcg_gen_shl_tl(t0, t1, t0);
3050 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3051 opn = "sllv";
3052 break;
3053 case OPC_SRAV:
3054 tcg_gen_andi_tl(t0, t0, 0x1f);
3055 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3056 opn = "srav";
3057 break;
3058 case OPC_SRLV:
3059 tcg_gen_ext32u_tl(t1, t1);
3060 tcg_gen_andi_tl(t0, t0, 0x1f);
3061 tcg_gen_shr_tl(t0, t1, t0);
3062 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3063 opn = "srlv";
3064 break;
3065 case OPC_ROTRV:
3067 TCGv_i32 t2 = tcg_temp_new_i32();
3068 TCGv_i32 t3 = tcg_temp_new_i32();
3070 tcg_gen_trunc_tl_i32(t2, t0);
3071 tcg_gen_trunc_tl_i32(t3, t1);
3072 tcg_gen_andi_i32(t2, t2, 0x1f);
3073 tcg_gen_rotr_i32(t2, t3, t2);
3074 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3075 tcg_temp_free_i32(t2);
3076 tcg_temp_free_i32(t3);
3077 opn = "rotrv";
3079 break;
3080 #if defined(TARGET_MIPS64)
3081 case OPC_DSLLV:
3082 tcg_gen_andi_tl(t0, t0, 0x3f);
3083 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3084 opn = "dsllv";
3085 break;
3086 case OPC_DSRAV:
3087 tcg_gen_andi_tl(t0, t0, 0x3f);
3088 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3089 opn = "dsrav";
3090 break;
3091 case OPC_DSRLV:
3092 tcg_gen_andi_tl(t0, t0, 0x3f);
3093 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3094 opn = "dsrlv";
3095 break;
3096 case OPC_DROTRV:
3097 tcg_gen_andi_tl(t0, t0, 0x3f);
3098 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3099 opn = "drotrv";
3100 break;
3101 #endif
3103 (void)opn; /* avoid a compiler warning */
3104 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3105 tcg_temp_free(t0);
3106 tcg_temp_free(t1);
3109 /* Arithmetic on HI/LO registers */
3110 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3112 const char *opn = "hilo";
3114 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3115 /* Treat as NOP. */
3116 MIPS_DEBUG("NOP");
3117 return;
3120 if (acc != 0) {
3121 check_dsp(ctx);
3124 switch (opc) {
3125 case OPC_MFHI:
3126 #if defined(TARGET_MIPS64)
3127 if (acc != 0) {
3128 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3129 } else
3130 #endif
3132 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3134 opn = "mfhi";
3135 break;
3136 case OPC_MFLO:
3137 #if defined(TARGET_MIPS64)
3138 if (acc != 0) {
3139 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3140 } else
3141 #endif
3143 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3145 opn = "mflo";
3146 break;
3147 case OPC_MTHI:
3148 if (reg != 0) {
3149 #if defined(TARGET_MIPS64)
3150 if (acc != 0) {
3151 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3152 } else
3153 #endif
3155 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3157 } else {
3158 tcg_gen_movi_tl(cpu_HI[acc], 0);
3160 opn = "mthi";
3161 break;
3162 case OPC_MTLO:
3163 if (reg != 0) {
3164 #if defined(TARGET_MIPS64)
3165 if (acc != 0) {
3166 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3167 } else
3168 #endif
3170 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3172 } else {
3173 tcg_gen_movi_tl(cpu_LO[acc], 0);
3175 opn = "mtlo";
3176 break;
3178 (void)opn; /* avoid a compiler warning */
3179 MIPS_DEBUG("%s %s", opn, regnames[reg]);
3182 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3183 TCGMemOp memop)
3185 TCGv t0 = tcg_const_tl(addr);
3186 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3187 gen_store_gpr(t0, reg);
3188 tcg_temp_free(t0);
3191 static inline void gen_pcrel(DisasContext *ctx, int rs, int16_t imm)
3193 target_long offset;
3194 target_long addr;
3196 switch (MASK_OPC_PCREL_TOP2BITS(ctx->opcode)) {
3197 case OPC_ADDIUPC:
3198 if (rs != 0) {
3199 offset = sextract32(ctx->opcode << 2, 0, 21);
3200 addr = addr_add(ctx, ctx->pc, offset);
3201 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3203 break;
3204 case R6_OPC_LWPC:
3205 offset = sextract32(ctx->opcode << 2, 0, 21);
3206 addr = addr_add(ctx, ctx->pc, offset);
3207 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3208 break;
3209 #if defined(TARGET_MIPS64)
3210 case OPC_LWUPC:
3211 check_mips_64(ctx);
3212 offset = sextract32(ctx->opcode << 2, 0, 21);
3213 addr = addr_add(ctx, ctx->pc, offset);
3214 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3215 break;
3216 #endif
3217 default:
3218 switch (MASK_OPC_PCREL_TOP5BITS(ctx->opcode)) {
3219 case OPC_AUIPC:
3220 if (rs != 0) {
3221 offset = imm << 16;
3222 addr = addr_add(ctx, ctx->pc, offset);
3223 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3225 break;
3226 case OPC_ALUIPC:
3227 if (rs != 0) {
3228 offset = imm << 16;
3229 addr = ~0xFFFF & addr_add(ctx, ctx->pc, offset);
3230 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3232 break;
3233 #if defined(TARGET_MIPS64)
3234 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3235 case R6_OPC_LDPC + (1 << 16):
3236 case R6_OPC_LDPC + (2 << 16):
3237 case R6_OPC_LDPC + (3 << 16):
3238 check_mips_64(ctx);
3239 offset = sextract32(ctx->opcode << 3, 0, 21);
3240 addr = addr_add(ctx, (ctx->pc & ~0x7), offset);
3241 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3242 break;
3243 #endif
3244 default:
3245 MIPS_INVAL("OPC_PCREL");
3246 generate_exception(ctx, EXCP_RI);
3247 break;
3249 break;
3253 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3255 const char *opn = "r6 mul/div";
3256 TCGv t0, t1;
3258 if (rd == 0) {
3259 /* Treat as NOP. */
3260 MIPS_DEBUG("NOP");
3261 return;
3264 t0 = tcg_temp_new();
3265 t1 = tcg_temp_new();
3267 gen_load_gpr(t0, rs);
3268 gen_load_gpr(t1, rt);
3270 switch (opc) {
3271 case R6_OPC_DIV:
3273 TCGv t2 = tcg_temp_new();
3274 TCGv t3 = tcg_temp_new();
3275 tcg_gen_ext32s_tl(t0, t0);
3276 tcg_gen_ext32s_tl(t1, t1);
3277 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3278 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3279 tcg_gen_and_tl(t2, t2, t3);
3280 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3281 tcg_gen_or_tl(t2, t2, t3);
3282 tcg_gen_movi_tl(t3, 0);
3283 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3284 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3285 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3286 tcg_temp_free(t3);
3287 tcg_temp_free(t2);
3289 opn = "div";
3290 break;
3291 case R6_OPC_MOD:
3293 TCGv t2 = tcg_temp_new();
3294 TCGv t3 = tcg_temp_new();
3295 tcg_gen_ext32s_tl(t0, t0);
3296 tcg_gen_ext32s_tl(t1, t1);
3297 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3298 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3299 tcg_gen_and_tl(t2, t2, t3);
3300 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3301 tcg_gen_or_tl(t2, t2, t3);
3302 tcg_gen_movi_tl(t3, 0);
3303 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3304 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3305 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3306 tcg_temp_free(t3);
3307 tcg_temp_free(t2);
3309 opn = "mod";
3310 break;
3311 case R6_OPC_DIVU:
3313 TCGv t2 = tcg_const_tl(0);
3314 TCGv t3 = tcg_const_tl(1);
3315 tcg_gen_ext32u_tl(t0, t0);
3316 tcg_gen_ext32u_tl(t1, t1);
3317 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3318 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3319 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3320 tcg_temp_free(t3);
3321 tcg_temp_free(t2);
3323 opn = "divu";
3324 break;
3325 case R6_OPC_MODU:
3327 TCGv t2 = tcg_const_tl(0);
3328 TCGv t3 = tcg_const_tl(1);
3329 tcg_gen_ext32u_tl(t0, t0);
3330 tcg_gen_ext32u_tl(t1, t1);
3331 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3332 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3333 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3334 tcg_temp_free(t3);
3335 tcg_temp_free(t2);
3337 opn = "modu";
3338 break;
3339 case R6_OPC_MUL:
3341 TCGv_i32 t2 = tcg_temp_new_i32();
3342 TCGv_i32 t3 = tcg_temp_new_i32();
3343 tcg_gen_trunc_tl_i32(t2, t0);
3344 tcg_gen_trunc_tl_i32(t3, t1);
3345 tcg_gen_mul_i32(t2, t2, t3);
3346 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3347 tcg_temp_free_i32(t2);
3348 tcg_temp_free_i32(t3);
3350 opn = "mul";
3351 break;
3352 case R6_OPC_MUH:
3354 TCGv_i32 t2 = tcg_temp_new_i32();
3355 TCGv_i32 t3 = tcg_temp_new_i32();
3356 tcg_gen_trunc_tl_i32(t2, t0);
3357 tcg_gen_trunc_tl_i32(t3, t1);
3358 tcg_gen_muls2_i32(t2, t3, t2, t3);
3359 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3360 tcg_temp_free_i32(t2);
3361 tcg_temp_free_i32(t3);
3363 opn = "muh";
3364 break;
3365 case R6_OPC_MULU:
3367 TCGv_i32 t2 = tcg_temp_new_i32();
3368 TCGv_i32 t3 = tcg_temp_new_i32();
3369 tcg_gen_trunc_tl_i32(t2, t0);
3370 tcg_gen_trunc_tl_i32(t3, t1);
3371 tcg_gen_mul_i32(t2, t2, t3);
3372 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3373 tcg_temp_free_i32(t2);
3374 tcg_temp_free_i32(t3);
3376 opn = "mulu";
3377 break;
3378 case R6_OPC_MUHU:
3380 TCGv_i32 t2 = tcg_temp_new_i32();
3381 TCGv_i32 t3 = tcg_temp_new_i32();
3382 tcg_gen_trunc_tl_i32(t2, t0);
3383 tcg_gen_trunc_tl_i32(t3, t1);
3384 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3385 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3386 tcg_temp_free_i32(t2);
3387 tcg_temp_free_i32(t3);
3389 opn = "muhu";
3390 break;
3391 #if defined(TARGET_MIPS64)
3392 case R6_OPC_DDIV:
3394 TCGv t2 = tcg_temp_new();
3395 TCGv t3 = tcg_temp_new();
3396 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3397 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3398 tcg_gen_and_tl(t2, t2, t3);
3399 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3400 tcg_gen_or_tl(t2, t2, t3);
3401 tcg_gen_movi_tl(t3, 0);
3402 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3403 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3404 tcg_temp_free(t3);
3405 tcg_temp_free(t2);
3407 opn = "ddiv";
3408 break;
3409 case R6_OPC_DMOD:
3411 TCGv t2 = tcg_temp_new();
3412 TCGv t3 = tcg_temp_new();
3413 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3414 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3415 tcg_gen_and_tl(t2, t2, t3);
3416 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3417 tcg_gen_or_tl(t2, t2, t3);
3418 tcg_gen_movi_tl(t3, 0);
3419 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3420 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3421 tcg_temp_free(t3);
3422 tcg_temp_free(t2);
3424 opn = "dmod";
3425 break;
3426 case R6_OPC_DDIVU:
3428 TCGv t2 = tcg_const_tl(0);
3429 TCGv t3 = tcg_const_tl(1);
3430 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3431 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3432 tcg_temp_free(t3);
3433 tcg_temp_free(t2);
3435 opn = "ddivu";
3436 break;
3437 case R6_OPC_DMODU:
3439 TCGv t2 = tcg_const_tl(0);
3440 TCGv t3 = tcg_const_tl(1);
3441 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3442 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3443 tcg_temp_free(t3);
3444 tcg_temp_free(t2);
3446 opn = "dmodu";
3447 break;
3448 case R6_OPC_DMUL:
3449 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3450 opn = "dmul";
3451 break;
3452 case R6_OPC_DMUH:
3454 TCGv t2 = tcg_temp_new();
3455 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3456 tcg_temp_free(t2);
3458 opn = "dmuh";
3459 break;
3460 case R6_OPC_DMULU:
3461 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3462 opn = "dmulu";
3463 break;
3464 case R6_OPC_DMUHU:
3466 TCGv t2 = tcg_temp_new();
3467 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3468 tcg_temp_free(t2);
3470 opn = "dmuhu";
3471 break;
3472 #endif
3473 default:
3474 MIPS_INVAL(opn);
3475 generate_exception(ctx, EXCP_RI);
3476 goto out;
3478 (void)opn; /* avoid a compiler warning */
3479 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3480 out:
3481 tcg_temp_free(t0);
3482 tcg_temp_free(t1);
3485 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3486 int acc, int rs, int rt)
3488 const char *opn = "mul/div";
3489 TCGv t0, t1;
3491 t0 = tcg_temp_new();
3492 t1 = tcg_temp_new();
3494 gen_load_gpr(t0, rs);
3495 gen_load_gpr(t1, rt);
3497 if (acc != 0) {
3498 check_dsp(ctx);
3501 switch (opc) {
3502 case OPC_DIV:
3504 TCGv t2 = tcg_temp_new();
3505 TCGv t3 = tcg_temp_new();
3506 tcg_gen_ext32s_tl(t0, t0);
3507 tcg_gen_ext32s_tl(t1, t1);
3508 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3509 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3510 tcg_gen_and_tl(t2, t2, t3);
3511 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3512 tcg_gen_or_tl(t2, t2, t3);
3513 tcg_gen_movi_tl(t3, 0);
3514 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3515 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3516 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3517 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3518 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3519 tcg_temp_free(t3);
3520 tcg_temp_free(t2);
3522 opn = "div";
3523 break;
3524 case OPC_DIVU:
3526 TCGv t2 = tcg_const_tl(0);
3527 TCGv t3 = tcg_const_tl(1);
3528 tcg_gen_ext32u_tl(t0, t0);
3529 tcg_gen_ext32u_tl(t1, t1);
3530 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3531 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3532 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3533 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3534 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3535 tcg_temp_free(t3);
3536 tcg_temp_free(t2);
3538 opn = "divu";
3539 break;
3540 case OPC_MULT:
3542 TCGv_i32 t2 = tcg_temp_new_i32();
3543 TCGv_i32 t3 = tcg_temp_new_i32();
3544 tcg_gen_trunc_tl_i32(t2, t0);
3545 tcg_gen_trunc_tl_i32(t3, t1);
3546 tcg_gen_muls2_i32(t2, t3, t2, t3);
3547 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3548 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3549 tcg_temp_free_i32(t2);
3550 tcg_temp_free_i32(t3);
3552 opn = "mult";
3553 break;
3554 case OPC_MULTU:
3556 TCGv_i32 t2 = tcg_temp_new_i32();
3557 TCGv_i32 t3 = tcg_temp_new_i32();
3558 tcg_gen_trunc_tl_i32(t2, t0);
3559 tcg_gen_trunc_tl_i32(t3, t1);
3560 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3561 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3562 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3563 tcg_temp_free_i32(t2);
3564 tcg_temp_free_i32(t3);
3566 opn = "multu";
3567 break;
3568 #if defined(TARGET_MIPS64)
3569 case OPC_DDIV:
3571 TCGv t2 = tcg_temp_new();
3572 TCGv t3 = tcg_temp_new();
3573 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3574 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3575 tcg_gen_and_tl(t2, t2, t3);
3576 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3577 tcg_gen_or_tl(t2, t2, t3);
3578 tcg_gen_movi_tl(t3, 0);
3579 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3580 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3581 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3582 tcg_temp_free(t3);
3583 tcg_temp_free(t2);
3585 opn = "ddiv";
3586 break;
3587 case OPC_DDIVU:
3589 TCGv t2 = tcg_const_tl(0);
3590 TCGv t3 = tcg_const_tl(1);
3591 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3592 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3593 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3594 tcg_temp_free(t3);
3595 tcg_temp_free(t2);
3597 opn = "ddivu";
3598 break;
3599 case OPC_DMULT:
3600 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3601 opn = "dmult";
3602 break;
3603 case OPC_DMULTU:
3604 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3605 opn = "dmultu";
3606 break;
3607 #endif
3608 case OPC_MADD:
3610 TCGv_i64 t2 = tcg_temp_new_i64();
3611 TCGv_i64 t3 = tcg_temp_new_i64();
3613 tcg_gen_ext_tl_i64(t2, t0);
3614 tcg_gen_ext_tl_i64(t3, t1);
3615 tcg_gen_mul_i64(t2, t2, t3);
3616 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3617 tcg_gen_add_i64(t2, t2, t3);
3618 tcg_temp_free_i64(t3);
3619 tcg_gen_trunc_i64_tl(t0, t2);
3620 tcg_gen_shri_i64(t2, t2, 32);
3621 tcg_gen_trunc_i64_tl(t1, t2);
3622 tcg_temp_free_i64(t2);
3623 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3624 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3626 opn = "madd";
3627 break;
3628 case OPC_MADDU:
3630 TCGv_i64 t2 = tcg_temp_new_i64();
3631 TCGv_i64 t3 = tcg_temp_new_i64();
3633 tcg_gen_ext32u_tl(t0, t0);
3634 tcg_gen_ext32u_tl(t1, t1);
3635 tcg_gen_extu_tl_i64(t2, t0);
3636 tcg_gen_extu_tl_i64(t3, t1);
3637 tcg_gen_mul_i64(t2, t2, t3);
3638 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3639 tcg_gen_add_i64(t2, t2, t3);
3640 tcg_temp_free_i64(t3);
3641 tcg_gen_trunc_i64_tl(t0, t2);
3642 tcg_gen_shri_i64(t2, t2, 32);
3643 tcg_gen_trunc_i64_tl(t1, t2);
3644 tcg_temp_free_i64(t2);
3645 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3646 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3648 opn = "maddu";
3649 break;
3650 case OPC_MSUB:
3652 TCGv_i64 t2 = tcg_temp_new_i64();
3653 TCGv_i64 t3 = tcg_temp_new_i64();
3655 tcg_gen_ext_tl_i64(t2, t0);
3656 tcg_gen_ext_tl_i64(t3, t1);
3657 tcg_gen_mul_i64(t2, t2, t3);
3658 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3659 tcg_gen_sub_i64(t2, t3, t2);
3660 tcg_temp_free_i64(t3);
3661 tcg_gen_trunc_i64_tl(t0, t2);
3662 tcg_gen_shri_i64(t2, t2, 32);
3663 tcg_gen_trunc_i64_tl(t1, t2);
3664 tcg_temp_free_i64(t2);
3665 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3666 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3668 opn = "msub";
3669 break;
3670 case OPC_MSUBU:
3672 TCGv_i64 t2 = tcg_temp_new_i64();
3673 TCGv_i64 t3 = tcg_temp_new_i64();
3675 tcg_gen_ext32u_tl(t0, t0);
3676 tcg_gen_ext32u_tl(t1, t1);
3677 tcg_gen_extu_tl_i64(t2, t0);
3678 tcg_gen_extu_tl_i64(t3, t1);
3679 tcg_gen_mul_i64(t2, t2, t3);
3680 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3681 tcg_gen_sub_i64(t2, t3, t2);
3682 tcg_temp_free_i64(t3);
3683 tcg_gen_trunc_i64_tl(t0, t2);
3684 tcg_gen_shri_i64(t2, t2, 32);
3685 tcg_gen_trunc_i64_tl(t1, t2);
3686 tcg_temp_free_i64(t2);
3687 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3688 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3690 opn = "msubu";
3691 break;
3692 default:
3693 MIPS_INVAL(opn);
3694 generate_exception(ctx, EXCP_RI);
3695 goto out;
3697 (void)opn; /* avoid a compiler warning */
3698 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3699 out:
3700 tcg_temp_free(t0);
3701 tcg_temp_free(t1);
3704 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3705 int rd, int rs, int rt)
3707 const char *opn = "mul vr54xx";
3708 TCGv t0 = tcg_temp_new();
3709 TCGv t1 = tcg_temp_new();
3711 gen_load_gpr(t0, rs);
3712 gen_load_gpr(t1, rt);
3714 switch (opc) {
3715 case OPC_VR54XX_MULS:
3716 gen_helper_muls(t0, cpu_env, t0, t1);
3717 opn = "muls";
3718 break;
3719 case OPC_VR54XX_MULSU:
3720 gen_helper_mulsu(t0, cpu_env, t0, t1);
3721 opn = "mulsu";
3722 break;
3723 case OPC_VR54XX_MACC:
3724 gen_helper_macc(t0, cpu_env, t0, t1);
3725 opn = "macc";
3726 break;
3727 case OPC_VR54XX_MACCU:
3728 gen_helper_maccu(t0, cpu_env, t0, t1);
3729 opn = "maccu";
3730 break;
3731 case OPC_VR54XX_MSAC:
3732 gen_helper_msac(t0, cpu_env, t0, t1);
3733 opn = "msac";
3734 break;
3735 case OPC_VR54XX_MSACU:
3736 gen_helper_msacu(t0, cpu_env, t0, t1);
3737 opn = "msacu";
3738 break;
3739 case OPC_VR54XX_MULHI:
3740 gen_helper_mulhi(t0, cpu_env, t0, t1);
3741 opn = "mulhi";
3742 break;
3743 case OPC_VR54XX_MULHIU:
3744 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3745 opn = "mulhiu";
3746 break;
3747 case OPC_VR54XX_MULSHI:
3748 gen_helper_mulshi(t0, cpu_env, t0, t1);
3749 opn = "mulshi";
3750 break;
3751 case OPC_VR54XX_MULSHIU:
3752 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3753 opn = "mulshiu";
3754 break;
3755 case OPC_VR54XX_MACCHI:
3756 gen_helper_macchi(t0, cpu_env, t0, t1);
3757 opn = "macchi";
3758 break;
3759 case OPC_VR54XX_MACCHIU:
3760 gen_helper_macchiu(t0, cpu_env, t0, t1);
3761 opn = "macchiu";
3762 break;
3763 case OPC_VR54XX_MSACHI:
3764 gen_helper_msachi(t0, cpu_env, t0, t1);
3765 opn = "msachi";
3766 break;
3767 case OPC_VR54XX_MSACHIU:
3768 gen_helper_msachiu(t0, cpu_env, t0, t1);
3769 opn = "msachiu";
3770 break;
3771 default:
3772 MIPS_INVAL("mul vr54xx");
3773 generate_exception(ctx, EXCP_RI);
3774 goto out;
3776 gen_store_gpr(t0, rd);
3777 (void)opn; /* avoid a compiler warning */
3778 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3780 out:
3781 tcg_temp_free(t0);
3782 tcg_temp_free(t1);
3785 static void gen_cl (DisasContext *ctx, uint32_t opc,
3786 int rd, int rs)
3788 const char *opn = "CLx";
3789 TCGv t0;
3791 if (rd == 0) {
3792 /* Treat as NOP. */
3793 MIPS_DEBUG("NOP");
3794 return;
3796 t0 = tcg_temp_new();
3797 gen_load_gpr(t0, rs);
3798 switch (opc) {
3799 case OPC_CLO:
3800 case R6_OPC_CLO:
3801 gen_helper_clo(cpu_gpr[rd], t0);
3802 opn = "clo";
3803 break;
3804 case OPC_CLZ:
3805 case R6_OPC_CLZ:
3806 gen_helper_clz(cpu_gpr[rd], t0);
3807 opn = "clz";
3808 break;
3809 #if defined(TARGET_MIPS64)
3810 case OPC_DCLO:
3811 case R6_OPC_DCLO:
3812 gen_helper_dclo(cpu_gpr[rd], t0);
3813 opn = "dclo";
3814 break;
3815 case OPC_DCLZ:
3816 case R6_OPC_DCLZ:
3817 gen_helper_dclz(cpu_gpr[rd], t0);
3818 opn = "dclz";
3819 break;
3820 #endif
3822 (void)opn; /* avoid a compiler warning */
3823 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3824 tcg_temp_free(t0);
3827 /* Godson integer instructions */
3828 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3829 int rd, int rs, int rt)
3831 const char *opn = "loongson";
3832 TCGv t0, t1;
3834 if (rd == 0) {
3835 /* Treat as NOP. */
3836 MIPS_DEBUG("NOP");
3837 return;
3840 switch (opc) {
3841 case OPC_MULT_G_2E:
3842 case OPC_MULT_G_2F:
3843 case OPC_MULTU_G_2E:
3844 case OPC_MULTU_G_2F:
3845 #if defined(TARGET_MIPS64)
3846 case OPC_DMULT_G_2E:
3847 case OPC_DMULT_G_2F:
3848 case OPC_DMULTU_G_2E:
3849 case OPC_DMULTU_G_2F:
3850 #endif
3851 t0 = tcg_temp_new();
3852 t1 = tcg_temp_new();
3853 break;
3854 default:
3855 t0 = tcg_temp_local_new();
3856 t1 = tcg_temp_local_new();
3857 break;
3860 gen_load_gpr(t0, rs);
3861 gen_load_gpr(t1, rt);
3863 switch (opc) {
3864 case OPC_MULT_G_2E:
3865 case OPC_MULT_G_2F:
3866 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3867 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3868 opn = "mult.g";
3869 break;
3870 case OPC_MULTU_G_2E:
3871 case OPC_MULTU_G_2F:
3872 tcg_gen_ext32u_tl(t0, t0);
3873 tcg_gen_ext32u_tl(t1, t1);
3874 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3875 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3876 opn = "multu.g";
3877 break;
3878 case OPC_DIV_G_2E:
3879 case OPC_DIV_G_2F:
3881 TCGLabel *l1 = gen_new_label();
3882 TCGLabel *l2 = gen_new_label();
3883 TCGLabel *l3 = gen_new_label();
3884 tcg_gen_ext32s_tl(t0, t0);
3885 tcg_gen_ext32s_tl(t1, t1);
3886 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3887 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3888 tcg_gen_br(l3);
3889 gen_set_label(l1);
3890 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3891 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3892 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3893 tcg_gen_br(l3);
3894 gen_set_label(l2);
3895 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3896 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3897 gen_set_label(l3);
3899 opn = "div.g";
3900 break;
3901 case OPC_DIVU_G_2E:
3902 case OPC_DIVU_G_2F:
3904 TCGLabel *l1 = gen_new_label();
3905 TCGLabel *l2 = gen_new_label();
3906 tcg_gen_ext32u_tl(t0, t0);
3907 tcg_gen_ext32u_tl(t1, t1);
3908 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3909 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3910 tcg_gen_br(l2);
3911 gen_set_label(l1);
3912 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3913 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3914 gen_set_label(l2);
3916 opn = "divu.g";
3917 break;
3918 case OPC_MOD_G_2E:
3919 case OPC_MOD_G_2F:
3921 TCGLabel *l1 = gen_new_label();
3922 TCGLabel *l2 = gen_new_label();
3923 TCGLabel *l3 = gen_new_label();
3924 tcg_gen_ext32u_tl(t0, t0);
3925 tcg_gen_ext32u_tl(t1, t1);
3926 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3927 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3928 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3929 gen_set_label(l1);
3930 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3931 tcg_gen_br(l3);
3932 gen_set_label(l2);
3933 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3934 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3935 gen_set_label(l3);
3937 opn = "mod.g";
3938 break;
3939 case OPC_MODU_G_2E:
3940 case OPC_MODU_G_2F:
3942 TCGLabel *l1 = gen_new_label();
3943 TCGLabel *l2 = gen_new_label();
3944 tcg_gen_ext32u_tl(t0, t0);
3945 tcg_gen_ext32u_tl(t1, t1);
3946 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3947 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3948 tcg_gen_br(l2);
3949 gen_set_label(l1);
3950 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3951 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3952 gen_set_label(l2);
3954 opn = "modu.g";
3955 break;
3956 #if defined(TARGET_MIPS64)
3957 case OPC_DMULT_G_2E:
3958 case OPC_DMULT_G_2F:
3959 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3960 opn = "dmult.g";
3961 break;
3962 case OPC_DMULTU_G_2E:
3963 case OPC_DMULTU_G_2F:
3964 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3965 opn = "dmultu.g";
3966 break;
3967 case OPC_DDIV_G_2E:
3968 case OPC_DDIV_G_2F:
3970 TCGLabel *l1 = gen_new_label();
3971 TCGLabel *l2 = gen_new_label();
3972 TCGLabel *l3 = gen_new_label();
3973 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3974 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3975 tcg_gen_br(l3);
3976 gen_set_label(l1);
3977 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3978 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3979 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3980 tcg_gen_br(l3);
3981 gen_set_label(l2);
3982 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3983 gen_set_label(l3);
3985 opn = "ddiv.g";
3986 break;
3987 case OPC_DDIVU_G_2E:
3988 case OPC_DDIVU_G_2F:
3990 TCGLabel *l1 = gen_new_label();
3991 TCGLabel *l2 = gen_new_label();
3992 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3993 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3994 tcg_gen_br(l2);
3995 gen_set_label(l1);
3996 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3997 gen_set_label(l2);
3999 opn = "ddivu.g";
4000 break;
4001 case OPC_DMOD_G_2E:
4002 case OPC_DMOD_G_2F:
4004 TCGLabel *l1 = gen_new_label();
4005 TCGLabel *l2 = gen_new_label();
4006 TCGLabel *l3 = gen_new_label();
4007 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4008 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4009 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4010 gen_set_label(l1);
4011 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4012 tcg_gen_br(l3);
4013 gen_set_label(l2);
4014 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4015 gen_set_label(l3);
4017 opn = "dmod.g";
4018 break;
4019 case OPC_DMODU_G_2E:
4020 case OPC_DMODU_G_2F:
4022 TCGLabel *l1 = gen_new_label();
4023 TCGLabel *l2 = gen_new_label();
4024 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4025 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4026 tcg_gen_br(l2);
4027 gen_set_label(l1);
4028 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4029 gen_set_label(l2);
4031 opn = "dmodu.g";
4032 break;
4033 #endif
4036 (void)opn; /* avoid a compiler warning */
4037 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
4038 tcg_temp_free(t0);
4039 tcg_temp_free(t1);
4042 /* Loongson multimedia instructions */
4043 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4045 const char *opn = "loongson_cp2";
4046 uint32_t opc, shift_max;
4047 TCGv_i64 t0, t1;
4049 opc = MASK_LMI(ctx->opcode);
4050 switch (opc) {
4051 case OPC_ADD_CP2:
4052 case OPC_SUB_CP2:
4053 case OPC_DADD_CP2:
4054 case OPC_DSUB_CP2:
4055 t0 = tcg_temp_local_new_i64();
4056 t1 = tcg_temp_local_new_i64();
4057 break;
4058 default:
4059 t0 = tcg_temp_new_i64();
4060 t1 = tcg_temp_new_i64();
4061 break;
4064 gen_load_fpr64(ctx, t0, rs);
4065 gen_load_fpr64(ctx, t1, rt);
4067 #define LMI_HELPER(UP, LO) \
4068 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
4069 #define LMI_HELPER_1(UP, LO) \
4070 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
4071 #define LMI_DIRECT(UP, LO, OP) \
4072 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
4074 switch (opc) {
4075 LMI_HELPER(PADDSH, paddsh);
4076 LMI_HELPER(PADDUSH, paddush);
4077 LMI_HELPER(PADDH, paddh);
4078 LMI_HELPER(PADDW, paddw);
4079 LMI_HELPER(PADDSB, paddsb);
4080 LMI_HELPER(PADDUSB, paddusb);
4081 LMI_HELPER(PADDB, paddb);
4083 LMI_HELPER(PSUBSH, psubsh);
4084 LMI_HELPER(PSUBUSH, psubush);
4085 LMI_HELPER(PSUBH, psubh);
4086 LMI_HELPER(PSUBW, psubw);
4087 LMI_HELPER(PSUBSB, psubsb);
4088 LMI_HELPER(PSUBUSB, psubusb);
4089 LMI_HELPER(PSUBB, psubb);
4091 LMI_HELPER(PSHUFH, pshufh);
4092 LMI_HELPER(PACKSSWH, packsswh);
4093 LMI_HELPER(PACKSSHB, packsshb);
4094 LMI_HELPER(PACKUSHB, packushb);
4096 LMI_HELPER(PUNPCKLHW, punpcklhw);
4097 LMI_HELPER(PUNPCKHHW, punpckhhw);
4098 LMI_HELPER(PUNPCKLBH, punpcklbh);
4099 LMI_HELPER(PUNPCKHBH, punpckhbh);
4100 LMI_HELPER(PUNPCKLWD, punpcklwd);
4101 LMI_HELPER(PUNPCKHWD, punpckhwd);
4103 LMI_HELPER(PAVGH, pavgh);
4104 LMI_HELPER(PAVGB, pavgb);
4105 LMI_HELPER(PMAXSH, pmaxsh);
4106 LMI_HELPER(PMINSH, pminsh);
4107 LMI_HELPER(PMAXUB, pmaxub);
4108 LMI_HELPER(PMINUB, pminub);
4110 LMI_HELPER(PCMPEQW, pcmpeqw);
4111 LMI_HELPER(PCMPGTW, pcmpgtw);
4112 LMI_HELPER(PCMPEQH, pcmpeqh);
4113 LMI_HELPER(PCMPGTH, pcmpgth);
4114 LMI_HELPER(PCMPEQB, pcmpeqb);
4115 LMI_HELPER(PCMPGTB, pcmpgtb);
4117 LMI_HELPER(PSLLW, psllw);
4118 LMI_HELPER(PSLLH, psllh);
4119 LMI_HELPER(PSRLW, psrlw);
4120 LMI_HELPER(PSRLH, psrlh);
4121 LMI_HELPER(PSRAW, psraw);
4122 LMI_HELPER(PSRAH, psrah);
4124 LMI_HELPER(PMULLH, pmullh);
4125 LMI_HELPER(PMULHH, pmulhh);
4126 LMI_HELPER(PMULHUH, pmulhuh);
4127 LMI_HELPER(PMADDHW, pmaddhw);
4129 LMI_HELPER(PASUBUB, pasubub);
4130 LMI_HELPER_1(BIADD, biadd);
4131 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4133 LMI_DIRECT(PADDD, paddd, add);
4134 LMI_DIRECT(PSUBD, psubd, sub);
4135 LMI_DIRECT(XOR_CP2, xor, xor);
4136 LMI_DIRECT(NOR_CP2, nor, nor);
4137 LMI_DIRECT(AND_CP2, and, and);
4138 LMI_DIRECT(PANDN, pandn, andc);
4139 LMI_DIRECT(OR, or, or);
4141 case OPC_PINSRH_0:
4142 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4143 opn = "pinsrh_0";
4144 break;
4145 case OPC_PINSRH_1:
4146 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4147 opn = "pinsrh_1";
4148 break;
4149 case OPC_PINSRH_2:
4150 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4151 opn = "pinsrh_2";
4152 break;
4153 case OPC_PINSRH_3:
4154 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4155 opn = "pinsrh_3";
4156 break;
4158 case OPC_PEXTRH:
4159 tcg_gen_andi_i64(t1, t1, 3);
4160 tcg_gen_shli_i64(t1, t1, 4);
4161 tcg_gen_shr_i64(t0, t0, t1);
4162 tcg_gen_ext16u_i64(t0, t0);
4163 opn = "pextrh";
4164 break;
4166 case OPC_ADDU_CP2:
4167 tcg_gen_add_i64(t0, t0, t1);
4168 tcg_gen_ext32s_i64(t0, t0);
4169 opn = "addu";
4170 break;
4171 case OPC_SUBU_CP2:
4172 tcg_gen_sub_i64(t0, t0, t1);
4173 tcg_gen_ext32s_i64(t0, t0);
4174 opn = "addu";
4175 break;
4177 case OPC_SLL_CP2:
4178 opn = "sll";
4179 shift_max = 32;
4180 goto do_shift;
4181 case OPC_SRL_CP2:
4182 opn = "srl";
4183 shift_max = 32;
4184 goto do_shift;
4185 case OPC_SRA_CP2:
4186 opn = "sra";
4187 shift_max = 32;
4188 goto do_shift;
4189 case OPC_DSLL_CP2:
4190 opn = "dsll";
4191 shift_max = 64;
4192 goto do_shift;
4193 case OPC_DSRL_CP2:
4194 opn = "dsrl";
4195 shift_max = 64;
4196 goto do_shift;
4197 case OPC_DSRA_CP2:
4198 opn = "dsra";
4199 shift_max = 64;
4200 goto do_shift;
4201 do_shift:
4202 /* Make sure shift count isn't TCG undefined behaviour. */
4203 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4205 switch (opc) {
4206 case OPC_SLL_CP2:
4207 case OPC_DSLL_CP2:
4208 tcg_gen_shl_i64(t0, t0, t1);
4209 break;
4210 case OPC_SRA_CP2:
4211 case OPC_DSRA_CP2:
4212 /* Since SRA is UndefinedResult without sign-extended inputs,
4213 we can treat SRA and DSRA the same. */
4214 tcg_gen_sar_i64(t0, t0, t1);
4215 break;
4216 case OPC_SRL_CP2:
4217 /* We want to shift in zeros for SRL; zero-extend first. */
4218 tcg_gen_ext32u_i64(t0, t0);
4219 /* FALLTHRU */
4220 case OPC_DSRL_CP2:
4221 tcg_gen_shr_i64(t0, t0, t1);
4222 break;
4225 if (shift_max == 32) {
4226 tcg_gen_ext32s_i64(t0, t0);
4229 /* Shifts larger than MAX produce zero. */
4230 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4231 tcg_gen_neg_i64(t1, t1);
4232 tcg_gen_and_i64(t0, t0, t1);
4233 break;
4235 case OPC_ADD_CP2:
4236 case OPC_DADD_CP2:
4238 TCGv_i64 t2 = tcg_temp_new_i64();
4239 TCGLabel *lab = gen_new_label();
4241 tcg_gen_mov_i64(t2, t0);
4242 tcg_gen_add_i64(t0, t1, t2);
4243 if (opc == OPC_ADD_CP2) {
4244 tcg_gen_ext32s_i64(t0, t0);
4246 tcg_gen_xor_i64(t1, t1, t2);
4247 tcg_gen_xor_i64(t2, t2, t0);
4248 tcg_gen_andc_i64(t1, t2, t1);
4249 tcg_temp_free_i64(t2);
4250 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4251 generate_exception(ctx, EXCP_OVERFLOW);
4252 gen_set_label(lab);
4254 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
4255 break;
4258 case OPC_SUB_CP2:
4259 case OPC_DSUB_CP2:
4261 TCGv_i64 t2 = tcg_temp_new_i64();
4262 TCGLabel *lab = gen_new_label();
4264 tcg_gen_mov_i64(t2, t0);
4265 tcg_gen_sub_i64(t0, t1, t2);
4266 if (opc == OPC_SUB_CP2) {
4267 tcg_gen_ext32s_i64(t0, t0);
4269 tcg_gen_xor_i64(t1, t1, t2);
4270 tcg_gen_xor_i64(t2, t2, t0);
4271 tcg_gen_and_i64(t1, t1, t2);
4272 tcg_temp_free_i64(t2);
4273 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4274 generate_exception(ctx, EXCP_OVERFLOW);
4275 gen_set_label(lab);
4277 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
4278 break;
4281 case OPC_PMULUW:
4282 tcg_gen_ext32u_i64(t0, t0);
4283 tcg_gen_ext32u_i64(t1, t1);
4284 tcg_gen_mul_i64(t0, t0, t1);
4285 opn = "pmuluw";
4286 break;
4288 case OPC_SEQU_CP2:
4289 case OPC_SEQ_CP2:
4290 case OPC_SLTU_CP2:
4291 case OPC_SLT_CP2:
4292 case OPC_SLEU_CP2:
4293 case OPC_SLE_CP2:
4294 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4295 FD field is the CC field? */
4296 default:
4297 MIPS_INVAL(opn);
4298 generate_exception(ctx, EXCP_RI);
4299 return;
4302 #undef LMI_HELPER
4303 #undef LMI_DIRECT
4305 gen_store_fpr64(ctx, t0, rd);
4307 (void)opn; /* avoid a compiler warning */
4308 MIPS_DEBUG("%s %s, %s, %s", opn,
4309 fregnames[rd], fregnames[rs], fregnames[rt]);
4310 tcg_temp_free_i64(t0);
4311 tcg_temp_free_i64(t1);
4314 /* Traps */
4315 static void gen_trap (DisasContext *ctx, uint32_t opc,
4316 int rs, int rt, int16_t imm)
4318 int cond;
4319 TCGv t0 = tcg_temp_new();
4320 TCGv t1 = tcg_temp_new();
4322 cond = 0;
4323 /* Load needed operands */
4324 switch (opc) {
4325 case OPC_TEQ:
4326 case OPC_TGE:
4327 case OPC_TGEU:
4328 case OPC_TLT:
4329 case OPC_TLTU:
4330 case OPC_TNE:
4331 /* Compare two registers */
4332 if (rs != rt) {
4333 gen_load_gpr(t0, rs);
4334 gen_load_gpr(t1, rt);
4335 cond = 1;
4337 break;
4338 case OPC_TEQI:
4339 case OPC_TGEI:
4340 case OPC_TGEIU:
4341 case OPC_TLTI:
4342 case OPC_TLTIU:
4343 case OPC_TNEI:
4344 /* Compare register to immediate */
4345 if (rs != 0 || imm != 0) {
4346 gen_load_gpr(t0, rs);
4347 tcg_gen_movi_tl(t1, (int32_t)imm);
4348 cond = 1;
4350 break;
4352 if (cond == 0) {
4353 switch (opc) {
4354 case OPC_TEQ: /* rs == rs */
4355 case OPC_TEQI: /* r0 == 0 */
4356 case OPC_TGE: /* rs >= rs */
4357 case OPC_TGEI: /* r0 >= 0 */
4358 case OPC_TGEU: /* rs >= rs unsigned */
4359 case OPC_TGEIU: /* r0 >= 0 unsigned */
4360 /* Always trap */
4361 generate_exception(ctx, EXCP_TRAP);
4362 break;
4363 case OPC_TLT: /* rs < rs */
4364 case OPC_TLTI: /* r0 < 0 */
4365 case OPC_TLTU: /* rs < rs unsigned */
4366 case OPC_TLTIU: /* r0 < 0 unsigned */
4367 case OPC_TNE: /* rs != rs */
4368 case OPC_TNEI: /* r0 != 0 */
4369 /* Never trap: treat as NOP. */
4370 break;
4372 } else {
4373 TCGLabel *l1 = gen_new_label();
4375 switch (opc) {
4376 case OPC_TEQ:
4377 case OPC_TEQI:
4378 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4379 break;
4380 case OPC_TGE:
4381 case OPC_TGEI:
4382 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4383 break;
4384 case OPC_TGEU:
4385 case OPC_TGEIU:
4386 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4387 break;
4388 case OPC_TLT:
4389 case OPC_TLTI:
4390 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4391 break;
4392 case OPC_TLTU:
4393 case OPC_TLTIU:
4394 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4395 break;
4396 case OPC_TNE:
4397 case OPC_TNEI:
4398 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4399 break;
4401 generate_exception(ctx, EXCP_TRAP);
4402 gen_set_label(l1);
4404 tcg_temp_free(t0);
4405 tcg_temp_free(t1);
4408 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4410 TranslationBlock *tb;
4411 tb = ctx->tb;
4412 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
4413 likely(!ctx->singlestep_enabled)) {
4414 tcg_gen_goto_tb(n);
4415 gen_save_pc(dest);
4416 tcg_gen_exit_tb((uintptr_t)tb + n);
4417 } else {
4418 gen_save_pc(dest);
4419 if (ctx->singlestep_enabled) {
4420 save_cpu_state(ctx, 0);
4421 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
4423 tcg_gen_exit_tb(0);
4427 /* Branches (before delay slot) */
4428 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4429 int insn_bytes,
4430 int rs, int rt, int32_t offset,
4431 int delayslot_size)
4433 target_ulong btgt = -1;
4434 int blink = 0;
4435 int bcond_compute = 0;
4436 TCGv t0 = tcg_temp_new();
4437 TCGv t1 = tcg_temp_new();
4439 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4440 #ifdef MIPS_DEBUG_DISAS
4441 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4442 TARGET_FMT_lx "\n", ctx->pc);
4443 #endif
4444 generate_exception(ctx, EXCP_RI);
4445 goto out;
4448 /* Load needed operands */
4449 switch (opc) {
4450 case OPC_BEQ:
4451 case OPC_BEQL:
4452 case OPC_BNE:
4453 case OPC_BNEL:
4454 /* Compare two registers */
4455 if (rs != rt) {
4456 gen_load_gpr(t0, rs);
4457 gen_load_gpr(t1, rt);
4458 bcond_compute = 1;
4460 btgt = ctx->pc + insn_bytes + offset;
4461 break;
4462 case OPC_BGEZ:
4463 case OPC_BGEZAL:
4464 case OPC_BGEZALL:
4465 case OPC_BGEZL:
4466 case OPC_BGTZ:
4467 case OPC_BGTZL:
4468 case OPC_BLEZ:
4469 case OPC_BLEZL:
4470 case OPC_BLTZ:
4471 case OPC_BLTZAL:
4472 case OPC_BLTZALL:
4473 case OPC_BLTZL:
4474 /* Compare to zero */
4475 if (rs != 0) {
4476 gen_load_gpr(t0, rs);
4477 bcond_compute = 1;
4479 btgt = ctx->pc + insn_bytes + offset;
4480 break;
4481 case OPC_BPOSGE32:
4482 #if defined(TARGET_MIPS64)
4483 case OPC_BPOSGE64:
4484 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4485 #else
4486 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4487 #endif
4488 bcond_compute = 1;
4489 btgt = ctx->pc + insn_bytes + offset;
4490 break;
4491 case OPC_J:
4492 case OPC_JAL:
4493 case OPC_JALX:
4494 /* Jump to immediate */
4495 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4496 break;
4497 case OPC_JR:
4498 case OPC_JALR:
4499 /* Jump to register */
4500 if (offset != 0 && offset != 16) {
4501 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4502 others are reserved. */
4503 MIPS_INVAL("jump hint");
4504 generate_exception(ctx, EXCP_RI);
4505 goto out;
4507 gen_load_gpr(btarget, rs);
4508 break;
4509 default:
4510 MIPS_INVAL("branch/jump");
4511 generate_exception(ctx, EXCP_RI);
4512 goto out;
4514 if (bcond_compute == 0) {
4515 /* No condition to be computed */
4516 switch (opc) {
4517 case OPC_BEQ: /* rx == rx */
4518 case OPC_BEQL: /* rx == rx likely */
4519 case OPC_BGEZ: /* 0 >= 0 */
4520 case OPC_BGEZL: /* 0 >= 0 likely */
4521 case OPC_BLEZ: /* 0 <= 0 */
4522 case OPC_BLEZL: /* 0 <= 0 likely */
4523 /* Always take */
4524 ctx->hflags |= MIPS_HFLAG_B;
4525 MIPS_DEBUG("balways");
4526 break;
4527 case OPC_BGEZAL: /* 0 >= 0 */
4528 case OPC_BGEZALL: /* 0 >= 0 likely */
4529 /* Always take and link */
4530 blink = 31;
4531 ctx->hflags |= MIPS_HFLAG_B;
4532 MIPS_DEBUG("balways and link");
4533 break;
4534 case OPC_BNE: /* rx != rx */
4535 case OPC_BGTZ: /* 0 > 0 */
4536 case OPC_BLTZ: /* 0 < 0 */
4537 /* Treat as NOP. */
4538 MIPS_DEBUG("bnever (NOP)");
4539 goto out;
4540 case OPC_BLTZAL: /* 0 < 0 */
4541 /* Handle as an unconditional branch to get correct delay
4542 slot checking. */
4543 blink = 31;
4544 btgt = ctx->pc + insn_bytes + delayslot_size;
4545 ctx->hflags |= MIPS_HFLAG_B;
4546 MIPS_DEBUG("bnever and link");
4547 break;
4548 case OPC_BLTZALL: /* 0 < 0 likely */
4549 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4550 /* Skip the instruction in the delay slot */
4551 MIPS_DEBUG("bnever, link and skip");
4552 ctx->pc += 4;
4553 goto out;
4554 case OPC_BNEL: /* rx != rx likely */
4555 case OPC_BGTZL: /* 0 > 0 likely */
4556 case OPC_BLTZL: /* 0 < 0 likely */
4557 /* Skip the instruction in the delay slot */
4558 MIPS_DEBUG("bnever and skip");
4559 ctx->pc += 4;
4560 goto out;
4561 case OPC_J:
4562 ctx->hflags |= MIPS_HFLAG_B;
4563 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
4564 break;
4565 case OPC_JALX:
4566 ctx->hflags |= MIPS_HFLAG_BX;
4567 /* Fallthrough */
4568 case OPC_JAL:
4569 blink = 31;
4570 ctx->hflags |= MIPS_HFLAG_B;
4571 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
4572 break;
4573 case OPC_JR:
4574 ctx->hflags |= MIPS_HFLAG_BR;
4575 MIPS_DEBUG("jr %s", regnames[rs]);
4576 break;
4577 case OPC_JALR:
4578 blink = rt;
4579 ctx->hflags |= MIPS_HFLAG_BR;
4580 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
4581 break;
4582 default:
4583 MIPS_INVAL("branch/jump");
4584 generate_exception(ctx, EXCP_RI);
4585 goto out;
4587 } else {
4588 switch (opc) {
4589 case OPC_BEQ:
4590 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4591 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
4592 regnames[rs], regnames[rt], btgt);
4593 goto not_likely;
4594 case OPC_BEQL:
4595 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4596 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
4597 regnames[rs], regnames[rt], btgt);
4598 goto likely;
4599 case OPC_BNE:
4600 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4601 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
4602 regnames[rs], regnames[rt], btgt);
4603 goto not_likely;
4604 case OPC_BNEL:
4605 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4606 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
4607 regnames[rs], regnames[rt], btgt);
4608 goto likely;
4609 case OPC_BGEZ:
4610 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4611 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4612 goto not_likely;
4613 case OPC_BGEZL:
4614 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4615 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4616 goto likely;
4617 case OPC_BGEZAL:
4618 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4619 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4620 blink = 31;
4621 goto not_likely;
4622 case OPC_BGEZALL:
4623 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4624 blink = 31;
4625 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4626 goto likely;
4627 case OPC_BGTZ:
4628 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4629 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4630 goto not_likely;
4631 case OPC_BGTZL:
4632 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4633 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4634 goto likely;
4635 case OPC_BLEZ:
4636 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4637 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4638 goto not_likely;
4639 case OPC_BLEZL:
4640 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4641 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4642 goto likely;
4643 case OPC_BLTZ:
4644 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4645 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4646 goto not_likely;
4647 case OPC_BLTZL:
4648 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4649 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4650 goto likely;
4651 case OPC_BPOSGE32:
4652 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4653 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
4654 goto not_likely;
4655 #if defined(TARGET_MIPS64)
4656 case OPC_BPOSGE64:
4657 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4658 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
4659 goto not_likely;
4660 #endif
4661 case OPC_BLTZAL:
4662 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4663 blink = 31;
4664 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4665 not_likely:
4666 ctx->hflags |= MIPS_HFLAG_BC;
4667 break;
4668 case OPC_BLTZALL:
4669 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4670 blink = 31;
4671 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4672 likely:
4673 ctx->hflags |= MIPS_HFLAG_BL;
4674 break;
4675 default:
4676 MIPS_INVAL("conditional branch/jump");
4677 generate_exception(ctx, EXCP_RI);
4678 goto out;
4681 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
4682 blink, ctx->hflags, btgt);
4684 ctx->btarget = btgt;
4686 switch (delayslot_size) {
4687 case 2:
4688 ctx->hflags |= MIPS_HFLAG_BDS16;
4689 break;
4690 case 4:
4691 ctx->hflags |= MIPS_HFLAG_BDS32;
4692 break;
4695 if (blink > 0) {
4696 int post_delay = insn_bytes + delayslot_size;
4697 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4699 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4702 out:
4703 if (insn_bytes == 2)
4704 ctx->hflags |= MIPS_HFLAG_B16;
4705 tcg_temp_free(t0);
4706 tcg_temp_free(t1);
4709 /* special3 bitfield operations */
4710 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4711 int rs, int lsb, int msb)
4713 TCGv t0 = tcg_temp_new();
4714 TCGv t1 = tcg_temp_new();
4716 gen_load_gpr(t1, rs);
4717 switch (opc) {
4718 case OPC_EXT:
4719 if (lsb + msb > 31)
4720 goto fail;
4721 tcg_gen_shri_tl(t0, t1, lsb);
4722 if (msb != 31) {
4723 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
4724 } else {
4725 tcg_gen_ext32s_tl(t0, t0);
4727 break;
4728 #if defined(TARGET_MIPS64)
4729 case OPC_DEXTM:
4730 tcg_gen_shri_tl(t0, t1, lsb);
4731 if (msb != 31) {
4732 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
4734 break;
4735 case OPC_DEXTU:
4736 tcg_gen_shri_tl(t0, t1, lsb + 32);
4737 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4738 break;
4739 case OPC_DEXT:
4740 tcg_gen_shri_tl(t0, t1, lsb);
4741 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4742 break;
4743 #endif
4744 case OPC_INS:
4745 if (lsb > msb)
4746 goto fail;
4747 gen_load_gpr(t0, rt);
4748 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4749 tcg_gen_ext32s_tl(t0, t0);
4750 break;
4751 #if defined(TARGET_MIPS64)
4752 case OPC_DINSM:
4753 gen_load_gpr(t0, rt);
4754 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb + 32 - lsb + 1);
4755 break;
4756 case OPC_DINSU:
4757 gen_load_gpr(t0, rt);
4758 tcg_gen_deposit_tl(t0, t0, t1, lsb + 32, msb - lsb + 1);
4759 break;
4760 case OPC_DINS:
4761 gen_load_gpr(t0, rt);
4762 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4763 break;
4764 #endif
4765 default:
4766 fail:
4767 MIPS_INVAL("bitops");
4768 generate_exception(ctx, EXCP_RI);
4769 tcg_temp_free(t0);
4770 tcg_temp_free(t1);
4771 return;
4773 gen_store_gpr(t0, rt);
4774 tcg_temp_free(t0);
4775 tcg_temp_free(t1);
4778 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4780 TCGv t0;
4782 if (rd == 0) {
4783 /* If no destination, treat it as a NOP. */
4784 MIPS_DEBUG("NOP");
4785 return;
4788 t0 = tcg_temp_new();
4789 gen_load_gpr(t0, rt);
4790 switch (op2) {
4791 case OPC_WSBH:
4793 TCGv t1 = tcg_temp_new();
4795 tcg_gen_shri_tl(t1, t0, 8);
4796 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4797 tcg_gen_shli_tl(t0, t0, 8);
4798 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4799 tcg_gen_or_tl(t0, t0, t1);
4800 tcg_temp_free(t1);
4801 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4803 break;
4804 case OPC_SEB:
4805 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4806 break;
4807 case OPC_SEH:
4808 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4809 break;
4810 #if defined(TARGET_MIPS64)
4811 case OPC_DSBH:
4813 TCGv t1 = tcg_temp_new();
4815 tcg_gen_shri_tl(t1, t0, 8);
4816 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4817 tcg_gen_shli_tl(t0, t0, 8);
4818 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4819 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4820 tcg_temp_free(t1);
4822 break;
4823 case OPC_DSHD:
4825 TCGv t1 = tcg_temp_new();
4827 tcg_gen_shri_tl(t1, t0, 16);
4828 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4829 tcg_gen_shli_tl(t0, t0, 16);
4830 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4831 tcg_gen_or_tl(t0, t0, t1);
4832 tcg_gen_shri_tl(t1, t0, 32);
4833 tcg_gen_shli_tl(t0, t0, 32);
4834 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4835 tcg_temp_free(t1);
4837 break;
4838 #endif
4839 default:
4840 MIPS_INVAL("bsfhl");
4841 generate_exception(ctx, EXCP_RI);
4842 tcg_temp_free(t0);
4843 return;
4845 tcg_temp_free(t0);
4848 #ifndef CONFIG_USER_ONLY
4849 /* CP0 (MMU and control) */
4850 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
4852 #if defined(TARGET_MIPS64)
4853 tcg_gen_ext32s_tl(ret, arg);
4854 #else
4855 tcg_gen_trunc_i64_tl(ret, arg);
4856 #endif
4859 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4861 TCGv_i64 t0 = tcg_temp_new_i64();
4862 TCGv_i64 t1 = tcg_temp_new_i64();
4864 tcg_gen_ext_tl_i64(t0, arg);
4865 tcg_gen_ld_i64(t1, cpu_env, off);
4866 #if defined(TARGET_MIPS64)
4867 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4868 #else
4869 tcg_gen_concat32_i64(t1, t1, t0);
4870 #endif
4871 tcg_gen_st_i64(t1, cpu_env, off);
4872 tcg_temp_free_i64(t1);
4873 tcg_temp_free_i64(t0);
4876 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4878 TCGv_i64 t0 = tcg_temp_new_i64();
4879 TCGv_i64 t1 = tcg_temp_new_i64();
4881 tcg_gen_ext_tl_i64(t0, arg);
4882 tcg_gen_ld_i64(t1, cpu_env, off);
4883 tcg_gen_concat32_i64(t1, t1, t0);
4884 tcg_gen_st_i64(t1, cpu_env, off);
4885 tcg_temp_free_i64(t1);
4886 tcg_temp_free_i64(t0);
4889 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
4891 TCGv_i64 t0 = tcg_temp_new_i64();
4893 tcg_gen_ld_i64(t0, cpu_env, off);
4894 #if defined(TARGET_MIPS64)
4895 tcg_gen_shri_i64(t0, t0, 30);
4896 #else
4897 tcg_gen_shri_i64(t0, t0, 32);
4898 #endif
4899 gen_move_low32(arg, t0);
4900 tcg_temp_free_i64(t0);
4903 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
4905 TCGv_i64 t0 = tcg_temp_new_i64();
4907 tcg_gen_ld_i64(t0, cpu_env, off);
4908 tcg_gen_shri_i64(t0, t0, 32 + shift);
4909 gen_move_low32(arg, t0);
4910 tcg_temp_free_i64(t0);
4913 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4915 TCGv_i32 t0 = tcg_temp_new_i32();
4917 tcg_gen_ld_i32(t0, cpu_env, off);
4918 tcg_gen_ext_i32_tl(arg, t0);
4919 tcg_temp_free_i32(t0);
4922 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4924 tcg_gen_ld_tl(arg, cpu_env, off);
4925 tcg_gen_ext32s_tl(arg, arg);
4928 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4930 TCGv_i32 t0 = tcg_temp_new_i32();
4932 tcg_gen_trunc_tl_i32(t0, arg);
4933 tcg_gen_st_i32(t0, cpu_env, off);
4934 tcg_temp_free_i32(t0);
4937 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
4939 tcg_gen_ext32s_tl(arg, arg);
4940 tcg_gen_st_tl(arg, cpu_env, off);
4943 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4945 const char *rn = "invalid";
4947 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
4948 goto mfhc0_read_zero;
4951 switch (reg) {
4952 case 2:
4953 switch (sel) {
4954 case 0:
4955 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4956 rn = "EntryLo0";
4957 break;
4958 default:
4959 goto mfhc0_read_zero;
4961 break;
4962 case 3:
4963 switch (sel) {
4964 case 0:
4965 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4966 rn = "EntryLo1";
4967 break;
4968 default:
4969 goto mfhc0_read_zero;
4971 break;
4972 case 17:
4973 switch (sel) {
4974 case 0:
4975 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
4976 ctx->CP0_LLAddr_shift);
4977 rn = "LLAddr";
4978 break;
4979 default:
4980 goto mfhc0_read_zero;
4982 break;
4983 case 28:
4984 switch (sel) {
4985 case 0:
4986 case 2:
4987 case 4:
4988 case 6:
4989 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
4990 rn = "TagLo";
4991 break;
4992 default:
4993 goto mfhc0_read_zero;
4995 break;
4996 default:
4997 goto mfhc0_read_zero;
5000 (void)rn; /* avoid a compiler warning */
5001 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5002 return;
5004 mfhc0_read_zero:
5005 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5006 tcg_gen_movi_tl(arg, 0);
5009 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5011 const char *rn = "invalid";
5012 uint64_t mask = ctx->PAMask >> 36;
5014 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
5015 goto mthc0_nop;
5018 switch (reg) {
5019 case 2:
5020 switch (sel) {
5021 case 0:
5022 tcg_gen_andi_tl(arg, arg, mask);
5023 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5024 rn = "EntryLo0";
5025 break;
5026 default:
5027 goto mthc0_nop;
5029 break;
5030 case 3:
5031 switch (sel) {
5032 case 0:
5033 tcg_gen_andi_tl(arg, arg, mask);
5034 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5035 rn = "EntryLo1";
5036 break;
5037 default:
5038 goto mthc0_nop;
5040 break;
5041 case 17:
5042 switch (sel) {
5043 case 0:
5044 /* LLAddr is read-only (the only exception is bit 0 if LLB is
5045 supported); the CP0_LLAddr_rw_bitmask does not seem to be
5046 relevant for modern MIPS cores supporting MTHC0, therefore
5047 treating MTHC0 to LLAddr as NOP. */
5048 rn = "LLAddr";
5049 break;
5050 default:
5051 goto mthc0_nop;
5053 break;
5054 case 28:
5055 switch (sel) {
5056 case 0:
5057 case 2:
5058 case 4:
5059 case 6:
5060 tcg_gen_andi_tl(arg, arg, mask);
5061 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5062 rn = "TagLo";
5063 break;
5064 default:
5065 goto mthc0_nop;
5067 break;
5068 default:
5069 goto mthc0_nop;
5072 (void)rn; /* avoid a compiler warning */
5073 mthc0_nop:
5074 LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
5077 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5079 if (ctx->insn_flags & ISA_MIPS32R6) {
5080 tcg_gen_movi_tl(arg, 0);
5081 } else {
5082 tcg_gen_movi_tl(arg, ~0);
5086 #define CP0_CHECK(c) \
5087 do { \
5088 if (!(c)) { \
5089 goto cp0_unimplemented; \
5091 } while (0)
5093 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5095 const char *rn = "invalid";
5097 if (sel != 0)
5098 check_insn(ctx, ISA_MIPS32);
5100 switch (reg) {
5101 case 0:
5102 switch (sel) {
5103 case 0:
5104 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5105 rn = "Index";
5106 break;
5107 case 1:
5108 CP0_CHECK(ctx->insn_flags & ASE_MT);
5109 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5110 rn = "MVPControl";
5111 break;
5112 case 2:
5113 CP0_CHECK(ctx->insn_flags & ASE_MT);
5114 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5115 rn = "MVPConf0";
5116 break;
5117 case 3:
5118 CP0_CHECK(ctx->insn_flags & ASE_MT);
5119 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5120 rn = "MVPConf1";
5121 break;
5122 default:
5123 goto cp0_unimplemented;
5125 break;
5126 case 1:
5127 switch (sel) {
5128 case 0:
5129 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5130 gen_helper_mfc0_random(arg, cpu_env);
5131 rn = "Random";
5132 break;
5133 case 1:
5134 CP0_CHECK(ctx->insn_flags & ASE_MT);
5135 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5136 rn = "VPEControl";
5137 break;
5138 case 2:
5139 CP0_CHECK(ctx->insn_flags & ASE_MT);
5140 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5141 rn = "VPEConf0";
5142 break;
5143 case 3:
5144 CP0_CHECK(ctx->insn_flags & ASE_MT);
5145 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5146 rn = "VPEConf1";
5147 break;
5148 case 4:
5149 CP0_CHECK(ctx->insn_flags & ASE_MT);
5150 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5151 rn = "YQMask";
5152 break;
5153 case 5:
5154 CP0_CHECK(ctx->insn_flags & ASE_MT);
5155 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5156 rn = "VPESchedule";
5157 break;
5158 case 6:
5159 CP0_CHECK(ctx->insn_flags & ASE_MT);
5160 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5161 rn = "VPEScheFBack";
5162 break;
5163 case 7:
5164 CP0_CHECK(ctx->insn_flags & ASE_MT);
5165 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5166 rn = "VPEOpt";
5167 break;
5168 default:
5169 goto cp0_unimplemented;
5171 break;
5172 case 2:
5173 switch (sel) {
5174 case 0:
5176 TCGv_i64 tmp = tcg_temp_new_i64();
5177 tcg_gen_ld_i64(tmp, cpu_env,
5178 offsetof(CPUMIPSState, CP0_EntryLo0));
5179 #if defined(TARGET_MIPS64)
5180 if (ctx->rxi) {
5181 /* Move RI/XI fields to bits 31:30 */
5182 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5183 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5185 #endif
5186 gen_move_low32(arg, tmp);
5187 tcg_temp_free_i64(tmp);
5189 rn = "EntryLo0";
5190 break;
5191 case 1:
5192 CP0_CHECK(ctx->insn_flags & ASE_MT);
5193 gen_helper_mfc0_tcstatus(arg, cpu_env);
5194 rn = "TCStatus";
5195 break;
5196 case 2:
5197 CP0_CHECK(ctx->insn_flags & ASE_MT);
5198 gen_helper_mfc0_tcbind(arg, cpu_env);
5199 rn = "TCBind";
5200 break;
5201 case 3:
5202 CP0_CHECK(ctx->insn_flags & ASE_MT);
5203 gen_helper_mfc0_tcrestart(arg, cpu_env);
5204 rn = "TCRestart";
5205 break;
5206 case 4:
5207 CP0_CHECK(ctx->insn_flags & ASE_MT);
5208 gen_helper_mfc0_tchalt(arg, cpu_env);
5209 rn = "TCHalt";
5210 break;
5211 case 5:
5212 CP0_CHECK(ctx->insn_flags & ASE_MT);
5213 gen_helper_mfc0_tccontext(arg, cpu_env);
5214 rn = "TCContext";
5215 break;
5216 case 6:
5217 CP0_CHECK(ctx->insn_flags & ASE_MT);
5218 gen_helper_mfc0_tcschedule(arg, cpu_env);
5219 rn = "TCSchedule";
5220 break;
5221 case 7:
5222 CP0_CHECK(ctx->insn_flags & ASE_MT);
5223 gen_helper_mfc0_tcschefback(arg, cpu_env);
5224 rn = "TCScheFBack";
5225 break;
5226 default:
5227 goto cp0_unimplemented;
5229 break;
5230 case 3:
5231 switch (sel) {
5232 case 0:
5234 TCGv_i64 tmp = tcg_temp_new_i64();
5235 tcg_gen_ld_i64(tmp, cpu_env,
5236 offsetof(CPUMIPSState, CP0_EntryLo1));
5237 #if defined(TARGET_MIPS64)
5238 if (ctx->rxi) {
5239 /* Move RI/XI fields to bits 31:30 */
5240 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5241 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5243 #endif
5244 gen_move_low32(arg, tmp);
5245 tcg_temp_free_i64(tmp);
5247 rn = "EntryLo1";
5248 break;
5249 default:
5250 goto cp0_unimplemented;
5252 break;
5253 case 4:
5254 switch (sel) {
5255 case 0:
5256 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5257 tcg_gen_ext32s_tl(arg, arg);
5258 rn = "Context";
5259 break;
5260 case 1:
5261 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5262 rn = "ContextConfig";
5263 goto cp0_unimplemented;
5264 // break;
5265 case 2:
5266 CP0_CHECK(ctx->ulri);
5267 tcg_gen_ld32s_tl(arg, cpu_env,
5268 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5269 rn = "UserLocal";
5270 break;
5271 default:
5272 goto cp0_unimplemented;
5274 break;
5275 case 5:
5276 switch (sel) {
5277 case 0:
5278 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5279 rn = "PageMask";
5280 break;
5281 case 1:
5282 check_insn(ctx, ISA_MIPS32R2);
5283 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5284 rn = "PageGrain";
5285 break;
5286 default:
5287 goto cp0_unimplemented;
5289 break;
5290 case 6:
5291 switch (sel) {
5292 case 0:
5293 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5294 rn = "Wired";
5295 break;
5296 case 1:
5297 check_insn(ctx, ISA_MIPS32R2);
5298 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5299 rn = "SRSConf0";
5300 break;
5301 case 2:
5302 check_insn(ctx, ISA_MIPS32R2);
5303 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5304 rn = "SRSConf1";
5305 break;
5306 case 3:
5307 check_insn(ctx, ISA_MIPS32R2);
5308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5309 rn = "SRSConf2";
5310 break;
5311 case 4:
5312 check_insn(ctx, ISA_MIPS32R2);
5313 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5314 rn = "SRSConf3";
5315 break;
5316 case 5:
5317 check_insn(ctx, ISA_MIPS32R2);
5318 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5319 rn = "SRSConf4";
5320 break;
5321 default:
5322 goto cp0_unimplemented;
5324 break;
5325 case 7:
5326 switch (sel) {
5327 case 0:
5328 check_insn(ctx, ISA_MIPS32R2);
5329 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5330 rn = "HWREna";
5331 break;
5332 default:
5333 goto cp0_unimplemented;
5335 break;
5336 case 8:
5337 switch (sel) {
5338 case 0:
5339 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5340 tcg_gen_ext32s_tl(arg, arg);
5341 rn = "BadVAddr";
5342 break;
5343 case 1:
5344 CP0_CHECK(ctx->bi);
5345 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5346 rn = "BadInstr";
5347 break;
5348 case 2:
5349 CP0_CHECK(ctx->bp);
5350 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5351 rn = "BadInstrP";
5352 break;
5353 default:
5354 goto cp0_unimplemented;
5356 break;
5357 case 9:
5358 switch (sel) {
5359 case 0:
5360 /* Mark as an IO operation because we read the time. */
5361 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5362 gen_io_start();
5364 gen_helper_mfc0_count(arg, cpu_env);
5365 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5366 gen_io_end();
5368 /* Break the TB to be able to take timer interrupts immediately
5369 after reading count. */
5370 ctx->bstate = BS_STOP;
5371 rn = "Count";
5372 break;
5373 /* 6,7 are implementation dependent */
5374 default:
5375 goto cp0_unimplemented;
5377 break;
5378 case 10:
5379 switch (sel) {
5380 case 0:
5381 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5382 tcg_gen_ext32s_tl(arg, arg);
5383 rn = "EntryHi";
5384 break;
5385 default:
5386 goto cp0_unimplemented;
5388 break;
5389 case 11:
5390 switch (sel) {
5391 case 0:
5392 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5393 rn = "Compare";
5394 break;
5395 /* 6,7 are implementation dependent */
5396 default:
5397 goto cp0_unimplemented;
5399 break;
5400 case 12:
5401 switch (sel) {
5402 case 0:
5403 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5404 rn = "Status";
5405 break;
5406 case 1:
5407 check_insn(ctx, ISA_MIPS32R2);
5408 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5409 rn = "IntCtl";
5410 break;
5411 case 2:
5412 check_insn(ctx, ISA_MIPS32R2);
5413 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5414 rn = "SRSCtl";
5415 break;
5416 case 3:
5417 check_insn(ctx, ISA_MIPS32R2);
5418 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5419 rn = "SRSMap";
5420 break;
5421 default:
5422 goto cp0_unimplemented;
5424 break;
5425 case 13:
5426 switch (sel) {
5427 case 0:
5428 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5429 rn = "Cause";
5430 break;
5431 default:
5432 goto cp0_unimplemented;
5434 break;
5435 case 14:
5436 switch (sel) {
5437 case 0:
5438 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5439 tcg_gen_ext32s_tl(arg, arg);
5440 rn = "EPC";
5441 break;
5442 default:
5443 goto cp0_unimplemented;
5445 break;
5446 case 15:
5447 switch (sel) {
5448 case 0:
5449 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5450 rn = "PRid";
5451 break;
5452 case 1:
5453 check_insn(ctx, ISA_MIPS32R2);
5454 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5455 rn = "EBase";
5456 break;
5457 default:
5458 goto cp0_unimplemented;
5460 break;
5461 case 16:
5462 switch (sel) {
5463 case 0:
5464 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5465 rn = "Config";
5466 break;
5467 case 1:
5468 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5469 rn = "Config1";
5470 break;
5471 case 2:
5472 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5473 rn = "Config2";
5474 break;
5475 case 3:
5476 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5477 rn = "Config3";
5478 break;
5479 case 4:
5480 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5481 rn = "Config4";
5482 break;
5483 case 5:
5484 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5485 rn = "Config5";
5486 break;
5487 /* 6,7 are implementation dependent */
5488 case 6:
5489 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5490 rn = "Config6";
5491 break;
5492 case 7:
5493 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5494 rn = "Config7";
5495 break;
5496 default:
5497 goto cp0_unimplemented;
5499 break;
5500 case 17:
5501 switch (sel) {
5502 case 0:
5503 gen_helper_mfc0_lladdr(arg, cpu_env);
5504 rn = "LLAddr";
5505 break;
5506 default:
5507 goto cp0_unimplemented;
5509 break;
5510 case 18:
5511 switch (sel) {
5512 case 0 ... 7:
5513 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5514 rn = "WatchLo";
5515 break;
5516 default:
5517 goto cp0_unimplemented;
5519 break;
5520 case 19:
5521 switch (sel) {
5522 case 0 ...7:
5523 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5524 rn = "WatchHi";
5525 break;
5526 default:
5527 goto cp0_unimplemented;
5529 break;
5530 case 20:
5531 switch (sel) {
5532 case 0:
5533 #if defined(TARGET_MIPS64)
5534 check_insn(ctx, ISA_MIPS3);
5535 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5536 tcg_gen_ext32s_tl(arg, arg);
5537 rn = "XContext";
5538 break;
5539 #endif
5540 default:
5541 goto cp0_unimplemented;
5543 break;
5544 case 21:
5545 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5546 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5547 switch (sel) {
5548 case 0:
5549 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5550 rn = "Framemask";
5551 break;
5552 default:
5553 goto cp0_unimplemented;
5555 break;
5556 case 22:
5557 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5558 rn = "'Diagnostic"; /* implementation dependent */
5559 break;
5560 case 23:
5561 switch (sel) {
5562 case 0:
5563 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5564 rn = "Debug";
5565 break;
5566 case 1:
5567 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5568 rn = "TraceControl";
5569 // break;
5570 case 2:
5571 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5572 rn = "TraceControl2";
5573 // break;
5574 case 3:
5575 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5576 rn = "UserTraceData";
5577 // break;
5578 case 4:
5579 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5580 rn = "TraceBPC";
5581 // break;
5582 default:
5583 goto cp0_unimplemented;
5585 break;
5586 case 24:
5587 switch (sel) {
5588 case 0:
5589 /* EJTAG support */
5590 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5591 tcg_gen_ext32s_tl(arg, arg);
5592 rn = "DEPC";
5593 break;
5594 default:
5595 goto cp0_unimplemented;
5597 break;
5598 case 25:
5599 switch (sel) {
5600 case 0:
5601 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5602 rn = "Performance0";
5603 break;
5604 case 1:
5605 // gen_helper_mfc0_performance1(arg);
5606 rn = "Performance1";
5607 // break;
5608 case 2:
5609 // gen_helper_mfc0_performance2(arg);
5610 rn = "Performance2";
5611 // break;
5612 case 3:
5613 // gen_helper_mfc0_performance3(arg);
5614 rn = "Performance3";
5615 // break;
5616 case 4:
5617 // gen_helper_mfc0_performance4(arg);
5618 rn = "Performance4";
5619 // break;
5620 case 5:
5621 // gen_helper_mfc0_performance5(arg);
5622 rn = "Performance5";
5623 // break;
5624 case 6:
5625 // gen_helper_mfc0_performance6(arg);
5626 rn = "Performance6";
5627 // break;
5628 case 7:
5629 // gen_helper_mfc0_performance7(arg);
5630 rn = "Performance7";
5631 // break;
5632 default:
5633 goto cp0_unimplemented;
5635 break;
5636 case 26:
5637 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5638 rn = "ECC";
5639 break;
5640 case 27:
5641 switch (sel) {
5642 case 0 ... 3:
5643 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5644 rn = "CacheErr";
5645 break;
5646 default:
5647 goto cp0_unimplemented;
5649 break;
5650 case 28:
5651 switch (sel) {
5652 case 0:
5653 case 2:
5654 case 4:
5655 case 6:
5657 TCGv_i64 tmp = tcg_temp_new_i64();
5658 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5659 gen_move_low32(arg, tmp);
5660 tcg_temp_free_i64(tmp);
5662 rn = "TagLo";
5663 break;
5664 case 1:
5665 case 3:
5666 case 5:
5667 case 7:
5668 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5669 rn = "DataLo";
5670 break;
5671 default:
5672 goto cp0_unimplemented;
5674 break;
5675 case 29:
5676 switch (sel) {
5677 case 0:
5678 case 2:
5679 case 4:
5680 case 6:
5681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5682 rn = "TagHi";
5683 break;
5684 case 1:
5685 case 3:
5686 case 5:
5687 case 7:
5688 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5689 rn = "DataHi";
5690 break;
5691 default:
5692 goto cp0_unimplemented;
5694 break;
5695 case 30:
5696 switch (sel) {
5697 case 0:
5698 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5699 tcg_gen_ext32s_tl(arg, arg);
5700 rn = "ErrorEPC";
5701 break;
5702 default:
5703 goto cp0_unimplemented;
5705 break;
5706 case 31:
5707 switch (sel) {
5708 case 0:
5709 /* EJTAG support */
5710 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5711 rn = "DESAVE";
5712 break;
5713 case 2 ... 7:
5714 CP0_CHECK(ctx->kscrexist & (1 << sel));
5715 tcg_gen_ld_tl(arg, cpu_env,
5716 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5717 tcg_gen_ext32s_tl(arg, arg);
5718 rn = "KScratch";
5719 break;
5720 default:
5721 goto cp0_unimplemented;
5723 break;
5724 default:
5725 goto cp0_unimplemented;
5727 (void)rn; /* avoid a compiler warning */
5728 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5729 return;
5731 cp0_unimplemented:
5732 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5733 gen_mfc0_unimplemented(ctx, arg);
5736 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5738 const char *rn = "invalid";
5740 if (sel != 0)
5741 check_insn(ctx, ISA_MIPS32);
5743 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5744 gen_io_start();
5747 switch (reg) {
5748 case 0:
5749 switch (sel) {
5750 case 0:
5751 gen_helper_mtc0_index(cpu_env, arg);
5752 rn = "Index";
5753 break;
5754 case 1:
5755 CP0_CHECK(ctx->insn_flags & ASE_MT);
5756 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5757 rn = "MVPControl";
5758 break;
5759 case 2:
5760 CP0_CHECK(ctx->insn_flags & ASE_MT);
5761 /* ignored */
5762 rn = "MVPConf0";
5763 break;
5764 case 3:
5765 CP0_CHECK(ctx->insn_flags & ASE_MT);
5766 /* ignored */
5767 rn = "MVPConf1";
5768 break;
5769 default:
5770 goto cp0_unimplemented;
5772 break;
5773 case 1:
5774 switch (sel) {
5775 case 0:
5776 /* ignored */
5777 rn = "Random";
5778 break;
5779 case 1:
5780 CP0_CHECK(ctx->insn_flags & ASE_MT);
5781 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5782 rn = "VPEControl";
5783 break;
5784 case 2:
5785 CP0_CHECK(ctx->insn_flags & ASE_MT);
5786 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5787 rn = "VPEConf0";
5788 break;
5789 case 3:
5790 CP0_CHECK(ctx->insn_flags & ASE_MT);
5791 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5792 rn = "VPEConf1";
5793 break;
5794 case 4:
5795 CP0_CHECK(ctx->insn_flags & ASE_MT);
5796 gen_helper_mtc0_yqmask(cpu_env, arg);
5797 rn = "YQMask";
5798 break;
5799 case 5:
5800 CP0_CHECK(ctx->insn_flags & ASE_MT);
5801 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5802 rn = "VPESchedule";
5803 break;
5804 case 6:
5805 CP0_CHECK(ctx->insn_flags & ASE_MT);
5806 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5807 rn = "VPEScheFBack";
5808 break;
5809 case 7:
5810 CP0_CHECK(ctx->insn_flags & ASE_MT);
5811 gen_helper_mtc0_vpeopt(cpu_env, arg);
5812 rn = "VPEOpt";
5813 break;
5814 default:
5815 goto cp0_unimplemented;
5817 break;
5818 case 2:
5819 switch (sel) {
5820 case 0:
5821 gen_helper_mtc0_entrylo0(cpu_env, arg);
5822 rn = "EntryLo0";
5823 break;
5824 case 1:
5825 CP0_CHECK(ctx->insn_flags & ASE_MT);
5826 gen_helper_mtc0_tcstatus(cpu_env, arg);
5827 rn = "TCStatus";
5828 break;
5829 case 2:
5830 CP0_CHECK(ctx->insn_flags & ASE_MT);
5831 gen_helper_mtc0_tcbind(cpu_env, arg);
5832 rn = "TCBind";
5833 break;
5834 case 3:
5835 CP0_CHECK(ctx->insn_flags & ASE_MT);
5836 gen_helper_mtc0_tcrestart(cpu_env, arg);
5837 rn = "TCRestart";
5838 break;
5839 case 4:
5840 CP0_CHECK(ctx->insn_flags & ASE_MT);
5841 gen_helper_mtc0_tchalt(cpu_env, arg);
5842 rn = "TCHalt";
5843 break;
5844 case 5:
5845 CP0_CHECK(ctx->insn_flags & ASE_MT);
5846 gen_helper_mtc0_tccontext(cpu_env, arg);
5847 rn = "TCContext";
5848 break;
5849 case 6:
5850 CP0_CHECK(ctx->insn_flags & ASE_MT);
5851 gen_helper_mtc0_tcschedule(cpu_env, arg);
5852 rn = "TCSchedule";
5853 break;
5854 case 7:
5855 CP0_CHECK(ctx->insn_flags & ASE_MT);
5856 gen_helper_mtc0_tcschefback(cpu_env, arg);
5857 rn = "TCScheFBack";
5858 break;
5859 default:
5860 goto cp0_unimplemented;
5862 break;
5863 case 3:
5864 switch (sel) {
5865 case 0:
5866 gen_helper_mtc0_entrylo1(cpu_env, arg);
5867 rn = "EntryLo1";
5868 break;
5869 default:
5870 goto cp0_unimplemented;
5872 break;
5873 case 4:
5874 switch (sel) {
5875 case 0:
5876 gen_helper_mtc0_context(cpu_env, arg);
5877 rn = "Context";
5878 break;
5879 case 1:
5880 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5881 rn = "ContextConfig";
5882 goto cp0_unimplemented;
5883 // break;
5884 case 2:
5885 CP0_CHECK(ctx->ulri);
5886 tcg_gen_st_tl(arg, cpu_env,
5887 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5888 rn = "UserLocal";
5889 break;
5890 default:
5891 goto cp0_unimplemented;
5893 break;
5894 case 5:
5895 switch (sel) {
5896 case 0:
5897 gen_helper_mtc0_pagemask(cpu_env, arg);
5898 rn = "PageMask";
5899 break;
5900 case 1:
5901 check_insn(ctx, ISA_MIPS32R2);
5902 gen_helper_mtc0_pagegrain(cpu_env, arg);
5903 rn = "PageGrain";
5904 ctx->bstate = BS_STOP;
5905 break;
5906 default:
5907 goto cp0_unimplemented;
5909 break;
5910 case 6:
5911 switch (sel) {
5912 case 0:
5913 gen_helper_mtc0_wired(cpu_env, arg);
5914 rn = "Wired";
5915 break;
5916 case 1:
5917 check_insn(ctx, ISA_MIPS32R2);
5918 gen_helper_mtc0_srsconf0(cpu_env, arg);
5919 rn = "SRSConf0";
5920 break;
5921 case 2:
5922 check_insn(ctx, ISA_MIPS32R2);
5923 gen_helper_mtc0_srsconf1(cpu_env, arg);
5924 rn = "SRSConf1";
5925 break;
5926 case 3:
5927 check_insn(ctx, ISA_MIPS32R2);
5928 gen_helper_mtc0_srsconf2(cpu_env, arg);
5929 rn = "SRSConf2";
5930 break;
5931 case 4:
5932 check_insn(ctx, ISA_MIPS32R2);
5933 gen_helper_mtc0_srsconf3(cpu_env, arg);
5934 rn = "SRSConf3";
5935 break;
5936 case 5:
5937 check_insn(ctx, ISA_MIPS32R2);
5938 gen_helper_mtc0_srsconf4(cpu_env, arg);
5939 rn = "SRSConf4";
5940 break;
5941 default:
5942 goto cp0_unimplemented;
5944 break;
5945 case 7:
5946 switch (sel) {
5947 case 0:
5948 check_insn(ctx, ISA_MIPS32R2);
5949 gen_helper_mtc0_hwrena(cpu_env, arg);
5950 ctx->bstate = BS_STOP;
5951 rn = "HWREna";
5952 break;
5953 default:
5954 goto cp0_unimplemented;
5956 break;
5957 case 8:
5958 switch (sel) {
5959 case 0:
5960 /* ignored */
5961 rn = "BadVAddr";
5962 break;
5963 case 1:
5964 /* ignored */
5965 rn = "BadInstr";
5966 break;
5967 case 2:
5968 /* ignored */
5969 rn = "BadInstrP";
5970 break;
5971 default:
5972 goto cp0_unimplemented;
5974 break;
5975 case 9:
5976 switch (sel) {
5977 case 0:
5978 gen_helper_mtc0_count(cpu_env, arg);
5979 rn = "Count";
5980 break;
5981 /* 6,7 are implementation dependent */
5982 default:
5983 goto cp0_unimplemented;
5985 break;
5986 case 10:
5987 switch (sel) {
5988 case 0:
5989 gen_helper_mtc0_entryhi(cpu_env, arg);
5990 rn = "EntryHi";
5991 break;
5992 default:
5993 goto cp0_unimplemented;
5995 break;
5996 case 11:
5997 switch (sel) {
5998 case 0:
5999 gen_helper_mtc0_compare(cpu_env, arg);
6000 rn = "Compare";
6001 break;
6002 /* 6,7 are implementation dependent */
6003 default:
6004 goto cp0_unimplemented;
6006 break;
6007 case 12:
6008 switch (sel) {
6009 case 0:
6010 save_cpu_state(ctx, 1);
6011 gen_helper_mtc0_status(cpu_env, arg);
6012 /* BS_STOP isn't good enough here, hflags may have changed. */
6013 gen_save_pc(ctx->pc + 4);
6014 ctx->bstate = BS_EXCP;
6015 rn = "Status";
6016 break;
6017 case 1:
6018 check_insn(ctx, ISA_MIPS32R2);
6019 gen_helper_mtc0_intctl(cpu_env, arg);
6020 /* Stop translation as we may have switched the execution mode */
6021 ctx->bstate = BS_STOP;
6022 rn = "IntCtl";
6023 break;
6024 case 2:
6025 check_insn(ctx, ISA_MIPS32R2);
6026 gen_helper_mtc0_srsctl(cpu_env, arg);
6027 /* Stop translation as we may have switched the execution mode */
6028 ctx->bstate = BS_STOP;
6029 rn = "SRSCtl";
6030 break;
6031 case 3:
6032 check_insn(ctx, ISA_MIPS32R2);
6033 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6034 /* Stop translation as we may have switched the execution mode */
6035 ctx->bstate = BS_STOP;
6036 rn = "SRSMap";
6037 break;
6038 default:
6039 goto cp0_unimplemented;
6041 break;
6042 case 13:
6043 switch (sel) {
6044 case 0:
6045 save_cpu_state(ctx, 1);
6046 gen_helper_mtc0_cause(cpu_env, arg);
6047 rn = "Cause";
6048 break;
6049 default:
6050 goto cp0_unimplemented;
6052 break;
6053 case 14:
6054 switch (sel) {
6055 case 0:
6056 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
6057 rn = "EPC";
6058 break;
6059 default:
6060 goto cp0_unimplemented;
6062 break;
6063 case 15:
6064 switch (sel) {
6065 case 0:
6066 /* ignored */
6067 rn = "PRid";
6068 break;
6069 case 1:
6070 check_insn(ctx, ISA_MIPS32R2);
6071 gen_helper_mtc0_ebase(cpu_env, arg);
6072 rn = "EBase";
6073 break;
6074 default:
6075 goto cp0_unimplemented;
6077 break;
6078 case 16:
6079 switch (sel) {
6080 case 0:
6081 gen_helper_mtc0_config0(cpu_env, arg);
6082 rn = "Config";
6083 /* Stop translation as we may have switched the execution mode */
6084 ctx->bstate = BS_STOP;
6085 break;
6086 case 1:
6087 /* ignored, read only */
6088 rn = "Config1";
6089 break;
6090 case 2:
6091 gen_helper_mtc0_config2(cpu_env, arg);
6092 rn = "Config2";
6093 /* Stop translation as we may have switched the execution mode */
6094 ctx->bstate = BS_STOP;
6095 break;
6096 case 3:
6097 gen_helper_mtc0_config3(cpu_env, arg);
6098 rn = "Config3";
6099 /* Stop translation as we may have switched the execution mode */
6100 ctx->bstate = BS_STOP;
6101 break;
6102 case 4:
6103 gen_helper_mtc0_config4(cpu_env, arg);
6104 rn = "Config4";
6105 ctx->bstate = BS_STOP;
6106 break;
6107 case 5:
6108 gen_helper_mtc0_config5(cpu_env, arg);
6109 rn = "Config5";
6110 /* Stop translation as we may have switched the execution mode */
6111 ctx->bstate = BS_STOP;
6112 break;
6113 /* 6,7 are implementation dependent */
6114 case 6:
6115 /* ignored */
6116 rn = "Config6";
6117 break;
6118 case 7:
6119 /* ignored */
6120 rn = "Config7";
6121 break;
6122 default:
6123 rn = "Invalid config selector";
6124 goto cp0_unimplemented;
6126 break;
6127 case 17:
6128 switch (sel) {
6129 case 0:
6130 gen_helper_mtc0_lladdr(cpu_env, arg);
6131 rn = "LLAddr";
6132 break;
6133 default:
6134 goto cp0_unimplemented;
6136 break;
6137 case 18:
6138 switch (sel) {
6139 case 0 ... 7:
6140 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6141 rn = "WatchLo";
6142 break;
6143 default:
6144 goto cp0_unimplemented;
6146 break;
6147 case 19:
6148 switch (sel) {
6149 case 0 ... 7:
6150 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6151 rn = "WatchHi";
6152 break;
6153 default:
6154 goto cp0_unimplemented;
6156 break;
6157 case 20:
6158 switch (sel) {
6159 case 0:
6160 #if defined(TARGET_MIPS64)
6161 check_insn(ctx, ISA_MIPS3);
6162 gen_helper_mtc0_xcontext(cpu_env, arg);
6163 rn = "XContext";
6164 break;
6165 #endif
6166 default:
6167 goto cp0_unimplemented;
6169 break;
6170 case 21:
6171 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6172 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6173 switch (sel) {
6174 case 0:
6175 gen_helper_mtc0_framemask(cpu_env, arg);
6176 rn = "Framemask";
6177 break;
6178 default:
6179 goto cp0_unimplemented;
6181 break;
6182 case 22:
6183 /* ignored */
6184 rn = "Diagnostic"; /* implementation dependent */
6185 break;
6186 case 23:
6187 switch (sel) {
6188 case 0:
6189 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6190 /* BS_STOP isn't good enough here, hflags may have changed. */
6191 gen_save_pc(ctx->pc + 4);
6192 ctx->bstate = BS_EXCP;
6193 rn = "Debug";
6194 break;
6195 case 1:
6196 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6197 rn = "TraceControl";
6198 /* Stop translation as we may have switched the execution mode */
6199 ctx->bstate = BS_STOP;
6200 // break;
6201 case 2:
6202 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6203 rn = "TraceControl2";
6204 /* Stop translation as we may have switched the execution mode */
6205 ctx->bstate = BS_STOP;
6206 // break;
6207 case 3:
6208 /* Stop translation as we may have switched the execution mode */
6209 ctx->bstate = BS_STOP;
6210 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6211 rn = "UserTraceData";
6212 /* Stop translation as we may have switched the execution mode */
6213 ctx->bstate = BS_STOP;
6214 // break;
6215 case 4:
6216 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6217 /* Stop translation as we may have switched the execution mode */
6218 ctx->bstate = BS_STOP;
6219 rn = "TraceBPC";
6220 // break;
6221 default:
6222 goto cp0_unimplemented;
6224 break;
6225 case 24:
6226 switch (sel) {
6227 case 0:
6228 /* EJTAG support */
6229 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
6230 rn = "DEPC";
6231 break;
6232 default:
6233 goto cp0_unimplemented;
6235 break;
6236 case 25:
6237 switch (sel) {
6238 case 0:
6239 gen_helper_mtc0_performance0(cpu_env, arg);
6240 rn = "Performance0";
6241 break;
6242 case 1:
6243 // gen_helper_mtc0_performance1(arg);
6244 rn = "Performance1";
6245 // break;
6246 case 2:
6247 // gen_helper_mtc0_performance2(arg);
6248 rn = "Performance2";
6249 // break;
6250 case 3:
6251 // gen_helper_mtc0_performance3(arg);
6252 rn = "Performance3";
6253 // break;
6254 case 4:
6255 // gen_helper_mtc0_performance4(arg);
6256 rn = "Performance4";
6257 // break;
6258 case 5:
6259 // gen_helper_mtc0_performance5(arg);
6260 rn = "Performance5";
6261 // break;
6262 case 6:
6263 // gen_helper_mtc0_performance6(arg);
6264 rn = "Performance6";
6265 // break;
6266 case 7:
6267 // gen_helper_mtc0_performance7(arg);
6268 rn = "Performance7";
6269 // break;
6270 default:
6271 goto cp0_unimplemented;
6273 break;
6274 case 26:
6275 /* ignored */
6276 rn = "ECC";
6277 break;
6278 case 27:
6279 switch (sel) {
6280 case 0 ... 3:
6281 /* ignored */
6282 rn = "CacheErr";
6283 break;
6284 default:
6285 goto cp0_unimplemented;
6287 break;
6288 case 28:
6289 switch (sel) {
6290 case 0:
6291 case 2:
6292 case 4:
6293 case 6:
6294 gen_helper_mtc0_taglo(cpu_env, arg);
6295 rn = "TagLo";
6296 break;
6297 case 1:
6298 case 3:
6299 case 5:
6300 case 7:
6301 gen_helper_mtc0_datalo(cpu_env, arg);
6302 rn = "DataLo";
6303 break;
6304 default:
6305 goto cp0_unimplemented;
6307 break;
6308 case 29:
6309 switch (sel) {
6310 case 0:
6311 case 2:
6312 case 4:
6313 case 6:
6314 gen_helper_mtc0_taghi(cpu_env, arg);
6315 rn = "TagHi";
6316 break;
6317 case 1:
6318 case 3:
6319 case 5:
6320 case 7:
6321 gen_helper_mtc0_datahi(cpu_env, arg);
6322 rn = "DataHi";
6323 break;
6324 default:
6325 rn = "invalid sel";
6326 goto cp0_unimplemented;
6328 break;
6329 case 30:
6330 switch (sel) {
6331 case 0:
6332 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
6333 rn = "ErrorEPC";
6334 break;
6335 default:
6336 goto cp0_unimplemented;
6338 break;
6339 case 31:
6340 switch (sel) {
6341 case 0:
6342 /* EJTAG support */
6343 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6344 rn = "DESAVE";
6345 break;
6346 case 2 ... 7:
6347 CP0_CHECK(ctx->kscrexist & (1 << sel));
6348 tcg_gen_st_tl(arg, cpu_env,
6349 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6350 rn = "KScratch";
6351 break;
6352 default:
6353 goto cp0_unimplemented;
6355 /* Stop translation as we may have switched the execution mode */
6356 ctx->bstate = BS_STOP;
6357 break;
6358 default:
6359 goto cp0_unimplemented;
6361 (void)rn; /* avoid a compiler warning */
6362 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6363 /* For simplicity assume that all writes can cause interrupts. */
6364 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6365 gen_io_end();
6366 ctx->bstate = BS_STOP;
6368 return;
6370 cp0_unimplemented:
6371 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6374 #if defined(TARGET_MIPS64)
6375 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6377 const char *rn = "invalid";
6379 if (sel != 0)
6380 check_insn(ctx, ISA_MIPS64);
6382 switch (reg) {
6383 case 0:
6384 switch (sel) {
6385 case 0:
6386 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6387 rn = "Index";
6388 break;
6389 case 1:
6390 CP0_CHECK(ctx->insn_flags & ASE_MT);
6391 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6392 rn = "MVPControl";
6393 break;
6394 case 2:
6395 CP0_CHECK(ctx->insn_flags & ASE_MT);
6396 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6397 rn = "MVPConf0";
6398 break;
6399 case 3:
6400 CP0_CHECK(ctx->insn_flags & ASE_MT);
6401 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6402 rn = "MVPConf1";
6403 break;
6404 default:
6405 goto cp0_unimplemented;
6407 break;
6408 case 1:
6409 switch (sel) {
6410 case 0:
6411 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6412 gen_helper_mfc0_random(arg, cpu_env);
6413 rn = "Random";
6414 break;
6415 case 1:
6416 CP0_CHECK(ctx->insn_flags & ASE_MT);
6417 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6418 rn = "VPEControl";
6419 break;
6420 case 2:
6421 CP0_CHECK(ctx->insn_flags & ASE_MT);
6422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6423 rn = "VPEConf0";
6424 break;
6425 case 3:
6426 CP0_CHECK(ctx->insn_flags & ASE_MT);
6427 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6428 rn = "VPEConf1";
6429 break;
6430 case 4:
6431 CP0_CHECK(ctx->insn_flags & ASE_MT);
6432 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6433 rn = "YQMask";
6434 break;
6435 case 5:
6436 CP0_CHECK(ctx->insn_flags & ASE_MT);
6437 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6438 rn = "VPESchedule";
6439 break;
6440 case 6:
6441 CP0_CHECK(ctx->insn_flags & ASE_MT);
6442 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6443 rn = "VPEScheFBack";
6444 break;
6445 case 7:
6446 CP0_CHECK(ctx->insn_flags & ASE_MT);
6447 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6448 rn = "VPEOpt";
6449 break;
6450 default:
6451 goto cp0_unimplemented;
6453 break;
6454 case 2:
6455 switch (sel) {
6456 case 0:
6457 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6458 rn = "EntryLo0";
6459 break;
6460 case 1:
6461 CP0_CHECK(ctx->insn_flags & ASE_MT);
6462 gen_helper_mfc0_tcstatus(arg, cpu_env);
6463 rn = "TCStatus";
6464 break;
6465 case 2:
6466 CP0_CHECK(ctx->insn_flags & ASE_MT);
6467 gen_helper_mfc0_tcbind(arg, cpu_env);
6468 rn = "TCBind";
6469 break;
6470 case 3:
6471 CP0_CHECK(ctx->insn_flags & ASE_MT);
6472 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6473 rn = "TCRestart";
6474 break;
6475 case 4:
6476 CP0_CHECK(ctx->insn_flags & ASE_MT);
6477 gen_helper_dmfc0_tchalt(arg, cpu_env);
6478 rn = "TCHalt";
6479 break;
6480 case 5:
6481 CP0_CHECK(ctx->insn_flags & ASE_MT);
6482 gen_helper_dmfc0_tccontext(arg, cpu_env);
6483 rn = "TCContext";
6484 break;
6485 case 6:
6486 CP0_CHECK(ctx->insn_flags & ASE_MT);
6487 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6488 rn = "TCSchedule";
6489 break;
6490 case 7:
6491 CP0_CHECK(ctx->insn_flags & ASE_MT);
6492 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6493 rn = "TCScheFBack";
6494 break;
6495 default:
6496 goto cp0_unimplemented;
6498 break;
6499 case 3:
6500 switch (sel) {
6501 case 0:
6502 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6503 rn = "EntryLo1";
6504 break;
6505 default:
6506 goto cp0_unimplemented;
6508 break;
6509 case 4:
6510 switch (sel) {
6511 case 0:
6512 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6513 rn = "Context";
6514 break;
6515 case 1:
6516 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6517 rn = "ContextConfig";
6518 goto cp0_unimplemented;
6519 // break;
6520 case 2:
6521 CP0_CHECK(ctx->ulri);
6522 tcg_gen_ld_tl(arg, cpu_env,
6523 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6524 rn = "UserLocal";
6525 break;
6526 default:
6527 goto cp0_unimplemented;
6529 break;
6530 case 5:
6531 switch (sel) {
6532 case 0:
6533 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6534 rn = "PageMask";
6535 break;
6536 case 1:
6537 check_insn(ctx, ISA_MIPS32R2);
6538 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6539 rn = "PageGrain";
6540 break;
6541 default:
6542 goto cp0_unimplemented;
6544 break;
6545 case 6:
6546 switch (sel) {
6547 case 0:
6548 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6549 rn = "Wired";
6550 break;
6551 case 1:
6552 check_insn(ctx, ISA_MIPS32R2);
6553 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6554 rn = "SRSConf0";
6555 break;
6556 case 2:
6557 check_insn(ctx, ISA_MIPS32R2);
6558 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6559 rn = "SRSConf1";
6560 break;
6561 case 3:
6562 check_insn(ctx, ISA_MIPS32R2);
6563 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6564 rn = "SRSConf2";
6565 break;
6566 case 4:
6567 check_insn(ctx, ISA_MIPS32R2);
6568 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6569 rn = "SRSConf3";
6570 break;
6571 case 5:
6572 check_insn(ctx, ISA_MIPS32R2);
6573 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6574 rn = "SRSConf4";
6575 break;
6576 default:
6577 goto cp0_unimplemented;
6579 break;
6580 case 7:
6581 switch (sel) {
6582 case 0:
6583 check_insn(ctx, ISA_MIPS32R2);
6584 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6585 rn = "HWREna";
6586 break;
6587 default:
6588 goto cp0_unimplemented;
6590 break;
6591 case 8:
6592 switch (sel) {
6593 case 0:
6594 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6595 rn = "BadVAddr";
6596 break;
6597 case 1:
6598 CP0_CHECK(ctx->bi);
6599 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6600 rn = "BadInstr";
6601 break;
6602 case 2:
6603 CP0_CHECK(ctx->bp);
6604 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6605 rn = "BadInstrP";
6606 break;
6607 default:
6608 goto cp0_unimplemented;
6610 break;
6611 case 9:
6612 switch (sel) {
6613 case 0:
6614 /* Mark as an IO operation because we read the time. */
6615 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6616 gen_io_start();
6618 gen_helper_mfc0_count(arg, cpu_env);
6619 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6620 gen_io_end();
6622 /* Break the TB to be able to take timer interrupts immediately
6623 after reading count. */
6624 ctx->bstate = BS_STOP;
6625 rn = "Count";
6626 break;
6627 /* 6,7 are implementation dependent */
6628 default:
6629 goto cp0_unimplemented;
6631 break;
6632 case 10:
6633 switch (sel) {
6634 case 0:
6635 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6636 rn = "EntryHi";
6637 break;
6638 default:
6639 goto cp0_unimplemented;
6641 break;
6642 case 11:
6643 switch (sel) {
6644 case 0:
6645 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6646 rn = "Compare";
6647 break;
6648 /* 6,7 are implementation dependent */
6649 default:
6650 goto cp0_unimplemented;
6652 break;
6653 case 12:
6654 switch (sel) {
6655 case 0:
6656 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6657 rn = "Status";
6658 break;
6659 case 1:
6660 check_insn(ctx, ISA_MIPS32R2);
6661 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6662 rn = "IntCtl";
6663 break;
6664 case 2:
6665 check_insn(ctx, ISA_MIPS32R2);
6666 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6667 rn = "SRSCtl";
6668 break;
6669 case 3:
6670 check_insn(ctx, ISA_MIPS32R2);
6671 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6672 rn = "SRSMap";
6673 break;
6674 default:
6675 goto cp0_unimplemented;
6677 break;
6678 case 13:
6679 switch (sel) {
6680 case 0:
6681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6682 rn = "Cause";
6683 break;
6684 default:
6685 goto cp0_unimplemented;
6687 break;
6688 case 14:
6689 switch (sel) {
6690 case 0:
6691 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6692 rn = "EPC";
6693 break;
6694 default:
6695 goto cp0_unimplemented;
6697 break;
6698 case 15:
6699 switch (sel) {
6700 case 0:
6701 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6702 rn = "PRid";
6703 break;
6704 case 1:
6705 check_insn(ctx, ISA_MIPS32R2);
6706 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6707 rn = "EBase";
6708 break;
6709 default:
6710 goto cp0_unimplemented;
6712 break;
6713 case 16:
6714 switch (sel) {
6715 case 0:
6716 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6717 rn = "Config";
6718 break;
6719 case 1:
6720 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6721 rn = "Config1";
6722 break;
6723 case 2:
6724 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6725 rn = "Config2";
6726 break;
6727 case 3:
6728 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6729 rn = "Config3";
6730 break;
6731 case 4:
6732 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6733 rn = "Config4";
6734 break;
6735 case 5:
6736 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6737 rn = "Config5";
6738 break;
6739 /* 6,7 are implementation dependent */
6740 case 6:
6741 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6742 rn = "Config6";
6743 break;
6744 case 7:
6745 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6746 rn = "Config7";
6747 break;
6748 default:
6749 goto cp0_unimplemented;
6751 break;
6752 case 17:
6753 switch (sel) {
6754 case 0:
6755 gen_helper_dmfc0_lladdr(arg, cpu_env);
6756 rn = "LLAddr";
6757 break;
6758 default:
6759 goto cp0_unimplemented;
6761 break;
6762 case 18:
6763 switch (sel) {
6764 case 0 ... 7:
6765 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6766 rn = "WatchLo";
6767 break;
6768 default:
6769 goto cp0_unimplemented;
6771 break;
6772 case 19:
6773 switch (sel) {
6774 case 0 ... 7:
6775 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6776 rn = "WatchHi";
6777 break;
6778 default:
6779 goto cp0_unimplemented;
6781 break;
6782 case 20:
6783 switch (sel) {
6784 case 0:
6785 check_insn(ctx, ISA_MIPS3);
6786 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6787 rn = "XContext";
6788 break;
6789 default:
6790 goto cp0_unimplemented;
6792 break;
6793 case 21:
6794 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6795 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6796 switch (sel) {
6797 case 0:
6798 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6799 rn = "Framemask";
6800 break;
6801 default:
6802 goto cp0_unimplemented;
6804 break;
6805 case 22:
6806 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6807 rn = "'Diagnostic"; /* implementation dependent */
6808 break;
6809 case 23:
6810 switch (sel) {
6811 case 0:
6812 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6813 rn = "Debug";
6814 break;
6815 case 1:
6816 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6817 rn = "TraceControl";
6818 // break;
6819 case 2:
6820 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6821 rn = "TraceControl2";
6822 // break;
6823 case 3:
6824 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6825 rn = "UserTraceData";
6826 // break;
6827 case 4:
6828 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6829 rn = "TraceBPC";
6830 // break;
6831 default:
6832 goto cp0_unimplemented;
6834 break;
6835 case 24:
6836 switch (sel) {
6837 case 0:
6838 /* EJTAG support */
6839 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6840 rn = "DEPC";
6841 break;
6842 default:
6843 goto cp0_unimplemented;
6845 break;
6846 case 25:
6847 switch (sel) {
6848 case 0:
6849 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6850 rn = "Performance0";
6851 break;
6852 case 1:
6853 // gen_helper_dmfc0_performance1(arg);
6854 rn = "Performance1";
6855 // break;
6856 case 2:
6857 // gen_helper_dmfc0_performance2(arg);
6858 rn = "Performance2";
6859 // break;
6860 case 3:
6861 // gen_helper_dmfc0_performance3(arg);
6862 rn = "Performance3";
6863 // break;
6864 case 4:
6865 // gen_helper_dmfc0_performance4(arg);
6866 rn = "Performance4";
6867 // break;
6868 case 5:
6869 // gen_helper_dmfc0_performance5(arg);
6870 rn = "Performance5";
6871 // break;
6872 case 6:
6873 // gen_helper_dmfc0_performance6(arg);
6874 rn = "Performance6";
6875 // break;
6876 case 7:
6877 // gen_helper_dmfc0_performance7(arg);
6878 rn = "Performance7";
6879 // break;
6880 default:
6881 goto cp0_unimplemented;
6883 break;
6884 case 26:
6885 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6886 rn = "ECC";
6887 break;
6888 case 27:
6889 switch (sel) {
6890 /* ignored */
6891 case 0 ... 3:
6892 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6893 rn = "CacheErr";
6894 break;
6895 default:
6896 goto cp0_unimplemented;
6898 break;
6899 case 28:
6900 switch (sel) {
6901 case 0:
6902 case 2:
6903 case 4:
6904 case 6:
6905 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
6906 rn = "TagLo";
6907 break;
6908 case 1:
6909 case 3:
6910 case 5:
6911 case 7:
6912 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6913 rn = "DataLo";
6914 break;
6915 default:
6916 goto cp0_unimplemented;
6918 break;
6919 case 29:
6920 switch (sel) {
6921 case 0:
6922 case 2:
6923 case 4:
6924 case 6:
6925 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6926 rn = "TagHi";
6927 break;
6928 case 1:
6929 case 3:
6930 case 5:
6931 case 7:
6932 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6933 rn = "DataHi";
6934 break;
6935 default:
6936 goto cp0_unimplemented;
6938 break;
6939 case 30:
6940 switch (sel) {
6941 case 0:
6942 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6943 rn = "ErrorEPC";
6944 break;
6945 default:
6946 goto cp0_unimplemented;
6948 break;
6949 case 31:
6950 switch (sel) {
6951 case 0:
6952 /* EJTAG support */
6953 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6954 rn = "DESAVE";
6955 break;
6956 case 2 ... 7:
6957 CP0_CHECK(ctx->kscrexist & (1 << sel));
6958 tcg_gen_ld_tl(arg, cpu_env,
6959 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6960 rn = "KScratch";
6961 break;
6962 default:
6963 goto cp0_unimplemented;
6965 break;
6966 default:
6967 goto cp0_unimplemented;
6969 (void)rn; /* avoid a compiler warning */
6970 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6971 return;
6973 cp0_unimplemented:
6974 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6975 gen_mfc0_unimplemented(ctx, arg);
6978 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6980 const char *rn = "invalid";
6982 if (sel != 0)
6983 check_insn(ctx, ISA_MIPS64);
6985 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6986 gen_io_start();
6989 switch (reg) {
6990 case 0:
6991 switch (sel) {
6992 case 0:
6993 gen_helper_mtc0_index(cpu_env, arg);
6994 rn = "Index";
6995 break;
6996 case 1:
6997 CP0_CHECK(ctx->insn_flags & ASE_MT);
6998 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6999 rn = "MVPControl";
7000 break;
7001 case 2:
7002 CP0_CHECK(ctx->insn_flags & ASE_MT);
7003 /* ignored */
7004 rn = "MVPConf0";
7005 break;
7006 case 3:
7007 CP0_CHECK(ctx->insn_flags & ASE_MT);
7008 /* ignored */
7009 rn = "MVPConf1";
7010 break;
7011 default:
7012 goto cp0_unimplemented;
7014 break;
7015 case 1:
7016 switch (sel) {
7017 case 0:
7018 /* ignored */
7019 rn = "Random";
7020 break;
7021 case 1:
7022 CP0_CHECK(ctx->insn_flags & ASE_MT);
7023 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7024 rn = "VPEControl";
7025 break;
7026 case 2:
7027 CP0_CHECK(ctx->insn_flags & ASE_MT);
7028 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7029 rn = "VPEConf0";
7030 break;
7031 case 3:
7032 CP0_CHECK(ctx->insn_flags & ASE_MT);
7033 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7034 rn = "VPEConf1";
7035 break;
7036 case 4:
7037 CP0_CHECK(ctx->insn_flags & ASE_MT);
7038 gen_helper_mtc0_yqmask(cpu_env, arg);
7039 rn = "YQMask";
7040 break;
7041 case 5:
7042 CP0_CHECK(ctx->insn_flags & ASE_MT);
7043 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7044 rn = "VPESchedule";
7045 break;
7046 case 6:
7047 CP0_CHECK(ctx->insn_flags & ASE_MT);
7048 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7049 rn = "VPEScheFBack";
7050 break;
7051 case 7:
7052 CP0_CHECK(ctx->insn_flags & ASE_MT);
7053 gen_helper_mtc0_vpeopt(cpu_env, arg);
7054 rn = "VPEOpt";
7055 break;
7056 default:
7057 goto cp0_unimplemented;
7059 break;
7060 case 2:
7061 switch (sel) {
7062 case 0:
7063 gen_helper_dmtc0_entrylo0(cpu_env, arg);
7064 rn = "EntryLo0";
7065 break;
7066 case 1:
7067 CP0_CHECK(ctx->insn_flags & ASE_MT);
7068 gen_helper_mtc0_tcstatus(cpu_env, arg);
7069 rn = "TCStatus";
7070 break;
7071 case 2:
7072 CP0_CHECK(ctx->insn_flags & ASE_MT);
7073 gen_helper_mtc0_tcbind(cpu_env, arg);
7074 rn = "TCBind";
7075 break;
7076 case 3:
7077 CP0_CHECK(ctx->insn_flags & ASE_MT);
7078 gen_helper_mtc0_tcrestart(cpu_env, arg);
7079 rn = "TCRestart";
7080 break;
7081 case 4:
7082 CP0_CHECK(ctx->insn_flags & ASE_MT);
7083 gen_helper_mtc0_tchalt(cpu_env, arg);
7084 rn = "TCHalt";
7085 break;
7086 case 5:
7087 CP0_CHECK(ctx->insn_flags & ASE_MT);
7088 gen_helper_mtc0_tccontext(cpu_env, arg);
7089 rn = "TCContext";
7090 break;
7091 case 6:
7092 CP0_CHECK(ctx->insn_flags & ASE_MT);
7093 gen_helper_mtc0_tcschedule(cpu_env, arg);
7094 rn = "TCSchedule";
7095 break;
7096 case 7:
7097 CP0_CHECK(ctx->insn_flags & ASE_MT);
7098 gen_helper_mtc0_tcschefback(cpu_env, arg);
7099 rn = "TCScheFBack";
7100 break;
7101 default:
7102 goto cp0_unimplemented;
7104 break;
7105 case 3:
7106 switch (sel) {
7107 case 0:
7108 gen_helper_dmtc0_entrylo1(cpu_env, arg);
7109 rn = "EntryLo1";
7110 break;
7111 default:
7112 goto cp0_unimplemented;
7114 break;
7115 case 4:
7116 switch (sel) {
7117 case 0:
7118 gen_helper_mtc0_context(cpu_env, arg);
7119 rn = "Context";
7120 break;
7121 case 1:
7122 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7123 rn = "ContextConfig";
7124 goto cp0_unimplemented;
7125 // break;
7126 case 2:
7127 CP0_CHECK(ctx->ulri);
7128 tcg_gen_st_tl(arg, cpu_env,
7129 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7130 rn = "UserLocal";
7131 break;
7132 default:
7133 goto cp0_unimplemented;
7135 break;
7136 case 5:
7137 switch (sel) {
7138 case 0:
7139 gen_helper_mtc0_pagemask(cpu_env, arg);
7140 rn = "PageMask";
7141 break;
7142 case 1:
7143 check_insn(ctx, ISA_MIPS32R2);
7144 gen_helper_mtc0_pagegrain(cpu_env, arg);
7145 rn = "PageGrain";
7146 break;
7147 default:
7148 goto cp0_unimplemented;
7150 break;
7151 case 6:
7152 switch (sel) {
7153 case 0:
7154 gen_helper_mtc0_wired(cpu_env, arg);
7155 rn = "Wired";
7156 break;
7157 case 1:
7158 check_insn(ctx, ISA_MIPS32R2);
7159 gen_helper_mtc0_srsconf0(cpu_env, arg);
7160 rn = "SRSConf0";
7161 break;
7162 case 2:
7163 check_insn(ctx, ISA_MIPS32R2);
7164 gen_helper_mtc0_srsconf1(cpu_env, arg);
7165 rn = "SRSConf1";
7166 break;
7167 case 3:
7168 check_insn(ctx, ISA_MIPS32R2);
7169 gen_helper_mtc0_srsconf2(cpu_env, arg);
7170 rn = "SRSConf2";
7171 break;
7172 case 4:
7173 check_insn(ctx, ISA_MIPS32R2);
7174 gen_helper_mtc0_srsconf3(cpu_env, arg);
7175 rn = "SRSConf3";
7176 break;
7177 case 5:
7178 check_insn(ctx, ISA_MIPS32R2);
7179 gen_helper_mtc0_srsconf4(cpu_env, arg);
7180 rn = "SRSConf4";
7181 break;
7182 default:
7183 goto cp0_unimplemented;
7185 break;
7186 case 7:
7187 switch (sel) {
7188 case 0:
7189 check_insn(ctx, ISA_MIPS32R2);
7190 gen_helper_mtc0_hwrena(cpu_env, arg);
7191 ctx->bstate = BS_STOP;
7192 rn = "HWREna";
7193 break;
7194 default:
7195 goto cp0_unimplemented;
7197 break;
7198 case 8:
7199 switch (sel) {
7200 case 0:
7201 /* ignored */
7202 rn = "BadVAddr";
7203 break;
7204 case 1:
7205 /* ignored */
7206 rn = "BadInstr";
7207 break;
7208 case 2:
7209 /* ignored */
7210 rn = "BadInstrP";
7211 break;
7212 default:
7213 goto cp0_unimplemented;
7215 break;
7216 case 9:
7217 switch (sel) {
7218 case 0:
7219 gen_helper_mtc0_count(cpu_env, arg);
7220 rn = "Count";
7221 break;
7222 /* 6,7 are implementation dependent */
7223 default:
7224 goto cp0_unimplemented;
7226 /* Stop translation as we may have switched the execution mode */
7227 ctx->bstate = BS_STOP;
7228 break;
7229 case 10:
7230 switch (sel) {
7231 case 0:
7232 gen_helper_mtc0_entryhi(cpu_env, arg);
7233 rn = "EntryHi";
7234 break;
7235 default:
7236 goto cp0_unimplemented;
7238 break;
7239 case 11:
7240 switch (sel) {
7241 case 0:
7242 gen_helper_mtc0_compare(cpu_env, arg);
7243 rn = "Compare";
7244 break;
7245 /* 6,7 are implementation dependent */
7246 default:
7247 goto cp0_unimplemented;
7249 /* Stop translation as we may have switched the execution mode */
7250 ctx->bstate = BS_STOP;
7251 break;
7252 case 12:
7253 switch (sel) {
7254 case 0:
7255 save_cpu_state(ctx, 1);
7256 gen_helper_mtc0_status(cpu_env, arg);
7257 /* BS_STOP isn't good enough here, hflags may have changed. */
7258 gen_save_pc(ctx->pc + 4);
7259 ctx->bstate = BS_EXCP;
7260 rn = "Status";
7261 break;
7262 case 1:
7263 check_insn(ctx, ISA_MIPS32R2);
7264 gen_helper_mtc0_intctl(cpu_env, arg);
7265 /* Stop translation as we may have switched the execution mode */
7266 ctx->bstate = BS_STOP;
7267 rn = "IntCtl";
7268 break;
7269 case 2:
7270 check_insn(ctx, ISA_MIPS32R2);
7271 gen_helper_mtc0_srsctl(cpu_env, arg);
7272 /* Stop translation as we may have switched the execution mode */
7273 ctx->bstate = BS_STOP;
7274 rn = "SRSCtl";
7275 break;
7276 case 3:
7277 check_insn(ctx, ISA_MIPS32R2);
7278 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7279 /* Stop translation as we may have switched the execution mode */
7280 ctx->bstate = BS_STOP;
7281 rn = "SRSMap";
7282 break;
7283 default:
7284 goto cp0_unimplemented;
7286 break;
7287 case 13:
7288 switch (sel) {
7289 case 0:
7290 save_cpu_state(ctx, 1);
7291 /* Mark as an IO operation because we may trigger a software
7292 interrupt. */
7293 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7294 gen_io_start();
7296 gen_helper_mtc0_cause(cpu_env, arg);
7297 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7298 gen_io_end();
7300 /* Stop translation as we may have triggered an intetrupt */
7301 ctx->bstate = BS_STOP;
7302 rn = "Cause";
7303 break;
7304 default:
7305 goto cp0_unimplemented;
7307 break;
7308 case 14:
7309 switch (sel) {
7310 case 0:
7311 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7312 rn = "EPC";
7313 break;
7314 default:
7315 goto cp0_unimplemented;
7317 break;
7318 case 15:
7319 switch (sel) {
7320 case 0:
7321 /* ignored */
7322 rn = "PRid";
7323 break;
7324 case 1:
7325 check_insn(ctx, ISA_MIPS32R2);
7326 gen_helper_mtc0_ebase(cpu_env, arg);
7327 rn = "EBase";
7328 break;
7329 default:
7330 goto cp0_unimplemented;
7332 break;
7333 case 16:
7334 switch (sel) {
7335 case 0:
7336 gen_helper_mtc0_config0(cpu_env, arg);
7337 rn = "Config";
7338 /* Stop translation as we may have switched the execution mode */
7339 ctx->bstate = BS_STOP;
7340 break;
7341 case 1:
7342 /* ignored, read only */
7343 rn = "Config1";
7344 break;
7345 case 2:
7346 gen_helper_mtc0_config2(cpu_env, arg);
7347 rn = "Config2";
7348 /* Stop translation as we may have switched the execution mode */
7349 ctx->bstate = BS_STOP;
7350 break;
7351 case 3:
7352 gen_helper_mtc0_config3(cpu_env, arg);
7353 rn = "Config3";
7354 /* Stop translation as we may have switched the execution mode */
7355 ctx->bstate = BS_STOP;
7356 break;
7357 case 4:
7358 /* currently ignored */
7359 rn = "Config4";
7360 break;
7361 case 5:
7362 gen_helper_mtc0_config5(cpu_env, arg);
7363 rn = "Config5";
7364 /* Stop translation as we may have switched the execution mode */
7365 ctx->bstate = BS_STOP;
7366 break;
7367 /* 6,7 are implementation dependent */
7368 default:
7369 rn = "Invalid config selector";
7370 goto cp0_unimplemented;
7372 break;
7373 case 17:
7374 switch (sel) {
7375 case 0:
7376 gen_helper_mtc0_lladdr(cpu_env, arg);
7377 rn = "LLAddr";
7378 break;
7379 default:
7380 goto cp0_unimplemented;
7382 break;
7383 case 18:
7384 switch (sel) {
7385 case 0 ... 7:
7386 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7387 rn = "WatchLo";
7388 break;
7389 default:
7390 goto cp0_unimplemented;
7392 break;
7393 case 19:
7394 switch (sel) {
7395 case 0 ... 7:
7396 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7397 rn = "WatchHi";
7398 break;
7399 default:
7400 goto cp0_unimplemented;
7402 break;
7403 case 20:
7404 switch (sel) {
7405 case 0:
7406 check_insn(ctx, ISA_MIPS3);
7407 gen_helper_mtc0_xcontext(cpu_env, arg);
7408 rn = "XContext";
7409 break;
7410 default:
7411 goto cp0_unimplemented;
7413 break;
7414 case 21:
7415 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7416 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7417 switch (sel) {
7418 case 0:
7419 gen_helper_mtc0_framemask(cpu_env, arg);
7420 rn = "Framemask";
7421 break;
7422 default:
7423 goto cp0_unimplemented;
7425 break;
7426 case 22:
7427 /* ignored */
7428 rn = "Diagnostic"; /* implementation dependent */
7429 break;
7430 case 23:
7431 switch (sel) {
7432 case 0:
7433 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7434 /* BS_STOP isn't good enough here, hflags may have changed. */
7435 gen_save_pc(ctx->pc + 4);
7436 ctx->bstate = BS_EXCP;
7437 rn = "Debug";
7438 break;
7439 case 1:
7440 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7441 /* Stop translation as we may have switched the execution mode */
7442 ctx->bstate = BS_STOP;
7443 rn = "TraceControl";
7444 // break;
7445 case 2:
7446 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7447 /* Stop translation as we may have switched the execution mode */
7448 ctx->bstate = BS_STOP;
7449 rn = "TraceControl2";
7450 // break;
7451 case 3:
7452 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7453 /* Stop translation as we may have switched the execution mode */
7454 ctx->bstate = BS_STOP;
7455 rn = "UserTraceData";
7456 // break;
7457 case 4:
7458 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7459 /* Stop translation as we may have switched the execution mode */
7460 ctx->bstate = BS_STOP;
7461 rn = "TraceBPC";
7462 // break;
7463 default:
7464 goto cp0_unimplemented;
7466 break;
7467 case 24:
7468 switch (sel) {
7469 case 0:
7470 /* EJTAG support */
7471 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7472 rn = "DEPC";
7473 break;
7474 default:
7475 goto cp0_unimplemented;
7477 break;
7478 case 25:
7479 switch (sel) {
7480 case 0:
7481 gen_helper_mtc0_performance0(cpu_env, arg);
7482 rn = "Performance0";
7483 break;
7484 case 1:
7485 // gen_helper_mtc0_performance1(cpu_env, arg);
7486 rn = "Performance1";
7487 // break;
7488 case 2:
7489 // gen_helper_mtc0_performance2(cpu_env, arg);
7490 rn = "Performance2";
7491 // break;
7492 case 3:
7493 // gen_helper_mtc0_performance3(cpu_env, arg);
7494 rn = "Performance3";
7495 // break;
7496 case 4:
7497 // gen_helper_mtc0_performance4(cpu_env, arg);
7498 rn = "Performance4";
7499 // break;
7500 case 5:
7501 // gen_helper_mtc0_performance5(cpu_env, arg);
7502 rn = "Performance5";
7503 // break;
7504 case 6:
7505 // gen_helper_mtc0_performance6(cpu_env, arg);
7506 rn = "Performance6";
7507 // break;
7508 case 7:
7509 // gen_helper_mtc0_performance7(cpu_env, arg);
7510 rn = "Performance7";
7511 // break;
7512 default:
7513 goto cp0_unimplemented;
7515 break;
7516 case 26:
7517 /* ignored */
7518 rn = "ECC";
7519 break;
7520 case 27:
7521 switch (sel) {
7522 case 0 ... 3:
7523 /* ignored */
7524 rn = "CacheErr";
7525 break;
7526 default:
7527 goto cp0_unimplemented;
7529 break;
7530 case 28:
7531 switch (sel) {
7532 case 0:
7533 case 2:
7534 case 4:
7535 case 6:
7536 gen_helper_mtc0_taglo(cpu_env, arg);
7537 rn = "TagLo";
7538 break;
7539 case 1:
7540 case 3:
7541 case 5:
7542 case 7:
7543 gen_helper_mtc0_datalo(cpu_env, arg);
7544 rn = "DataLo";
7545 break;
7546 default:
7547 goto cp0_unimplemented;
7549 break;
7550 case 29:
7551 switch (sel) {
7552 case 0:
7553 case 2:
7554 case 4:
7555 case 6:
7556 gen_helper_mtc0_taghi(cpu_env, arg);
7557 rn = "TagHi";
7558 break;
7559 case 1:
7560 case 3:
7561 case 5:
7562 case 7:
7563 gen_helper_mtc0_datahi(cpu_env, arg);
7564 rn = "DataHi";
7565 break;
7566 default:
7567 rn = "invalid sel";
7568 goto cp0_unimplemented;
7570 break;
7571 case 30:
7572 switch (sel) {
7573 case 0:
7574 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7575 rn = "ErrorEPC";
7576 break;
7577 default:
7578 goto cp0_unimplemented;
7580 break;
7581 case 31:
7582 switch (sel) {
7583 case 0:
7584 /* EJTAG support */
7585 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7586 rn = "DESAVE";
7587 break;
7588 case 2 ... 7:
7589 CP0_CHECK(ctx->kscrexist & (1 << sel));
7590 tcg_gen_st_tl(arg, cpu_env,
7591 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7592 rn = "KScratch";
7593 break;
7594 default:
7595 goto cp0_unimplemented;
7597 /* Stop translation as we may have switched the execution mode */
7598 ctx->bstate = BS_STOP;
7599 break;
7600 default:
7601 goto cp0_unimplemented;
7603 (void)rn; /* avoid a compiler warning */
7604 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7605 /* For simplicity assume that all writes can cause interrupts. */
7606 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7607 gen_io_end();
7608 ctx->bstate = BS_STOP;
7610 return;
7612 cp0_unimplemented:
7613 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7615 #endif /* TARGET_MIPS64 */
7617 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7618 int u, int sel, int h)
7620 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7621 TCGv t0 = tcg_temp_local_new();
7623 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7624 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7625 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7626 tcg_gen_movi_tl(t0, -1);
7627 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7628 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7629 tcg_gen_movi_tl(t0, -1);
7630 else if (u == 0) {
7631 switch (rt) {
7632 case 1:
7633 switch (sel) {
7634 case 1:
7635 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7636 break;
7637 case 2:
7638 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7639 break;
7640 default:
7641 goto die;
7642 break;
7644 break;
7645 case 2:
7646 switch (sel) {
7647 case 1:
7648 gen_helper_mftc0_tcstatus(t0, cpu_env);
7649 break;
7650 case 2:
7651 gen_helper_mftc0_tcbind(t0, cpu_env);
7652 break;
7653 case 3:
7654 gen_helper_mftc0_tcrestart(t0, cpu_env);
7655 break;
7656 case 4:
7657 gen_helper_mftc0_tchalt(t0, cpu_env);
7658 break;
7659 case 5:
7660 gen_helper_mftc0_tccontext(t0, cpu_env);
7661 break;
7662 case 6:
7663 gen_helper_mftc0_tcschedule(t0, cpu_env);
7664 break;
7665 case 7:
7666 gen_helper_mftc0_tcschefback(t0, cpu_env);
7667 break;
7668 default:
7669 gen_mfc0(ctx, t0, rt, sel);
7670 break;
7672 break;
7673 case 10:
7674 switch (sel) {
7675 case 0:
7676 gen_helper_mftc0_entryhi(t0, cpu_env);
7677 break;
7678 default:
7679 gen_mfc0(ctx, t0, rt, sel);
7680 break;
7682 case 12:
7683 switch (sel) {
7684 case 0:
7685 gen_helper_mftc0_status(t0, cpu_env);
7686 break;
7687 default:
7688 gen_mfc0(ctx, t0, rt, sel);
7689 break;
7691 case 13:
7692 switch (sel) {
7693 case 0:
7694 gen_helper_mftc0_cause(t0, cpu_env);
7695 break;
7696 default:
7697 goto die;
7698 break;
7700 break;
7701 case 14:
7702 switch (sel) {
7703 case 0:
7704 gen_helper_mftc0_epc(t0, cpu_env);
7705 break;
7706 default:
7707 goto die;
7708 break;
7710 break;
7711 case 15:
7712 switch (sel) {
7713 case 1:
7714 gen_helper_mftc0_ebase(t0, cpu_env);
7715 break;
7716 default:
7717 goto die;
7718 break;
7720 break;
7721 case 16:
7722 switch (sel) {
7723 case 0 ... 7:
7724 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7725 break;
7726 default:
7727 goto die;
7728 break;
7730 break;
7731 case 23:
7732 switch (sel) {
7733 case 0:
7734 gen_helper_mftc0_debug(t0, cpu_env);
7735 break;
7736 default:
7737 gen_mfc0(ctx, t0, rt, sel);
7738 break;
7740 break;
7741 default:
7742 gen_mfc0(ctx, t0, rt, sel);
7744 } else switch (sel) {
7745 /* GPR registers. */
7746 case 0:
7747 gen_helper_1e0i(mftgpr, t0, rt);
7748 break;
7749 /* Auxiliary CPU registers */
7750 case 1:
7751 switch (rt) {
7752 case 0:
7753 gen_helper_1e0i(mftlo, t0, 0);
7754 break;
7755 case 1:
7756 gen_helper_1e0i(mfthi, t0, 0);
7757 break;
7758 case 2:
7759 gen_helper_1e0i(mftacx, t0, 0);
7760 break;
7761 case 4:
7762 gen_helper_1e0i(mftlo, t0, 1);
7763 break;
7764 case 5:
7765 gen_helper_1e0i(mfthi, t0, 1);
7766 break;
7767 case 6:
7768 gen_helper_1e0i(mftacx, t0, 1);
7769 break;
7770 case 8:
7771 gen_helper_1e0i(mftlo, t0, 2);
7772 break;
7773 case 9:
7774 gen_helper_1e0i(mfthi, t0, 2);
7775 break;
7776 case 10:
7777 gen_helper_1e0i(mftacx, t0, 2);
7778 break;
7779 case 12:
7780 gen_helper_1e0i(mftlo, t0, 3);
7781 break;
7782 case 13:
7783 gen_helper_1e0i(mfthi, t0, 3);
7784 break;
7785 case 14:
7786 gen_helper_1e0i(mftacx, t0, 3);
7787 break;
7788 case 16:
7789 gen_helper_mftdsp(t0, cpu_env);
7790 break;
7791 default:
7792 goto die;
7794 break;
7795 /* Floating point (COP1). */
7796 case 2:
7797 /* XXX: For now we support only a single FPU context. */
7798 if (h == 0) {
7799 TCGv_i32 fp0 = tcg_temp_new_i32();
7801 gen_load_fpr32(ctx, fp0, rt);
7802 tcg_gen_ext_i32_tl(t0, fp0);
7803 tcg_temp_free_i32(fp0);
7804 } else {
7805 TCGv_i32 fp0 = tcg_temp_new_i32();
7807 gen_load_fpr32h(ctx, fp0, rt);
7808 tcg_gen_ext_i32_tl(t0, fp0);
7809 tcg_temp_free_i32(fp0);
7811 break;
7812 case 3:
7813 /* XXX: For now we support only a single FPU context. */
7814 gen_helper_1e0i(cfc1, t0, rt);
7815 break;
7816 /* COP2: Not implemented. */
7817 case 4:
7818 case 5:
7819 /* fall through */
7820 default:
7821 goto die;
7823 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7824 gen_store_gpr(t0, rd);
7825 tcg_temp_free(t0);
7826 return;
7828 die:
7829 tcg_temp_free(t0);
7830 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7831 generate_exception(ctx, EXCP_RI);
7834 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7835 int u, int sel, int h)
7837 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7838 TCGv t0 = tcg_temp_local_new();
7840 gen_load_gpr(t0, rt);
7841 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7842 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7843 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7844 /* NOP */ ;
7845 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7846 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7847 /* NOP */ ;
7848 else if (u == 0) {
7849 switch (rd) {
7850 case 1:
7851 switch (sel) {
7852 case 1:
7853 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7854 break;
7855 case 2:
7856 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7857 break;
7858 default:
7859 goto die;
7860 break;
7862 break;
7863 case 2:
7864 switch (sel) {
7865 case 1:
7866 gen_helper_mttc0_tcstatus(cpu_env, t0);
7867 break;
7868 case 2:
7869 gen_helper_mttc0_tcbind(cpu_env, t0);
7870 break;
7871 case 3:
7872 gen_helper_mttc0_tcrestart(cpu_env, t0);
7873 break;
7874 case 4:
7875 gen_helper_mttc0_tchalt(cpu_env, t0);
7876 break;
7877 case 5:
7878 gen_helper_mttc0_tccontext(cpu_env, t0);
7879 break;
7880 case 6:
7881 gen_helper_mttc0_tcschedule(cpu_env, t0);
7882 break;
7883 case 7:
7884 gen_helper_mttc0_tcschefback(cpu_env, t0);
7885 break;
7886 default:
7887 gen_mtc0(ctx, t0, rd, sel);
7888 break;
7890 break;
7891 case 10:
7892 switch (sel) {
7893 case 0:
7894 gen_helper_mttc0_entryhi(cpu_env, t0);
7895 break;
7896 default:
7897 gen_mtc0(ctx, t0, rd, sel);
7898 break;
7900 case 12:
7901 switch (sel) {
7902 case 0:
7903 gen_helper_mttc0_status(cpu_env, t0);
7904 break;
7905 default:
7906 gen_mtc0(ctx, t0, rd, sel);
7907 break;
7909 case 13:
7910 switch (sel) {
7911 case 0:
7912 gen_helper_mttc0_cause(cpu_env, t0);
7913 break;
7914 default:
7915 goto die;
7916 break;
7918 break;
7919 case 15:
7920 switch (sel) {
7921 case 1:
7922 gen_helper_mttc0_ebase(cpu_env, t0);
7923 break;
7924 default:
7925 goto die;
7926 break;
7928 break;
7929 case 23:
7930 switch (sel) {
7931 case 0:
7932 gen_helper_mttc0_debug(cpu_env, t0);
7933 break;
7934 default:
7935 gen_mtc0(ctx, t0, rd, sel);
7936 break;
7938 break;
7939 default:
7940 gen_mtc0(ctx, t0, rd, sel);
7942 } else switch (sel) {
7943 /* GPR registers. */
7944 case 0:
7945 gen_helper_0e1i(mttgpr, t0, rd);
7946 break;
7947 /* Auxiliary CPU registers */
7948 case 1:
7949 switch (rd) {
7950 case 0:
7951 gen_helper_0e1i(mttlo, t0, 0);
7952 break;
7953 case 1:
7954 gen_helper_0e1i(mtthi, t0, 0);
7955 break;
7956 case 2:
7957 gen_helper_0e1i(mttacx, t0, 0);
7958 break;
7959 case 4:
7960 gen_helper_0e1i(mttlo, t0, 1);
7961 break;
7962 case 5:
7963 gen_helper_0e1i(mtthi, t0, 1);
7964 break;
7965 case 6:
7966 gen_helper_0e1i(mttacx, t0, 1);
7967 break;
7968 case 8:
7969 gen_helper_0e1i(mttlo, t0, 2);
7970 break;
7971 case 9:
7972 gen_helper_0e1i(mtthi, t0, 2);
7973 break;
7974 case 10:
7975 gen_helper_0e1i(mttacx, t0, 2);
7976 break;
7977 case 12:
7978 gen_helper_0e1i(mttlo, t0, 3);
7979 break;
7980 case 13:
7981 gen_helper_0e1i(mtthi, t0, 3);
7982 break;
7983 case 14:
7984 gen_helper_0e1i(mttacx, t0, 3);
7985 break;
7986 case 16:
7987 gen_helper_mttdsp(cpu_env, t0);
7988 break;
7989 default:
7990 goto die;
7992 break;
7993 /* Floating point (COP1). */
7994 case 2:
7995 /* XXX: For now we support only a single FPU context. */
7996 if (h == 0) {
7997 TCGv_i32 fp0 = tcg_temp_new_i32();
7999 tcg_gen_trunc_tl_i32(fp0, t0);
8000 gen_store_fpr32(ctx, fp0, rd);
8001 tcg_temp_free_i32(fp0);
8002 } else {
8003 TCGv_i32 fp0 = tcg_temp_new_i32();
8005 tcg_gen_trunc_tl_i32(fp0, t0);
8006 gen_store_fpr32h(ctx, fp0, rd);
8007 tcg_temp_free_i32(fp0);
8009 break;
8010 case 3:
8011 /* XXX: For now we support only a single FPU context. */
8012 save_cpu_state(ctx, 1);
8014 TCGv_i32 fs_tmp = tcg_const_i32(rd);
8016 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8017 tcg_temp_free_i32(fs_tmp);
8019 /* Stop translation as we may have changed hflags */
8020 ctx->bstate = BS_STOP;
8021 break;
8022 /* COP2: Not implemented. */
8023 case 4:
8024 case 5:
8025 /* fall through */
8026 default:
8027 goto die;
8029 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8030 tcg_temp_free(t0);
8031 return;
8033 die:
8034 tcg_temp_free(t0);
8035 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8036 generate_exception(ctx, EXCP_RI);
8039 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
8041 const char *opn = "ldst";
8043 check_cp0_enabled(ctx);
8044 switch (opc) {
8045 case OPC_MFC0:
8046 if (rt == 0) {
8047 /* Treat as NOP. */
8048 return;
8050 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8051 opn = "mfc0";
8052 break;
8053 case OPC_MTC0:
8055 TCGv t0 = tcg_temp_new();
8057 gen_load_gpr(t0, rt);
8058 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8059 tcg_temp_free(t0);
8061 opn = "mtc0";
8062 break;
8063 #if defined(TARGET_MIPS64)
8064 case OPC_DMFC0:
8065 check_insn(ctx, ISA_MIPS3);
8066 if (rt == 0) {
8067 /* Treat as NOP. */
8068 return;
8070 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8071 opn = "dmfc0";
8072 break;
8073 case OPC_DMTC0:
8074 check_insn(ctx, ISA_MIPS3);
8076 TCGv t0 = tcg_temp_new();
8078 gen_load_gpr(t0, rt);
8079 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8080 tcg_temp_free(t0);
8082 opn = "dmtc0";
8083 break;
8084 #endif
8085 case OPC_MFHC0:
8086 check_mvh(ctx);
8087 if (rt == 0) {
8088 /* Treat as NOP. */
8089 return;
8091 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8092 opn = "mfhc0";
8093 break;
8094 case OPC_MTHC0:
8095 check_mvh(ctx);
8097 TCGv t0 = tcg_temp_new();
8098 gen_load_gpr(t0, rt);
8099 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8100 tcg_temp_free(t0);
8102 opn = "mthc0";
8103 break;
8104 case OPC_MFTR:
8105 check_insn(ctx, ASE_MT);
8106 if (rd == 0) {
8107 /* Treat as NOP. */
8108 return;
8110 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8111 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8112 opn = "mftr";
8113 break;
8114 case OPC_MTTR:
8115 check_insn(ctx, ASE_MT);
8116 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8117 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8118 opn = "mttr";
8119 break;
8120 case OPC_TLBWI:
8121 opn = "tlbwi";
8122 if (!env->tlb->helper_tlbwi)
8123 goto die;
8124 gen_helper_tlbwi(cpu_env);
8125 break;
8126 case OPC_TLBINV:
8127 opn = "tlbinv";
8128 if (ctx->ie >= 2) {
8129 if (!env->tlb->helper_tlbinv) {
8130 goto die;
8132 gen_helper_tlbinv(cpu_env);
8133 } /* treat as nop if TLBINV not supported */
8134 break;
8135 case OPC_TLBINVF:
8136 opn = "tlbinvf";
8137 if (ctx->ie >= 2) {
8138 if (!env->tlb->helper_tlbinvf) {
8139 goto die;
8141 gen_helper_tlbinvf(cpu_env);
8142 } /* treat as nop if TLBINV not supported */
8143 break;
8144 case OPC_TLBWR:
8145 opn = "tlbwr";
8146 if (!env->tlb->helper_tlbwr)
8147 goto die;
8148 gen_helper_tlbwr(cpu_env);
8149 break;
8150 case OPC_TLBP:
8151 opn = "tlbp";
8152 if (!env->tlb->helper_tlbp)
8153 goto die;
8154 gen_helper_tlbp(cpu_env);
8155 break;
8156 case OPC_TLBR:
8157 opn = "tlbr";
8158 if (!env->tlb->helper_tlbr)
8159 goto die;
8160 gen_helper_tlbr(cpu_env);
8161 break;
8162 case OPC_ERET: /* OPC_ERETNC */
8163 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8164 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8165 MIPS_DEBUG("CTI in delay / forbidden slot");
8166 goto die;
8167 } else {
8168 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8169 if (ctx->opcode & (1 << bit_shift)) {
8170 /* OPC_ERETNC */
8171 opn = "eretnc";
8172 check_insn(ctx, ISA_MIPS32R5);
8173 gen_helper_eretnc(cpu_env);
8174 } else {
8175 /* OPC_ERET */
8176 opn = "eret";
8177 check_insn(ctx, ISA_MIPS2);
8178 gen_helper_eret(cpu_env);
8180 ctx->bstate = BS_EXCP;
8182 break;
8183 case OPC_DERET:
8184 opn = "deret";
8185 check_insn(ctx, ISA_MIPS32);
8186 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8187 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8188 MIPS_DEBUG("CTI in delay / forbidden slot");
8189 goto die;
8191 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8192 MIPS_INVAL(opn);
8193 generate_exception(ctx, EXCP_RI);
8194 } else {
8195 gen_helper_deret(cpu_env);
8196 ctx->bstate = BS_EXCP;
8198 break;
8199 case OPC_WAIT:
8200 opn = "wait";
8201 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8202 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8203 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8204 MIPS_DEBUG("CTI in delay / forbidden slot");
8205 goto die;
8207 /* If we get an exception, we want to restart at next instruction */
8208 ctx->pc += 4;
8209 save_cpu_state(ctx, 1);
8210 ctx->pc -= 4;
8211 gen_helper_wait(cpu_env);
8212 ctx->bstate = BS_EXCP;
8213 break;
8214 default:
8215 die:
8216 MIPS_INVAL(opn);
8217 generate_exception(ctx, EXCP_RI);
8218 return;
8220 (void)opn; /* avoid a compiler warning */
8221 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
8223 #endif /* !CONFIG_USER_ONLY */
8225 /* CP1 Branches (before delay slot) */
8226 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8227 int32_t cc, int32_t offset)
8229 target_ulong btarget;
8230 const char *opn = "cp1 cond branch";
8231 TCGv_i32 t0 = tcg_temp_new_i32();
8233 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8234 MIPS_DEBUG("CTI in delay / forbidden slot");
8235 generate_exception(ctx, EXCP_RI);
8236 goto out;
8239 if (cc != 0)
8240 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8242 btarget = ctx->pc + 4 + offset;
8244 switch (op) {
8245 case OPC_BC1F:
8246 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8247 tcg_gen_not_i32(t0, t0);
8248 tcg_gen_andi_i32(t0, t0, 1);
8249 tcg_gen_extu_i32_tl(bcond, t0);
8250 opn = "bc1f";
8251 goto not_likely;
8252 case OPC_BC1FL:
8253 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8254 tcg_gen_not_i32(t0, t0);
8255 tcg_gen_andi_i32(t0, t0, 1);
8256 tcg_gen_extu_i32_tl(bcond, t0);
8257 opn = "bc1fl";
8258 goto likely;
8259 case OPC_BC1T:
8260 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8261 tcg_gen_andi_i32(t0, t0, 1);
8262 tcg_gen_extu_i32_tl(bcond, t0);
8263 opn = "bc1t";
8264 goto not_likely;
8265 case OPC_BC1TL:
8266 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8267 tcg_gen_andi_i32(t0, t0, 1);
8268 tcg_gen_extu_i32_tl(bcond, t0);
8269 opn = "bc1tl";
8270 likely:
8271 ctx->hflags |= MIPS_HFLAG_BL;
8272 break;
8273 case OPC_BC1FANY2:
8275 TCGv_i32 t1 = tcg_temp_new_i32();
8276 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8277 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8278 tcg_gen_nand_i32(t0, t0, t1);
8279 tcg_temp_free_i32(t1);
8280 tcg_gen_andi_i32(t0, t0, 1);
8281 tcg_gen_extu_i32_tl(bcond, t0);
8283 opn = "bc1any2f";
8284 goto not_likely;
8285 case OPC_BC1TANY2:
8287 TCGv_i32 t1 = tcg_temp_new_i32();
8288 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8289 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8290 tcg_gen_or_i32(t0, t0, t1);
8291 tcg_temp_free_i32(t1);
8292 tcg_gen_andi_i32(t0, t0, 1);
8293 tcg_gen_extu_i32_tl(bcond, t0);
8295 opn = "bc1any2t";
8296 goto not_likely;
8297 case OPC_BC1FANY4:
8299 TCGv_i32 t1 = tcg_temp_new_i32();
8300 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8301 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8302 tcg_gen_and_i32(t0, t0, t1);
8303 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8304 tcg_gen_and_i32(t0, t0, t1);
8305 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8306 tcg_gen_nand_i32(t0, t0, t1);
8307 tcg_temp_free_i32(t1);
8308 tcg_gen_andi_i32(t0, t0, 1);
8309 tcg_gen_extu_i32_tl(bcond, t0);
8311 opn = "bc1any4f";
8312 goto not_likely;
8313 case OPC_BC1TANY4:
8315 TCGv_i32 t1 = tcg_temp_new_i32();
8316 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8317 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8318 tcg_gen_or_i32(t0, t0, t1);
8319 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8320 tcg_gen_or_i32(t0, t0, t1);
8321 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8322 tcg_gen_or_i32(t0, t0, t1);
8323 tcg_temp_free_i32(t1);
8324 tcg_gen_andi_i32(t0, t0, 1);
8325 tcg_gen_extu_i32_tl(bcond, t0);
8327 opn = "bc1any4t";
8328 not_likely:
8329 ctx->hflags |= MIPS_HFLAG_BC;
8330 break;
8331 default:
8332 MIPS_INVAL(opn);
8333 generate_exception (ctx, EXCP_RI);
8334 goto out;
8336 (void)opn; /* avoid a compiler warning */
8337 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8338 ctx->hflags, btarget);
8339 ctx->btarget = btarget;
8340 ctx->hflags |= MIPS_HFLAG_BDS32;
8341 out:
8342 tcg_temp_free_i32(t0);
8345 /* R6 CP1 Branches */
8346 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8347 int32_t ft, int32_t offset)
8349 target_ulong btarget;
8350 const char *opn = "cp1 cond branch";
8351 TCGv_i64 t0 = tcg_temp_new_i64();
8353 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8354 #ifdef MIPS_DEBUG_DISAS
8355 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8356 "\n", ctx->pc);
8357 #endif
8358 generate_exception(ctx, EXCP_RI);
8359 goto out;
8362 gen_load_fpr64(ctx, t0, ft);
8363 tcg_gen_andi_i64(t0, t0, 1);
8365 btarget = addr_add(ctx, ctx->pc + 4, offset);
8367 switch (op) {
8368 case OPC_BC1EQZ:
8369 tcg_gen_xori_i64(t0, t0, 1);
8370 opn = "bc1eqz";
8371 ctx->hflags |= MIPS_HFLAG_BC;
8372 break;
8373 case OPC_BC1NEZ:
8374 /* t0 already set */
8375 opn = "bc1nez";
8376 ctx->hflags |= MIPS_HFLAG_BC;
8377 break;
8378 default:
8379 MIPS_INVAL(opn);
8380 generate_exception(ctx, EXCP_RI);
8381 goto out;
8384 tcg_gen_trunc_i64_tl(bcond, t0);
8386 (void)opn; /* avoid a compiler warning */
8387 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8388 ctx->hflags, btarget);
8389 ctx->btarget = btarget;
8390 ctx->hflags |= MIPS_HFLAG_BDS32;
8392 out:
8393 tcg_temp_free_i64(t0);
8396 /* Coprocessor 1 (FPU) */
8398 #define FOP(func, fmt) (((fmt) << 21) | (func))
8400 enum fopcode {
8401 OPC_ADD_S = FOP(0, FMT_S),
8402 OPC_SUB_S = FOP(1, FMT_S),
8403 OPC_MUL_S = FOP(2, FMT_S),
8404 OPC_DIV_S = FOP(3, FMT_S),
8405 OPC_SQRT_S = FOP(4, FMT_S),
8406 OPC_ABS_S = FOP(5, FMT_S),
8407 OPC_MOV_S = FOP(6, FMT_S),
8408 OPC_NEG_S = FOP(7, FMT_S),
8409 OPC_ROUND_L_S = FOP(8, FMT_S),
8410 OPC_TRUNC_L_S = FOP(9, FMT_S),
8411 OPC_CEIL_L_S = FOP(10, FMT_S),
8412 OPC_FLOOR_L_S = FOP(11, FMT_S),
8413 OPC_ROUND_W_S = FOP(12, FMT_S),
8414 OPC_TRUNC_W_S = FOP(13, FMT_S),
8415 OPC_CEIL_W_S = FOP(14, FMT_S),
8416 OPC_FLOOR_W_S = FOP(15, FMT_S),
8417 OPC_SEL_S = FOP(16, FMT_S),
8418 OPC_MOVCF_S = FOP(17, FMT_S),
8419 OPC_MOVZ_S = FOP(18, FMT_S),
8420 OPC_MOVN_S = FOP(19, FMT_S),
8421 OPC_SELEQZ_S = FOP(20, FMT_S),
8422 OPC_RECIP_S = FOP(21, FMT_S),
8423 OPC_RSQRT_S = FOP(22, FMT_S),
8424 OPC_SELNEZ_S = FOP(23, FMT_S),
8425 OPC_MADDF_S = FOP(24, FMT_S),
8426 OPC_MSUBF_S = FOP(25, FMT_S),
8427 OPC_RINT_S = FOP(26, FMT_S),
8428 OPC_CLASS_S = FOP(27, FMT_S),
8429 OPC_MIN_S = FOP(28, FMT_S),
8430 OPC_RECIP2_S = FOP(28, FMT_S),
8431 OPC_MINA_S = FOP(29, FMT_S),
8432 OPC_RECIP1_S = FOP(29, FMT_S),
8433 OPC_MAX_S = FOP(30, FMT_S),
8434 OPC_RSQRT1_S = FOP(30, FMT_S),
8435 OPC_MAXA_S = FOP(31, FMT_S),
8436 OPC_RSQRT2_S = FOP(31, FMT_S),
8437 OPC_CVT_D_S = FOP(33, FMT_S),
8438 OPC_CVT_W_S = FOP(36, FMT_S),
8439 OPC_CVT_L_S = FOP(37, FMT_S),
8440 OPC_CVT_PS_S = FOP(38, FMT_S),
8441 OPC_CMP_F_S = FOP (48, FMT_S),
8442 OPC_CMP_UN_S = FOP (49, FMT_S),
8443 OPC_CMP_EQ_S = FOP (50, FMT_S),
8444 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8445 OPC_CMP_OLT_S = FOP (52, FMT_S),
8446 OPC_CMP_ULT_S = FOP (53, FMT_S),
8447 OPC_CMP_OLE_S = FOP (54, FMT_S),
8448 OPC_CMP_ULE_S = FOP (55, FMT_S),
8449 OPC_CMP_SF_S = FOP (56, FMT_S),
8450 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8451 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8452 OPC_CMP_NGL_S = FOP (59, FMT_S),
8453 OPC_CMP_LT_S = FOP (60, FMT_S),
8454 OPC_CMP_NGE_S = FOP (61, FMT_S),
8455 OPC_CMP_LE_S = FOP (62, FMT_S),
8456 OPC_CMP_NGT_S = FOP (63, FMT_S),
8458 OPC_ADD_D = FOP(0, FMT_D),
8459 OPC_SUB_D = FOP(1, FMT_D),
8460 OPC_MUL_D = FOP(2, FMT_D),
8461 OPC_DIV_D = FOP(3, FMT_D),
8462 OPC_SQRT_D = FOP(4, FMT_D),
8463 OPC_ABS_D = FOP(5, FMT_D),
8464 OPC_MOV_D = FOP(6, FMT_D),
8465 OPC_NEG_D = FOP(7, FMT_D),
8466 OPC_ROUND_L_D = FOP(8, FMT_D),
8467 OPC_TRUNC_L_D = FOP(9, FMT_D),
8468 OPC_CEIL_L_D = FOP(10, FMT_D),
8469 OPC_FLOOR_L_D = FOP(11, FMT_D),
8470 OPC_ROUND_W_D = FOP(12, FMT_D),
8471 OPC_TRUNC_W_D = FOP(13, FMT_D),
8472 OPC_CEIL_W_D = FOP(14, FMT_D),
8473 OPC_FLOOR_W_D = FOP(15, FMT_D),
8474 OPC_SEL_D = FOP(16, FMT_D),
8475 OPC_MOVCF_D = FOP(17, FMT_D),
8476 OPC_MOVZ_D = FOP(18, FMT_D),
8477 OPC_MOVN_D = FOP(19, FMT_D),
8478 OPC_SELEQZ_D = FOP(20, FMT_D),
8479 OPC_RECIP_D = FOP(21, FMT_D),
8480 OPC_RSQRT_D = FOP(22, FMT_D),
8481 OPC_SELNEZ_D = FOP(23, FMT_D),
8482 OPC_MADDF_D = FOP(24, FMT_D),
8483 OPC_MSUBF_D = FOP(25, FMT_D),
8484 OPC_RINT_D = FOP(26, FMT_D),
8485 OPC_CLASS_D = FOP(27, FMT_D),
8486 OPC_MIN_D = FOP(28, FMT_D),
8487 OPC_RECIP2_D = FOP(28, FMT_D),
8488 OPC_MINA_D = FOP(29, FMT_D),
8489 OPC_RECIP1_D = FOP(29, FMT_D),
8490 OPC_MAX_D = FOP(30, FMT_D),
8491 OPC_RSQRT1_D = FOP(30, FMT_D),
8492 OPC_MAXA_D = FOP(31, FMT_D),
8493 OPC_RSQRT2_D = FOP(31, FMT_D),
8494 OPC_CVT_S_D = FOP(32, FMT_D),
8495 OPC_CVT_W_D = FOP(36, FMT_D),
8496 OPC_CVT_L_D = FOP(37, FMT_D),
8497 OPC_CMP_F_D = FOP (48, FMT_D),
8498 OPC_CMP_UN_D = FOP (49, FMT_D),
8499 OPC_CMP_EQ_D = FOP (50, FMT_D),
8500 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8501 OPC_CMP_OLT_D = FOP (52, FMT_D),
8502 OPC_CMP_ULT_D = FOP (53, FMT_D),
8503 OPC_CMP_OLE_D = FOP (54, FMT_D),
8504 OPC_CMP_ULE_D = FOP (55, FMT_D),
8505 OPC_CMP_SF_D = FOP (56, FMT_D),
8506 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8507 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8508 OPC_CMP_NGL_D = FOP (59, FMT_D),
8509 OPC_CMP_LT_D = FOP (60, FMT_D),
8510 OPC_CMP_NGE_D = FOP (61, FMT_D),
8511 OPC_CMP_LE_D = FOP (62, FMT_D),
8512 OPC_CMP_NGT_D = FOP (63, FMT_D),
8514 OPC_CVT_S_W = FOP(32, FMT_W),
8515 OPC_CVT_D_W = FOP(33, FMT_W),
8516 OPC_CVT_S_L = FOP(32, FMT_L),
8517 OPC_CVT_D_L = FOP(33, FMT_L),
8518 OPC_CVT_PS_PW = FOP(38, FMT_W),
8520 OPC_ADD_PS = FOP(0, FMT_PS),
8521 OPC_SUB_PS = FOP(1, FMT_PS),
8522 OPC_MUL_PS = FOP(2, FMT_PS),
8523 OPC_DIV_PS = FOP(3, FMT_PS),
8524 OPC_ABS_PS = FOP(5, FMT_PS),
8525 OPC_MOV_PS = FOP(6, FMT_PS),
8526 OPC_NEG_PS = FOP(7, FMT_PS),
8527 OPC_MOVCF_PS = FOP(17, FMT_PS),
8528 OPC_MOVZ_PS = FOP(18, FMT_PS),
8529 OPC_MOVN_PS = FOP(19, FMT_PS),
8530 OPC_ADDR_PS = FOP(24, FMT_PS),
8531 OPC_MULR_PS = FOP(26, FMT_PS),
8532 OPC_RECIP2_PS = FOP(28, FMT_PS),
8533 OPC_RECIP1_PS = FOP(29, FMT_PS),
8534 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8535 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8537 OPC_CVT_S_PU = FOP(32, FMT_PS),
8538 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8539 OPC_CVT_S_PL = FOP(40, FMT_PS),
8540 OPC_PLL_PS = FOP(44, FMT_PS),
8541 OPC_PLU_PS = FOP(45, FMT_PS),
8542 OPC_PUL_PS = FOP(46, FMT_PS),
8543 OPC_PUU_PS = FOP(47, FMT_PS),
8544 OPC_CMP_F_PS = FOP (48, FMT_PS),
8545 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8546 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8547 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8548 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8549 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8550 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8551 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8552 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8553 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8554 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8555 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8556 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8557 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8558 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8559 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8562 enum r6_f_cmp_op {
8563 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8564 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8565 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8566 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8567 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8568 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8569 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8570 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8571 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8572 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8573 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8574 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8575 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8576 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8577 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8578 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8579 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8580 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8581 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8582 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8583 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8584 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8586 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8587 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8588 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8589 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8590 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8591 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8592 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8593 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8594 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8595 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8596 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8597 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8598 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8599 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8600 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8601 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8602 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8603 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8604 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8605 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8606 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8607 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8609 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8611 const char *opn = "cp1 move";
8612 TCGv t0 = tcg_temp_new();
8614 switch (opc) {
8615 case OPC_MFC1:
8617 TCGv_i32 fp0 = tcg_temp_new_i32();
8619 gen_load_fpr32(ctx, fp0, fs);
8620 tcg_gen_ext_i32_tl(t0, fp0);
8621 tcg_temp_free_i32(fp0);
8623 gen_store_gpr(t0, rt);
8624 opn = "mfc1";
8625 break;
8626 case OPC_MTC1:
8627 gen_load_gpr(t0, rt);
8629 TCGv_i32 fp0 = tcg_temp_new_i32();
8631 tcg_gen_trunc_tl_i32(fp0, t0);
8632 gen_store_fpr32(ctx, fp0, fs);
8633 tcg_temp_free_i32(fp0);
8635 opn = "mtc1";
8636 break;
8637 case OPC_CFC1:
8638 gen_helper_1e0i(cfc1, t0, fs);
8639 gen_store_gpr(t0, rt);
8640 opn = "cfc1";
8641 break;
8642 case OPC_CTC1:
8643 gen_load_gpr(t0, rt);
8644 save_cpu_state(ctx, 1);
8646 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8648 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8649 tcg_temp_free_i32(fs_tmp);
8651 /* Stop translation as we may have changed hflags */
8652 ctx->bstate = BS_STOP;
8653 opn = "ctc1";
8654 break;
8655 #if defined(TARGET_MIPS64)
8656 case OPC_DMFC1:
8657 gen_load_fpr64(ctx, t0, fs);
8658 gen_store_gpr(t0, rt);
8659 opn = "dmfc1";
8660 break;
8661 case OPC_DMTC1:
8662 gen_load_gpr(t0, rt);
8663 gen_store_fpr64(ctx, t0, fs);
8664 opn = "dmtc1";
8665 break;
8666 #endif
8667 case OPC_MFHC1:
8669 TCGv_i32 fp0 = tcg_temp_new_i32();
8671 gen_load_fpr32h(ctx, fp0, fs);
8672 tcg_gen_ext_i32_tl(t0, fp0);
8673 tcg_temp_free_i32(fp0);
8675 gen_store_gpr(t0, rt);
8676 opn = "mfhc1";
8677 break;
8678 case OPC_MTHC1:
8679 gen_load_gpr(t0, rt);
8681 TCGv_i32 fp0 = tcg_temp_new_i32();
8683 tcg_gen_trunc_tl_i32(fp0, t0);
8684 gen_store_fpr32h(ctx, fp0, fs);
8685 tcg_temp_free_i32(fp0);
8687 opn = "mthc1";
8688 break;
8689 default:
8690 MIPS_INVAL(opn);
8691 generate_exception (ctx, EXCP_RI);
8692 goto out;
8694 (void)opn; /* avoid a compiler warning */
8695 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
8697 out:
8698 tcg_temp_free(t0);
8701 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8703 TCGLabel *l1;
8704 TCGCond cond;
8705 TCGv_i32 t0;
8707 if (rd == 0) {
8708 /* Treat as NOP. */
8709 return;
8712 if (tf)
8713 cond = TCG_COND_EQ;
8714 else
8715 cond = TCG_COND_NE;
8717 l1 = gen_new_label();
8718 t0 = tcg_temp_new_i32();
8719 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8720 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8721 tcg_temp_free_i32(t0);
8722 if (rs == 0) {
8723 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8724 } else {
8725 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8727 gen_set_label(l1);
8730 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
8731 int tf)
8733 int cond;
8734 TCGv_i32 t0 = tcg_temp_new_i32();
8735 TCGLabel *l1 = gen_new_label();
8737 if (tf)
8738 cond = TCG_COND_EQ;
8739 else
8740 cond = TCG_COND_NE;
8742 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8743 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8744 gen_load_fpr32(ctx, t0, fs);
8745 gen_store_fpr32(ctx, t0, fd);
8746 gen_set_label(l1);
8747 tcg_temp_free_i32(t0);
8750 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8752 int cond;
8753 TCGv_i32 t0 = tcg_temp_new_i32();
8754 TCGv_i64 fp0;
8755 TCGLabel *l1 = gen_new_label();
8757 if (tf)
8758 cond = TCG_COND_EQ;
8759 else
8760 cond = TCG_COND_NE;
8762 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8763 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8764 tcg_temp_free_i32(t0);
8765 fp0 = tcg_temp_new_i64();
8766 gen_load_fpr64(ctx, fp0, fs);
8767 gen_store_fpr64(ctx, fp0, fd);
8768 tcg_temp_free_i64(fp0);
8769 gen_set_label(l1);
8772 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8773 int cc, int tf)
8775 int cond;
8776 TCGv_i32 t0 = tcg_temp_new_i32();
8777 TCGLabel *l1 = gen_new_label();
8778 TCGLabel *l2 = gen_new_label();
8780 if (tf)
8781 cond = TCG_COND_EQ;
8782 else
8783 cond = TCG_COND_NE;
8785 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8786 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8787 gen_load_fpr32(ctx, t0, fs);
8788 gen_store_fpr32(ctx, t0, fd);
8789 gen_set_label(l1);
8791 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8792 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8793 gen_load_fpr32h(ctx, t0, fs);
8794 gen_store_fpr32h(ctx, t0, fd);
8795 tcg_temp_free_i32(t0);
8796 gen_set_label(l2);
8799 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8800 int fs)
8802 TCGv_i32 t1 = tcg_const_i32(0);
8803 TCGv_i32 fp0 = tcg_temp_new_i32();
8804 TCGv_i32 fp1 = tcg_temp_new_i32();
8805 TCGv_i32 fp2 = tcg_temp_new_i32();
8806 gen_load_fpr32(ctx, fp0, fd);
8807 gen_load_fpr32(ctx, fp1, ft);
8808 gen_load_fpr32(ctx, fp2, fs);
8810 switch (op1) {
8811 case OPC_SEL_S:
8812 tcg_gen_andi_i32(fp0, fp0, 1);
8813 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8814 break;
8815 case OPC_SELEQZ_S:
8816 tcg_gen_andi_i32(fp1, fp1, 1);
8817 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8818 break;
8819 case OPC_SELNEZ_S:
8820 tcg_gen_andi_i32(fp1, fp1, 1);
8821 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8822 break;
8823 default:
8824 MIPS_INVAL("gen_sel_s");
8825 generate_exception (ctx, EXCP_RI);
8826 break;
8829 gen_store_fpr32(ctx, fp0, fd);
8830 tcg_temp_free_i32(fp2);
8831 tcg_temp_free_i32(fp1);
8832 tcg_temp_free_i32(fp0);
8833 tcg_temp_free_i32(t1);
8836 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8837 int fs)
8839 TCGv_i64 t1 = tcg_const_i64(0);
8840 TCGv_i64 fp0 = tcg_temp_new_i64();
8841 TCGv_i64 fp1 = tcg_temp_new_i64();
8842 TCGv_i64 fp2 = tcg_temp_new_i64();
8843 gen_load_fpr64(ctx, fp0, fd);
8844 gen_load_fpr64(ctx, fp1, ft);
8845 gen_load_fpr64(ctx, fp2, fs);
8847 switch (op1) {
8848 case OPC_SEL_D:
8849 tcg_gen_andi_i64(fp0, fp0, 1);
8850 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8851 break;
8852 case OPC_SELEQZ_D:
8853 tcg_gen_andi_i64(fp1, fp1, 1);
8854 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8855 break;
8856 case OPC_SELNEZ_D:
8857 tcg_gen_andi_i64(fp1, fp1, 1);
8858 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8859 break;
8860 default:
8861 MIPS_INVAL("gen_sel_d");
8862 generate_exception (ctx, EXCP_RI);
8863 break;
8866 gen_store_fpr64(ctx, fp0, fd);
8867 tcg_temp_free_i64(fp2);
8868 tcg_temp_free_i64(fp1);
8869 tcg_temp_free_i64(fp0);
8870 tcg_temp_free_i64(t1);
8873 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8874 int ft, int fs, int fd, int cc)
8876 const char *opn = "farith";
8877 const char *condnames[] = {
8878 "c.f",
8879 "c.un",
8880 "c.eq",
8881 "c.ueq",
8882 "c.olt",
8883 "c.ult",
8884 "c.ole",
8885 "c.ule",
8886 "c.sf",
8887 "c.ngle",
8888 "c.seq",
8889 "c.ngl",
8890 "c.lt",
8891 "c.nge",
8892 "c.le",
8893 "c.ngt",
8895 const char *condnames_abs[] = {
8896 "cabs.f",
8897 "cabs.un",
8898 "cabs.eq",
8899 "cabs.ueq",
8900 "cabs.olt",
8901 "cabs.ult",
8902 "cabs.ole",
8903 "cabs.ule",
8904 "cabs.sf",
8905 "cabs.ngle",
8906 "cabs.seq",
8907 "cabs.ngl",
8908 "cabs.lt",
8909 "cabs.nge",
8910 "cabs.le",
8911 "cabs.ngt",
8913 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
8914 uint32_t func = ctx->opcode & 0x3f;
8916 switch (op1) {
8917 case OPC_ADD_S:
8919 TCGv_i32 fp0 = tcg_temp_new_i32();
8920 TCGv_i32 fp1 = tcg_temp_new_i32();
8922 gen_load_fpr32(ctx, fp0, fs);
8923 gen_load_fpr32(ctx, fp1, ft);
8924 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
8925 tcg_temp_free_i32(fp1);
8926 gen_store_fpr32(ctx, fp0, fd);
8927 tcg_temp_free_i32(fp0);
8929 opn = "add.s";
8930 optype = BINOP;
8931 break;
8932 case OPC_SUB_S:
8934 TCGv_i32 fp0 = tcg_temp_new_i32();
8935 TCGv_i32 fp1 = tcg_temp_new_i32();
8937 gen_load_fpr32(ctx, fp0, fs);
8938 gen_load_fpr32(ctx, fp1, ft);
8939 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
8940 tcg_temp_free_i32(fp1);
8941 gen_store_fpr32(ctx, fp0, fd);
8942 tcg_temp_free_i32(fp0);
8944 opn = "sub.s";
8945 optype = BINOP;
8946 break;
8947 case OPC_MUL_S:
8949 TCGv_i32 fp0 = tcg_temp_new_i32();
8950 TCGv_i32 fp1 = tcg_temp_new_i32();
8952 gen_load_fpr32(ctx, fp0, fs);
8953 gen_load_fpr32(ctx, fp1, ft);
8954 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
8955 tcg_temp_free_i32(fp1);
8956 gen_store_fpr32(ctx, fp0, fd);
8957 tcg_temp_free_i32(fp0);
8959 opn = "mul.s";
8960 optype = BINOP;
8961 break;
8962 case OPC_DIV_S:
8964 TCGv_i32 fp0 = tcg_temp_new_i32();
8965 TCGv_i32 fp1 = tcg_temp_new_i32();
8967 gen_load_fpr32(ctx, fp0, fs);
8968 gen_load_fpr32(ctx, fp1, ft);
8969 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
8970 tcg_temp_free_i32(fp1);
8971 gen_store_fpr32(ctx, fp0, fd);
8972 tcg_temp_free_i32(fp0);
8974 opn = "div.s";
8975 optype = BINOP;
8976 break;
8977 case OPC_SQRT_S:
8979 TCGv_i32 fp0 = tcg_temp_new_i32();
8981 gen_load_fpr32(ctx, fp0, fs);
8982 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
8983 gen_store_fpr32(ctx, fp0, fd);
8984 tcg_temp_free_i32(fp0);
8986 opn = "sqrt.s";
8987 break;
8988 case OPC_ABS_S:
8990 TCGv_i32 fp0 = tcg_temp_new_i32();
8992 gen_load_fpr32(ctx, fp0, fs);
8993 gen_helper_float_abs_s(fp0, fp0);
8994 gen_store_fpr32(ctx, fp0, fd);
8995 tcg_temp_free_i32(fp0);
8997 opn = "abs.s";
8998 break;
8999 case OPC_MOV_S:
9001 TCGv_i32 fp0 = tcg_temp_new_i32();
9003 gen_load_fpr32(ctx, fp0, fs);
9004 gen_store_fpr32(ctx, fp0, fd);
9005 tcg_temp_free_i32(fp0);
9007 opn = "mov.s";
9008 break;
9009 case OPC_NEG_S:
9011 TCGv_i32 fp0 = tcg_temp_new_i32();
9013 gen_load_fpr32(ctx, fp0, fs);
9014 gen_helper_float_chs_s(fp0, fp0);
9015 gen_store_fpr32(ctx, fp0, fd);
9016 tcg_temp_free_i32(fp0);
9018 opn = "neg.s";
9019 break;
9020 case OPC_ROUND_L_S:
9021 check_cp1_64bitmode(ctx);
9023 TCGv_i32 fp32 = tcg_temp_new_i32();
9024 TCGv_i64 fp64 = tcg_temp_new_i64();
9026 gen_load_fpr32(ctx, fp32, fs);
9027 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
9028 tcg_temp_free_i32(fp32);
9029 gen_store_fpr64(ctx, fp64, fd);
9030 tcg_temp_free_i64(fp64);
9032 opn = "round.l.s";
9033 break;
9034 case OPC_TRUNC_L_S:
9035 check_cp1_64bitmode(ctx);
9037 TCGv_i32 fp32 = tcg_temp_new_i32();
9038 TCGv_i64 fp64 = tcg_temp_new_i64();
9040 gen_load_fpr32(ctx, fp32, fs);
9041 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
9042 tcg_temp_free_i32(fp32);
9043 gen_store_fpr64(ctx, fp64, fd);
9044 tcg_temp_free_i64(fp64);
9046 opn = "trunc.l.s";
9047 break;
9048 case OPC_CEIL_L_S:
9049 check_cp1_64bitmode(ctx);
9051 TCGv_i32 fp32 = tcg_temp_new_i32();
9052 TCGv_i64 fp64 = tcg_temp_new_i64();
9054 gen_load_fpr32(ctx, fp32, fs);
9055 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
9056 tcg_temp_free_i32(fp32);
9057 gen_store_fpr64(ctx, fp64, fd);
9058 tcg_temp_free_i64(fp64);
9060 opn = "ceil.l.s";
9061 break;
9062 case OPC_FLOOR_L_S:
9063 check_cp1_64bitmode(ctx);
9065 TCGv_i32 fp32 = tcg_temp_new_i32();
9066 TCGv_i64 fp64 = tcg_temp_new_i64();
9068 gen_load_fpr32(ctx, fp32, fs);
9069 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
9070 tcg_temp_free_i32(fp32);
9071 gen_store_fpr64(ctx, fp64, fd);
9072 tcg_temp_free_i64(fp64);
9074 opn = "floor.l.s";
9075 break;
9076 case OPC_ROUND_W_S:
9078 TCGv_i32 fp0 = tcg_temp_new_i32();
9080 gen_load_fpr32(ctx, fp0, fs);
9081 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
9082 gen_store_fpr32(ctx, fp0, fd);
9083 tcg_temp_free_i32(fp0);
9085 opn = "round.w.s";
9086 break;
9087 case OPC_TRUNC_W_S:
9089 TCGv_i32 fp0 = tcg_temp_new_i32();
9091 gen_load_fpr32(ctx, fp0, fs);
9092 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
9093 gen_store_fpr32(ctx, fp0, fd);
9094 tcg_temp_free_i32(fp0);
9096 opn = "trunc.w.s";
9097 break;
9098 case OPC_CEIL_W_S:
9100 TCGv_i32 fp0 = tcg_temp_new_i32();
9102 gen_load_fpr32(ctx, fp0, fs);
9103 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
9104 gen_store_fpr32(ctx, fp0, fd);
9105 tcg_temp_free_i32(fp0);
9107 opn = "ceil.w.s";
9108 break;
9109 case OPC_FLOOR_W_S:
9111 TCGv_i32 fp0 = tcg_temp_new_i32();
9113 gen_load_fpr32(ctx, fp0, fs);
9114 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
9115 gen_store_fpr32(ctx, fp0, fd);
9116 tcg_temp_free_i32(fp0);
9118 opn = "floor.w.s";
9119 break;
9120 case OPC_SEL_S:
9121 check_insn(ctx, ISA_MIPS32R6);
9122 gen_sel_s(ctx, op1, fd, ft, fs);
9123 opn = "sel.s";
9124 break;
9125 case OPC_SELEQZ_S:
9126 check_insn(ctx, ISA_MIPS32R6);
9127 gen_sel_s(ctx, op1, fd, ft, fs);
9128 opn = "seleqz.s";
9129 break;
9130 case OPC_SELNEZ_S:
9131 check_insn(ctx, ISA_MIPS32R6);
9132 gen_sel_s(ctx, op1, fd, ft, fs);
9133 opn = "selnez.s";
9134 break;
9135 case OPC_MOVCF_S:
9136 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9137 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9138 opn = "movcf.s";
9139 break;
9140 case OPC_MOVZ_S:
9141 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9143 TCGLabel *l1 = gen_new_label();
9144 TCGv_i32 fp0;
9146 if (ft != 0) {
9147 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9149 fp0 = tcg_temp_new_i32();
9150 gen_load_fpr32(ctx, fp0, fs);
9151 gen_store_fpr32(ctx, fp0, fd);
9152 tcg_temp_free_i32(fp0);
9153 gen_set_label(l1);
9155 opn = "movz.s";
9156 break;
9157 case OPC_MOVN_S:
9158 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9160 TCGLabel *l1 = gen_new_label();
9161 TCGv_i32 fp0;
9163 if (ft != 0) {
9164 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9165 fp0 = tcg_temp_new_i32();
9166 gen_load_fpr32(ctx, fp0, fs);
9167 gen_store_fpr32(ctx, fp0, fd);
9168 tcg_temp_free_i32(fp0);
9169 gen_set_label(l1);
9172 opn = "movn.s";
9173 break;
9174 case OPC_RECIP_S:
9175 check_cop1x(ctx);
9177 TCGv_i32 fp0 = tcg_temp_new_i32();
9179 gen_load_fpr32(ctx, fp0, fs);
9180 gen_helper_float_recip_s(fp0, cpu_env, fp0);
9181 gen_store_fpr32(ctx, fp0, fd);
9182 tcg_temp_free_i32(fp0);
9184 opn = "recip.s";
9185 break;
9186 case OPC_RSQRT_S:
9187 check_cop1x(ctx);
9189 TCGv_i32 fp0 = tcg_temp_new_i32();
9191 gen_load_fpr32(ctx, fp0, fs);
9192 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
9193 gen_store_fpr32(ctx, fp0, fd);
9194 tcg_temp_free_i32(fp0);
9196 opn = "rsqrt.s";
9197 break;
9198 case OPC_MADDF_S:
9199 check_insn(ctx, ISA_MIPS32R6);
9201 TCGv_i32 fp0 = tcg_temp_new_i32();
9202 TCGv_i32 fp1 = tcg_temp_new_i32();
9203 TCGv_i32 fp2 = tcg_temp_new_i32();
9204 gen_load_fpr32(ctx, fp0, fs);
9205 gen_load_fpr32(ctx, fp1, ft);
9206 gen_load_fpr32(ctx, fp2, fd);
9207 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
9208 gen_store_fpr32(ctx, fp2, fd);
9209 tcg_temp_free_i32(fp2);
9210 tcg_temp_free_i32(fp1);
9211 tcg_temp_free_i32(fp0);
9212 opn = "maddf.s";
9214 break;
9215 case OPC_MSUBF_S:
9216 check_insn(ctx, ISA_MIPS32R6);
9218 TCGv_i32 fp0 = tcg_temp_new_i32();
9219 TCGv_i32 fp1 = tcg_temp_new_i32();
9220 TCGv_i32 fp2 = tcg_temp_new_i32();
9221 gen_load_fpr32(ctx, fp0, fs);
9222 gen_load_fpr32(ctx, fp1, ft);
9223 gen_load_fpr32(ctx, fp2, fd);
9224 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9225 gen_store_fpr32(ctx, fp2, fd);
9226 tcg_temp_free_i32(fp2);
9227 tcg_temp_free_i32(fp1);
9228 tcg_temp_free_i32(fp0);
9229 opn = "msubf.s";
9231 break;
9232 case OPC_RINT_S:
9233 check_insn(ctx, ISA_MIPS32R6);
9235 TCGv_i32 fp0 = tcg_temp_new_i32();
9236 gen_load_fpr32(ctx, fp0, fs);
9237 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9238 gen_store_fpr32(ctx, fp0, fd);
9239 tcg_temp_free_i32(fp0);
9240 opn = "rint.s";
9242 break;
9243 case OPC_CLASS_S:
9244 check_insn(ctx, ISA_MIPS32R6);
9246 TCGv_i32 fp0 = tcg_temp_new_i32();
9247 gen_load_fpr32(ctx, fp0, fs);
9248 gen_helper_float_class_s(fp0, fp0);
9249 gen_store_fpr32(ctx, fp0, fd);
9250 tcg_temp_free_i32(fp0);
9251 opn = "class.s";
9253 break;
9254 case OPC_MIN_S: /* OPC_RECIP2_S */
9255 if (ctx->insn_flags & ISA_MIPS32R6) {
9256 /* OPC_MIN_S */
9257 TCGv_i32 fp0 = tcg_temp_new_i32();
9258 TCGv_i32 fp1 = tcg_temp_new_i32();
9259 TCGv_i32 fp2 = tcg_temp_new_i32();
9260 gen_load_fpr32(ctx, fp0, fs);
9261 gen_load_fpr32(ctx, fp1, ft);
9262 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9263 gen_store_fpr32(ctx, fp2, fd);
9264 tcg_temp_free_i32(fp2);
9265 tcg_temp_free_i32(fp1);
9266 tcg_temp_free_i32(fp0);
9267 opn = "min.s";
9268 } else {
9269 /* OPC_RECIP2_S */
9270 check_cp1_64bitmode(ctx);
9272 TCGv_i32 fp0 = tcg_temp_new_i32();
9273 TCGv_i32 fp1 = tcg_temp_new_i32();
9275 gen_load_fpr32(ctx, fp0, fs);
9276 gen_load_fpr32(ctx, fp1, ft);
9277 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9278 tcg_temp_free_i32(fp1);
9279 gen_store_fpr32(ctx, fp0, fd);
9280 tcg_temp_free_i32(fp0);
9282 opn = "recip2.s";
9284 break;
9285 case OPC_MINA_S: /* OPC_RECIP1_S */
9286 if (ctx->insn_flags & ISA_MIPS32R6) {
9287 /* OPC_MINA_S */
9288 TCGv_i32 fp0 = tcg_temp_new_i32();
9289 TCGv_i32 fp1 = tcg_temp_new_i32();
9290 TCGv_i32 fp2 = tcg_temp_new_i32();
9291 gen_load_fpr32(ctx, fp0, fs);
9292 gen_load_fpr32(ctx, fp1, ft);
9293 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9294 gen_store_fpr32(ctx, fp2, fd);
9295 tcg_temp_free_i32(fp2);
9296 tcg_temp_free_i32(fp1);
9297 tcg_temp_free_i32(fp0);
9298 opn = "mina.s";
9299 } else {
9300 /* OPC_RECIP1_S */
9301 check_cp1_64bitmode(ctx);
9303 TCGv_i32 fp0 = tcg_temp_new_i32();
9305 gen_load_fpr32(ctx, fp0, fs);
9306 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9307 gen_store_fpr32(ctx, fp0, fd);
9308 tcg_temp_free_i32(fp0);
9310 opn = "recip1.s";
9312 break;
9313 case OPC_MAX_S: /* OPC_RSQRT1_S */
9314 if (ctx->insn_flags & ISA_MIPS32R6) {
9315 /* OPC_MAX_S */
9316 TCGv_i32 fp0 = tcg_temp_new_i32();
9317 TCGv_i32 fp1 = tcg_temp_new_i32();
9318 gen_load_fpr32(ctx, fp0, fs);
9319 gen_load_fpr32(ctx, fp1, ft);
9320 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9321 gen_store_fpr32(ctx, fp1, fd);
9322 tcg_temp_free_i32(fp1);
9323 tcg_temp_free_i32(fp0);
9324 opn = "max.s";
9325 } else {
9326 /* OPC_RSQRT1_S */
9327 check_cp1_64bitmode(ctx);
9329 TCGv_i32 fp0 = tcg_temp_new_i32();
9331 gen_load_fpr32(ctx, fp0, fs);
9332 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9333 gen_store_fpr32(ctx, fp0, fd);
9334 tcg_temp_free_i32(fp0);
9336 opn = "rsqrt1.s";
9338 break;
9339 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9340 if (ctx->insn_flags & ISA_MIPS32R6) {
9341 /* OPC_MAXA_S */
9342 TCGv_i32 fp0 = tcg_temp_new_i32();
9343 TCGv_i32 fp1 = tcg_temp_new_i32();
9344 gen_load_fpr32(ctx, fp0, fs);
9345 gen_load_fpr32(ctx, fp1, ft);
9346 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9347 gen_store_fpr32(ctx, fp1, fd);
9348 tcg_temp_free_i32(fp1);
9349 tcg_temp_free_i32(fp0);
9350 opn = "maxa.s";
9351 } else {
9352 /* OPC_RSQRT2_S */
9353 check_cp1_64bitmode(ctx);
9355 TCGv_i32 fp0 = tcg_temp_new_i32();
9356 TCGv_i32 fp1 = tcg_temp_new_i32();
9358 gen_load_fpr32(ctx, fp0, fs);
9359 gen_load_fpr32(ctx, fp1, ft);
9360 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9361 tcg_temp_free_i32(fp1);
9362 gen_store_fpr32(ctx, fp0, fd);
9363 tcg_temp_free_i32(fp0);
9365 opn = "rsqrt2.s";
9367 break;
9368 case OPC_CVT_D_S:
9369 check_cp1_registers(ctx, fd);
9371 TCGv_i32 fp32 = tcg_temp_new_i32();
9372 TCGv_i64 fp64 = tcg_temp_new_i64();
9374 gen_load_fpr32(ctx, fp32, fs);
9375 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9376 tcg_temp_free_i32(fp32);
9377 gen_store_fpr64(ctx, fp64, fd);
9378 tcg_temp_free_i64(fp64);
9380 opn = "cvt.d.s";
9381 break;
9382 case OPC_CVT_W_S:
9384 TCGv_i32 fp0 = tcg_temp_new_i32();
9386 gen_load_fpr32(ctx, fp0, fs);
9387 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
9388 gen_store_fpr32(ctx, fp0, fd);
9389 tcg_temp_free_i32(fp0);
9391 opn = "cvt.w.s";
9392 break;
9393 case OPC_CVT_L_S:
9394 check_cp1_64bitmode(ctx);
9396 TCGv_i32 fp32 = tcg_temp_new_i32();
9397 TCGv_i64 fp64 = tcg_temp_new_i64();
9399 gen_load_fpr32(ctx, fp32, fs);
9400 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
9401 tcg_temp_free_i32(fp32);
9402 gen_store_fpr64(ctx, fp64, fd);
9403 tcg_temp_free_i64(fp64);
9405 opn = "cvt.l.s";
9406 break;
9407 case OPC_CVT_PS_S:
9408 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9409 check_cp1_64bitmode(ctx);
9411 TCGv_i64 fp64 = tcg_temp_new_i64();
9412 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9413 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9415 gen_load_fpr32(ctx, fp32_0, fs);
9416 gen_load_fpr32(ctx, fp32_1, ft);
9417 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9418 tcg_temp_free_i32(fp32_1);
9419 tcg_temp_free_i32(fp32_0);
9420 gen_store_fpr64(ctx, fp64, fd);
9421 tcg_temp_free_i64(fp64);
9423 opn = "cvt.ps.s";
9424 break;
9425 case OPC_CMP_F_S:
9426 case OPC_CMP_UN_S:
9427 case OPC_CMP_EQ_S:
9428 case OPC_CMP_UEQ_S:
9429 case OPC_CMP_OLT_S:
9430 case OPC_CMP_ULT_S:
9431 case OPC_CMP_OLE_S:
9432 case OPC_CMP_ULE_S:
9433 case OPC_CMP_SF_S:
9434 case OPC_CMP_NGLE_S:
9435 case OPC_CMP_SEQ_S:
9436 case OPC_CMP_NGL_S:
9437 case OPC_CMP_LT_S:
9438 case OPC_CMP_NGE_S:
9439 case OPC_CMP_LE_S:
9440 case OPC_CMP_NGT_S:
9441 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9442 if (ctx->opcode & (1 << 6)) {
9443 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9444 opn = condnames_abs[func-48];
9445 } else {
9446 gen_cmp_s(ctx, func-48, ft, fs, cc);
9447 opn = condnames[func-48];
9449 break;
9450 case OPC_ADD_D:
9451 check_cp1_registers(ctx, fs | ft | fd);
9453 TCGv_i64 fp0 = tcg_temp_new_i64();
9454 TCGv_i64 fp1 = tcg_temp_new_i64();
9456 gen_load_fpr64(ctx, fp0, fs);
9457 gen_load_fpr64(ctx, fp1, ft);
9458 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9459 tcg_temp_free_i64(fp1);
9460 gen_store_fpr64(ctx, fp0, fd);
9461 tcg_temp_free_i64(fp0);
9463 opn = "add.d";
9464 optype = BINOP;
9465 break;
9466 case OPC_SUB_D:
9467 check_cp1_registers(ctx, fs | ft | fd);
9469 TCGv_i64 fp0 = tcg_temp_new_i64();
9470 TCGv_i64 fp1 = tcg_temp_new_i64();
9472 gen_load_fpr64(ctx, fp0, fs);
9473 gen_load_fpr64(ctx, fp1, ft);
9474 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9475 tcg_temp_free_i64(fp1);
9476 gen_store_fpr64(ctx, fp0, fd);
9477 tcg_temp_free_i64(fp0);
9479 opn = "sub.d";
9480 optype = BINOP;
9481 break;
9482 case OPC_MUL_D:
9483 check_cp1_registers(ctx, fs | ft | fd);
9485 TCGv_i64 fp0 = tcg_temp_new_i64();
9486 TCGv_i64 fp1 = tcg_temp_new_i64();
9488 gen_load_fpr64(ctx, fp0, fs);
9489 gen_load_fpr64(ctx, fp1, ft);
9490 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9491 tcg_temp_free_i64(fp1);
9492 gen_store_fpr64(ctx, fp0, fd);
9493 tcg_temp_free_i64(fp0);
9495 opn = "mul.d";
9496 optype = BINOP;
9497 break;
9498 case OPC_DIV_D:
9499 check_cp1_registers(ctx, fs | ft | fd);
9501 TCGv_i64 fp0 = tcg_temp_new_i64();
9502 TCGv_i64 fp1 = tcg_temp_new_i64();
9504 gen_load_fpr64(ctx, fp0, fs);
9505 gen_load_fpr64(ctx, fp1, ft);
9506 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9507 tcg_temp_free_i64(fp1);
9508 gen_store_fpr64(ctx, fp0, fd);
9509 tcg_temp_free_i64(fp0);
9511 opn = "div.d";
9512 optype = BINOP;
9513 break;
9514 case OPC_SQRT_D:
9515 check_cp1_registers(ctx, fs | fd);
9517 TCGv_i64 fp0 = tcg_temp_new_i64();
9519 gen_load_fpr64(ctx, fp0, fs);
9520 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9521 gen_store_fpr64(ctx, fp0, fd);
9522 tcg_temp_free_i64(fp0);
9524 opn = "sqrt.d";
9525 break;
9526 case OPC_ABS_D:
9527 check_cp1_registers(ctx, fs | fd);
9529 TCGv_i64 fp0 = tcg_temp_new_i64();
9531 gen_load_fpr64(ctx, fp0, fs);
9532 gen_helper_float_abs_d(fp0, fp0);
9533 gen_store_fpr64(ctx, fp0, fd);
9534 tcg_temp_free_i64(fp0);
9536 opn = "abs.d";
9537 break;
9538 case OPC_MOV_D:
9539 check_cp1_registers(ctx, fs | fd);
9541 TCGv_i64 fp0 = tcg_temp_new_i64();
9543 gen_load_fpr64(ctx, fp0, fs);
9544 gen_store_fpr64(ctx, fp0, fd);
9545 tcg_temp_free_i64(fp0);
9547 opn = "mov.d";
9548 break;
9549 case OPC_NEG_D:
9550 check_cp1_registers(ctx, fs | fd);
9552 TCGv_i64 fp0 = tcg_temp_new_i64();
9554 gen_load_fpr64(ctx, fp0, fs);
9555 gen_helper_float_chs_d(fp0, fp0);
9556 gen_store_fpr64(ctx, fp0, fd);
9557 tcg_temp_free_i64(fp0);
9559 opn = "neg.d";
9560 break;
9561 case OPC_ROUND_L_D:
9562 check_cp1_64bitmode(ctx);
9564 TCGv_i64 fp0 = tcg_temp_new_i64();
9566 gen_load_fpr64(ctx, fp0, fs);
9567 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
9568 gen_store_fpr64(ctx, fp0, fd);
9569 tcg_temp_free_i64(fp0);
9571 opn = "round.l.d";
9572 break;
9573 case OPC_TRUNC_L_D:
9574 check_cp1_64bitmode(ctx);
9576 TCGv_i64 fp0 = tcg_temp_new_i64();
9578 gen_load_fpr64(ctx, fp0, fs);
9579 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
9580 gen_store_fpr64(ctx, fp0, fd);
9581 tcg_temp_free_i64(fp0);
9583 opn = "trunc.l.d";
9584 break;
9585 case OPC_CEIL_L_D:
9586 check_cp1_64bitmode(ctx);
9588 TCGv_i64 fp0 = tcg_temp_new_i64();
9590 gen_load_fpr64(ctx, fp0, fs);
9591 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
9592 gen_store_fpr64(ctx, fp0, fd);
9593 tcg_temp_free_i64(fp0);
9595 opn = "ceil.l.d";
9596 break;
9597 case OPC_FLOOR_L_D:
9598 check_cp1_64bitmode(ctx);
9600 TCGv_i64 fp0 = tcg_temp_new_i64();
9602 gen_load_fpr64(ctx, fp0, fs);
9603 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
9604 gen_store_fpr64(ctx, fp0, fd);
9605 tcg_temp_free_i64(fp0);
9607 opn = "floor.l.d";
9608 break;
9609 case OPC_ROUND_W_D:
9610 check_cp1_registers(ctx, fs);
9612 TCGv_i32 fp32 = tcg_temp_new_i32();
9613 TCGv_i64 fp64 = tcg_temp_new_i64();
9615 gen_load_fpr64(ctx, fp64, fs);
9616 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
9617 tcg_temp_free_i64(fp64);
9618 gen_store_fpr32(ctx, fp32, fd);
9619 tcg_temp_free_i32(fp32);
9621 opn = "round.w.d";
9622 break;
9623 case OPC_TRUNC_W_D:
9624 check_cp1_registers(ctx, fs);
9626 TCGv_i32 fp32 = tcg_temp_new_i32();
9627 TCGv_i64 fp64 = tcg_temp_new_i64();
9629 gen_load_fpr64(ctx, fp64, fs);
9630 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
9631 tcg_temp_free_i64(fp64);
9632 gen_store_fpr32(ctx, fp32, fd);
9633 tcg_temp_free_i32(fp32);
9635 opn = "trunc.w.d";
9636 break;
9637 case OPC_CEIL_W_D:
9638 check_cp1_registers(ctx, fs);
9640 TCGv_i32 fp32 = tcg_temp_new_i32();
9641 TCGv_i64 fp64 = tcg_temp_new_i64();
9643 gen_load_fpr64(ctx, fp64, fs);
9644 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
9645 tcg_temp_free_i64(fp64);
9646 gen_store_fpr32(ctx, fp32, fd);
9647 tcg_temp_free_i32(fp32);
9649 opn = "ceil.w.d";
9650 break;
9651 case OPC_FLOOR_W_D:
9652 check_cp1_registers(ctx, fs);
9654 TCGv_i32 fp32 = tcg_temp_new_i32();
9655 TCGv_i64 fp64 = tcg_temp_new_i64();
9657 gen_load_fpr64(ctx, fp64, fs);
9658 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
9659 tcg_temp_free_i64(fp64);
9660 gen_store_fpr32(ctx, fp32, fd);
9661 tcg_temp_free_i32(fp32);
9663 opn = "floor.w.d";
9664 break;
9665 case OPC_SEL_D:
9666 check_insn(ctx, ISA_MIPS32R6);
9667 gen_sel_d(ctx, op1, fd, ft, fs);
9668 opn = "sel.d";
9669 break;
9670 case OPC_SELEQZ_D:
9671 check_insn(ctx, ISA_MIPS32R6);
9672 gen_sel_d(ctx, op1, fd, ft, fs);
9673 opn = "seleqz.d";
9674 break;
9675 case OPC_SELNEZ_D:
9676 check_insn(ctx, ISA_MIPS32R6);
9677 gen_sel_d(ctx, op1, fd, ft, fs);
9678 opn = "selnez.d";
9679 break;
9680 case OPC_MOVCF_D:
9681 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9682 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9683 opn = "movcf.d";
9684 break;
9685 case OPC_MOVZ_D:
9686 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9688 TCGLabel *l1 = gen_new_label();
9689 TCGv_i64 fp0;
9691 if (ft != 0) {
9692 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9694 fp0 = tcg_temp_new_i64();
9695 gen_load_fpr64(ctx, fp0, fs);
9696 gen_store_fpr64(ctx, fp0, fd);
9697 tcg_temp_free_i64(fp0);
9698 gen_set_label(l1);
9700 opn = "movz.d";
9701 break;
9702 case OPC_MOVN_D:
9703 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9705 TCGLabel *l1 = gen_new_label();
9706 TCGv_i64 fp0;
9708 if (ft != 0) {
9709 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9710 fp0 = tcg_temp_new_i64();
9711 gen_load_fpr64(ctx, fp0, fs);
9712 gen_store_fpr64(ctx, fp0, fd);
9713 tcg_temp_free_i64(fp0);
9714 gen_set_label(l1);
9717 opn = "movn.d";
9718 break;
9719 case OPC_RECIP_D:
9720 check_cp1_64bitmode(ctx);
9722 TCGv_i64 fp0 = tcg_temp_new_i64();
9724 gen_load_fpr64(ctx, fp0, fs);
9725 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9726 gen_store_fpr64(ctx, fp0, fd);
9727 tcg_temp_free_i64(fp0);
9729 opn = "recip.d";
9730 break;
9731 case OPC_RSQRT_D:
9732 check_cp1_64bitmode(ctx);
9734 TCGv_i64 fp0 = tcg_temp_new_i64();
9736 gen_load_fpr64(ctx, fp0, fs);
9737 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9738 gen_store_fpr64(ctx, fp0, fd);
9739 tcg_temp_free_i64(fp0);
9741 opn = "rsqrt.d";
9742 break;
9743 case OPC_MADDF_D:
9744 check_insn(ctx, ISA_MIPS32R6);
9746 TCGv_i64 fp0 = tcg_temp_new_i64();
9747 TCGv_i64 fp1 = tcg_temp_new_i64();
9748 TCGv_i64 fp2 = tcg_temp_new_i64();
9749 gen_load_fpr64(ctx, fp0, fs);
9750 gen_load_fpr64(ctx, fp1, ft);
9751 gen_load_fpr64(ctx, fp2, fd);
9752 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9753 gen_store_fpr64(ctx, fp2, fd);
9754 tcg_temp_free_i64(fp2);
9755 tcg_temp_free_i64(fp1);
9756 tcg_temp_free_i64(fp0);
9757 opn = "maddf.d";
9759 break;
9760 case OPC_MSUBF_D:
9761 check_insn(ctx, ISA_MIPS32R6);
9763 TCGv_i64 fp0 = tcg_temp_new_i64();
9764 TCGv_i64 fp1 = tcg_temp_new_i64();
9765 TCGv_i64 fp2 = tcg_temp_new_i64();
9766 gen_load_fpr64(ctx, fp0, fs);
9767 gen_load_fpr64(ctx, fp1, ft);
9768 gen_load_fpr64(ctx, fp2, fd);
9769 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9770 gen_store_fpr64(ctx, fp2, fd);
9771 tcg_temp_free_i64(fp2);
9772 tcg_temp_free_i64(fp1);
9773 tcg_temp_free_i64(fp0);
9774 opn = "msubf.d";
9776 break;
9777 case OPC_RINT_D:
9778 check_insn(ctx, ISA_MIPS32R6);
9780 TCGv_i64 fp0 = tcg_temp_new_i64();
9781 gen_load_fpr64(ctx, fp0, fs);
9782 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9783 gen_store_fpr64(ctx, fp0, fd);
9784 tcg_temp_free_i64(fp0);
9785 opn = "rint.d";
9787 break;
9788 case OPC_CLASS_D:
9789 check_insn(ctx, ISA_MIPS32R6);
9791 TCGv_i64 fp0 = tcg_temp_new_i64();
9792 gen_load_fpr64(ctx, fp0, fs);
9793 gen_helper_float_class_d(fp0, fp0);
9794 gen_store_fpr64(ctx, fp0, fd);
9795 tcg_temp_free_i64(fp0);
9796 opn = "class.d";
9798 break;
9799 case OPC_MIN_D: /* OPC_RECIP2_D */
9800 if (ctx->insn_flags & ISA_MIPS32R6) {
9801 /* OPC_MIN_D */
9802 TCGv_i64 fp0 = tcg_temp_new_i64();
9803 TCGv_i64 fp1 = tcg_temp_new_i64();
9804 gen_load_fpr64(ctx, fp0, fs);
9805 gen_load_fpr64(ctx, fp1, ft);
9806 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9807 gen_store_fpr64(ctx, fp1, fd);
9808 tcg_temp_free_i64(fp1);
9809 tcg_temp_free_i64(fp0);
9810 opn = "min.d";
9811 } else {
9812 /* OPC_RECIP2_D */
9813 check_cp1_64bitmode(ctx);
9815 TCGv_i64 fp0 = tcg_temp_new_i64();
9816 TCGv_i64 fp1 = tcg_temp_new_i64();
9818 gen_load_fpr64(ctx, fp0, fs);
9819 gen_load_fpr64(ctx, fp1, ft);
9820 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9821 tcg_temp_free_i64(fp1);
9822 gen_store_fpr64(ctx, fp0, fd);
9823 tcg_temp_free_i64(fp0);
9825 opn = "recip2.d";
9827 break;
9828 case OPC_MINA_D: /* OPC_RECIP1_D */
9829 if (ctx->insn_flags & ISA_MIPS32R6) {
9830 /* OPC_MINA_D */
9831 TCGv_i64 fp0 = tcg_temp_new_i64();
9832 TCGv_i64 fp1 = tcg_temp_new_i64();
9833 gen_load_fpr64(ctx, fp0, fs);
9834 gen_load_fpr64(ctx, fp1, ft);
9835 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9836 gen_store_fpr64(ctx, fp1, fd);
9837 tcg_temp_free_i64(fp1);
9838 tcg_temp_free_i64(fp0);
9839 opn = "mina.d";
9840 } else {
9841 /* OPC_RECIP1_D */
9842 check_cp1_64bitmode(ctx);
9844 TCGv_i64 fp0 = tcg_temp_new_i64();
9846 gen_load_fpr64(ctx, fp0, fs);
9847 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9848 gen_store_fpr64(ctx, fp0, fd);
9849 tcg_temp_free_i64(fp0);
9851 opn = "recip1.d";
9853 break;
9854 case OPC_MAX_D: /* OPC_RSQRT1_D */
9855 if (ctx->insn_flags & ISA_MIPS32R6) {
9856 /* OPC_MAX_D */
9857 TCGv_i64 fp0 = tcg_temp_new_i64();
9858 TCGv_i64 fp1 = tcg_temp_new_i64();
9859 gen_load_fpr64(ctx, fp0, fs);
9860 gen_load_fpr64(ctx, fp1, ft);
9861 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9862 gen_store_fpr64(ctx, fp1, fd);
9863 tcg_temp_free_i64(fp1);
9864 tcg_temp_free_i64(fp0);
9865 opn = "max.d";
9866 } else {
9867 /* OPC_RSQRT1_D */
9868 check_cp1_64bitmode(ctx);
9870 TCGv_i64 fp0 = tcg_temp_new_i64();
9872 gen_load_fpr64(ctx, fp0, fs);
9873 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9874 gen_store_fpr64(ctx, fp0, fd);
9875 tcg_temp_free_i64(fp0);
9877 opn = "rsqrt1.d";
9879 break;
9880 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9881 if (ctx->insn_flags & ISA_MIPS32R6) {
9882 /* OPC_MAXA_D */
9883 TCGv_i64 fp0 = tcg_temp_new_i64();
9884 TCGv_i64 fp1 = tcg_temp_new_i64();
9885 gen_load_fpr64(ctx, fp0, fs);
9886 gen_load_fpr64(ctx, fp1, ft);
9887 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9888 gen_store_fpr64(ctx, fp1, fd);
9889 tcg_temp_free_i64(fp1);
9890 tcg_temp_free_i64(fp0);
9891 opn = "maxa.d";
9892 } else {
9893 /* OPC_RSQRT2_D */
9894 check_cp1_64bitmode(ctx);
9896 TCGv_i64 fp0 = tcg_temp_new_i64();
9897 TCGv_i64 fp1 = tcg_temp_new_i64();
9899 gen_load_fpr64(ctx, fp0, fs);
9900 gen_load_fpr64(ctx, fp1, ft);
9901 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9902 tcg_temp_free_i64(fp1);
9903 gen_store_fpr64(ctx, fp0, fd);
9904 tcg_temp_free_i64(fp0);
9906 opn = "rsqrt2.d";
9908 break;
9909 case OPC_CMP_F_D:
9910 case OPC_CMP_UN_D:
9911 case OPC_CMP_EQ_D:
9912 case OPC_CMP_UEQ_D:
9913 case OPC_CMP_OLT_D:
9914 case OPC_CMP_ULT_D:
9915 case OPC_CMP_OLE_D:
9916 case OPC_CMP_ULE_D:
9917 case OPC_CMP_SF_D:
9918 case OPC_CMP_NGLE_D:
9919 case OPC_CMP_SEQ_D:
9920 case OPC_CMP_NGL_D:
9921 case OPC_CMP_LT_D:
9922 case OPC_CMP_NGE_D:
9923 case OPC_CMP_LE_D:
9924 case OPC_CMP_NGT_D:
9925 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9926 if (ctx->opcode & (1 << 6)) {
9927 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9928 opn = condnames_abs[func-48];
9929 } else {
9930 gen_cmp_d(ctx, func-48, ft, fs, cc);
9931 opn = condnames[func-48];
9933 break;
9934 case OPC_CVT_S_D:
9935 check_cp1_registers(ctx, fs);
9937 TCGv_i32 fp32 = tcg_temp_new_i32();
9938 TCGv_i64 fp64 = tcg_temp_new_i64();
9940 gen_load_fpr64(ctx, fp64, fs);
9941 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
9942 tcg_temp_free_i64(fp64);
9943 gen_store_fpr32(ctx, fp32, fd);
9944 tcg_temp_free_i32(fp32);
9946 opn = "cvt.s.d";
9947 break;
9948 case OPC_CVT_W_D:
9949 check_cp1_registers(ctx, fs);
9951 TCGv_i32 fp32 = tcg_temp_new_i32();
9952 TCGv_i64 fp64 = tcg_temp_new_i64();
9954 gen_load_fpr64(ctx, fp64, fs);
9955 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
9956 tcg_temp_free_i64(fp64);
9957 gen_store_fpr32(ctx, fp32, fd);
9958 tcg_temp_free_i32(fp32);
9960 opn = "cvt.w.d";
9961 break;
9962 case OPC_CVT_L_D:
9963 check_cp1_64bitmode(ctx);
9965 TCGv_i64 fp0 = tcg_temp_new_i64();
9967 gen_load_fpr64(ctx, fp0, fs);
9968 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
9969 gen_store_fpr64(ctx, fp0, fd);
9970 tcg_temp_free_i64(fp0);
9972 opn = "cvt.l.d";
9973 break;
9974 case OPC_CVT_S_W:
9976 TCGv_i32 fp0 = tcg_temp_new_i32();
9978 gen_load_fpr32(ctx, fp0, fs);
9979 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
9980 gen_store_fpr32(ctx, fp0, fd);
9981 tcg_temp_free_i32(fp0);
9983 opn = "cvt.s.w";
9984 break;
9985 case OPC_CVT_D_W:
9986 check_cp1_registers(ctx, fd);
9988 TCGv_i32 fp32 = tcg_temp_new_i32();
9989 TCGv_i64 fp64 = tcg_temp_new_i64();
9991 gen_load_fpr32(ctx, fp32, fs);
9992 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
9993 tcg_temp_free_i32(fp32);
9994 gen_store_fpr64(ctx, fp64, fd);
9995 tcg_temp_free_i64(fp64);
9997 opn = "cvt.d.w";
9998 break;
9999 case OPC_CVT_S_L:
10000 check_cp1_64bitmode(ctx);
10002 TCGv_i32 fp32 = tcg_temp_new_i32();
10003 TCGv_i64 fp64 = tcg_temp_new_i64();
10005 gen_load_fpr64(ctx, fp64, fs);
10006 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
10007 tcg_temp_free_i64(fp64);
10008 gen_store_fpr32(ctx, fp32, fd);
10009 tcg_temp_free_i32(fp32);
10011 opn = "cvt.s.l";
10012 break;
10013 case OPC_CVT_D_L:
10014 check_cp1_64bitmode(ctx);
10016 TCGv_i64 fp0 = tcg_temp_new_i64();
10018 gen_load_fpr64(ctx, fp0, fs);
10019 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
10020 gen_store_fpr64(ctx, fp0, fd);
10021 tcg_temp_free_i64(fp0);
10023 opn = "cvt.d.l";
10024 break;
10025 case OPC_CVT_PS_PW:
10026 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10027 check_cp1_64bitmode(ctx);
10029 TCGv_i64 fp0 = tcg_temp_new_i64();
10031 gen_load_fpr64(ctx, fp0, fs);
10032 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
10033 gen_store_fpr64(ctx, fp0, fd);
10034 tcg_temp_free_i64(fp0);
10036 opn = "cvt.ps.pw";
10037 break;
10038 case OPC_ADD_PS:
10039 check_cp1_64bitmode(ctx);
10041 TCGv_i64 fp0 = tcg_temp_new_i64();
10042 TCGv_i64 fp1 = tcg_temp_new_i64();
10044 gen_load_fpr64(ctx, fp0, fs);
10045 gen_load_fpr64(ctx, fp1, ft);
10046 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
10047 tcg_temp_free_i64(fp1);
10048 gen_store_fpr64(ctx, fp0, fd);
10049 tcg_temp_free_i64(fp0);
10051 opn = "add.ps";
10052 break;
10053 case OPC_SUB_PS:
10054 check_cp1_64bitmode(ctx);
10056 TCGv_i64 fp0 = tcg_temp_new_i64();
10057 TCGv_i64 fp1 = tcg_temp_new_i64();
10059 gen_load_fpr64(ctx, fp0, fs);
10060 gen_load_fpr64(ctx, fp1, ft);
10061 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
10062 tcg_temp_free_i64(fp1);
10063 gen_store_fpr64(ctx, fp0, fd);
10064 tcg_temp_free_i64(fp0);
10066 opn = "sub.ps";
10067 break;
10068 case OPC_MUL_PS:
10069 check_cp1_64bitmode(ctx);
10071 TCGv_i64 fp0 = tcg_temp_new_i64();
10072 TCGv_i64 fp1 = tcg_temp_new_i64();
10074 gen_load_fpr64(ctx, fp0, fs);
10075 gen_load_fpr64(ctx, fp1, ft);
10076 gen_helper_float_mul_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 opn = "mul.ps";
10082 break;
10083 case OPC_ABS_PS:
10084 check_cp1_64bitmode(ctx);
10086 TCGv_i64 fp0 = tcg_temp_new_i64();
10088 gen_load_fpr64(ctx, fp0, fs);
10089 gen_helper_float_abs_ps(fp0, fp0);
10090 gen_store_fpr64(ctx, fp0, fd);
10091 tcg_temp_free_i64(fp0);
10093 opn = "abs.ps";
10094 break;
10095 case OPC_MOV_PS:
10096 check_cp1_64bitmode(ctx);
10098 TCGv_i64 fp0 = tcg_temp_new_i64();
10100 gen_load_fpr64(ctx, fp0, fs);
10101 gen_store_fpr64(ctx, fp0, fd);
10102 tcg_temp_free_i64(fp0);
10104 opn = "mov.ps";
10105 break;
10106 case OPC_NEG_PS:
10107 check_cp1_64bitmode(ctx);
10109 TCGv_i64 fp0 = tcg_temp_new_i64();
10111 gen_load_fpr64(ctx, fp0, fs);
10112 gen_helper_float_chs_ps(fp0, fp0);
10113 gen_store_fpr64(ctx, fp0, fd);
10114 tcg_temp_free_i64(fp0);
10116 opn = "neg.ps";
10117 break;
10118 case OPC_MOVCF_PS:
10119 check_cp1_64bitmode(ctx);
10120 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10121 opn = "movcf.ps";
10122 break;
10123 case OPC_MOVZ_PS:
10124 check_cp1_64bitmode(ctx);
10126 TCGLabel *l1 = gen_new_label();
10127 TCGv_i64 fp0;
10129 if (ft != 0)
10130 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10131 fp0 = tcg_temp_new_i64();
10132 gen_load_fpr64(ctx, fp0, fs);
10133 gen_store_fpr64(ctx, fp0, fd);
10134 tcg_temp_free_i64(fp0);
10135 gen_set_label(l1);
10137 opn = "movz.ps";
10138 break;
10139 case OPC_MOVN_PS:
10140 check_cp1_64bitmode(ctx);
10142 TCGLabel *l1 = gen_new_label();
10143 TCGv_i64 fp0;
10145 if (ft != 0) {
10146 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10147 fp0 = tcg_temp_new_i64();
10148 gen_load_fpr64(ctx, fp0, fs);
10149 gen_store_fpr64(ctx, fp0, fd);
10150 tcg_temp_free_i64(fp0);
10151 gen_set_label(l1);
10154 opn = "movn.ps";
10155 break;
10156 case OPC_ADDR_PS:
10157 check_cp1_64bitmode(ctx);
10159 TCGv_i64 fp0 = tcg_temp_new_i64();
10160 TCGv_i64 fp1 = tcg_temp_new_i64();
10162 gen_load_fpr64(ctx, fp0, ft);
10163 gen_load_fpr64(ctx, fp1, fs);
10164 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
10165 tcg_temp_free_i64(fp1);
10166 gen_store_fpr64(ctx, fp0, fd);
10167 tcg_temp_free_i64(fp0);
10169 opn = "addr.ps";
10170 break;
10171 case OPC_MULR_PS:
10172 check_cp1_64bitmode(ctx);
10174 TCGv_i64 fp0 = tcg_temp_new_i64();
10175 TCGv_i64 fp1 = tcg_temp_new_i64();
10177 gen_load_fpr64(ctx, fp0, ft);
10178 gen_load_fpr64(ctx, fp1, fs);
10179 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
10180 tcg_temp_free_i64(fp1);
10181 gen_store_fpr64(ctx, fp0, fd);
10182 tcg_temp_free_i64(fp0);
10184 opn = "mulr.ps";
10185 break;
10186 case OPC_RECIP2_PS:
10187 check_cp1_64bitmode(ctx);
10189 TCGv_i64 fp0 = tcg_temp_new_i64();
10190 TCGv_i64 fp1 = tcg_temp_new_i64();
10192 gen_load_fpr64(ctx, fp0, fs);
10193 gen_load_fpr64(ctx, fp1, ft);
10194 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
10195 tcg_temp_free_i64(fp1);
10196 gen_store_fpr64(ctx, fp0, fd);
10197 tcg_temp_free_i64(fp0);
10199 opn = "recip2.ps";
10200 break;
10201 case OPC_RECIP1_PS:
10202 check_cp1_64bitmode(ctx);
10204 TCGv_i64 fp0 = tcg_temp_new_i64();
10206 gen_load_fpr64(ctx, fp0, fs);
10207 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
10208 gen_store_fpr64(ctx, fp0, fd);
10209 tcg_temp_free_i64(fp0);
10211 opn = "recip1.ps";
10212 break;
10213 case OPC_RSQRT1_PS:
10214 check_cp1_64bitmode(ctx);
10216 TCGv_i64 fp0 = tcg_temp_new_i64();
10218 gen_load_fpr64(ctx, fp0, fs);
10219 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
10220 gen_store_fpr64(ctx, fp0, fd);
10221 tcg_temp_free_i64(fp0);
10223 opn = "rsqrt1.ps";
10224 break;
10225 case OPC_RSQRT2_PS:
10226 check_cp1_64bitmode(ctx);
10228 TCGv_i64 fp0 = tcg_temp_new_i64();
10229 TCGv_i64 fp1 = tcg_temp_new_i64();
10231 gen_load_fpr64(ctx, fp0, fs);
10232 gen_load_fpr64(ctx, fp1, ft);
10233 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
10234 tcg_temp_free_i64(fp1);
10235 gen_store_fpr64(ctx, fp0, fd);
10236 tcg_temp_free_i64(fp0);
10238 opn = "rsqrt2.ps";
10239 break;
10240 case OPC_CVT_S_PU:
10241 check_cp1_64bitmode(ctx);
10243 TCGv_i32 fp0 = tcg_temp_new_i32();
10245 gen_load_fpr32h(ctx, fp0, fs);
10246 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
10247 gen_store_fpr32(ctx, fp0, fd);
10248 tcg_temp_free_i32(fp0);
10250 opn = "cvt.s.pu";
10251 break;
10252 case OPC_CVT_PW_PS:
10253 check_cp1_64bitmode(ctx);
10255 TCGv_i64 fp0 = tcg_temp_new_i64();
10257 gen_load_fpr64(ctx, fp0, fs);
10258 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
10259 gen_store_fpr64(ctx, fp0, fd);
10260 tcg_temp_free_i64(fp0);
10262 opn = "cvt.pw.ps";
10263 break;
10264 case OPC_CVT_S_PL:
10265 check_cp1_64bitmode(ctx);
10267 TCGv_i32 fp0 = tcg_temp_new_i32();
10269 gen_load_fpr32(ctx, fp0, fs);
10270 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10271 gen_store_fpr32(ctx, fp0, fd);
10272 tcg_temp_free_i32(fp0);
10274 opn = "cvt.s.pl";
10275 break;
10276 case OPC_PLL_PS:
10277 check_cp1_64bitmode(ctx);
10279 TCGv_i32 fp0 = tcg_temp_new_i32();
10280 TCGv_i32 fp1 = tcg_temp_new_i32();
10282 gen_load_fpr32(ctx, fp0, fs);
10283 gen_load_fpr32(ctx, fp1, ft);
10284 gen_store_fpr32h(ctx, fp0, fd);
10285 gen_store_fpr32(ctx, fp1, fd);
10286 tcg_temp_free_i32(fp0);
10287 tcg_temp_free_i32(fp1);
10289 opn = "pll.ps";
10290 break;
10291 case OPC_PLU_PS:
10292 check_cp1_64bitmode(ctx);
10294 TCGv_i32 fp0 = tcg_temp_new_i32();
10295 TCGv_i32 fp1 = tcg_temp_new_i32();
10297 gen_load_fpr32(ctx, fp0, fs);
10298 gen_load_fpr32h(ctx, fp1, ft);
10299 gen_store_fpr32(ctx, fp1, fd);
10300 gen_store_fpr32h(ctx, fp0, fd);
10301 tcg_temp_free_i32(fp0);
10302 tcg_temp_free_i32(fp1);
10304 opn = "plu.ps";
10305 break;
10306 case OPC_PUL_PS:
10307 check_cp1_64bitmode(ctx);
10309 TCGv_i32 fp0 = tcg_temp_new_i32();
10310 TCGv_i32 fp1 = tcg_temp_new_i32();
10312 gen_load_fpr32h(ctx, fp0, fs);
10313 gen_load_fpr32(ctx, fp1, ft);
10314 gen_store_fpr32(ctx, fp1, fd);
10315 gen_store_fpr32h(ctx, fp0, fd);
10316 tcg_temp_free_i32(fp0);
10317 tcg_temp_free_i32(fp1);
10319 opn = "pul.ps";
10320 break;
10321 case OPC_PUU_PS:
10322 check_cp1_64bitmode(ctx);
10324 TCGv_i32 fp0 = tcg_temp_new_i32();
10325 TCGv_i32 fp1 = tcg_temp_new_i32();
10327 gen_load_fpr32h(ctx, fp0, fs);
10328 gen_load_fpr32h(ctx, fp1, ft);
10329 gen_store_fpr32(ctx, fp1, fd);
10330 gen_store_fpr32h(ctx, fp0, fd);
10331 tcg_temp_free_i32(fp0);
10332 tcg_temp_free_i32(fp1);
10334 opn = "puu.ps";
10335 break;
10336 case OPC_CMP_F_PS:
10337 case OPC_CMP_UN_PS:
10338 case OPC_CMP_EQ_PS:
10339 case OPC_CMP_UEQ_PS:
10340 case OPC_CMP_OLT_PS:
10341 case OPC_CMP_ULT_PS:
10342 case OPC_CMP_OLE_PS:
10343 case OPC_CMP_ULE_PS:
10344 case OPC_CMP_SF_PS:
10345 case OPC_CMP_NGLE_PS:
10346 case OPC_CMP_SEQ_PS:
10347 case OPC_CMP_NGL_PS:
10348 case OPC_CMP_LT_PS:
10349 case OPC_CMP_NGE_PS:
10350 case OPC_CMP_LE_PS:
10351 case OPC_CMP_NGT_PS:
10352 if (ctx->opcode & (1 << 6)) {
10353 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10354 opn = condnames_abs[func-48];
10355 } else {
10356 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10357 opn = condnames[func-48];
10359 break;
10360 default:
10361 MIPS_INVAL(opn);
10362 generate_exception (ctx, EXCP_RI);
10363 return;
10365 (void)opn; /* avoid a compiler warning */
10366 switch (optype) {
10367 case BINOP:
10368 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
10369 break;
10370 case CMPOP:
10371 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
10372 break;
10373 default:
10374 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
10375 break;
10379 /* Coprocessor 3 (FPU) */
10380 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10381 int fd, int fs, int base, int index)
10383 const char *opn = "extended float load/store";
10384 int store = 0;
10385 TCGv t0 = tcg_temp_new();
10387 if (base == 0) {
10388 gen_load_gpr(t0, index);
10389 } else if (index == 0) {
10390 gen_load_gpr(t0, base);
10391 } else {
10392 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10394 /* Don't do NOP if destination is zero: we must perform the actual
10395 memory access. */
10396 switch (opc) {
10397 case OPC_LWXC1:
10398 check_cop1x(ctx);
10400 TCGv_i32 fp0 = tcg_temp_new_i32();
10402 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10403 tcg_gen_trunc_tl_i32(fp0, t0);
10404 gen_store_fpr32(ctx, fp0, fd);
10405 tcg_temp_free_i32(fp0);
10407 opn = "lwxc1";
10408 break;
10409 case OPC_LDXC1:
10410 check_cop1x(ctx);
10411 check_cp1_registers(ctx, fd);
10413 TCGv_i64 fp0 = tcg_temp_new_i64();
10414 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10415 gen_store_fpr64(ctx, fp0, fd);
10416 tcg_temp_free_i64(fp0);
10418 opn = "ldxc1";
10419 break;
10420 case OPC_LUXC1:
10421 check_cp1_64bitmode(ctx);
10422 tcg_gen_andi_tl(t0, t0, ~0x7);
10424 TCGv_i64 fp0 = tcg_temp_new_i64();
10426 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10427 gen_store_fpr64(ctx, fp0, fd);
10428 tcg_temp_free_i64(fp0);
10430 opn = "luxc1";
10431 break;
10432 case OPC_SWXC1:
10433 check_cop1x(ctx);
10435 TCGv_i32 fp0 = tcg_temp_new_i32();
10436 gen_load_fpr32(ctx, fp0, fs);
10437 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10438 tcg_temp_free_i32(fp0);
10440 opn = "swxc1";
10441 store = 1;
10442 break;
10443 case OPC_SDXC1:
10444 check_cop1x(ctx);
10445 check_cp1_registers(ctx, fs);
10447 TCGv_i64 fp0 = tcg_temp_new_i64();
10448 gen_load_fpr64(ctx, fp0, fs);
10449 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10450 tcg_temp_free_i64(fp0);
10452 opn = "sdxc1";
10453 store = 1;
10454 break;
10455 case OPC_SUXC1:
10456 check_cp1_64bitmode(ctx);
10457 tcg_gen_andi_tl(t0, t0, ~0x7);
10459 TCGv_i64 fp0 = tcg_temp_new_i64();
10460 gen_load_fpr64(ctx, fp0, fs);
10461 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10462 tcg_temp_free_i64(fp0);
10464 opn = "suxc1";
10465 store = 1;
10466 break;
10468 tcg_temp_free(t0);
10469 (void)opn; (void)store; /* avoid compiler warnings */
10470 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
10471 regnames[index], regnames[base]);
10474 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10475 int fd, int fr, int fs, int ft)
10477 const char *opn = "flt3_arith";
10479 switch (opc) {
10480 case OPC_ALNV_PS:
10481 check_cp1_64bitmode(ctx);
10483 TCGv t0 = tcg_temp_local_new();
10484 TCGv_i32 fp = tcg_temp_new_i32();
10485 TCGv_i32 fph = tcg_temp_new_i32();
10486 TCGLabel *l1 = gen_new_label();
10487 TCGLabel *l2 = gen_new_label();
10489 gen_load_gpr(t0, fr);
10490 tcg_gen_andi_tl(t0, t0, 0x7);
10492 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10493 gen_load_fpr32(ctx, fp, fs);
10494 gen_load_fpr32h(ctx, fph, fs);
10495 gen_store_fpr32(ctx, fp, fd);
10496 gen_store_fpr32h(ctx, fph, fd);
10497 tcg_gen_br(l2);
10498 gen_set_label(l1);
10499 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10500 tcg_temp_free(t0);
10501 #ifdef TARGET_WORDS_BIGENDIAN
10502 gen_load_fpr32(ctx, fp, fs);
10503 gen_load_fpr32h(ctx, fph, ft);
10504 gen_store_fpr32h(ctx, fp, fd);
10505 gen_store_fpr32(ctx, fph, fd);
10506 #else
10507 gen_load_fpr32h(ctx, fph, fs);
10508 gen_load_fpr32(ctx, fp, ft);
10509 gen_store_fpr32(ctx, fph, fd);
10510 gen_store_fpr32h(ctx, fp, fd);
10511 #endif
10512 gen_set_label(l2);
10513 tcg_temp_free_i32(fp);
10514 tcg_temp_free_i32(fph);
10516 opn = "alnv.ps";
10517 break;
10518 case OPC_MADD_S:
10519 check_cop1x(ctx);
10521 TCGv_i32 fp0 = tcg_temp_new_i32();
10522 TCGv_i32 fp1 = tcg_temp_new_i32();
10523 TCGv_i32 fp2 = tcg_temp_new_i32();
10525 gen_load_fpr32(ctx, fp0, fs);
10526 gen_load_fpr32(ctx, fp1, ft);
10527 gen_load_fpr32(ctx, fp2, fr);
10528 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10529 tcg_temp_free_i32(fp0);
10530 tcg_temp_free_i32(fp1);
10531 gen_store_fpr32(ctx, fp2, fd);
10532 tcg_temp_free_i32(fp2);
10534 opn = "madd.s";
10535 break;
10536 case OPC_MADD_D:
10537 check_cop1x(ctx);
10538 check_cp1_registers(ctx, fd | fs | ft | fr);
10540 TCGv_i64 fp0 = tcg_temp_new_i64();
10541 TCGv_i64 fp1 = tcg_temp_new_i64();
10542 TCGv_i64 fp2 = tcg_temp_new_i64();
10544 gen_load_fpr64(ctx, fp0, fs);
10545 gen_load_fpr64(ctx, fp1, ft);
10546 gen_load_fpr64(ctx, fp2, fr);
10547 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10548 tcg_temp_free_i64(fp0);
10549 tcg_temp_free_i64(fp1);
10550 gen_store_fpr64(ctx, fp2, fd);
10551 tcg_temp_free_i64(fp2);
10553 opn = "madd.d";
10554 break;
10555 case OPC_MADD_PS:
10556 check_cp1_64bitmode(ctx);
10558 TCGv_i64 fp0 = tcg_temp_new_i64();
10559 TCGv_i64 fp1 = tcg_temp_new_i64();
10560 TCGv_i64 fp2 = tcg_temp_new_i64();
10562 gen_load_fpr64(ctx, fp0, fs);
10563 gen_load_fpr64(ctx, fp1, ft);
10564 gen_load_fpr64(ctx, fp2, fr);
10565 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10566 tcg_temp_free_i64(fp0);
10567 tcg_temp_free_i64(fp1);
10568 gen_store_fpr64(ctx, fp2, fd);
10569 tcg_temp_free_i64(fp2);
10571 opn = "madd.ps";
10572 break;
10573 case OPC_MSUB_S:
10574 check_cop1x(ctx);
10576 TCGv_i32 fp0 = tcg_temp_new_i32();
10577 TCGv_i32 fp1 = tcg_temp_new_i32();
10578 TCGv_i32 fp2 = tcg_temp_new_i32();
10580 gen_load_fpr32(ctx, fp0, fs);
10581 gen_load_fpr32(ctx, fp1, ft);
10582 gen_load_fpr32(ctx, fp2, fr);
10583 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10584 tcg_temp_free_i32(fp0);
10585 tcg_temp_free_i32(fp1);
10586 gen_store_fpr32(ctx, fp2, fd);
10587 tcg_temp_free_i32(fp2);
10589 opn = "msub.s";
10590 break;
10591 case OPC_MSUB_D:
10592 check_cop1x(ctx);
10593 check_cp1_registers(ctx, fd | fs | ft | fr);
10595 TCGv_i64 fp0 = tcg_temp_new_i64();
10596 TCGv_i64 fp1 = tcg_temp_new_i64();
10597 TCGv_i64 fp2 = tcg_temp_new_i64();
10599 gen_load_fpr64(ctx, fp0, fs);
10600 gen_load_fpr64(ctx, fp1, ft);
10601 gen_load_fpr64(ctx, fp2, fr);
10602 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10603 tcg_temp_free_i64(fp0);
10604 tcg_temp_free_i64(fp1);
10605 gen_store_fpr64(ctx, fp2, fd);
10606 tcg_temp_free_i64(fp2);
10608 opn = "msub.d";
10609 break;
10610 case OPC_MSUB_PS:
10611 check_cp1_64bitmode(ctx);
10613 TCGv_i64 fp0 = tcg_temp_new_i64();
10614 TCGv_i64 fp1 = tcg_temp_new_i64();
10615 TCGv_i64 fp2 = tcg_temp_new_i64();
10617 gen_load_fpr64(ctx, fp0, fs);
10618 gen_load_fpr64(ctx, fp1, ft);
10619 gen_load_fpr64(ctx, fp2, fr);
10620 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10621 tcg_temp_free_i64(fp0);
10622 tcg_temp_free_i64(fp1);
10623 gen_store_fpr64(ctx, fp2, fd);
10624 tcg_temp_free_i64(fp2);
10626 opn = "msub.ps";
10627 break;
10628 case OPC_NMADD_S:
10629 check_cop1x(ctx);
10631 TCGv_i32 fp0 = tcg_temp_new_i32();
10632 TCGv_i32 fp1 = tcg_temp_new_i32();
10633 TCGv_i32 fp2 = tcg_temp_new_i32();
10635 gen_load_fpr32(ctx, fp0, fs);
10636 gen_load_fpr32(ctx, fp1, ft);
10637 gen_load_fpr32(ctx, fp2, fr);
10638 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10639 tcg_temp_free_i32(fp0);
10640 tcg_temp_free_i32(fp1);
10641 gen_store_fpr32(ctx, fp2, fd);
10642 tcg_temp_free_i32(fp2);
10644 opn = "nmadd.s";
10645 break;
10646 case OPC_NMADD_D:
10647 check_cop1x(ctx);
10648 check_cp1_registers(ctx, fd | fs | ft | fr);
10650 TCGv_i64 fp0 = tcg_temp_new_i64();
10651 TCGv_i64 fp1 = tcg_temp_new_i64();
10652 TCGv_i64 fp2 = tcg_temp_new_i64();
10654 gen_load_fpr64(ctx, fp0, fs);
10655 gen_load_fpr64(ctx, fp1, ft);
10656 gen_load_fpr64(ctx, fp2, fr);
10657 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10658 tcg_temp_free_i64(fp0);
10659 tcg_temp_free_i64(fp1);
10660 gen_store_fpr64(ctx, fp2, fd);
10661 tcg_temp_free_i64(fp2);
10663 opn = "nmadd.d";
10664 break;
10665 case OPC_NMADD_PS:
10666 check_cp1_64bitmode(ctx);
10668 TCGv_i64 fp0 = tcg_temp_new_i64();
10669 TCGv_i64 fp1 = tcg_temp_new_i64();
10670 TCGv_i64 fp2 = tcg_temp_new_i64();
10672 gen_load_fpr64(ctx, fp0, fs);
10673 gen_load_fpr64(ctx, fp1, ft);
10674 gen_load_fpr64(ctx, fp2, fr);
10675 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10676 tcg_temp_free_i64(fp0);
10677 tcg_temp_free_i64(fp1);
10678 gen_store_fpr64(ctx, fp2, fd);
10679 tcg_temp_free_i64(fp2);
10681 opn = "nmadd.ps";
10682 break;
10683 case OPC_NMSUB_S:
10684 check_cop1x(ctx);
10686 TCGv_i32 fp0 = tcg_temp_new_i32();
10687 TCGv_i32 fp1 = tcg_temp_new_i32();
10688 TCGv_i32 fp2 = tcg_temp_new_i32();
10690 gen_load_fpr32(ctx, fp0, fs);
10691 gen_load_fpr32(ctx, fp1, ft);
10692 gen_load_fpr32(ctx, fp2, fr);
10693 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10694 tcg_temp_free_i32(fp0);
10695 tcg_temp_free_i32(fp1);
10696 gen_store_fpr32(ctx, fp2, fd);
10697 tcg_temp_free_i32(fp2);
10699 opn = "nmsub.s";
10700 break;
10701 case OPC_NMSUB_D:
10702 check_cop1x(ctx);
10703 check_cp1_registers(ctx, fd | fs | ft | fr);
10705 TCGv_i64 fp0 = tcg_temp_new_i64();
10706 TCGv_i64 fp1 = tcg_temp_new_i64();
10707 TCGv_i64 fp2 = tcg_temp_new_i64();
10709 gen_load_fpr64(ctx, fp0, fs);
10710 gen_load_fpr64(ctx, fp1, ft);
10711 gen_load_fpr64(ctx, fp2, fr);
10712 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10713 tcg_temp_free_i64(fp0);
10714 tcg_temp_free_i64(fp1);
10715 gen_store_fpr64(ctx, fp2, fd);
10716 tcg_temp_free_i64(fp2);
10718 opn = "nmsub.d";
10719 break;
10720 case OPC_NMSUB_PS:
10721 check_cp1_64bitmode(ctx);
10723 TCGv_i64 fp0 = tcg_temp_new_i64();
10724 TCGv_i64 fp1 = tcg_temp_new_i64();
10725 TCGv_i64 fp2 = tcg_temp_new_i64();
10727 gen_load_fpr64(ctx, fp0, fs);
10728 gen_load_fpr64(ctx, fp1, ft);
10729 gen_load_fpr64(ctx, fp2, fr);
10730 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10731 tcg_temp_free_i64(fp0);
10732 tcg_temp_free_i64(fp1);
10733 gen_store_fpr64(ctx, fp2, fd);
10734 tcg_temp_free_i64(fp2);
10736 opn = "nmsub.ps";
10737 break;
10738 default:
10739 MIPS_INVAL(opn);
10740 generate_exception (ctx, EXCP_RI);
10741 return;
10743 (void)opn; /* avoid a compiler warning */
10744 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
10745 fregnames[fs], fregnames[ft]);
10748 static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
10750 TCGv t0;
10752 #if !defined(CONFIG_USER_ONLY)
10753 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10754 Therefore only check the ISA in system mode. */
10755 check_insn(ctx, ISA_MIPS32R2);
10756 #endif
10757 t0 = tcg_temp_new();
10759 switch (rd) {
10760 case 0:
10761 save_cpu_state(ctx, 1);
10762 gen_helper_rdhwr_cpunum(t0, cpu_env);
10763 gen_store_gpr(t0, rt);
10764 break;
10765 case 1:
10766 save_cpu_state(ctx, 1);
10767 gen_helper_rdhwr_synci_step(t0, cpu_env);
10768 gen_store_gpr(t0, rt);
10769 break;
10770 case 2:
10771 save_cpu_state(ctx, 1);
10772 gen_helper_rdhwr_cc(t0, cpu_env);
10773 gen_store_gpr(t0, rt);
10774 break;
10775 case 3:
10776 save_cpu_state(ctx, 1);
10777 gen_helper_rdhwr_ccres(t0, cpu_env);
10778 gen_store_gpr(t0, rt);
10779 break;
10780 case 29:
10781 #if defined(CONFIG_USER_ONLY)
10782 tcg_gen_ld_tl(t0, cpu_env,
10783 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10784 gen_store_gpr(t0, rt);
10785 break;
10786 #else
10787 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10788 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10789 tcg_gen_ld_tl(t0, cpu_env,
10790 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10791 gen_store_gpr(t0, rt);
10792 } else {
10793 generate_exception(ctx, EXCP_RI);
10795 break;
10796 #endif
10797 default: /* Invalid */
10798 MIPS_INVAL("rdhwr");
10799 generate_exception(ctx, EXCP_RI);
10800 break;
10802 tcg_temp_free(t0);
10805 static inline void clear_branch_hflags(DisasContext *ctx)
10807 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10808 if (ctx->bstate == BS_NONE) {
10809 save_cpu_state(ctx, 0);
10810 } else {
10811 /* it is not safe to save ctx->hflags as hflags may be changed
10812 in execution time by the instruction in delay / forbidden slot. */
10813 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10817 static void gen_branch(DisasContext *ctx, int insn_bytes)
10819 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10820 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10821 /* Branches completion */
10822 clear_branch_hflags(ctx);
10823 ctx->bstate = BS_BRANCH;
10824 /* FIXME: Need to clear can_do_io. */
10825 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10826 case MIPS_HFLAG_FBNSLOT:
10827 MIPS_DEBUG("forbidden slot");
10828 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10829 break;
10830 case MIPS_HFLAG_B:
10831 /* unconditional branch */
10832 MIPS_DEBUG("unconditional branch");
10833 if (proc_hflags & MIPS_HFLAG_BX) {
10834 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10836 gen_goto_tb(ctx, 0, ctx->btarget);
10837 break;
10838 case MIPS_HFLAG_BL:
10839 /* blikely taken case */
10840 MIPS_DEBUG("blikely branch taken");
10841 gen_goto_tb(ctx, 0, ctx->btarget);
10842 break;
10843 case MIPS_HFLAG_BC:
10844 /* Conditional branch */
10845 MIPS_DEBUG("conditional branch");
10847 TCGLabel *l1 = gen_new_label();
10849 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10850 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10851 gen_set_label(l1);
10852 gen_goto_tb(ctx, 0, ctx->btarget);
10854 break;
10855 case MIPS_HFLAG_BR:
10856 /* unconditional branch to register */
10857 MIPS_DEBUG("branch to register");
10858 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10859 TCGv t0 = tcg_temp_new();
10860 TCGv_i32 t1 = tcg_temp_new_i32();
10862 tcg_gen_andi_tl(t0, btarget, 0x1);
10863 tcg_gen_trunc_tl_i32(t1, t0);
10864 tcg_temp_free(t0);
10865 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10866 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10867 tcg_gen_or_i32(hflags, hflags, t1);
10868 tcg_temp_free_i32(t1);
10870 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10871 } else {
10872 tcg_gen_mov_tl(cpu_PC, btarget);
10874 if (ctx->singlestep_enabled) {
10875 save_cpu_state(ctx, 0);
10876 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
10878 tcg_gen_exit_tb(0);
10879 break;
10880 default:
10881 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
10882 abort();
10887 /* ISA extensions (ASEs) */
10888 /* MIPS16 extension to MIPS32 */
10890 /* MIPS16 major opcodes */
10891 enum {
10892 M16_OPC_ADDIUSP = 0x00,
10893 M16_OPC_ADDIUPC = 0x01,
10894 M16_OPC_B = 0x02,
10895 M16_OPC_JAL = 0x03,
10896 M16_OPC_BEQZ = 0x04,
10897 M16_OPC_BNEQZ = 0x05,
10898 M16_OPC_SHIFT = 0x06,
10899 M16_OPC_LD = 0x07,
10900 M16_OPC_RRIA = 0x08,
10901 M16_OPC_ADDIU8 = 0x09,
10902 M16_OPC_SLTI = 0x0a,
10903 M16_OPC_SLTIU = 0x0b,
10904 M16_OPC_I8 = 0x0c,
10905 M16_OPC_LI = 0x0d,
10906 M16_OPC_CMPI = 0x0e,
10907 M16_OPC_SD = 0x0f,
10908 M16_OPC_LB = 0x10,
10909 M16_OPC_LH = 0x11,
10910 M16_OPC_LWSP = 0x12,
10911 M16_OPC_LW = 0x13,
10912 M16_OPC_LBU = 0x14,
10913 M16_OPC_LHU = 0x15,
10914 M16_OPC_LWPC = 0x16,
10915 M16_OPC_LWU = 0x17,
10916 M16_OPC_SB = 0x18,
10917 M16_OPC_SH = 0x19,
10918 M16_OPC_SWSP = 0x1a,
10919 M16_OPC_SW = 0x1b,
10920 M16_OPC_RRR = 0x1c,
10921 M16_OPC_RR = 0x1d,
10922 M16_OPC_EXTEND = 0x1e,
10923 M16_OPC_I64 = 0x1f
10926 /* I8 funct field */
10927 enum {
10928 I8_BTEQZ = 0x0,
10929 I8_BTNEZ = 0x1,
10930 I8_SWRASP = 0x2,
10931 I8_ADJSP = 0x3,
10932 I8_SVRS = 0x4,
10933 I8_MOV32R = 0x5,
10934 I8_MOVR32 = 0x7
10937 /* RRR f field */
10938 enum {
10939 RRR_DADDU = 0x0,
10940 RRR_ADDU = 0x1,
10941 RRR_DSUBU = 0x2,
10942 RRR_SUBU = 0x3
10945 /* RR funct field */
10946 enum {
10947 RR_JR = 0x00,
10948 RR_SDBBP = 0x01,
10949 RR_SLT = 0x02,
10950 RR_SLTU = 0x03,
10951 RR_SLLV = 0x04,
10952 RR_BREAK = 0x05,
10953 RR_SRLV = 0x06,
10954 RR_SRAV = 0x07,
10955 RR_DSRL = 0x08,
10956 RR_CMP = 0x0a,
10957 RR_NEG = 0x0b,
10958 RR_AND = 0x0c,
10959 RR_OR = 0x0d,
10960 RR_XOR = 0x0e,
10961 RR_NOT = 0x0f,
10962 RR_MFHI = 0x10,
10963 RR_CNVT = 0x11,
10964 RR_MFLO = 0x12,
10965 RR_DSRA = 0x13,
10966 RR_DSLLV = 0x14,
10967 RR_DSRLV = 0x16,
10968 RR_DSRAV = 0x17,
10969 RR_MULT = 0x18,
10970 RR_MULTU = 0x19,
10971 RR_DIV = 0x1a,
10972 RR_DIVU = 0x1b,
10973 RR_DMULT = 0x1c,
10974 RR_DMULTU = 0x1d,
10975 RR_DDIV = 0x1e,
10976 RR_DDIVU = 0x1f
10979 /* I64 funct field */
10980 enum {
10981 I64_LDSP = 0x0,
10982 I64_SDSP = 0x1,
10983 I64_SDRASP = 0x2,
10984 I64_DADJSP = 0x3,
10985 I64_LDPC = 0x4,
10986 I64_DADDIU5 = 0x5,
10987 I64_DADDIUPC = 0x6,
10988 I64_DADDIUSP = 0x7
10991 /* RR ry field for CNVT */
10992 enum {
10993 RR_RY_CNVT_ZEB = 0x0,
10994 RR_RY_CNVT_ZEH = 0x1,
10995 RR_RY_CNVT_ZEW = 0x2,
10996 RR_RY_CNVT_SEB = 0x4,
10997 RR_RY_CNVT_SEH = 0x5,
10998 RR_RY_CNVT_SEW = 0x6,
11001 static int xlat (int r)
11003 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11005 return map[r];
11008 static void gen_mips16_save (DisasContext *ctx,
11009 int xsregs, int aregs,
11010 int do_ra, int do_s0, int do_s1,
11011 int framesize)
11013 TCGv t0 = tcg_temp_new();
11014 TCGv t1 = tcg_temp_new();
11015 TCGv t2 = tcg_temp_new();
11016 int args, astatic;
11018 switch (aregs) {
11019 case 0:
11020 case 1:
11021 case 2:
11022 case 3:
11023 case 11:
11024 args = 0;
11025 break;
11026 case 4:
11027 case 5:
11028 case 6:
11029 case 7:
11030 args = 1;
11031 break;
11032 case 8:
11033 case 9:
11034 case 10:
11035 args = 2;
11036 break;
11037 case 12:
11038 case 13:
11039 args = 3;
11040 break;
11041 case 14:
11042 args = 4;
11043 break;
11044 default:
11045 generate_exception(ctx, EXCP_RI);
11046 return;
11049 switch (args) {
11050 case 4:
11051 gen_base_offset_addr(ctx, t0, 29, 12);
11052 gen_load_gpr(t1, 7);
11053 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11054 /* Fall through */
11055 case 3:
11056 gen_base_offset_addr(ctx, t0, 29, 8);
11057 gen_load_gpr(t1, 6);
11058 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11059 /* Fall through */
11060 case 2:
11061 gen_base_offset_addr(ctx, t0, 29, 4);
11062 gen_load_gpr(t1, 5);
11063 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11064 /* Fall through */
11065 case 1:
11066 gen_base_offset_addr(ctx, t0, 29, 0);
11067 gen_load_gpr(t1, 4);
11068 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11071 gen_load_gpr(t0, 29);
11073 #define DECR_AND_STORE(reg) do { \
11074 tcg_gen_movi_tl(t2, -4); \
11075 gen_op_addr_add(ctx, t0, t0, t2); \
11076 gen_load_gpr(t1, reg); \
11077 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
11078 } while (0)
11080 if (do_ra) {
11081 DECR_AND_STORE(31);
11084 switch (xsregs) {
11085 case 7:
11086 DECR_AND_STORE(30);
11087 /* Fall through */
11088 case 6:
11089 DECR_AND_STORE(23);
11090 /* Fall through */
11091 case 5:
11092 DECR_AND_STORE(22);
11093 /* Fall through */
11094 case 4:
11095 DECR_AND_STORE(21);
11096 /* Fall through */
11097 case 3:
11098 DECR_AND_STORE(20);
11099 /* Fall through */
11100 case 2:
11101 DECR_AND_STORE(19);
11102 /* Fall through */
11103 case 1:
11104 DECR_AND_STORE(18);
11107 if (do_s1) {
11108 DECR_AND_STORE(17);
11110 if (do_s0) {
11111 DECR_AND_STORE(16);
11114 switch (aregs) {
11115 case 0:
11116 case 4:
11117 case 8:
11118 case 12:
11119 case 14:
11120 astatic = 0;
11121 break;
11122 case 1:
11123 case 5:
11124 case 9:
11125 case 13:
11126 astatic = 1;
11127 break;
11128 case 2:
11129 case 6:
11130 case 10:
11131 astatic = 2;
11132 break;
11133 case 3:
11134 case 7:
11135 astatic = 3;
11136 break;
11137 case 11:
11138 astatic = 4;
11139 break;
11140 default:
11141 generate_exception(ctx, EXCP_RI);
11142 return;
11145 if (astatic > 0) {
11146 DECR_AND_STORE(7);
11147 if (astatic > 1) {
11148 DECR_AND_STORE(6);
11149 if (astatic > 2) {
11150 DECR_AND_STORE(5);
11151 if (astatic > 3) {
11152 DECR_AND_STORE(4);
11157 #undef DECR_AND_STORE
11159 tcg_gen_movi_tl(t2, -framesize);
11160 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11161 tcg_temp_free(t0);
11162 tcg_temp_free(t1);
11163 tcg_temp_free(t2);
11166 static void gen_mips16_restore (DisasContext *ctx,
11167 int xsregs, int aregs,
11168 int do_ra, int do_s0, int do_s1,
11169 int framesize)
11171 int astatic;
11172 TCGv t0 = tcg_temp_new();
11173 TCGv t1 = tcg_temp_new();
11174 TCGv t2 = tcg_temp_new();
11176 tcg_gen_movi_tl(t2, framesize);
11177 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11179 #define DECR_AND_LOAD(reg) do { \
11180 tcg_gen_movi_tl(t2, -4); \
11181 gen_op_addr_add(ctx, t0, t0, t2); \
11182 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11183 gen_store_gpr(t1, reg); \
11184 } while (0)
11186 if (do_ra) {
11187 DECR_AND_LOAD(31);
11190 switch (xsregs) {
11191 case 7:
11192 DECR_AND_LOAD(30);
11193 /* Fall through */
11194 case 6:
11195 DECR_AND_LOAD(23);
11196 /* Fall through */
11197 case 5:
11198 DECR_AND_LOAD(22);
11199 /* Fall through */
11200 case 4:
11201 DECR_AND_LOAD(21);
11202 /* Fall through */
11203 case 3:
11204 DECR_AND_LOAD(20);
11205 /* Fall through */
11206 case 2:
11207 DECR_AND_LOAD(19);
11208 /* Fall through */
11209 case 1:
11210 DECR_AND_LOAD(18);
11213 if (do_s1) {
11214 DECR_AND_LOAD(17);
11216 if (do_s0) {
11217 DECR_AND_LOAD(16);
11220 switch (aregs) {
11221 case 0:
11222 case 4:
11223 case 8:
11224 case 12:
11225 case 14:
11226 astatic = 0;
11227 break;
11228 case 1:
11229 case 5:
11230 case 9:
11231 case 13:
11232 astatic = 1;
11233 break;
11234 case 2:
11235 case 6:
11236 case 10:
11237 astatic = 2;
11238 break;
11239 case 3:
11240 case 7:
11241 astatic = 3;
11242 break;
11243 case 11:
11244 astatic = 4;
11245 break;
11246 default:
11247 generate_exception(ctx, EXCP_RI);
11248 return;
11251 if (astatic > 0) {
11252 DECR_AND_LOAD(7);
11253 if (astatic > 1) {
11254 DECR_AND_LOAD(6);
11255 if (astatic > 2) {
11256 DECR_AND_LOAD(5);
11257 if (astatic > 3) {
11258 DECR_AND_LOAD(4);
11263 #undef DECR_AND_LOAD
11265 tcg_gen_movi_tl(t2, framesize);
11266 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11267 tcg_temp_free(t0);
11268 tcg_temp_free(t1);
11269 tcg_temp_free(t2);
11272 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11273 int is_64_bit, int extended)
11275 TCGv t0;
11277 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11278 generate_exception(ctx, EXCP_RI);
11279 return;
11282 t0 = tcg_temp_new();
11284 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11285 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11286 if (!is_64_bit) {
11287 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11290 tcg_temp_free(t0);
11293 #if defined(TARGET_MIPS64)
11294 static void decode_i64_mips16 (DisasContext *ctx,
11295 int ry, int funct, int16_t offset,
11296 int extended)
11298 switch (funct) {
11299 case I64_LDSP:
11300 check_insn(ctx, ISA_MIPS3);
11301 check_mips_64(ctx);
11302 offset = extended ? offset : offset << 3;
11303 gen_ld(ctx, OPC_LD, ry, 29, offset);
11304 break;
11305 case I64_SDSP:
11306 check_insn(ctx, ISA_MIPS3);
11307 check_mips_64(ctx);
11308 offset = extended ? offset : offset << 3;
11309 gen_st(ctx, OPC_SD, ry, 29, offset);
11310 break;
11311 case I64_SDRASP:
11312 check_insn(ctx, ISA_MIPS3);
11313 check_mips_64(ctx);
11314 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11315 gen_st(ctx, OPC_SD, 31, 29, offset);
11316 break;
11317 case I64_DADJSP:
11318 check_insn(ctx, ISA_MIPS3);
11319 check_mips_64(ctx);
11320 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11321 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11322 break;
11323 case I64_LDPC:
11324 check_insn(ctx, ISA_MIPS3);
11325 check_mips_64(ctx);
11326 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11327 generate_exception(ctx, EXCP_RI);
11328 } else {
11329 offset = extended ? offset : offset << 3;
11330 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11332 break;
11333 case I64_DADDIU5:
11334 check_insn(ctx, ISA_MIPS3);
11335 check_mips_64(ctx);
11336 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11337 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11338 break;
11339 case I64_DADDIUPC:
11340 check_insn(ctx, ISA_MIPS3);
11341 check_mips_64(ctx);
11342 offset = extended ? offset : offset << 2;
11343 gen_addiupc(ctx, ry, offset, 1, extended);
11344 break;
11345 case I64_DADDIUSP:
11346 check_insn(ctx, ISA_MIPS3);
11347 check_mips_64(ctx);
11348 offset = extended ? offset : offset << 2;
11349 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11350 break;
11353 #endif
11355 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11357 int extend = cpu_lduw_code(env, ctx->pc + 2);
11358 int op, rx, ry, funct, sa;
11359 int16_t imm, offset;
11361 ctx->opcode = (ctx->opcode << 16) | extend;
11362 op = (ctx->opcode >> 11) & 0x1f;
11363 sa = (ctx->opcode >> 22) & 0x1f;
11364 funct = (ctx->opcode >> 8) & 0x7;
11365 rx = xlat((ctx->opcode >> 8) & 0x7);
11366 ry = xlat((ctx->opcode >> 5) & 0x7);
11367 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11368 | ((ctx->opcode >> 21) & 0x3f) << 5
11369 | (ctx->opcode & 0x1f));
11371 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11372 counterparts. */
11373 switch (op) {
11374 case M16_OPC_ADDIUSP:
11375 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11376 break;
11377 case M16_OPC_ADDIUPC:
11378 gen_addiupc(ctx, rx, imm, 0, 1);
11379 break;
11380 case M16_OPC_B:
11381 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11382 /* No delay slot, so just process as a normal instruction */
11383 break;
11384 case M16_OPC_BEQZ:
11385 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11386 /* No delay slot, so just process as a normal instruction */
11387 break;
11388 case M16_OPC_BNEQZ:
11389 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11390 /* No delay slot, so just process as a normal instruction */
11391 break;
11392 case M16_OPC_SHIFT:
11393 switch (ctx->opcode & 0x3) {
11394 case 0x0:
11395 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11396 break;
11397 case 0x1:
11398 #if defined(TARGET_MIPS64)
11399 check_mips_64(ctx);
11400 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11401 #else
11402 generate_exception(ctx, EXCP_RI);
11403 #endif
11404 break;
11405 case 0x2:
11406 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11407 break;
11408 case 0x3:
11409 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11410 break;
11412 break;
11413 #if defined(TARGET_MIPS64)
11414 case M16_OPC_LD:
11415 check_insn(ctx, ISA_MIPS3);
11416 check_mips_64(ctx);
11417 gen_ld(ctx, OPC_LD, ry, rx, offset);
11418 break;
11419 #endif
11420 case M16_OPC_RRIA:
11421 imm = ctx->opcode & 0xf;
11422 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11423 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11424 imm = (int16_t) (imm << 1) >> 1;
11425 if ((ctx->opcode >> 4) & 0x1) {
11426 #if defined(TARGET_MIPS64)
11427 check_mips_64(ctx);
11428 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11429 #else
11430 generate_exception(ctx, EXCP_RI);
11431 #endif
11432 } else {
11433 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11435 break;
11436 case M16_OPC_ADDIU8:
11437 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11438 break;
11439 case M16_OPC_SLTI:
11440 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11441 break;
11442 case M16_OPC_SLTIU:
11443 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11444 break;
11445 case M16_OPC_I8:
11446 switch (funct) {
11447 case I8_BTEQZ:
11448 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11449 break;
11450 case I8_BTNEZ:
11451 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11452 break;
11453 case I8_SWRASP:
11454 gen_st(ctx, OPC_SW, 31, 29, imm);
11455 break;
11456 case I8_ADJSP:
11457 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11458 break;
11459 case I8_SVRS:
11460 check_insn(ctx, ISA_MIPS32);
11462 int xsregs = (ctx->opcode >> 24) & 0x7;
11463 int aregs = (ctx->opcode >> 16) & 0xf;
11464 int do_ra = (ctx->opcode >> 6) & 0x1;
11465 int do_s0 = (ctx->opcode >> 5) & 0x1;
11466 int do_s1 = (ctx->opcode >> 4) & 0x1;
11467 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11468 | (ctx->opcode & 0xf)) << 3;
11470 if (ctx->opcode & (1 << 7)) {
11471 gen_mips16_save(ctx, xsregs, aregs,
11472 do_ra, do_s0, do_s1,
11473 framesize);
11474 } else {
11475 gen_mips16_restore(ctx, xsregs, aregs,
11476 do_ra, do_s0, do_s1,
11477 framesize);
11480 break;
11481 default:
11482 generate_exception(ctx, EXCP_RI);
11483 break;
11485 break;
11486 case M16_OPC_LI:
11487 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11488 break;
11489 case M16_OPC_CMPI:
11490 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11491 break;
11492 #if defined(TARGET_MIPS64)
11493 case M16_OPC_SD:
11494 check_insn(ctx, ISA_MIPS3);
11495 check_mips_64(ctx);
11496 gen_st(ctx, OPC_SD, ry, rx, offset);
11497 break;
11498 #endif
11499 case M16_OPC_LB:
11500 gen_ld(ctx, OPC_LB, ry, rx, offset);
11501 break;
11502 case M16_OPC_LH:
11503 gen_ld(ctx, OPC_LH, ry, rx, offset);
11504 break;
11505 case M16_OPC_LWSP:
11506 gen_ld(ctx, OPC_LW, rx, 29, offset);
11507 break;
11508 case M16_OPC_LW:
11509 gen_ld(ctx, OPC_LW, ry, rx, offset);
11510 break;
11511 case M16_OPC_LBU:
11512 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11513 break;
11514 case M16_OPC_LHU:
11515 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11516 break;
11517 case M16_OPC_LWPC:
11518 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11519 break;
11520 #if defined(TARGET_MIPS64)
11521 case M16_OPC_LWU:
11522 check_insn(ctx, ISA_MIPS3);
11523 check_mips_64(ctx);
11524 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11525 break;
11526 #endif
11527 case M16_OPC_SB:
11528 gen_st(ctx, OPC_SB, ry, rx, offset);
11529 break;
11530 case M16_OPC_SH:
11531 gen_st(ctx, OPC_SH, ry, rx, offset);
11532 break;
11533 case M16_OPC_SWSP:
11534 gen_st(ctx, OPC_SW, rx, 29, offset);
11535 break;
11536 case M16_OPC_SW:
11537 gen_st(ctx, OPC_SW, ry, rx, offset);
11538 break;
11539 #if defined(TARGET_MIPS64)
11540 case M16_OPC_I64:
11541 decode_i64_mips16(ctx, ry, funct, offset, 1);
11542 break;
11543 #endif
11544 default:
11545 generate_exception(ctx, EXCP_RI);
11546 break;
11549 return 4;
11552 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11554 int rx, ry;
11555 int sa;
11556 int op, cnvt_op, op1, offset;
11557 int funct;
11558 int n_bytes;
11560 op = (ctx->opcode >> 11) & 0x1f;
11561 sa = (ctx->opcode >> 2) & 0x7;
11562 sa = sa == 0 ? 8 : sa;
11563 rx = xlat((ctx->opcode >> 8) & 0x7);
11564 cnvt_op = (ctx->opcode >> 5) & 0x7;
11565 ry = xlat((ctx->opcode >> 5) & 0x7);
11566 op1 = offset = ctx->opcode & 0x1f;
11568 n_bytes = 2;
11570 switch (op) {
11571 case M16_OPC_ADDIUSP:
11573 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11575 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11577 break;
11578 case M16_OPC_ADDIUPC:
11579 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11580 break;
11581 case M16_OPC_B:
11582 offset = (ctx->opcode & 0x7ff) << 1;
11583 offset = (int16_t)(offset << 4) >> 4;
11584 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11585 /* No delay slot, so just process as a normal instruction */
11586 break;
11587 case M16_OPC_JAL:
11588 offset = cpu_lduw_code(env, ctx->pc + 2);
11589 offset = (((ctx->opcode & 0x1f) << 21)
11590 | ((ctx->opcode >> 5) & 0x1f) << 16
11591 | offset) << 2;
11592 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11593 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11594 n_bytes = 4;
11595 break;
11596 case M16_OPC_BEQZ:
11597 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11598 ((int8_t)ctx->opcode) << 1, 0);
11599 /* No delay slot, so just process as a normal instruction */
11600 break;
11601 case M16_OPC_BNEQZ:
11602 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11603 ((int8_t)ctx->opcode) << 1, 0);
11604 /* No delay slot, so just process as a normal instruction */
11605 break;
11606 case M16_OPC_SHIFT:
11607 switch (ctx->opcode & 0x3) {
11608 case 0x0:
11609 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11610 break;
11611 case 0x1:
11612 #if defined(TARGET_MIPS64)
11613 check_insn(ctx, ISA_MIPS3);
11614 check_mips_64(ctx);
11615 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11616 #else
11617 generate_exception(ctx, EXCP_RI);
11618 #endif
11619 break;
11620 case 0x2:
11621 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11622 break;
11623 case 0x3:
11624 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11625 break;
11627 break;
11628 #if defined(TARGET_MIPS64)
11629 case M16_OPC_LD:
11630 check_insn(ctx, ISA_MIPS3);
11631 check_mips_64(ctx);
11632 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
11633 break;
11634 #endif
11635 case M16_OPC_RRIA:
11637 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
11639 if ((ctx->opcode >> 4) & 1) {
11640 #if defined(TARGET_MIPS64)
11641 check_insn(ctx, ISA_MIPS3);
11642 check_mips_64(ctx);
11643 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11644 #else
11645 generate_exception(ctx, EXCP_RI);
11646 #endif
11647 } else {
11648 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11651 break;
11652 case M16_OPC_ADDIU8:
11654 int16_t imm = (int8_t) ctx->opcode;
11656 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11658 break;
11659 case M16_OPC_SLTI:
11661 int16_t imm = (uint8_t) ctx->opcode;
11662 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11664 break;
11665 case M16_OPC_SLTIU:
11667 int16_t imm = (uint8_t) ctx->opcode;
11668 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11670 break;
11671 case M16_OPC_I8:
11673 int reg32;
11675 funct = (ctx->opcode >> 8) & 0x7;
11676 switch (funct) {
11677 case I8_BTEQZ:
11678 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
11679 ((int8_t)ctx->opcode) << 1, 0);
11680 break;
11681 case I8_BTNEZ:
11682 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
11683 ((int8_t)ctx->opcode) << 1, 0);
11684 break;
11685 case I8_SWRASP:
11686 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
11687 break;
11688 case I8_ADJSP:
11689 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
11690 ((int8_t)ctx->opcode) << 3);
11691 break;
11692 case I8_SVRS:
11693 check_insn(ctx, ISA_MIPS32);
11695 int do_ra = ctx->opcode & (1 << 6);
11696 int do_s0 = ctx->opcode & (1 << 5);
11697 int do_s1 = ctx->opcode & (1 << 4);
11698 int framesize = ctx->opcode & 0xf;
11700 if (framesize == 0) {
11701 framesize = 128;
11702 } else {
11703 framesize = framesize << 3;
11706 if (ctx->opcode & (1 << 7)) {
11707 gen_mips16_save(ctx, 0, 0,
11708 do_ra, do_s0, do_s1, framesize);
11709 } else {
11710 gen_mips16_restore(ctx, 0, 0,
11711 do_ra, do_s0, do_s1, framesize);
11714 break;
11715 case I8_MOV32R:
11717 int rz = xlat(ctx->opcode & 0x7);
11719 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
11720 ((ctx->opcode >> 5) & 0x7);
11721 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
11723 break;
11724 case I8_MOVR32:
11725 reg32 = ctx->opcode & 0x1f;
11726 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
11727 break;
11728 default:
11729 generate_exception(ctx, EXCP_RI);
11730 break;
11733 break;
11734 case M16_OPC_LI:
11736 int16_t imm = (uint8_t) ctx->opcode;
11738 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
11740 break;
11741 case M16_OPC_CMPI:
11743 int16_t imm = (uint8_t) ctx->opcode;
11744 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
11746 break;
11747 #if defined(TARGET_MIPS64)
11748 case M16_OPC_SD:
11749 check_insn(ctx, ISA_MIPS3);
11750 check_mips_64(ctx);
11751 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
11752 break;
11753 #endif
11754 case M16_OPC_LB:
11755 gen_ld(ctx, OPC_LB, ry, rx, offset);
11756 break;
11757 case M16_OPC_LH:
11758 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
11759 break;
11760 case M16_OPC_LWSP:
11761 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11762 break;
11763 case M16_OPC_LW:
11764 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
11765 break;
11766 case M16_OPC_LBU:
11767 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11768 break;
11769 case M16_OPC_LHU:
11770 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
11771 break;
11772 case M16_OPC_LWPC:
11773 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
11774 break;
11775 #if defined (TARGET_MIPS64)
11776 case M16_OPC_LWU:
11777 check_insn(ctx, ISA_MIPS3);
11778 check_mips_64(ctx);
11779 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
11780 break;
11781 #endif
11782 case M16_OPC_SB:
11783 gen_st(ctx, OPC_SB, ry, rx, offset);
11784 break;
11785 case M16_OPC_SH:
11786 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
11787 break;
11788 case M16_OPC_SWSP:
11789 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11790 break;
11791 case M16_OPC_SW:
11792 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
11793 break;
11794 case M16_OPC_RRR:
11796 int rz = xlat((ctx->opcode >> 2) & 0x7);
11797 int mips32_op;
11799 switch (ctx->opcode & 0x3) {
11800 case RRR_ADDU:
11801 mips32_op = OPC_ADDU;
11802 break;
11803 case RRR_SUBU:
11804 mips32_op = OPC_SUBU;
11805 break;
11806 #if defined(TARGET_MIPS64)
11807 case RRR_DADDU:
11808 mips32_op = OPC_DADDU;
11809 check_insn(ctx, ISA_MIPS3);
11810 check_mips_64(ctx);
11811 break;
11812 case RRR_DSUBU:
11813 mips32_op = OPC_DSUBU;
11814 check_insn(ctx, ISA_MIPS3);
11815 check_mips_64(ctx);
11816 break;
11817 #endif
11818 default:
11819 generate_exception(ctx, EXCP_RI);
11820 goto done;
11823 gen_arith(ctx, mips32_op, rz, rx, ry);
11824 done:
11827 break;
11828 case M16_OPC_RR:
11829 switch (op1) {
11830 case RR_JR:
11832 int nd = (ctx->opcode >> 7) & 0x1;
11833 int link = (ctx->opcode >> 6) & 0x1;
11834 int ra = (ctx->opcode >> 5) & 0x1;
11836 if (nd) {
11837 check_insn(ctx, ISA_MIPS32);
11840 if (link) {
11841 op = OPC_JALR;
11842 } else {
11843 op = OPC_JR;
11846 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
11847 (nd ? 0 : 2));
11849 break;
11850 case RR_SDBBP:
11851 /* XXX: not clear which exception should be raised
11852 * when in debug mode...
11854 check_insn(ctx, ISA_MIPS32);
11855 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11856 generate_exception(ctx, EXCP_DBp);
11857 } else {
11858 generate_exception(ctx, EXCP_DBp);
11860 break;
11861 case RR_SLT:
11862 gen_slt(ctx, OPC_SLT, 24, rx, ry);
11863 break;
11864 case RR_SLTU:
11865 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
11866 break;
11867 case RR_BREAK:
11868 generate_exception(ctx, EXCP_BREAK);
11869 break;
11870 case RR_SLLV:
11871 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
11872 break;
11873 case RR_SRLV:
11874 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
11875 break;
11876 case RR_SRAV:
11877 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
11878 break;
11879 #if defined (TARGET_MIPS64)
11880 case RR_DSRL:
11881 check_insn(ctx, ISA_MIPS3);
11882 check_mips_64(ctx);
11883 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
11884 break;
11885 #endif
11886 case RR_CMP:
11887 gen_logic(ctx, OPC_XOR, 24, rx, ry);
11888 break;
11889 case RR_NEG:
11890 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
11891 break;
11892 case RR_AND:
11893 gen_logic(ctx, OPC_AND, rx, rx, ry);
11894 break;
11895 case RR_OR:
11896 gen_logic(ctx, OPC_OR, rx, rx, ry);
11897 break;
11898 case RR_XOR:
11899 gen_logic(ctx, OPC_XOR, rx, rx, ry);
11900 break;
11901 case RR_NOT:
11902 gen_logic(ctx, OPC_NOR, rx, ry, 0);
11903 break;
11904 case RR_MFHI:
11905 gen_HILO(ctx, OPC_MFHI, 0, rx);
11906 break;
11907 case RR_CNVT:
11908 check_insn(ctx, ISA_MIPS32);
11909 switch (cnvt_op) {
11910 case RR_RY_CNVT_ZEB:
11911 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11912 break;
11913 case RR_RY_CNVT_ZEH:
11914 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11915 break;
11916 case RR_RY_CNVT_SEB:
11917 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11918 break;
11919 case RR_RY_CNVT_SEH:
11920 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11921 break;
11922 #if defined (TARGET_MIPS64)
11923 case RR_RY_CNVT_ZEW:
11924 check_insn(ctx, ISA_MIPS64);
11925 check_mips_64(ctx);
11926 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11927 break;
11928 case RR_RY_CNVT_SEW:
11929 check_insn(ctx, ISA_MIPS64);
11930 check_mips_64(ctx);
11931 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11932 break;
11933 #endif
11934 default:
11935 generate_exception(ctx, EXCP_RI);
11936 break;
11938 break;
11939 case RR_MFLO:
11940 gen_HILO(ctx, OPC_MFLO, 0, rx);
11941 break;
11942 #if defined (TARGET_MIPS64)
11943 case RR_DSRA:
11944 check_insn(ctx, ISA_MIPS3);
11945 check_mips_64(ctx);
11946 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
11947 break;
11948 case RR_DSLLV:
11949 check_insn(ctx, ISA_MIPS3);
11950 check_mips_64(ctx);
11951 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
11952 break;
11953 case RR_DSRLV:
11954 check_insn(ctx, ISA_MIPS3);
11955 check_mips_64(ctx);
11956 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
11957 break;
11958 case RR_DSRAV:
11959 check_insn(ctx, ISA_MIPS3);
11960 check_mips_64(ctx);
11961 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
11962 break;
11963 #endif
11964 case RR_MULT:
11965 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
11966 break;
11967 case RR_MULTU:
11968 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
11969 break;
11970 case RR_DIV:
11971 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
11972 break;
11973 case RR_DIVU:
11974 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
11975 break;
11976 #if defined (TARGET_MIPS64)
11977 case RR_DMULT:
11978 check_insn(ctx, ISA_MIPS3);
11979 check_mips_64(ctx);
11980 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
11981 break;
11982 case RR_DMULTU:
11983 check_insn(ctx, ISA_MIPS3);
11984 check_mips_64(ctx);
11985 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
11986 break;
11987 case RR_DDIV:
11988 check_insn(ctx, ISA_MIPS3);
11989 check_mips_64(ctx);
11990 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
11991 break;
11992 case RR_DDIVU:
11993 check_insn(ctx, ISA_MIPS3);
11994 check_mips_64(ctx);
11995 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
11996 break;
11997 #endif
11998 default:
11999 generate_exception(ctx, EXCP_RI);
12000 break;
12002 break;
12003 case M16_OPC_EXTEND:
12004 decode_extended_mips16_opc(env, ctx);
12005 n_bytes = 4;
12006 break;
12007 #if defined(TARGET_MIPS64)
12008 case M16_OPC_I64:
12009 funct = (ctx->opcode >> 8) & 0x7;
12010 decode_i64_mips16(ctx, ry, funct, offset, 0);
12011 break;
12012 #endif
12013 default:
12014 generate_exception(ctx, EXCP_RI);
12015 break;
12018 return n_bytes;
12021 /* microMIPS extension to MIPS32/MIPS64 */
12024 * microMIPS32/microMIPS64 major opcodes
12026 * 1. MIPS Architecture for Programmers Volume II-B:
12027 * The microMIPS32 Instruction Set (Revision 3.05)
12029 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12031 * 2. MIPS Architecture For Programmers Volume II-A:
12032 * The MIPS64 Instruction Set (Revision 3.51)
12035 enum {
12036 POOL32A = 0x00,
12037 POOL16A = 0x01,
12038 LBU16 = 0x02,
12039 MOVE16 = 0x03,
12040 ADDI32 = 0x04,
12041 LBU32 = 0x05,
12042 SB32 = 0x06,
12043 LB32 = 0x07,
12045 POOL32B = 0x08,
12046 POOL16B = 0x09,
12047 LHU16 = 0x0a,
12048 ANDI16 = 0x0b,
12049 ADDIU32 = 0x0c,
12050 LHU32 = 0x0d,
12051 SH32 = 0x0e,
12052 LH32 = 0x0f,
12054 POOL32I = 0x10,
12055 POOL16C = 0x11,
12056 LWSP16 = 0x12,
12057 POOL16D = 0x13,
12058 ORI32 = 0x14,
12059 POOL32F = 0x15,
12060 POOL32S = 0x16, /* MIPS64 */
12061 DADDIU32 = 0x17, /* MIPS64 */
12063 /* 0x1f is reserved */
12064 POOL32C = 0x18,
12065 LWGP16 = 0x19,
12066 LW16 = 0x1a,
12067 POOL16E = 0x1b,
12068 XORI32 = 0x1c,
12069 JALS32 = 0x1d,
12070 ADDIUPC = 0x1e,
12072 /* 0x20 is reserved */
12073 RES_20 = 0x20,
12074 POOL16F = 0x21,
12075 SB16 = 0x22,
12076 BEQZ16 = 0x23,
12077 SLTI32 = 0x24,
12078 BEQ32 = 0x25,
12079 SWC132 = 0x26,
12080 LWC132 = 0x27,
12082 /* 0x28 and 0x29 are reserved */
12083 RES_28 = 0x28,
12084 RES_29 = 0x29,
12085 SH16 = 0x2a,
12086 BNEZ16 = 0x2b,
12087 SLTIU32 = 0x2c,
12088 BNE32 = 0x2d,
12089 SDC132 = 0x2e,
12090 LDC132 = 0x2f,
12092 /* 0x30 and 0x31 are reserved */
12093 RES_30 = 0x30,
12094 RES_31 = 0x31,
12095 SWSP16 = 0x32,
12096 B16 = 0x33,
12097 ANDI32 = 0x34,
12098 J32 = 0x35,
12099 SD32 = 0x36, /* MIPS64 */
12100 LD32 = 0x37, /* MIPS64 */
12102 /* 0x38 and 0x39 are reserved */
12103 RES_38 = 0x38,
12104 RES_39 = 0x39,
12105 SW16 = 0x3a,
12106 LI16 = 0x3b,
12107 JALX32 = 0x3c,
12108 JAL32 = 0x3d,
12109 SW32 = 0x3e,
12110 LW32 = 0x3f
12113 /* POOL32A encoding of minor opcode field */
12115 enum {
12116 /* These opcodes are distinguished only by bits 9..6; those bits are
12117 * what are recorded below. */
12118 SLL32 = 0x0,
12119 SRL32 = 0x1,
12120 SRA = 0x2,
12121 ROTR = 0x3,
12123 SLLV = 0x0,
12124 SRLV = 0x1,
12125 SRAV = 0x2,
12126 ROTRV = 0x3,
12127 ADD = 0x4,
12128 ADDU32 = 0x5,
12129 SUB = 0x6,
12130 SUBU32 = 0x7,
12131 MUL = 0x8,
12132 AND = 0x9,
12133 OR32 = 0xa,
12134 NOR = 0xb,
12135 XOR32 = 0xc,
12136 SLT = 0xd,
12137 SLTU = 0xe,
12139 MOVN = 0x0,
12140 MOVZ = 0x1,
12141 LWXS = 0x4,
12143 /* The following can be distinguished by their lower 6 bits. */
12144 INS = 0x0c,
12145 EXT = 0x2c,
12146 POOL32AXF = 0x3c
12149 /* POOL32AXF encoding of minor opcode field extension */
12152 * 1. MIPS Architecture for Programmers Volume II-B:
12153 * The microMIPS32 Instruction Set (Revision 3.05)
12155 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12157 * 2. MIPS Architecture for Programmers VolumeIV-e:
12158 * The MIPS DSP Application-Specific Extension
12159 * to the microMIPS32 Architecture (Revision 2.34)
12161 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12164 enum {
12165 /* bits 11..6 */
12166 TEQ = 0x00,
12167 TGE = 0x08,
12168 TGEU = 0x10,
12169 TLT = 0x20,
12170 TLTU = 0x28,
12171 TNE = 0x30,
12173 MFC0 = 0x03,
12174 MTC0 = 0x0b,
12176 /* begin of microMIPS32 DSP */
12178 /* bits 13..12 for 0x01 */
12179 MFHI_ACC = 0x0,
12180 MFLO_ACC = 0x1,
12181 MTHI_ACC = 0x2,
12182 MTLO_ACC = 0x3,
12184 /* bits 13..12 for 0x2a */
12185 MADD_ACC = 0x0,
12186 MADDU_ACC = 0x1,
12187 MSUB_ACC = 0x2,
12188 MSUBU_ACC = 0x3,
12190 /* bits 13..12 for 0x32 */
12191 MULT_ACC = 0x0,
12192 MULTU_ACC = 0x1,
12194 /* end of microMIPS32 DSP */
12196 /* bits 15..12 for 0x2c */
12197 SEB = 0x2,
12198 SEH = 0x3,
12199 CLO = 0x4,
12200 CLZ = 0x5,
12201 RDHWR = 0x6,
12202 WSBH = 0x7,
12203 MULT = 0x8,
12204 MULTU = 0x9,
12205 DIV = 0xa,
12206 DIVU = 0xb,
12207 MADD = 0xc,
12208 MADDU = 0xd,
12209 MSUB = 0xe,
12210 MSUBU = 0xf,
12212 /* bits 15..12 for 0x34 */
12213 MFC2 = 0x4,
12214 MTC2 = 0x5,
12215 MFHC2 = 0x8,
12216 MTHC2 = 0x9,
12217 CFC2 = 0xc,
12218 CTC2 = 0xd,
12220 /* bits 15..12 for 0x3c */
12221 JALR = 0x0,
12222 JR = 0x0, /* alias */
12223 JALR_HB = 0x1,
12224 JALRS = 0x4,
12225 JALRS_HB = 0x5,
12227 /* bits 15..12 for 0x05 */
12228 RDPGPR = 0xe,
12229 WRPGPR = 0xf,
12231 /* bits 15..12 for 0x0d */
12232 TLBP = 0x0,
12233 TLBR = 0x1,
12234 TLBWI = 0x2,
12235 TLBWR = 0x3,
12236 WAIT = 0x9,
12237 IRET = 0xd,
12238 DERET = 0xe,
12239 ERET = 0xf,
12241 /* bits 15..12 for 0x15 */
12242 DMT = 0x0,
12243 DVPE = 0x1,
12244 EMT = 0x2,
12245 EVPE = 0x3,
12247 /* bits 15..12 for 0x1d */
12248 DI = 0x4,
12249 EI = 0x5,
12251 /* bits 15..12 for 0x2d */
12252 SYNC = 0x6,
12253 SYSCALL = 0x8,
12254 SDBBP = 0xd,
12256 /* bits 15..12 for 0x35 */
12257 MFHI32 = 0x0,
12258 MFLO32 = 0x1,
12259 MTHI32 = 0x2,
12260 MTLO32 = 0x3,
12263 /* POOL32B encoding of minor opcode field (bits 15..12) */
12265 enum {
12266 LWC2 = 0x0,
12267 LWP = 0x1,
12268 LDP = 0x4,
12269 LWM32 = 0x5,
12270 CACHE = 0x6,
12271 LDM = 0x7,
12272 SWC2 = 0x8,
12273 SWP = 0x9,
12274 SDP = 0xc,
12275 SWM32 = 0xd,
12276 SDM = 0xf
12279 /* POOL32C encoding of minor opcode field (bits 15..12) */
12281 enum {
12282 LWL = 0x0,
12283 SWL = 0x8,
12284 LWR = 0x1,
12285 SWR = 0x9,
12286 PREF = 0x2,
12287 /* 0xa is reserved */
12288 LL = 0x3,
12289 SC = 0xb,
12290 LDL = 0x4,
12291 SDL = 0xc,
12292 LDR = 0x5,
12293 SDR = 0xd,
12294 /* 0x6 is reserved */
12295 LWU = 0xe,
12296 LLD = 0x7,
12297 SCD = 0xf
12300 /* POOL32F encoding of minor opcode field (bits 5..0) */
12302 enum {
12303 /* These are the bit 7..6 values */
12304 ADD_FMT = 0x0,
12305 MOVN_FMT = 0x0,
12307 SUB_FMT = 0x1,
12308 MOVZ_FMT = 0x1,
12310 MUL_FMT = 0x2,
12312 DIV_FMT = 0x3,
12314 /* These are the bit 8..6 values */
12315 RSQRT2_FMT = 0x0,
12316 MOVF_FMT = 0x0,
12318 LWXC1 = 0x1,
12319 MOVT_FMT = 0x1,
12321 PLL_PS = 0x2,
12322 SWXC1 = 0x2,
12324 PLU_PS = 0x3,
12325 LDXC1 = 0x3,
12327 PUL_PS = 0x4,
12328 SDXC1 = 0x4,
12329 RECIP2_FMT = 0x4,
12331 PUU_PS = 0x5,
12332 LUXC1 = 0x5,
12334 CVT_PS_S = 0x6,
12335 SUXC1 = 0x6,
12336 ADDR_PS = 0x6,
12337 PREFX = 0x6,
12339 MULR_PS = 0x7,
12341 MADD_S = 0x01,
12342 MADD_D = 0x09,
12343 MADD_PS = 0x11,
12344 ALNV_PS = 0x19,
12345 MSUB_S = 0x21,
12346 MSUB_D = 0x29,
12347 MSUB_PS = 0x31,
12349 NMADD_S = 0x02,
12350 NMADD_D = 0x0a,
12351 NMADD_PS = 0x12,
12352 NMSUB_S = 0x22,
12353 NMSUB_D = 0x2a,
12354 NMSUB_PS = 0x32,
12356 POOL32FXF = 0x3b,
12358 CABS_COND_FMT = 0x1c, /* MIPS3D */
12359 C_COND_FMT = 0x3c
12362 /* POOL32Fxf encoding of minor opcode extension field */
12364 enum {
12365 CVT_L = 0x04,
12366 RSQRT_FMT = 0x08,
12367 FLOOR_L = 0x0c,
12368 CVT_PW_PS = 0x1c,
12369 CVT_W = 0x24,
12370 SQRT_FMT = 0x28,
12371 FLOOR_W = 0x2c,
12372 CVT_PS_PW = 0x3c,
12373 CFC1 = 0x40,
12374 RECIP_FMT = 0x48,
12375 CEIL_L = 0x4c,
12376 CTC1 = 0x60,
12377 CEIL_W = 0x6c,
12378 MFC1 = 0x80,
12379 CVT_S_PL = 0x84,
12380 TRUNC_L = 0x8c,
12381 MTC1 = 0xa0,
12382 CVT_S_PU = 0xa4,
12383 TRUNC_W = 0xac,
12384 MFHC1 = 0xc0,
12385 ROUND_L = 0xcc,
12386 MTHC1 = 0xe0,
12387 ROUND_W = 0xec,
12389 MOV_FMT = 0x01,
12390 MOVF = 0x05,
12391 ABS_FMT = 0x0d,
12392 RSQRT1_FMT = 0x1d,
12393 MOVT = 0x25,
12394 NEG_FMT = 0x2d,
12395 CVT_D = 0x4d,
12396 RECIP1_FMT = 0x5d,
12397 CVT_S = 0x6d
12400 /* POOL32I encoding of minor opcode field (bits 25..21) */
12402 enum {
12403 BLTZ = 0x00,
12404 BLTZAL = 0x01,
12405 BGEZ = 0x02,
12406 BGEZAL = 0x03,
12407 BLEZ = 0x04,
12408 BNEZC = 0x05,
12409 BGTZ = 0x06,
12410 BEQZC = 0x07,
12411 TLTI = 0x08,
12412 TGEI = 0x09,
12413 TLTIU = 0x0a,
12414 TGEIU = 0x0b,
12415 TNEI = 0x0c,
12416 LUI = 0x0d,
12417 TEQI = 0x0e,
12418 SYNCI = 0x10,
12419 BLTZALS = 0x11,
12420 BGEZALS = 0x13,
12421 BC2F = 0x14,
12422 BC2T = 0x15,
12423 BPOSGE64 = 0x1a,
12424 BPOSGE32 = 0x1b,
12425 /* These overlap and are distinguished by bit16 of the instruction */
12426 BC1F = 0x1c,
12427 BC1T = 0x1d,
12428 BC1ANY2F = 0x1c,
12429 BC1ANY2T = 0x1d,
12430 BC1ANY4F = 0x1e,
12431 BC1ANY4T = 0x1f
12434 /* POOL16A encoding of minor opcode field */
12436 enum {
12437 ADDU16 = 0x0,
12438 SUBU16 = 0x1
12441 /* POOL16B encoding of minor opcode field */
12443 enum {
12444 SLL16 = 0x0,
12445 SRL16 = 0x1
12448 /* POOL16C encoding of minor opcode field */
12450 enum {
12451 NOT16 = 0x00,
12452 XOR16 = 0x04,
12453 AND16 = 0x08,
12454 OR16 = 0x0c,
12455 LWM16 = 0x10,
12456 SWM16 = 0x14,
12457 JR16 = 0x18,
12458 JRC16 = 0x1a,
12459 JALR16 = 0x1c,
12460 JALR16S = 0x1e,
12461 MFHI16 = 0x20,
12462 MFLO16 = 0x24,
12463 BREAK16 = 0x28,
12464 SDBBP16 = 0x2c,
12465 JRADDIUSP = 0x30
12468 /* POOL16D encoding of minor opcode field */
12470 enum {
12471 ADDIUS5 = 0x0,
12472 ADDIUSP = 0x1
12475 /* POOL16E encoding of minor opcode field */
12477 enum {
12478 ADDIUR2 = 0x0,
12479 ADDIUR1SP = 0x1
12482 static int mmreg (int r)
12484 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12486 return map[r];
12489 /* Used for 16-bit store instructions. */
12490 static int mmreg2 (int r)
12492 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12494 return map[r];
12497 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12498 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12499 #define uMIPS_RS2(op) uMIPS_RS(op)
12500 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12501 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12502 #define uMIPS_RS5(op) (op & 0x1f)
12504 /* Signed immediate */
12505 #define SIMM(op, start, width) \
12506 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12507 << (32-width)) \
12508 >> (32-width))
12509 /* Zero-extended immediate */
12510 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12512 static void gen_addiur1sp(DisasContext *ctx)
12514 int rd = mmreg(uMIPS_RD(ctx->opcode));
12516 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12519 static void gen_addiur2(DisasContext *ctx)
12521 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12522 int rd = mmreg(uMIPS_RD(ctx->opcode));
12523 int rs = mmreg(uMIPS_RS(ctx->opcode));
12525 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12528 static void gen_addiusp(DisasContext *ctx)
12530 int encoded = ZIMM(ctx->opcode, 1, 9);
12531 int decoded;
12533 if (encoded <= 1) {
12534 decoded = 256 + encoded;
12535 } else if (encoded <= 255) {
12536 decoded = encoded;
12537 } else if (encoded <= 509) {
12538 decoded = encoded - 512;
12539 } else {
12540 decoded = encoded - 768;
12543 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
12546 static void gen_addius5(DisasContext *ctx)
12548 int imm = SIMM(ctx->opcode, 1, 4);
12549 int rd = (ctx->opcode >> 5) & 0x1f;
12551 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
12554 static void gen_andi16(DisasContext *ctx)
12556 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
12557 31, 32, 63, 64, 255, 32768, 65535 };
12558 int rd = mmreg(uMIPS_RD(ctx->opcode));
12559 int rs = mmreg(uMIPS_RS(ctx->opcode));
12560 int encoded = ZIMM(ctx->opcode, 0, 4);
12562 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
12565 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
12566 int base, int16_t offset)
12568 const char *opn = "ldst_multiple";
12569 TCGv t0, t1;
12570 TCGv_i32 t2;
12572 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12573 generate_exception(ctx, EXCP_RI);
12574 return;
12577 t0 = tcg_temp_new();
12579 gen_base_offset_addr(ctx, t0, base, offset);
12581 t1 = tcg_const_tl(reglist);
12582 t2 = tcg_const_i32(ctx->mem_idx);
12584 save_cpu_state(ctx, 1);
12585 switch (opc) {
12586 case LWM32:
12587 gen_helper_lwm(cpu_env, t0, t1, t2);
12588 opn = "lwm";
12589 break;
12590 case SWM32:
12591 gen_helper_swm(cpu_env, t0, t1, t2);
12592 opn = "swm";
12593 break;
12594 #ifdef TARGET_MIPS64
12595 case LDM:
12596 gen_helper_ldm(cpu_env, t0, t1, t2);
12597 opn = "ldm";
12598 break;
12599 case SDM:
12600 gen_helper_sdm(cpu_env, t0, t1, t2);
12601 opn = "sdm";
12602 break;
12603 #endif
12605 (void)opn;
12606 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
12607 tcg_temp_free(t0);
12608 tcg_temp_free(t1);
12609 tcg_temp_free_i32(t2);
12613 static void gen_pool16c_insn(DisasContext *ctx)
12615 int rd = mmreg((ctx->opcode >> 3) & 0x7);
12616 int rs = mmreg(ctx->opcode & 0x7);
12618 switch (((ctx->opcode) >> 4) & 0x3f) {
12619 case NOT16 + 0:
12620 case NOT16 + 1:
12621 case NOT16 + 2:
12622 case NOT16 + 3:
12623 gen_logic(ctx, OPC_NOR, rd, rs, 0);
12624 break;
12625 case XOR16 + 0:
12626 case XOR16 + 1:
12627 case XOR16 + 2:
12628 case XOR16 + 3:
12629 gen_logic(ctx, OPC_XOR, rd, rd, rs);
12630 break;
12631 case AND16 + 0:
12632 case AND16 + 1:
12633 case AND16 + 2:
12634 case AND16 + 3:
12635 gen_logic(ctx, OPC_AND, rd, rd, rs);
12636 break;
12637 case OR16 + 0:
12638 case OR16 + 1:
12639 case OR16 + 2:
12640 case OR16 + 3:
12641 gen_logic(ctx, OPC_OR, rd, rd, rs);
12642 break;
12643 case LWM16 + 0:
12644 case LWM16 + 1:
12645 case LWM16 + 2:
12646 case LWM16 + 3:
12648 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12649 int offset = ZIMM(ctx->opcode, 0, 4);
12651 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
12652 29, offset << 2);
12654 break;
12655 case SWM16 + 0:
12656 case SWM16 + 1:
12657 case SWM16 + 2:
12658 case SWM16 + 3:
12660 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12661 int offset = ZIMM(ctx->opcode, 0, 4);
12663 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
12664 29, offset << 2);
12666 break;
12667 case JR16 + 0:
12668 case JR16 + 1:
12670 int reg = ctx->opcode & 0x1f;
12672 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
12674 break;
12675 case JRC16 + 0:
12676 case JRC16 + 1:
12678 int reg = ctx->opcode & 0x1f;
12679 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
12680 /* Let normal delay slot handling in our caller take us
12681 to the branch target. */
12683 break;
12684 case JALR16 + 0:
12685 case JALR16 + 1:
12686 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
12687 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12688 break;
12689 case JALR16S + 0:
12690 case JALR16S + 1:
12691 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
12692 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12693 break;
12694 case MFHI16 + 0:
12695 case MFHI16 + 1:
12696 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
12697 break;
12698 case MFLO16 + 0:
12699 case MFLO16 + 1:
12700 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
12701 break;
12702 case BREAK16:
12703 generate_exception(ctx, EXCP_BREAK);
12704 break;
12705 case SDBBP16:
12706 /* XXX: not clear which exception should be raised
12707 * when in debug mode...
12709 check_insn(ctx, ISA_MIPS32);
12710 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
12711 generate_exception(ctx, EXCP_DBp);
12712 } else {
12713 generate_exception(ctx, EXCP_DBp);
12715 break;
12716 case JRADDIUSP + 0:
12717 case JRADDIUSP + 1:
12719 int imm = ZIMM(ctx->opcode, 0, 5);
12720 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12721 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12722 /* Let normal delay slot handling in our caller take us
12723 to the branch target. */
12725 break;
12726 default:
12727 generate_exception(ctx, EXCP_RI);
12728 break;
12732 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
12734 TCGv t0 = tcg_temp_new();
12735 TCGv t1 = tcg_temp_new();
12737 gen_load_gpr(t0, base);
12739 if (index != 0) {
12740 gen_load_gpr(t1, index);
12741 tcg_gen_shli_tl(t1, t1, 2);
12742 gen_op_addr_add(ctx, t0, t1, t0);
12745 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12746 gen_store_gpr(t1, rd);
12748 tcg_temp_free(t0);
12749 tcg_temp_free(t1);
12752 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
12753 int base, int16_t offset)
12755 const char *opn = "ldst_pair";
12756 TCGv t0, t1;
12758 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
12759 generate_exception(ctx, EXCP_RI);
12760 return;
12763 t0 = tcg_temp_new();
12764 t1 = tcg_temp_new();
12766 gen_base_offset_addr(ctx, t0, base, offset);
12768 switch (opc) {
12769 case LWP:
12770 if (rd == base) {
12771 generate_exception(ctx, EXCP_RI);
12772 return;
12774 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12775 gen_store_gpr(t1, rd);
12776 tcg_gen_movi_tl(t1, 4);
12777 gen_op_addr_add(ctx, t0, t0, t1);
12778 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12779 gen_store_gpr(t1, rd+1);
12780 opn = "lwp";
12781 break;
12782 case SWP:
12783 gen_load_gpr(t1, rd);
12784 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12785 tcg_gen_movi_tl(t1, 4);
12786 gen_op_addr_add(ctx, t0, t0, t1);
12787 gen_load_gpr(t1, rd+1);
12788 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12789 opn = "swp";
12790 break;
12791 #ifdef TARGET_MIPS64
12792 case LDP:
12793 if (rd == base) {
12794 generate_exception(ctx, EXCP_RI);
12795 return;
12797 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12798 gen_store_gpr(t1, rd);
12799 tcg_gen_movi_tl(t1, 8);
12800 gen_op_addr_add(ctx, t0, t0, t1);
12801 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12802 gen_store_gpr(t1, rd+1);
12803 opn = "ldp";
12804 break;
12805 case SDP:
12806 gen_load_gpr(t1, rd);
12807 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12808 tcg_gen_movi_tl(t1, 8);
12809 gen_op_addr_add(ctx, t0, t0, t1);
12810 gen_load_gpr(t1, rd+1);
12811 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12812 opn = "sdp";
12813 break;
12814 #endif
12816 (void)opn; /* avoid a compiler warning */
12817 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
12818 tcg_temp_free(t0);
12819 tcg_temp_free(t1);
12822 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
12824 int extension = (ctx->opcode >> 6) & 0x3f;
12825 int minor = (ctx->opcode >> 12) & 0xf;
12826 uint32_t mips32_op;
12828 switch (extension) {
12829 case TEQ:
12830 mips32_op = OPC_TEQ;
12831 goto do_trap;
12832 case TGE:
12833 mips32_op = OPC_TGE;
12834 goto do_trap;
12835 case TGEU:
12836 mips32_op = OPC_TGEU;
12837 goto do_trap;
12838 case TLT:
12839 mips32_op = OPC_TLT;
12840 goto do_trap;
12841 case TLTU:
12842 mips32_op = OPC_TLTU;
12843 goto do_trap;
12844 case TNE:
12845 mips32_op = OPC_TNE;
12846 do_trap:
12847 gen_trap(ctx, mips32_op, rs, rt, -1);
12848 break;
12849 #ifndef CONFIG_USER_ONLY
12850 case MFC0:
12851 case MFC0 + 32:
12852 check_cp0_enabled(ctx);
12853 if (rt == 0) {
12854 /* Treat as NOP. */
12855 break;
12857 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
12858 break;
12859 case MTC0:
12860 case MTC0 + 32:
12861 check_cp0_enabled(ctx);
12863 TCGv t0 = tcg_temp_new();
12865 gen_load_gpr(t0, rt);
12866 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
12867 tcg_temp_free(t0);
12869 break;
12870 #endif
12871 case 0x2a:
12872 switch (minor & 3) {
12873 case MADD_ACC:
12874 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
12875 break;
12876 case MADDU_ACC:
12877 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
12878 break;
12879 case MSUB_ACC:
12880 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
12881 break;
12882 case MSUBU_ACC:
12883 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
12884 break;
12885 default:
12886 goto pool32axf_invalid;
12888 break;
12889 case 0x32:
12890 switch (minor & 3) {
12891 case MULT_ACC:
12892 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
12893 break;
12894 case MULTU_ACC:
12895 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
12896 break;
12897 default:
12898 goto pool32axf_invalid;
12900 break;
12901 case 0x2c:
12902 switch (minor) {
12903 case SEB:
12904 gen_bshfl(ctx, OPC_SEB, rs, rt);
12905 break;
12906 case SEH:
12907 gen_bshfl(ctx, OPC_SEH, rs, rt);
12908 break;
12909 case CLO:
12910 mips32_op = OPC_CLO;
12911 goto do_cl;
12912 case CLZ:
12913 mips32_op = OPC_CLZ;
12914 do_cl:
12915 check_insn(ctx, ISA_MIPS32);
12916 gen_cl(ctx, mips32_op, rt, rs);
12917 break;
12918 case RDHWR:
12919 gen_rdhwr(ctx, rt, rs);
12920 break;
12921 case WSBH:
12922 gen_bshfl(ctx, OPC_WSBH, rs, rt);
12923 break;
12924 case MULT:
12925 mips32_op = OPC_MULT;
12926 goto do_mul;
12927 case MULTU:
12928 mips32_op = OPC_MULTU;
12929 goto do_mul;
12930 case DIV:
12931 mips32_op = OPC_DIV;
12932 goto do_div;
12933 case DIVU:
12934 mips32_op = OPC_DIVU;
12935 goto do_div;
12936 do_div:
12937 check_insn(ctx, ISA_MIPS32);
12938 gen_muldiv(ctx, mips32_op, 0, rs, rt);
12939 break;
12940 case MADD:
12941 mips32_op = OPC_MADD;
12942 goto do_mul;
12943 case MADDU:
12944 mips32_op = OPC_MADDU;
12945 goto do_mul;
12946 case MSUB:
12947 mips32_op = OPC_MSUB;
12948 goto do_mul;
12949 case MSUBU:
12950 mips32_op = OPC_MSUBU;
12951 do_mul:
12952 check_insn(ctx, ISA_MIPS32);
12953 gen_muldiv(ctx, mips32_op, 0, rs, rt);
12954 break;
12955 default:
12956 goto pool32axf_invalid;
12958 break;
12959 case 0x34:
12960 switch (minor) {
12961 case MFC2:
12962 case MTC2:
12963 case MFHC2:
12964 case MTHC2:
12965 case CFC2:
12966 case CTC2:
12967 generate_exception_err(ctx, EXCP_CpU, 2);
12968 break;
12969 default:
12970 goto pool32axf_invalid;
12972 break;
12973 case 0x3c:
12974 switch (minor) {
12975 case JALR:
12976 case JALR_HB:
12977 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
12978 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12979 break;
12980 case JALRS:
12981 case JALRS_HB:
12982 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
12983 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12984 break;
12985 default:
12986 goto pool32axf_invalid;
12988 break;
12989 case 0x05:
12990 switch (minor) {
12991 case RDPGPR:
12992 check_cp0_enabled(ctx);
12993 check_insn(ctx, ISA_MIPS32R2);
12994 gen_load_srsgpr(rt, rs);
12995 break;
12996 case WRPGPR:
12997 check_cp0_enabled(ctx);
12998 check_insn(ctx, ISA_MIPS32R2);
12999 gen_store_srsgpr(rt, rs);
13000 break;
13001 default:
13002 goto pool32axf_invalid;
13004 break;
13005 #ifndef CONFIG_USER_ONLY
13006 case 0x0d:
13007 switch (minor) {
13008 case TLBP:
13009 mips32_op = OPC_TLBP;
13010 goto do_cp0;
13011 case TLBR:
13012 mips32_op = OPC_TLBR;
13013 goto do_cp0;
13014 case TLBWI:
13015 mips32_op = OPC_TLBWI;
13016 goto do_cp0;
13017 case TLBWR:
13018 mips32_op = OPC_TLBWR;
13019 goto do_cp0;
13020 case WAIT:
13021 mips32_op = OPC_WAIT;
13022 goto do_cp0;
13023 case DERET:
13024 mips32_op = OPC_DERET;
13025 goto do_cp0;
13026 case ERET:
13027 mips32_op = OPC_ERET;
13028 do_cp0:
13029 gen_cp0(env, ctx, mips32_op, rt, rs);
13030 break;
13031 default:
13032 goto pool32axf_invalid;
13034 break;
13035 case 0x1d:
13036 switch (minor) {
13037 case DI:
13038 check_cp0_enabled(ctx);
13040 TCGv t0 = tcg_temp_new();
13042 save_cpu_state(ctx, 1);
13043 gen_helper_di(t0, cpu_env);
13044 gen_store_gpr(t0, rs);
13045 /* Stop translation as we may have switched the execution mode */
13046 ctx->bstate = BS_STOP;
13047 tcg_temp_free(t0);
13049 break;
13050 case EI:
13051 check_cp0_enabled(ctx);
13053 TCGv t0 = tcg_temp_new();
13055 save_cpu_state(ctx, 1);
13056 gen_helper_ei(t0, cpu_env);
13057 gen_store_gpr(t0, rs);
13058 /* Stop translation as we may have switched the execution mode */
13059 ctx->bstate = BS_STOP;
13060 tcg_temp_free(t0);
13062 break;
13063 default:
13064 goto pool32axf_invalid;
13066 break;
13067 #endif
13068 case 0x2d:
13069 switch (minor) {
13070 case SYNC:
13071 /* NOP */
13072 break;
13073 case SYSCALL:
13074 generate_exception(ctx, EXCP_SYSCALL);
13075 ctx->bstate = BS_STOP;
13076 break;
13077 case SDBBP:
13078 check_insn(ctx, ISA_MIPS32);
13079 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
13080 generate_exception(ctx, EXCP_DBp);
13081 } else {
13082 generate_exception(ctx, EXCP_DBp);
13084 break;
13085 default:
13086 goto pool32axf_invalid;
13088 break;
13089 case 0x01:
13090 switch (minor & 3) {
13091 case MFHI_ACC:
13092 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
13093 break;
13094 case MFLO_ACC:
13095 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
13096 break;
13097 case MTHI_ACC:
13098 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
13099 break;
13100 case MTLO_ACC:
13101 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
13102 break;
13103 default:
13104 goto pool32axf_invalid;
13106 break;
13107 case 0x35:
13108 switch (minor) {
13109 case MFHI32:
13110 gen_HILO(ctx, OPC_MFHI, 0, rs);
13111 break;
13112 case MFLO32:
13113 gen_HILO(ctx, OPC_MFLO, 0, rs);
13114 break;
13115 case MTHI32:
13116 gen_HILO(ctx, OPC_MTHI, 0, rs);
13117 break;
13118 case MTLO32:
13119 gen_HILO(ctx, OPC_MTLO, 0, rs);
13120 break;
13121 default:
13122 goto pool32axf_invalid;
13124 break;
13125 default:
13126 pool32axf_invalid:
13127 MIPS_INVAL("pool32axf");
13128 generate_exception(ctx, EXCP_RI);
13129 break;
13133 /* Values for microMIPS fmt field. Variable-width, depending on which
13134 formats the instruction supports. */
13136 enum {
13137 FMT_SD_S = 0,
13138 FMT_SD_D = 1,
13140 FMT_SDPS_S = 0,
13141 FMT_SDPS_D = 1,
13142 FMT_SDPS_PS = 2,
13144 FMT_SWL_S = 0,
13145 FMT_SWL_W = 1,
13146 FMT_SWL_L = 2,
13148 FMT_DWL_D = 0,
13149 FMT_DWL_W = 1,
13150 FMT_DWL_L = 2
13153 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
13155 int extension = (ctx->opcode >> 6) & 0x3ff;
13156 uint32_t mips32_op;
13158 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
13159 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
13160 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
13162 switch (extension) {
13163 case FLOAT_1BIT_FMT(CFC1, 0):
13164 mips32_op = OPC_CFC1;
13165 goto do_cp1;
13166 case FLOAT_1BIT_FMT(CTC1, 0):
13167 mips32_op = OPC_CTC1;
13168 goto do_cp1;
13169 case FLOAT_1BIT_FMT(MFC1, 0):
13170 mips32_op = OPC_MFC1;
13171 goto do_cp1;
13172 case FLOAT_1BIT_FMT(MTC1, 0):
13173 mips32_op = OPC_MTC1;
13174 goto do_cp1;
13175 case FLOAT_1BIT_FMT(MFHC1, 0):
13176 mips32_op = OPC_MFHC1;
13177 goto do_cp1;
13178 case FLOAT_1BIT_FMT(MTHC1, 0):
13179 mips32_op = OPC_MTHC1;
13180 do_cp1:
13181 gen_cp1(ctx, mips32_op, rt, rs);
13182 break;
13184 /* Reciprocal square root */
13185 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
13186 mips32_op = OPC_RSQRT_S;
13187 goto do_unaryfp;
13188 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
13189 mips32_op = OPC_RSQRT_D;
13190 goto do_unaryfp;
13192 /* Square root */
13193 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
13194 mips32_op = OPC_SQRT_S;
13195 goto do_unaryfp;
13196 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
13197 mips32_op = OPC_SQRT_D;
13198 goto do_unaryfp;
13200 /* Reciprocal */
13201 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
13202 mips32_op = OPC_RECIP_S;
13203 goto do_unaryfp;
13204 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
13205 mips32_op = OPC_RECIP_D;
13206 goto do_unaryfp;
13208 /* Floor */
13209 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
13210 mips32_op = OPC_FLOOR_L_S;
13211 goto do_unaryfp;
13212 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
13213 mips32_op = OPC_FLOOR_L_D;
13214 goto do_unaryfp;
13215 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
13216 mips32_op = OPC_FLOOR_W_S;
13217 goto do_unaryfp;
13218 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
13219 mips32_op = OPC_FLOOR_W_D;
13220 goto do_unaryfp;
13222 /* Ceiling */
13223 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
13224 mips32_op = OPC_CEIL_L_S;
13225 goto do_unaryfp;
13226 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
13227 mips32_op = OPC_CEIL_L_D;
13228 goto do_unaryfp;
13229 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
13230 mips32_op = OPC_CEIL_W_S;
13231 goto do_unaryfp;
13232 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
13233 mips32_op = OPC_CEIL_W_D;
13234 goto do_unaryfp;
13236 /* Truncation */
13237 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
13238 mips32_op = OPC_TRUNC_L_S;
13239 goto do_unaryfp;
13240 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
13241 mips32_op = OPC_TRUNC_L_D;
13242 goto do_unaryfp;
13243 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
13244 mips32_op = OPC_TRUNC_W_S;
13245 goto do_unaryfp;
13246 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
13247 mips32_op = OPC_TRUNC_W_D;
13248 goto do_unaryfp;
13250 /* Round */
13251 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
13252 mips32_op = OPC_ROUND_L_S;
13253 goto do_unaryfp;
13254 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
13255 mips32_op = OPC_ROUND_L_D;
13256 goto do_unaryfp;
13257 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
13258 mips32_op = OPC_ROUND_W_S;
13259 goto do_unaryfp;
13260 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
13261 mips32_op = OPC_ROUND_W_D;
13262 goto do_unaryfp;
13264 /* Integer to floating-point conversion */
13265 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
13266 mips32_op = OPC_CVT_L_S;
13267 goto do_unaryfp;
13268 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
13269 mips32_op = OPC_CVT_L_D;
13270 goto do_unaryfp;
13271 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
13272 mips32_op = OPC_CVT_W_S;
13273 goto do_unaryfp;
13274 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
13275 mips32_op = OPC_CVT_W_D;
13276 goto do_unaryfp;
13278 /* Paired-foo conversions */
13279 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
13280 mips32_op = OPC_CVT_S_PL;
13281 goto do_unaryfp;
13282 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13283 mips32_op = OPC_CVT_S_PU;
13284 goto do_unaryfp;
13285 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13286 mips32_op = OPC_CVT_PW_PS;
13287 goto do_unaryfp;
13288 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13289 mips32_op = OPC_CVT_PS_PW;
13290 goto do_unaryfp;
13292 /* Floating-point moves */
13293 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13294 mips32_op = OPC_MOV_S;
13295 goto do_unaryfp;
13296 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13297 mips32_op = OPC_MOV_D;
13298 goto do_unaryfp;
13299 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13300 mips32_op = OPC_MOV_PS;
13301 goto do_unaryfp;
13303 /* Absolute value */
13304 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13305 mips32_op = OPC_ABS_S;
13306 goto do_unaryfp;
13307 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13308 mips32_op = OPC_ABS_D;
13309 goto do_unaryfp;
13310 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13311 mips32_op = OPC_ABS_PS;
13312 goto do_unaryfp;
13314 /* Negation */
13315 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13316 mips32_op = OPC_NEG_S;
13317 goto do_unaryfp;
13318 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13319 mips32_op = OPC_NEG_D;
13320 goto do_unaryfp;
13321 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13322 mips32_op = OPC_NEG_PS;
13323 goto do_unaryfp;
13325 /* Reciprocal square root step */
13326 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13327 mips32_op = OPC_RSQRT1_S;
13328 goto do_unaryfp;
13329 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13330 mips32_op = OPC_RSQRT1_D;
13331 goto do_unaryfp;
13332 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13333 mips32_op = OPC_RSQRT1_PS;
13334 goto do_unaryfp;
13336 /* Reciprocal step */
13337 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13338 mips32_op = OPC_RECIP1_S;
13339 goto do_unaryfp;
13340 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13341 mips32_op = OPC_RECIP1_S;
13342 goto do_unaryfp;
13343 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13344 mips32_op = OPC_RECIP1_PS;
13345 goto do_unaryfp;
13347 /* Conversions from double */
13348 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13349 mips32_op = OPC_CVT_D_S;
13350 goto do_unaryfp;
13351 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13352 mips32_op = OPC_CVT_D_W;
13353 goto do_unaryfp;
13354 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13355 mips32_op = OPC_CVT_D_L;
13356 goto do_unaryfp;
13358 /* Conversions from single */
13359 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13360 mips32_op = OPC_CVT_S_D;
13361 goto do_unaryfp;
13362 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13363 mips32_op = OPC_CVT_S_W;
13364 goto do_unaryfp;
13365 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13366 mips32_op = OPC_CVT_S_L;
13367 do_unaryfp:
13368 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13369 break;
13371 /* Conditional moves on floating-point codes */
13372 case COND_FLOAT_MOV(MOVT, 0):
13373 case COND_FLOAT_MOV(MOVT, 1):
13374 case COND_FLOAT_MOV(MOVT, 2):
13375 case COND_FLOAT_MOV(MOVT, 3):
13376 case COND_FLOAT_MOV(MOVT, 4):
13377 case COND_FLOAT_MOV(MOVT, 5):
13378 case COND_FLOAT_MOV(MOVT, 6):
13379 case COND_FLOAT_MOV(MOVT, 7):
13380 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13381 break;
13382 case COND_FLOAT_MOV(MOVF, 0):
13383 case COND_FLOAT_MOV(MOVF, 1):
13384 case COND_FLOAT_MOV(MOVF, 2):
13385 case COND_FLOAT_MOV(MOVF, 3):
13386 case COND_FLOAT_MOV(MOVF, 4):
13387 case COND_FLOAT_MOV(MOVF, 5):
13388 case COND_FLOAT_MOV(MOVF, 6):
13389 case COND_FLOAT_MOV(MOVF, 7):
13390 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13391 break;
13392 default:
13393 MIPS_INVAL("pool32fxf");
13394 generate_exception(ctx, EXCP_RI);
13395 break;
13399 static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
13400 uint16_t insn_hw1)
13402 int32_t offset;
13403 uint16_t insn;
13404 int rt, rs, rd, rr;
13405 int16_t imm;
13406 uint32_t op, minor, mips32_op;
13407 uint32_t cond, fmt, cc;
13409 insn = cpu_lduw_code(env, ctx->pc + 2);
13410 ctx->opcode = (ctx->opcode << 16) | insn;
13412 rt = (ctx->opcode >> 21) & 0x1f;
13413 rs = (ctx->opcode >> 16) & 0x1f;
13414 rd = (ctx->opcode >> 11) & 0x1f;
13415 rr = (ctx->opcode >> 6) & 0x1f;
13416 imm = (int16_t) ctx->opcode;
13418 op = (ctx->opcode >> 26) & 0x3f;
13419 switch (op) {
13420 case POOL32A:
13421 minor = ctx->opcode & 0x3f;
13422 switch (minor) {
13423 case 0x00:
13424 minor = (ctx->opcode >> 6) & 0xf;
13425 switch (minor) {
13426 case SLL32:
13427 mips32_op = OPC_SLL;
13428 goto do_shifti;
13429 case SRA:
13430 mips32_op = OPC_SRA;
13431 goto do_shifti;
13432 case SRL32:
13433 mips32_op = OPC_SRL;
13434 goto do_shifti;
13435 case ROTR:
13436 mips32_op = OPC_ROTR;
13437 do_shifti:
13438 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
13439 break;
13440 default:
13441 goto pool32a_invalid;
13443 break;
13444 case 0x10:
13445 minor = (ctx->opcode >> 6) & 0xf;
13446 switch (minor) {
13447 /* Arithmetic */
13448 case ADD:
13449 mips32_op = OPC_ADD;
13450 goto do_arith;
13451 case ADDU32:
13452 mips32_op = OPC_ADDU;
13453 goto do_arith;
13454 case SUB:
13455 mips32_op = OPC_SUB;
13456 goto do_arith;
13457 case SUBU32:
13458 mips32_op = OPC_SUBU;
13459 goto do_arith;
13460 case MUL:
13461 mips32_op = OPC_MUL;
13462 do_arith:
13463 gen_arith(ctx, mips32_op, rd, rs, rt);
13464 break;
13465 /* Shifts */
13466 case SLLV:
13467 mips32_op = OPC_SLLV;
13468 goto do_shift;
13469 case SRLV:
13470 mips32_op = OPC_SRLV;
13471 goto do_shift;
13472 case SRAV:
13473 mips32_op = OPC_SRAV;
13474 goto do_shift;
13475 case ROTRV:
13476 mips32_op = OPC_ROTRV;
13477 do_shift:
13478 gen_shift(ctx, mips32_op, rd, rs, rt);
13479 break;
13480 /* Logical operations */
13481 case AND:
13482 mips32_op = OPC_AND;
13483 goto do_logic;
13484 case OR32:
13485 mips32_op = OPC_OR;
13486 goto do_logic;
13487 case NOR:
13488 mips32_op = OPC_NOR;
13489 goto do_logic;
13490 case XOR32:
13491 mips32_op = OPC_XOR;
13492 do_logic:
13493 gen_logic(ctx, mips32_op, rd, rs, rt);
13494 break;
13495 /* Set less than */
13496 case SLT:
13497 mips32_op = OPC_SLT;
13498 goto do_slt;
13499 case SLTU:
13500 mips32_op = OPC_SLTU;
13501 do_slt:
13502 gen_slt(ctx, mips32_op, rd, rs, rt);
13503 break;
13504 default:
13505 goto pool32a_invalid;
13507 break;
13508 case 0x18:
13509 minor = (ctx->opcode >> 6) & 0xf;
13510 switch (minor) {
13511 /* Conditional moves */
13512 case MOVN:
13513 mips32_op = OPC_MOVN;
13514 goto do_cmov;
13515 case MOVZ:
13516 mips32_op = OPC_MOVZ;
13517 do_cmov:
13518 gen_cond_move(ctx, mips32_op, rd, rs, rt);
13519 break;
13520 case LWXS:
13521 gen_ldxs(ctx, rs, rt, rd);
13522 break;
13523 default:
13524 goto pool32a_invalid;
13526 break;
13527 case INS:
13528 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
13529 return;
13530 case EXT:
13531 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
13532 return;
13533 case POOL32AXF:
13534 gen_pool32axf(env, ctx, rt, rs);
13535 break;
13536 case 0x07:
13537 generate_exception(ctx, EXCP_BREAK);
13538 break;
13539 default:
13540 pool32a_invalid:
13541 MIPS_INVAL("pool32a");
13542 generate_exception(ctx, EXCP_RI);
13543 break;
13545 break;
13546 case POOL32B:
13547 minor = (ctx->opcode >> 12) & 0xf;
13548 switch (minor) {
13549 case CACHE:
13550 check_cp0_enabled(ctx);
13551 /* Treat as no-op. */
13552 break;
13553 case LWC2:
13554 case SWC2:
13555 /* COP2: Not implemented. */
13556 generate_exception_err(ctx, EXCP_CpU, 2);
13557 break;
13558 #ifdef TARGET_MIPS64
13559 case LDP:
13560 case SDP:
13561 check_insn(ctx, ISA_MIPS3);
13562 check_mips_64(ctx);
13563 /* Fallthrough */
13564 #endif
13565 case LWP:
13566 case SWP:
13567 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13568 break;
13569 #ifdef TARGET_MIPS64
13570 case LDM:
13571 case SDM:
13572 check_insn(ctx, ISA_MIPS3);
13573 check_mips_64(ctx);
13574 /* Fallthrough */
13575 #endif
13576 case LWM32:
13577 case SWM32:
13578 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13579 break;
13580 default:
13581 MIPS_INVAL("pool32b");
13582 generate_exception(ctx, EXCP_RI);
13583 break;
13585 break;
13586 case POOL32F:
13587 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
13588 minor = ctx->opcode & 0x3f;
13589 check_cp1_enabled(ctx);
13590 switch (minor) {
13591 case ALNV_PS:
13592 mips32_op = OPC_ALNV_PS;
13593 goto do_madd;
13594 case MADD_S:
13595 mips32_op = OPC_MADD_S;
13596 goto do_madd;
13597 case MADD_D:
13598 mips32_op = OPC_MADD_D;
13599 goto do_madd;
13600 case MADD_PS:
13601 mips32_op = OPC_MADD_PS;
13602 goto do_madd;
13603 case MSUB_S:
13604 mips32_op = OPC_MSUB_S;
13605 goto do_madd;
13606 case MSUB_D:
13607 mips32_op = OPC_MSUB_D;
13608 goto do_madd;
13609 case MSUB_PS:
13610 mips32_op = OPC_MSUB_PS;
13611 goto do_madd;
13612 case NMADD_S:
13613 mips32_op = OPC_NMADD_S;
13614 goto do_madd;
13615 case NMADD_D:
13616 mips32_op = OPC_NMADD_D;
13617 goto do_madd;
13618 case NMADD_PS:
13619 mips32_op = OPC_NMADD_PS;
13620 goto do_madd;
13621 case NMSUB_S:
13622 mips32_op = OPC_NMSUB_S;
13623 goto do_madd;
13624 case NMSUB_D:
13625 mips32_op = OPC_NMSUB_D;
13626 goto do_madd;
13627 case NMSUB_PS:
13628 mips32_op = OPC_NMSUB_PS;
13629 do_madd:
13630 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
13631 break;
13632 case CABS_COND_FMT:
13633 cond = (ctx->opcode >> 6) & 0xf;
13634 cc = (ctx->opcode >> 13) & 0x7;
13635 fmt = (ctx->opcode >> 10) & 0x3;
13636 switch (fmt) {
13637 case 0x0:
13638 gen_cmpabs_s(ctx, cond, rt, rs, cc);
13639 break;
13640 case 0x1:
13641 gen_cmpabs_d(ctx, cond, rt, rs, cc);
13642 break;
13643 case 0x2:
13644 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
13645 break;
13646 default:
13647 goto pool32f_invalid;
13649 break;
13650 case C_COND_FMT:
13651 cond = (ctx->opcode >> 6) & 0xf;
13652 cc = (ctx->opcode >> 13) & 0x7;
13653 fmt = (ctx->opcode >> 10) & 0x3;
13654 switch (fmt) {
13655 case 0x0:
13656 gen_cmp_s(ctx, cond, rt, rs, cc);
13657 break;
13658 case 0x1:
13659 gen_cmp_d(ctx, cond, rt, rs, cc);
13660 break;
13661 case 0x2:
13662 gen_cmp_ps(ctx, cond, rt, rs, cc);
13663 break;
13664 default:
13665 goto pool32f_invalid;
13667 break;
13668 case POOL32FXF:
13669 gen_pool32fxf(ctx, rt, rs);
13670 break;
13671 case 0x00:
13672 /* PLL foo */
13673 switch ((ctx->opcode >> 6) & 0x7) {
13674 case PLL_PS:
13675 mips32_op = OPC_PLL_PS;
13676 goto do_ps;
13677 case PLU_PS:
13678 mips32_op = OPC_PLU_PS;
13679 goto do_ps;
13680 case PUL_PS:
13681 mips32_op = OPC_PUL_PS;
13682 goto do_ps;
13683 case PUU_PS:
13684 mips32_op = OPC_PUU_PS;
13685 goto do_ps;
13686 case CVT_PS_S:
13687 mips32_op = OPC_CVT_PS_S;
13688 do_ps:
13689 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13690 break;
13691 default:
13692 goto pool32f_invalid;
13694 break;
13695 case 0x08:
13696 /* [LS][WDU]XC1 */
13697 switch ((ctx->opcode >> 6) & 0x7) {
13698 case LWXC1:
13699 mips32_op = OPC_LWXC1;
13700 goto do_ldst_cp1;
13701 case SWXC1:
13702 mips32_op = OPC_SWXC1;
13703 goto do_ldst_cp1;
13704 case LDXC1:
13705 mips32_op = OPC_LDXC1;
13706 goto do_ldst_cp1;
13707 case SDXC1:
13708 mips32_op = OPC_SDXC1;
13709 goto do_ldst_cp1;
13710 case LUXC1:
13711 mips32_op = OPC_LUXC1;
13712 goto do_ldst_cp1;
13713 case SUXC1:
13714 mips32_op = OPC_SUXC1;
13715 do_ldst_cp1:
13716 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
13717 break;
13718 default:
13719 goto pool32f_invalid;
13721 break;
13722 case 0x18:
13723 /* 3D insns */
13724 fmt = (ctx->opcode >> 9) & 0x3;
13725 switch ((ctx->opcode >> 6) & 0x7) {
13726 case RSQRT2_FMT:
13727 switch (fmt) {
13728 case FMT_SDPS_S:
13729 mips32_op = OPC_RSQRT2_S;
13730 goto do_3d;
13731 case FMT_SDPS_D:
13732 mips32_op = OPC_RSQRT2_D;
13733 goto do_3d;
13734 case FMT_SDPS_PS:
13735 mips32_op = OPC_RSQRT2_PS;
13736 goto do_3d;
13737 default:
13738 goto pool32f_invalid;
13740 break;
13741 case RECIP2_FMT:
13742 switch (fmt) {
13743 case FMT_SDPS_S:
13744 mips32_op = OPC_RECIP2_S;
13745 goto do_3d;
13746 case FMT_SDPS_D:
13747 mips32_op = OPC_RECIP2_D;
13748 goto do_3d;
13749 case FMT_SDPS_PS:
13750 mips32_op = OPC_RECIP2_PS;
13751 goto do_3d;
13752 default:
13753 goto pool32f_invalid;
13755 break;
13756 case ADDR_PS:
13757 mips32_op = OPC_ADDR_PS;
13758 goto do_3d;
13759 case MULR_PS:
13760 mips32_op = OPC_MULR_PS;
13761 do_3d:
13762 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13763 break;
13764 default:
13765 goto pool32f_invalid;
13767 break;
13768 case 0x20:
13769 /* MOV[FT].fmt and PREFX */
13770 cc = (ctx->opcode >> 13) & 0x7;
13771 fmt = (ctx->opcode >> 9) & 0x3;
13772 switch ((ctx->opcode >> 6) & 0x7) {
13773 case MOVF_FMT:
13774 switch (fmt) {
13775 case FMT_SDPS_S:
13776 gen_movcf_s(ctx, rs, rt, cc, 0);
13777 break;
13778 case FMT_SDPS_D:
13779 gen_movcf_d(ctx, rs, rt, cc, 0);
13780 break;
13781 case FMT_SDPS_PS:
13782 gen_movcf_ps(ctx, rs, rt, cc, 0);
13783 break;
13784 default:
13785 goto pool32f_invalid;
13787 break;
13788 case MOVT_FMT:
13789 switch (fmt) {
13790 case FMT_SDPS_S:
13791 gen_movcf_s(ctx, rs, rt, cc, 1);
13792 break;
13793 case FMT_SDPS_D:
13794 gen_movcf_d(ctx, rs, rt, cc, 1);
13795 break;
13796 case FMT_SDPS_PS:
13797 gen_movcf_ps(ctx, rs, rt, cc, 1);
13798 break;
13799 default:
13800 goto pool32f_invalid;
13802 break;
13803 case PREFX:
13804 break;
13805 default:
13806 goto pool32f_invalid;
13808 break;
13809 #define FINSN_3ARG_SDPS(prfx) \
13810 switch ((ctx->opcode >> 8) & 0x3) { \
13811 case FMT_SDPS_S: \
13812 mips32_op = OPC_##prfx##_S; \
13813 goto do_fpop; \
13814 case FMT_SDPS_D: \
13815 mips32_op = OPC_##prfx##_D; \
13816 goto do_fpop; \
13817 case FMT_SDPS_PS: \
13818 mips32_op = OPC_##prfx##_PS; \
13819 goto do_fpop; \
13820 default: \
13821 goto pool32f_invalid; \
13823 case 0x30:
13824 /* regular FP ops */
13825 switch ((ctx->opcode >> 6) & 0x3) {
13826 case ADD_FMT:
13827 FINSN_3ARG_SDPS(ADD);
13828 break;
13829 case SUB_FMT:
13830 FINSN_3ARG_SDPS(SUB);
13831 break;
13832 case MUL_FMT:
13833 FINSN_3ARG_SDPS(MUL);
13834 break;
13835 case DIV_FMT:
13836 fmt = (ctx->opcode >> 8) & 0x3;
13837 if (fmt == 1) {
13838 mips32_op = OPC_DIV_D;
13839 } else if (fmt == 0) {
13840 mips32_op = OPC_DIV_S;
13841 } else {
13842 goto pool32f_invalid;
13844 goto do_fpop;
13845 default:
13846 goto pool32f_invalid;
13848 break;
13849 case 0x38:
13850 /* cmovs */
13851 switch ((ctx->opcode >> 6) & 0x3) {
13852 case MOVN_FMT:
13853 FINSN_3ARG_SDPS(MOVN);
13854 break;
13855 case MOVZ_FMT:
13856 FINSN_3ARG_SDPS(MOVZ);
13857 break;
13858 default:
13859 goto pool32f_invalid;
13861 break;
13862 do_fpop:
13863 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13864 break;
13865 default:
13866 pool32f_invalid:
13867 MIPS_INVAL("pool32f");
13868 generate_exception(ctx, EXCP_RI);
13869 break;
13871 } else {
13872 generate_exception_err(ctx, EXCP_CpU, 1);
13874 break;
13875 case POOL32I:
13876 minor = (ctx->opcode >> 21) & 0x1f;
13877 switch (minor) {
13878 case BLTZ:
13879 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
13880 break;
13881 case BLTZAL:
13882 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
13883 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13884 break;
13885 case BLTZALS:
13886 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
13887 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13888 break;
13889 case BGEZ:
13890 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
13891 break;
13892 case BGEZAL:
13893 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
13894 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13895 break;
13896 case BGEZALS:
13897 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
13898 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13899 break;
13900 case BLEZ:
13901 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
13902 break;
13903 case BGTZ:
13904 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
13905 break;
13907 /* Traps */
13908 case TLTI:
13909 mips32_op = OPC_TLTI;
13910 goto do_trapi;
13911 case TGEI:
13912 mips32_op = OPC_TGEI;
13913 goto do_trapi;
13914 case TLTIU:
13915 mips32_op = OPC_TLTIU;
13916 goto do_trapi;
13917 case TGEIU:
13918 mips32_op = OPC_TGEIU;
13919 goto do_trapi;
13920 case TNEI:
13921 mips32_op = OPC_TNEI;
13922 goto do_trapi;
13923 case TEQI:
13924 mips32_op = OPC_TEQI;
13925 do_trapi:
13926 gen_trap(ctx, mips32_op, rs, -1, imm);
13927 break;
13929 case BNEZC:
13930 case BEQZC:
13931 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
13932 4, rs, 0, imm << 1, 0);
13933 /* Compact branches don't have a delay slot, so just let
13934 the normal delay slot handling take us to the branch
13935 target. */
13936 break;
13937 case LUI:
13938 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
13939 break;
13940 case SYNCI:
13941 /* Break the TB to be able to sync copied instructions
13942 immediately */
13943 ctx->bstate = BS_STOP;
13944 break;
13945 case BC2F:
13946 case BC2T:
13947 /* COP2: Not implemented. */
13948 generate_exception_err(ctx, EXCP_CpU, 2);
13949 break;
13950 case BC1F:
13951 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
13952 goto do_cp1branch;
13953 case BC1T:
13954 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
13955 goto do_cp1branch;
13956 case BC1ANY4F:
13957 mips32_op = OPC_BC1FANY4;
13958 goto do_cp1mips3d;
13959 case BC1ANY4T:
13960 mips32_op = OPC_BC1TANY4;
13961 do_cp1mips3d:
13962 check_cop1x(ctx);
13963 check_insn(ctx, ASE_MIPS3D);
13964 /* Fall through */
13965 do_cp1branch:
13966 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
13967 check_cp1_enabled(ctx);
13968 gen_compute_branch1(ctx, mips32_op,
13969 (ctx->opcode >> 18) & 0x7, imm << 1);
13970 } else {
13971 generate_exception_err(ctx, EXCP_CpU, 1);
13973 break;
13974 case BPOSGE64:
13975 case BPOSGE32:
13976 /* MIPS DSP: not implemented */
13977 /* Fall through */
13978 default:
13979 MIPS_INVAL("pool32i");
13980 generate_exception(ctx, EXCP_RI);
13981 break;
13983 break;
13984 case POOL32C:
13985 minor = (ctx->opcode >> 12) & 0xf;
13986 switch (minor) {
13987 case LWL:
13988 mips32_op = OPC_LWL;
13989 goto do_ld_lr;
13990 case SWL:
13991 mips32_op = OPC_SWL;
13992 goto do_st_lr;
13993 case LWR:
13994 mips32_op = OPC_LWR;
13995 goto do_ld_lr;
13996 case SWR:
13997 mips32_op = OPC_SWR;
13998 goto do_st_lr;
13999 #if defined(TARGET_MIPS64)
14000 case LDL:
14001 check_insn(ctx, ISA_MIPS3);
14002 check_mips_64(ctx);
14003 mips32_op = OPC_LDL;
14004 goto do_ld_lr;
14005 case SDL:
14006 check_insn(ctx, ISA_MIPS3);
14007 check_mips_64(ctx);
14008 mips32_op = OPC_SDL;
14009 goto do_st_lr;
14010 case LDR:
14011 check_insn(ctx, ISA_MIPS3);
14012 check_mips_64(ctx);
14013 mips32_op = OPC_LDR;
14014 goto do_ld_lr;
14015 case SDR:
14016 check_insn(ctx, ISA_MIPS3);
14017 check_mips_64(ctx);
14018 mips32_op = OPC_SDR;
14019 goto do_st_lr;
14020 case LWU:
14021 check_insn(ctx, ISA_MIPS3);
14022 check_mips_64(ctx);
14023 mips32_op = OPC_LWU;
14024 goto do_ld_lr;
14025 case LLD:
14026 check_insn(ctx, ISA_MIPS3);
14027 check_mips_64(ctx);
14028 mips32_op = OPC_LLD;
14029 goto do_ld_lr;
14030 #endif
14031 case LL:
14032 mips32_op = OPC_LL;
14033 goto do_ld_lr;
14034 do_ld_lr:
14035 gen_ld(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
14036 break;
14037 do_st_lr:
14038 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
14039 break;
14040 case SC:
14041 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
14042 break;
14043 #if defined(TARGET_MIPS64)
14044 case SCD:
14045 check_insn(ctx, ISA_MIPS3);
14046 check_mips_64(ctx);
14047 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
14048 break;
14049 #endif
14050 case PREF:
14051 /* Treat as no-op */
14052 break;
14053 default:
14054 MIPS_INVAL("pool32c");
14055 generate_exception(ctx, EXCP_RI);
14056 break;
14058 break;
14059 case ADDI32:
14060 mips32_op = OPC_ADDI;
14061 goto do_addi;
14062 case ADDIU32:
14063 mips32_op = OPC_ADDIU;
14064 do_addi:
14065 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
14066 break;
14068 /* Logical operations */
14069 case ORI32:
14070 mips32_op = OPC_ORI;
14071 goto do_logici;
14072 case XORI32:
14073 mips32_op = OPC_XORI;
14074 goto do_logici;
14075 case ANDI32:
14076 mips32_op = OPC_ANDI;
14077 do_logici:
14078 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
14079 break;
14081 /* Set less than immediate */
14082 case SLTI32:
14083 mips32_op = OPC_SLTI;
14084 goto do_slti;
14085 case SLTIU32:
14086 mips32_op = OPC_SLTIU;
14087 do_slti:
14088 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
14089 break;
14090 case JALX32:
14091 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14092 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
14093 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14094 break;
14095 case JALS32:
14096 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
14097 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
14098 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14099 break;
14100 case BEQ32:
14101 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
14102 break;
14103 case BNE32:
14104 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
14105 break;
14106 case J32:
14107 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
14108 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14109 break;
14110 case JAL32:
14111 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
14112 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14113 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14114 break;
14115 /* Floating point (COP1) */
14116 case LWC132:
14117 mips32_op = OPC_LWC1;
14118 goto do_cop1;
14119 case LDC132:
14120 mips32_op = OPC_LDC1;
14121 goto do_cop1;
14122 case SWC132:
14123 mips32_op = OPC_SWC1;
14124 goto do_cop1;
14125 case SDC132:
14126 mips32_op = OPC_SDC1;
14127 do_cop1:
14128 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
14129 break;
14130 case ADDIUPC:
14132 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
14133 int offset = SIMM(ctx->opcode, 0, 23) << 2;
14135 gen_addiupc(ctx, reg, offset, 0, 0);
14137 break;
14138 /* Loads and stores */
14139 case LB32:
14140 mips32_op = OPC_LB;
14141 goto do_ld;
14142 case LBU32:
14143 mips32_op = OPC_LBU;
14144 goto do_ld;
14145 case LH32:
14146 mips32_op = OPC_LH;
14147 goto do_ld;
14148 case LHU32:
14149 mips32_op = OPC_LHU;
14150 goto do_ld;
14151 case LW32:
14152 mips32_op = OPC_LW;
14153 goto do_ld;
14154 #ifdef TARGET_MIPS64
14155 case LD32:
14156 check_insn(ctx, ISA_MIPS3);
14157 check_mips_64(ctx);
14158 mips32_op = OPC_LD;
14159 goto do_ld;
14160 case SD32:
14161 check_insn(ctx, ISA_MIPS3);
14162 check_mips_64(ctx);
14163 mips32_op = OPC_SD;
14164 goto do_st;
14165 #endif
14166 case SB32:
14167 mips32_op = OPC_SB;
14168 goto do_st;
14169 case SH32:
14170 mips32_op = OPC_SH;
14171 goto do_st;
14172 case SW32:
14173 mips32_op = OPC_SW;
14174 goto do_st;
14175 do_ld:
14176 gen_ld(ctx, mips32_op, rt, rs, imm);
14177 break;
14178 do_st:
14179 gen_st(ctx, mips32_op, rt, rs, imm);
14180 break;
14181 default:
14182 generate_exception(ctx, EXCP_RI);
14183 break;
14187 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
14189 uint32_t op;
14191 /* make sure instructions are on a halfword boundary */
14192 if (ctx->pc & 0x1) {
14193 env->CP0_BadVAddr = ctx->pc;
14194 generate_exception(ctx, EXCP_AdEL);
14195 ctx->bstate = BS_STOP;
14196 return 2;
14199 op = (ctx->opcode >> 10) & 0x3f;
14200 /* Enforce properly-sized instructions in a delay slot */
14201 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
14202 switch (op & 0x7) { /* MSB-3..MSB-5 */
14203 case 0:
14204 /* POOL32A, POOL32B, POOL32I, POOL32C */
14205 case 4:
14206 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
14207 case 5:
14208 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
14209 case 6:
14210 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
14211 case 7:
14212 /* LB32, LH32, LWC132, LDC132, LW32 */
14213 if (ctx->hflags & MIPS_HFLAG_BDS16) {
14214 generate_exception(ctx, EXCP_RI);
14215 /* Just stop translation; the user is confused. */
14216 ctx->bstate = BS_STOP;
14217 return 2;
14219 break;
14220 case 1:
14221 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
14222 case 2:
14223 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
14224 case 3:
14225 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
14226 if (ctx->hflags & MIPS_HFLAG_BDS32) {
14227 generate_exception(ctx, EXCP_RI);
14228 /* Just stop translation; the user is confused. */
14229 ctx->bstate = BS_STOP;
14230 return 2;
14232 break;
14236 switch (op) {
14237 case POOL16A:
14239 int rd = mmreg(uMIPS_RD(ctx->opcode));
14240 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
14241 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
14242 uint32_t opc = 0;
14244 switch (ctx->opcode & 0x1) {
14245 case ADDU16:
14246 opc = OPC_ADDU;
14247 break;
14248 case SUBU16:
14249 opc = OPC_SUBU;
14250 break;
14253 gen_arith(ctx, opc, rd, rs1, rs2);
14255 break;
14256 case POOL16B:
14258 int rd = mmreg(uMIPS_RD(ctx->opcode));
14259 int rs = mmreg(uMIPS_RS(ctx->opcode));
14260 int amount = (ctx->opcode >> 1) & 0x7;
14261 uint32_t opc = 0;
14262 amount = amount == 0 ? 8 : amount;
14264 switch (ctx->opcode & 0x1) {
14265 case SLL16:
14266 opc = OPC_SLL;
14267 break;
14268 case SRL16:
14269 opc = OPC_SRL;
14270 break;
14273 gen_shift_imm(ctx, opc, rd, rs, amount);
14275 break;
14276 case POOL16C:
14277 gen_pool16c_insn(ctx);
14278 break;
14279 case LWGP16:
14281 int rd = mmreg(uMIPS_RD(ctx->opcode));
14282 int rb = 28; /* GP */
14283 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
14285 gen_ld(ctx, OPC_LW, rd, rb, offset);
14287 break;
14288 case POOL16F:
14289 if (ctx->opcode & 1) {
14290 generate_exception(ctx, EXCP_RI);
14291 } else {
14292 /* MOVEP */
14293 int enc_dest = uMIPS_RD(ctx->opcode);
14294 int enc_rt = uMIPS_RS2(ctx->opcode);
14295 int enc_rs = uMIPS_RS1(ctx->opcode);
14296 int rd, rs, re, rt;
14297 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14298 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14299 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14301 rd = rd_enc[enc_dest];
14302 re = re_enc[enc_dest];
14303 rs = rs_rt_enc[enc_rs];
14304 rt = rs_rt_enc[enc_rt];
14306 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
14307 gen_arith(ctx, OPC_ADDU, re, rt, 0);
14309 break;
14310 case LBU16:
14312 int rd = mmreg(uMIPS_RD(ctx->opcode));
14313 int rb = mmreg(uMIPS_RS(ctx->opcode));
14314 int16_t offset = ZIMM(ctx->opcode, 0, 4);
14315 offset = (offset == 0xf ? -1 : offset);
14317 gen_ld(ctx, OPC_LBU, rd, rb, offset);
14319 break;
14320 case LHU16:
14322 int rd = mmreg(uMIPS_RD(ctx->opcode));
14323 int rb = mmreg(uMIPS_RS(ctx->opcode));
14324 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
14326 gen_ld(ctx, OPC_LHU, rd, rb, offset);
14328 break;
14329 case LWSP16:
14331 int rd = (ctx->opcode >> 5) & 0x1f;
14332 int rb = 29; /* SP */
14333 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
14335 gen_ld(ctx, OPC_LW, rd, rb, offset);
14337 break;
14338 case LW16:
14340 int rd = mmreg(uMIPS_RD(ctx->opcode));
14341 int rb = mmreg(uMIPS_RS(ctx->opcode));
14342 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
14344 gen_ld(ctx, OPC_LW, rd, rb, offset);
14346 break;
14347 case SB16:
14349 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14350 int rb = mmreg(uMIPS_RS(ctx->opcode));
14351 int16_t offset = ZIMM(ctx->opcode, 0, 4);
14353 gen_st(ctx, OPC_SB, rd, rb, offset);
14355 break;
14356 case SH16:
14358 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14359 int rb = mmreg(uMIPS_RS(ctx->opcode));
14360 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
14362 gen_st(ctx, OPC_SH, rd, rb, offset);
14364 break;
14365 case SWSP16:
14367 int rd = (ctx->opcode >> 5) & 0x1f;
14368 int rb = 29; /* SP */
14369 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
14371 gen_st(ctx, OPC_SW, rd, rb, offset);
14373 break;
14374 case SW16:
14376 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14377 int rb = mmreg(uMIPS_RS(ctx->opcode));
14378 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
14380 gen_st(ctx, OPC_SW, rd, rb, offset);
14382 break;
14383 case MOVE16:
14385 int rd = uMIPS_RD5(ctx->opcode);
14386 int rs = uMIPS_RS5(ctx->opcode);
14388 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
14390 break;
14391 case ANDI16:
14392 gen_andi16(ctx);
14393 break;
14394 case POOL16D:
14395 switch (ctx->opcode & 0x1) {
14396 case ADDIUS5:
14397 gen_addius5(ctx);
14398 break;
14399 case ADDIUSP:
14400 gen_addiusp(ctx);
14401 break;
14403 break;
14404 case POOL16E:
14405 switch (ctx->opcode & 0x1) {
14406 case ADDIUR2:
14407 gen_addiur2(ctx);
14408 break;
14409 case ADDIUR1SP:
14410 gen_addiur1sp(ctx);
14411 break;
14413 break;
14414 case B16:
14415 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
14416 SIMM(ctx->opcode, 0, 10) << 1, 4);
14417 break;
14418 case BNEZ16:
14419 case BEQZ16:
14420 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
14421 mmreg(uMIPS_RD(ctx->opcode)),
14422 0, SIMM(ctx->opcode, 0, 7) << 1, 4);
14423 break;
14424 case LI16:
14426 int reg = mmreg(uMIPS_RD(ctx->opcode));
14427 int imm = ZIMM(ctx->opcode, 0, 7);
14429 imm = (imm == 0x7f ? -1 : imm);
14430 tcg_gen_movi_tl(cpu_gpr[reg], imm);
14432 break;
14433 case RES_20:
14434 case RES_28:
14435 case RES_29:
14436 case RES_30:
14437 case RES_31:
14438 case RES_38:
14439 case RES_39:
14440 generate_exception(ctx, EXCP_RI);
14441 break;
14442 default:
14443 decode_micromips32_opc (env, ctx, op);
14444 return 4;
14447 return 2;
14450 /* SmartMIPS extension to MIPS32 */
14452 #if defined(TARGET_MIPS64)
14454 /* MDMX extension to MIPS64 */
14456 #endif
14458 /* MIPSDSP functions. */
14459 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
14460 int rd, int base, int offset)
14462 const char *opn = "ldx";
14463 TCGv t0;
14465 check_dsp(ctx);
14466 t0 = tcg_temp_new();
14468 if (base == 0) {
14469 gen_load_gpr(t0, offset);
14470 } else if (offset == 0) {
14471 gen_load_gpr(t0, base);
14472 } else {
14473 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
14476 switch (opc) {
14477 case OPC_LBUX:
14478 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
14479 gen_store_gpr(t0, rd);
14480 opn = "lbux";
14481 break;
14482 case OPC_LHX:
14483 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
14484 gen_store_gpr(t0, rd);
14485 opn = "lhx";
14486 break;
14487 case OPC_LWX:
14488 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
14489 gen_store_gpr(t0, rd);
14490 opn = "lwx";
14491 break;
14492 #if defined(TARGET_MIPS64)
14493 case OPC_LDX:
14494 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
14495 gen_store_gpr(t0, rd);
14496 opn = "ldx";
14497 break;
14498 #endif
14500 (void)opn; /* avoid a compiler warning */
14501 MIPS_DEBUG("%s %s, %s(%s)", opn,
14502 regnames[rd], regnames[offset], regnames[base]);
14503 tcg_temp_free(t0);
14506 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
14507 int ret, int v1, int v2)
14509 const char *opn = "mipsdsp arith";
14510 TCGv v1_t;
14511 TCGv v2_t;
14513 if (ret == 0) {
14514 /* Treat as NOP. */
14515 MIPS_DEBUG("NOP");
14516 return;
14519 v1_t = tcg_temp_new();
14520 v2_t = tcg_temp_new();
14522 gen_load_gpr(v1_t, v1);
14523 gen_load_gpr(v2_t, v2);
14525 switch (op1) {
14526 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
14527 case OPC_MULT_G_2E:
14528 check_dspr2(ctx);
14529 switch (op2) {
14530 case OPC_ADDUH_QB:
14531 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
14532 break;
14533 case OPC_ADDUH_R_QB:
14534 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
14535 break;
14536 case OPC_ADDQH_PH:
14537 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
14538 break;
14539 case OPC_ADDQH_R_PH:
14540 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
14541 break;
14542 case OPC_ADDQH_W:
14543 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
14544 break;
14545 case OPC_ADDQH_R_W:
14546 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
14547 break;
14548 case OPC_SUBUH_QB:
14549 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
14550 break;
14551 case OPC_SUBUH_R_QB:
14552 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
14553 break;
14554 case OPC_SUBQH_PH:
14555 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
14556 break;
14557 case OPC_SUBQH_R_PH:
14558 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
14559 break;
14560 case OPC_SUBQH_W:
14561 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
14562 break;
14563 case OPC_SUBQH_R_W:
14564 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
14565 break;
14567 break;
14568 case OPC_ABSQ_S_PH_DSP:
14569 switch (op2) {
14570 case OPC_ABSQ_S_QB:
14571 check_dspr2(ctx);
14572 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
14573 break;
14574 case OPC_ABSQ_S_PH:
14575 check_dsp(ctx);
14576 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
14577 break;
14578 case OPC_ABSQ_S_W:
14579 check_dsp(ctx);
14580 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
14581 break;
14582 case OPC_PRECEQ_W_PHL:
14583 check_dsp(ctx);
14584 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
14585 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
14586 break;
14587 case OPC_PRECEQ_W_PHR:
14588 check_dsp(ctx);
14589 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
14590 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
14591 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
14592 break;
14593 case OPC_PRECEQU_PH_QBL:
14594 check_dsp(ctx);
14595 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
14596 break;
14597 case OPC_PRECEQU_PH_QBR:
14598 check_dsp(ctx);
14599 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
14600 break;
14601 case OPC_PRECEQU_PH_QBLA:
14602 check_dsp(ctx);
14603 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
14604 break;
14605 case OPC_PRECEQU_PH_QBRA:
14606 check_dsp(ctx);
14607 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
14608 break;
14609 case OPC_PRECEU_PH_QBL:
14610 check_dsp(ctx);
14611 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
14612 break;
14613 case OPC_PRECEU_PH_QBR:
14614 check_dsp(ctx);
14615 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
14616 break;
14617 case OPC_PRECEU_PH_QBLA:
14618 check_dsp(ctx);
14619 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
14620 break;
14621 case OPC_PRECEU_PH_QBRA:
14622 check_dsp(ctx);
14623 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
14624 break;
14626 break;
14627 case OPC_ADDU_QB_DSP:
14628 switch (op2) {
14629 case OPC_ADDQ_PH:
14630 check_dsp(ctx);
14631 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14632 break;
14633 case OPC_ADDQ_S_PH:
14634 check_dsp(ctx);
14635 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14636 break;
14637 case OPC_ADDQ_S_W:
14638 check_dsp(ctx);
14639 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14640 break;
14641 case OPC_ADDU_QB:
14642 check_dsp(ctx);
14643 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14644 break;
14645 case OPC_ADDU_S_QB:
14646 check_dsp(ctx);
14647 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14648 break;
14649 case OPC_ADDU_PH:
14650 check_dspr2(ctx);
14651 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14652 break;
14653 case OPC_ADDU_S_PH:
14654 check_dspr2(ctx);
14655 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14656 break;
14657 case OPC_SUBQ_PH:
14658 check_dsp(ctx);
14659 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14660 break;
14661 case OPC_SUBQ_S_PH:
14662 check_dsp(ctx);
14663 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14664 break;
14665 case OPC_SUBQ_S_W:
14666 check_dsp(ctx);
14667 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14668 break;
14669 case OPC_SUBU_QB:
14670 check_dsp(ctx);
14671 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14672 break;
14673 case OPC_SUBU_S_QB:
14674 check_dsp(ctx);
14675 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14676 break;
14677 case OPC_SUBU_PH:
14678 check_dspr2(ctx);
14679 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14680 break;
14681 case OPC_SUBU_S_PH:
14682 check_dspr2(ctx);
14683 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14684 break;
14685 case OPC_ADDSC:
14686 check_dsp(ctx);
14687 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14688 break;
14689 case OPC_ADDWC:
14690 check_dsp(ctx);
14691 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14692 break;
14693 case OPC_MODSUB:
14694 check_dsp(ctx);
14695 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
14696 break;
14697 case OPC_RADDU_W_QB:
14698 check_dsp(ctx);
14699 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
14700 break;
14702 break;
14703 case OPC_CMPU_EQ_QB_DSP:
14704 switch (op2) {
14705 case OPC_PRECR_QB_PH:
14706 check_dspr2(ctx);
14707 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
14708 break;
14709 case OPC_PRECRQ_QB_PH:
14710 check_dsp(ctx);
14711 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
14712 break;
14713 case OPC_PRECR_SRA_PH_W:
14714 check_dspr2(ctx);
14716 TCGv_i32 sa_t = tcg_const_i32(v2);
14717 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
14718 cpu_gpr[ret]);
14719 tcg_temp_free_i32(sa_t);
14720 break;
14722 case OPC_PRECR_SRA_R_PH_W:
14723 check_dspr2(ctx);
14725 TCGv_i32 sa_t = tcg_const_i32(v2);
14726 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
14727 cpu_gpr[ret]);
14728 tcg_temp_free_i32(sa_t);
14729 break;
14731 case OPC_PRECRQ_PH_W:
14732 check_dsp(ctx);
14733 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
14734 break;
14735 case OPC_PRECRQ_RS_PH_W:
14736 check_dsp(ctx);
14737 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14738 break;
14739 case OPC_PRECRQU_S_QB_PH:
14740 check_dsp(ctx);
14741 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14742 break;
14744 break;
14745 #ifdef TARGET_MIPS64
14746 case OPC_ABSQ_S_QH_DSP:
14747 switch (op2) {
14748 case OPC_PRECEQ_L_PWL:
14749 check_dsp(ctx);
14750 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
14751 break;
14752 case OPC_PRECEQ_L_PWR:
14753 check_dsp(ctx);
14754 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
14755 break;
14756 case OPC_PRECEQ_PW_QHL:
14757 check_dsp(ctx);
14758 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
14759 break;
14760 case OPC_PRECEQ_PW_QHR:
14761 check_dsp(ctx);
14762 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
14763 break;
14764 case OPC_PRECEQ_PW_QHLA:
14765 check_dsp(ctx);
14766 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
14767 break;
14768 case OPC_PRECEQ_PW_QHRA:
14769 check_dsp(ctx);
14770 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
14771 break;
14772 case OPC_PRECEQU_QH_OBL:
14773 check_dsp(ctx);
14774 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
14775 break;
14776 case OPC_PRECEQU_QH_OBR:
14777 check_dsp(ctx);
14778 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
14779 break;
14780 case OPC_PRECEQU_QH_OBLA:
14781 check_dsp(ctx);
14782 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
14783 break;
14784 case OPC_PRECEQU_QH_OBRA:
14785 check_dsp(ctx);
14786 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
14787 break;
14788 case OPC_PRECEU_QH_OBL:
14789 check_dsp(ctx);
14790 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
14791 break;
14792 case OPC_PRECEU_QH_OBR:
14793 check_dsp(ctx);
14794 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
14795 break;
14796 case OPC_PRECEU_QH_OBLA:
14797 check_dsp(ctx);
14798 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
14799 break;
14800 case OPC_PRECEU_QH_OBRA:
14801 check_dsp(ctx);
14802 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
14803 break;
14804 case OPC_ABSQ_S_OB:
14805 check_dspr2(ctx);
14806 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
14807 break;
14808 case OPC_ABSQ_S_PW:
14809 check_dsp(ctx);
14810 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
14811 break;
14812 case OPC_ABSQ_S_QH:
14813 check_dsp(ctx);
14814 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
14815 break;
14817 break;
14818 case OPC_ADDU_OB_DSP:
14819 switch (op2) {
14820 case OPC_RADDU_L_OB:
14821 check_dsp(ctx);
14822 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
14823 break;
14824 case OPC_SUBQ_PW:
14825 check_dsp(ctx);
14826 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14827 break;
14828 case OPC_SUBQ_S_PW:
14829 check_dsp(ctx);
14830 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14831 break;
14832 case OPC_SUBQ_QH:
14833 check_dsp(ctx);
14834 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14835 break;
14836 case OPC_SUBQ_S_QH:
14837 check_dsp(ctx);
14838 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14839 break;
14840 case OPC_SUBU_OB:
14841 check_dsp(ctx);
14842 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14843 break;
14844 case OPC_SUBU_S_OB:
14845 check_dsp(ctx);
14846 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14847 break;
14848 case OPC_SUBU_QH:
14849 check_dspr2(ctx);
14850 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14851 break;
14852 case OPC_SUBU_S_QH:
14853 check_dspr2(ctx);
14854 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14855 break;
14856 case OPC_SUBUH_OB:
14857 check_dspr2(ctx);
14858 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
14859 break;
14860 case OPC_SUBUH_R_OB:
14861 check_dspr2(ctx);
14862 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
14863 break;
14864 case OPC_ADDQ_PW:
14865 check_dsp(ctx);
14866 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14867 break;
14868 case OPC_ADDQ_S_PW:
14869 check_dsp(ctx);
14870 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14871 break;
14872 case OPC_ADDQ_QH:
14873 check_dsp(ctx);
14874 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14875 break;
14876 case OPC_ADDQ_S_QH:
14877 check_dsp(ctx);
14878 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14879 break;
14880 case OPC_ADDU_OB:
14881 check_dsp(ctx);
14882 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14883 break;
14884 case OPC_ADDU_S_OB:
14885 check_dsp(ctx);
14886 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14887 break;
14888 case OPC_ADDU_QH:
14889 check_dspr2(ctx);
14890 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14891 break;
14892 case OPC_ADDU_S_QH:
14893 check_dspr2(ctx);
14894 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14895 break;
14896 case OPC_ADDUH_OB:
14897 check_dspr2(ctx);
14898 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
14899 break;
14900 case OPC_ADDUH_R_OB:
14901 check_dspr2(ctx);
14902 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
14903 break;
14905 break;
14906 case OPC_CMPU_EQ_OB_DSP:
14907 switch (op2) {
14908 case OPC_PRECR_OB_QH:
14909 check_dspr2(ctx);
14910 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
14911 break;
14912 case OPC_PRECR_SRA_QH_PW:
14913 check_dspr2(ctx);
14915 TCGv_i32 ret_t = tcg_const_i32(ret);
14916 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
14917 tcg_temp_free_i32(ret_t);
14918 break;
14920 case OPC_PRECR_SRA_R_QH_PW:
14921 check_dspr2(ctx);
14923 TCGv_i32 sa_v = tcg_const_i32(ret);
14924 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
14925 tcg_temp_free_i32(sa_v);
14926 break;
14928 case OPC_PRECRQ_OB_QH:
14929 check_dsp(ctx);
14930 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
14931 break;
14932 case OPC_PRECRQ_PW_L:
14933 check_dsp(ctx);
14934 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
14935 break;
14936 case OPC_PRECRQ_QH_PW:
14937 check_dsp(ctx);
14938 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
14939 break;
14940 case OPC_PRECRQ_RS_QH_PW:
14941 check_dsp(ctx);
14942 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14943 break;
14944 case OPC_PRECRQU_S_OB_QH:
14945 check_dsp(ctx);
14946 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14947 break;
14949 break;
14950 #endif
14953 tcg_temp_free(v1_t);
14954 tcg_temp_free(v2_t);
14956 (void)opn; /* avoid a compiler warning */
14957 MIPS_DEBUG("%s", opn);
14960 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
14961 int ret, int v1, int v2)
14963 uint32_t op2;
14964 const char *opn = "mipsdsp shift";
14965 TCGv t0;
14966 TCGv v1_t;
14967 TCGv v2_t;
14969 if (ret == 0) {
14970 /* Treat as NOP. */
14971 MIPS_DEBUG("NOP");
14972 return;
14975 t0 = tcg_temp_new();
14976 v1_t = tcg_temp_new();
14977 v2_t = tcg_temp_new();
14979 tcg_gen_movi_tl(t0, v1);
14980 gen_load_gpr(v1_t, v1);
14981 gen_load_gpr(v2_t, v2);
14983 switch (opc) {
14984 case OPC_SHLL_QB_DSP:
14986 op2 = MASK_SHLL_QB(ctx->opcode);
14987 switch (op2) {
14988 case OPC_SHLL_QB:
14989 check_dsp(ctx);
14990 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
14991 break;
14992 case OPC_SHLLV_QB:
14993 check_dsp(ctx);
14994 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14995 break;
14996 case OPC_SHLL_PH:
14997 check_dsp(ctx);
14998 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
14999 break;
15000 case OPC_SHLLV_PH:
15001 check_dsp(ctx);
15002 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15003 break;
15004 case OPC_SHLL_S_PH:
15005 check_dsp(ctx);
15006 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15007 break;
15008 case OPC_SHLLV_S_PH:
15009 check_dsp(ctx);
15010 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15011 break;
15012 case OPC_SHLL_S_W:
15013 check_dsp(ctx);
15014 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
15015 break;
15016 case OPC_SHLLV_S_W:
15017 check_dsp(ctx);
15018 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15019 break;
15020 case OPC_SHRL_QB:
15021 check_dsp(ctx);
15022 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
15023 break;
15024 case OPC_SHRLV_QB:
15025 check_dsp(ctx);
15026 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
15027 break;
15028 case OPC_SHRL_PH:
15029 check_dspr2(ctx);
15030 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
15031 break;
15032 case OPC_SHRLV_PH:
15033 check_dspr2(ctx);
15034 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
15035 break;
15036 case OPC_SHRA_QB:
15037 check_dspr2(ctx);
15038 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
15039 break;
15040 case OPC_SHRA_R_QB:
15041 check_dspr2(ctx);
15042 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
15043 break;
15044 case OPC_SHRAV_QB:
15045 check_dspr2(ctx);
15046 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
15047 break;
15048 case OPC_SHRAV_R_QB:
15049 check_dspr2(ctx);
15050 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
15051 break;
15052 case OPC_SHRA_PH:
15053 check_dsp(ctx);
15054 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
15055 break;
15056 case OPC_SHRA_R_PH:
15057 check_dsp(ctx);
15058 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
15059 break;
15060 case OPC_SHRAV_PH:
15061 check_dsp(ctx);
15062 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
15063 break;
15064 case OPC_SHRAV_R_PH:
15065 check_dsp(ctx);
15066 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
15067 break;
15068 case OPC_SHRA_R_W:
15069 check_dsp(ctx);
15070 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
15071 break;
15072 case OPC_SHRAV_R_W:
15073 check_dsp(ctx);
15074 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
15075 break;
15076 default: /* Invalid */
15077 MIPS_INVAL("MASK SHLL.QB");
15078 generate_exception(ctx, EXCP_RI);
15079 break;
15081 break;
15083 #ifdef TARGET_MIPS64
15084 case OPC_SHLL_OB_DSP:
15085 op2 = MASK_SHLL_OB(ctx->opcode);
15086 switch (op2) {
15087 case OPC_SHLL_PW:
15088 check_dsp(ctx);
15089 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15090 break;
15091 case OPC_SHLLV_PW:
15092 check_dsp(ctx);
15093 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15094 break;
15095 case OPC_SHLL_S_PW:
15096 check_dsp(ctx);
15097 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15098 break;
15099 case OPC_SHLLV_S_PW:
15100 check_dsp(ctx);
15101 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15102 break;
15103 case OPC_SHLL_OB:
15104 check_dsp(ctx);
15105 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
15106 break;
15107 case OPC_SHLLV_OB:
15108 check_dsp(ctx);
15109 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15110 break;
15111 case OPC_SHLL_QH:
15112 check_dsp(ctx);
15113 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15114 break;
15115 case OPC_SHLLV_QH:
15116 check_dsp(ctx);
15117 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15118 break;
15119 case OPC_SHLL_S_QH:
15120 check_dsp(ctx);
15121 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15122 break;
15123 case OPC_SHLLV_S_QH:
15124 check_dsp(ctx);
15125 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15126 break;
15127 case OPC_SHRA_OB:
15128 check_dspr2(ctx);
15129 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
15130 break;
15131 case OPC_SHRAV_OB:
15132 check_dspr2(ctx);
15133 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
15134 break;
15135 case OPC_SHRA_R_OB:
15136 check_dspr2(ctx);
15137 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
15138 break;
15139 case OPC_SHRAV_R_OB:
15140 check_dspr2(ctx);
15141 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
15142 break;
15143 case OPC_SHRA_PW:
15144 check_dsp(ctx);
15145 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
15146 break;
15147 case OPC_SHRAV_PW:
15148 check_dsp(ctx);
15149 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
15150 break;
15151 case OPC_SHRA_R_PW:
15152 check_dsp(ctx);
15153 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
15154 break;
15155 case OPC_SHRAV_R_PW:
15156 check_dsp(ctx);
15157 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
15158 break;
15159 case OPC_SHRA_QH:
15160 check_dsp(ctx);
15161 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
15162 break;
15163 case OPC_SHRAV_QH:
15164 check_dsp(ctx);
15165 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
15166 break;
15167 case OPC_SHRA_R_QH:
15168 check_dsp(ctx);
15169 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
15170 break;
15171 case OPC_SHRAV_R_QH:
15172 check_dsp(ctx);
15173 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
15174 break;
15175 case OPC_SHRL_OB:
15176 check_dsp(ctx);
15177 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
15178 break;
15179 case OPC_SHRLV_OB:
15180 check_dsp(ctx);
15181 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
15182 break;
15183 case OPC_SHRL_QH:
15184 check_dspr2(ctx);
15185 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
15186 break;
15187 case OPC_SHRLV_QH:
15188 check_dspr2(ctx);
15189 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
15190 break;
15191 default: /* Invalid */
15192 MIPS_INVAL("MASK SHLL.OB");
15193 generate_exception(ctx, EXCP_RI);
15194 break;
15196 break;
15197 #endif
15200 tcg_temp_free(t0);
15201 tcg_temp_free(v1_t);
15202 tcg_temp_free(v2_t);
15203 (void)opn; /* avoid a compiler warning */
15204 MIPS_DEBUG("%s", opn);
15207 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
15208 int ret, int v1, int v2, int check_ret)
15210 const char *opn = "mipsdsp multiply";
15211 TCGv_i32 t0;
15212 TCGv v1_t;
15213 TCGv v2_t;
15215 if ((ret == 0) && (check_ret == 1)) {
15216 /* Treat as NOP. */
15217 MIPS_DEBUG("NOP");
15218 return;
15221 t0 = tcg_temp_new_i32();
15222 v1_t = tcg_temp_new();
15223 v2_t = tcg_temp_new();
15225 tcg_gen_movi_i32(t0, ret);
15226 gen_load_gpr(v1_t, v1);
15227 gen_load_gpr(v2_t, v2);
15229 switch (op1) {
15230 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
15231 * the same mask and op1. */
15232 case OPC_MULT_G_2E:
15233 check_dspr2(ctx);
15234 switch (op2) {
15235 case OPC_MUL_PH:
15236 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15237 break;
15238 case OPC_MUL_S_PH:
15239 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15240 break;
15241 case OPC_MULQ_S_W:
15242 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15243 break;
15244 case OPC_MULQ_RS_W:
15245 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15246 break;
15248 break;
15249 case OPC_DPA_W_PH_DSP:
15250 switch (op2) {
15251 case OPC_DPAU_H_QBL:
15252 check_dsp(ctx);
15253 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
15254 break;
15255 case OPC_DPAU_H_QBR:
15256 check_dsp(ctx);
15257 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
15258 break;
15259 case OPC_DPSU_H_QBL:
15260 check_dsp(ctx);
15261 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
15262 break;
15263 case OPC_DPSU_H_QBR:
15264 check_dsp(ctx);
15265 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
15266 break;
15267 case OPC_DPA_W_PH:
15268 check_dspr2(ctx);
15269 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
15270 break;
15271 case OPC_DPAX_W_PH:
15272 check_dspr2(ctx);
15273 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
15274 break;
15275 case OPC_DPAQ_S_W_PH:
15276 check_dsp(ctx);
15277 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15278 break;
15279 case OPC_DPAQX_S_W_PH:
15280 check_dspr2(ctx);
15281 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
15282 break;
15283 case OPC_DPAQX_SA_W_PH:
15284 check_dspr2(ctx);
15285 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
15286 break;
15287 case OPC_DPS_W_PH:
15288 check_dspr2(ctx);
15289 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
15290 break;
15291 case OPC_DPSX_W_PH:
15292 check_dspr2(ctx);
15293 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
15294 break;
15295 case OPC_DPSQ_S_W_PH:
15296 check_dsp(ctx);
15297 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15298 break;
15299 case OPC_DPSQX_S_W_PH:
15300 check_dspr2(ctx);
15301 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
15302 break;
15303 case OPC_DPSQX_SA_W_PH:
15304 check_dspr2(ctx);
15305 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
15306 break;
15307 case OPC_MULSAQ_S_W_PH:
15308 check_dsp(ctx);
15309 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15310 break;
15311 case OPC_DPAQ_SA_L_W:
15312 check_dsp(ctx);
15313 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
15314 break;
15315 case OPC_DPSQ_SA_L_W:
15316 check_dsp(ctx);
15317 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
15318 break;
15319 case OPC_MAQ_S_W_PHL:
15320 check_dsp(ctx);
15321 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
15322 break;
15323 case OPC_MAQ_S_W_PHR:
15324 check_dsp(ctx);
15325 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
15326 break;
15327 case OPC_MAQ_SA_W_PHL:
15328 check_dsp(ctx);
15329 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
15330 break;
15331 case OPC_MAQ_SA_W_PHR:
15332 check_dsp(ctx);
15333 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
15334 break;
15335 case OPC_MULSA_W_PH:
15336 check_dspr2(ctx);
15337 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
15338 break;
15340 break;
15341 #ifdef TARGET_MIPS64
15342 case OPC_DPAQ_W_QH_DSP:
15344 int ac = ret & 0x03;
15345 tcg_gen_movi_i32(t0, ac);
15347 switch (op2) {
15348 case OPC_DMADD:
15349 check_dsp(ctx);
15350 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
15351 break;
15352 case OPC_DMADDU:
15353 check_dsp(ctx);
15354 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
15355 break;
15356 case OPC_DMSUB:
15357 check_dsp(ctx);
15358 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
15359 break;
15360 case OPC_DMSUBU:
15361 check_dsp(ctx);
15362 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
15363 break;
15364 case OPC_DPA_W_QH:
15365 check_dspr2(ctx);
15366 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
15367 break;
15368 case OPC_DPAQ_S_W_QH:
15369 check_dsp(ctx);
15370 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15371 break;
15372 case OPC_DPAQ_SA_L_PW:
15373 check_dsp(ctx);
15374 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
15375 break;
15376 case OPC_DPAU_H_OBL:
15377 check_dsp(ctx);
15378 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
15379 break;
15380 case OPC_DPAU_H_OBR:
15381 check_dsp(ctx);
15382 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
15383 break;
15384 case OPC_DPS_W_QH:
15385 check_dspr2(ctx);
15386 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
15387 break;
15388 case OPC_DPSQ_S_W_QH:
15389 check_dsp(ctx);
15390 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15391 break;
15392 case OPC_DPSQ_SA_L_PW:
15393 check_dsp(ctx);
15394 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
15395 break;
15396 case OPC_DPSU_H_OBL:
15397 check_dsp(ctx);
15398 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
15399 break;
15400 case OPC_DPSU_H_OBR:
15401 check_dsp(ctx);
15402 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
15403 break;
15404 case OPC_MAQ_S_L_PWL:
15405 check_dsp(ctx);
15406 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
15407 break;
15408 case OPC_MAQ_S_L_PWR:
15409 check_dsp(ctx);
15410 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
15411 break;
15412 case OPC_MAQ_S_W_QHLL:
15413 check_dsp(ctx);
15414 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
15415 break;
15416 case OPC_MAQ_SA_W_QHLL:
15417 check_dsp(ctx);
15418 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
15419 break;
15420 case OPC_MAQ_S_W_QHLR:
15421 check_dsp(ctx);
15422 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
15423 break;
15424 case OPC_MAQ_SA_W_QHLR:
15425 check_dsp(ctx);
15426 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
15427 break;
15428 case OPC_MAQ_S_W_QHRL:
15429 check_dsp(ctx);
15430 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
15431 break;
15432 case OPC_MAQ_SA_W_QHRL:
15433 check_dsp(ctx);
15434 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
15435 break;
15436 case OPC_MAQ_S_W_QHRR:
15437 check_dsp(ctx);
15438 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
15439 break;
15440 case OPC_MAQ_SA_W_QHRR:
15441 check_dsp(ctx);
15442 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
15443 break;
15444 case OPC_MULSAQ_S_L_PW:
15445 check_dsp(ctx);
15446 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
15447 break;
15448 case OPC_MULSAQ_S_W_QH:
15449 check_dsp(ctx);
15450 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15451 break;
15454 break;
15455 #endif
15456 case OPC_ADDU_QB_DSP:
15457 switch (op2) {
15458 case OPC_MULEU_S_PH_QBL:
15459 check_dsp(ctx);
15460 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15461 break;
15462 case OPC_MULEU_S_PH_QBR:
15463 check_dsp(ctx);
15464 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15465 break;
15466 case OPC_MULQ_RS_PH:
15467 check_dsp(ctx);
15468 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15469 break;
15470 case OPC_MULEQ_S_W_PHL:
15471 check_dsp(ctx);
15472 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15473 break;
15474 case OPC_MULEQ_S_W_PHR:
15475 check_dsp(ctx);
15476 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15477 break;
15478 case OPC_MULQ_S_PH:
15479 check_dspr2(ctx);
15480 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15481 break;
15483 break;
15484 #ifdef TARGET_MIPS64
15485 case OPC_ADDU_OB_DSP:
15486 switch (op2) {
15487 case OPC_MULEQ_S_PW_QHL:
15488 check_dsp(ctx);
15489 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15490 break;
15491 case OPC_MULEQ_S_PW_QHR:
15492 check_dsp(ctx);
15493 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15494 break;
15495 case OPC_MULEU_S_QH_OBL:
15496 check_dsp(ctx);
15497 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15498 break;
15499 case OPC_MULEU_S_QH_OBR:
15500 check_dsp(ctx);
15501 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15502 break;
15503 case OPC_MULQ_RS_QH:
15504 check_dsp(ctx);
15505 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15506 break;
15508 break;
15509 #endif
15512 tcg_temp_free_i32(t0);
15513 tcg_temp_free(v1_t);
15514 tcg_temp_free(v2_t);
15516 (void)opn; /* avoid a compiler warning */
15517 MIPS_DEBUG("%s", opn);
15521 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
15522 int ret, int val)
15524 const char *opn = "mipsdsp Bit/ Manipulation";
15525 int16_t imm;
15526 TCGv t0;
15527 TCGv val_t;
15529 if (ret == 0) {
15530 /* Treat as NOP. */
15531 MIPS_DEBUG("NOP");
15532 return;
15535 t0 = tcg_temp_new();
15536 val_t = tcg_temp_new();
15537 gen_load_gpr(val_t, val);
15539 switch (op1) {
15540 case OPC_ABSQ_S_PH_DSP:
15541 switch (op2) {
15542 case OPC_BITREV:
15543 check_dsp(ctx);
15544 gen_helper_bitrev(cpu_gpr[ret], val_t);
15545 break;
15546 case OPC_REPL_QB:
15547 check_dsp(ctx);
15549 target_long result;
15550 imm = (ctx->opcode >> 16) & 0xFF;
15551 result = (uint32_t)imm << 24 |
15552 (uint32_t)imm << 16 |
15553 (uint32_t)imm << 8 |
15554 (uint32_t)imm;
15555 result = (int32_t)result;
15556 tcg_gen_movi_tl(cpu_gpr[ret], result);
15558 break;
15559 case OPC_REPLV_QB:
15560 check_dsp(ctx);
15561 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
15562 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
15563 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15564 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
15565 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15566 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15567 break;
15568 case OPC_REPL_PH:
15569 check_dsp(ctx);
15571 imm = (ctx->opcode >> 16) & 0x03FF;
15572 imm = (int16_t)(imm << 6) >> 6;
15573 tcg_gen_movi_tl(cpu_gpr[ret], \
15574 (target_long)((int32_t)imm << 16 | \
15575 (uint16_t)imm));
15577 break;
15578 case OPC_REPLV_PH:
15579 check_dsp(ctx);
15580 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
15581 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
15582 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15583 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15584 break;
15586 break;
15587 #ifdef TARGET_MIPS64
15588 case OPC_ABSQ_S_QH_DSP:
15589 switch (op2) {
15590 case OPC_REPL_OB:
15591 check_dsp(ctx);
15593 target_long temp;
15595 imm = (ctx->opcode >> 16) & 0xFF;
15596 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
15597 temp = (temp << 16) | temp;
15598 temp = (temp << 32) | temp;
15599 tcg_gen_movi_tl(cpu_gpr[ret], temp);
15600 break;
15602 case OPC_REPL_PW:
15603 check_dsp(ctx);
15605 target_long temp;
15607 imm = (ctx->opcode >> 16) & 0x03FF;
15608 imm = (int16_t)(imm << 6) >> 6;
15609 temp = ((target_long)imm << 32) \
15610 | ((target_long)imm & 0xFFFFFFFF);
15611 tcg_gen_movi_tl(cpu_gpr[ret], temp);
15612 break;
15614 case OPC_REPL_QH:
15615 check_dsp(ctx);
15617 target_long temp;
15619 imm = (ctx->opcode >> 16) & 0x03FF;
15620 imm = (int16_t)(imm << 6) >> 6;
15622 temp = ((uint64_t)(uint16_t)imm << 48) |
15623 ((uint64_t)(uint16_t)imm << 32) |
15624 ((uint64_t)(uint16_t)imm << 16) |
15625 (uint64_t)(uint16_t)imm;
15626 tcg_gen_movi_tl(cpu_gpr[ret], temp);
15627 break;
15629 case OPC_REPLV_OB:
15630 check_dsp(ctx);
15631 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
15632 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
15633 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15634 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
15635 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15636 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
15637 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15638 break;
15639 case OPC_REPLV_PW:
15640 check_dsp(ctx);
15641 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
15642 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
15643 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15644 break;
15645 case OPC_REPLV_QH:
15646 check_dsp(ctx);
15647 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
15648 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
15649 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15650 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
15651 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15652 break;
15654 break;
15655 #endif
15657 tcg_temp_free(t0);
15658 tcg_temp_free(val_t);
15660 (void)opn; /* avoid a compiler warning */
15661 MIPS_DEBUG("%s", opn);
15664 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
15665 uint32_t op1, uint32_t op2,
15666 int ret, int v1, int v2, int check_ret)
15668 const char *opn = "mipsdsp add compare pick";
15669 TCGv t1;
15670 TCGv v1_t;
15671 TCGv v2_t;
15673 if ((ret == 0) && (check_ret == 1)) {
15674 /* Treat as NOP. */
15675 MIPS_DEBUG("NOP");
15676 return;
15679 t1 = tcg_temp_new();
15680 v1_t = tcg_temp_new();
15681 v2_t = tcg_temp_new();
15683 gen_load_gpr(v1_t, v1);
15684 gen_load_gpr(v2_t, v2);
15686 switch (op1) {
15687 case OPC_CMPU_EQ_QB_DSP:
15688 switch (op2) {
15689 case OPC_CMPU_EQ_QB:
15690 check_dsp(ctx);
15691 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
15692 break;
15693 case OPC_CMPU_LT_QB:
15694 check_dsp(ctx);
15695 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
15696 break;
15697 case OPC_CMPU_LE_QB:
15698 check_dsp(ctx);
15699 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
15700 break;
15701 case OPC_CMPGU_EQ_QB:
15702 check_dsp(ctx);
15703 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
15704 break;
15705 case OPC_CMPGU_LT_QB:
15706 check_dsp(ctx);
15707 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
15708 break;
15709 case OPC_CMPGU_LE_QB:
15710 check_dsp(ctx);
15711 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
15712 break;
15713 case OPC_CMPGDU_EQ_QB:
15714 check_dspr2(ctx);
15715 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
15716 tcg_gen_mov_tl(cpu_gpr[ret], t1);
15717 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
15718 tcg_gen_shli_tl(t1, t1, 24);
15719 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
15720 break;
15721 case OPC_CMPGDU_LT_QB:
15722 check_dspr2(ctx);
15723 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
15724 tcg_gen_mov_tl(cpu_gpr[ret], t1);
15725 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
15726 tcg_gen_shli_tl(t1, t1, 24);
15727 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
15728 break;
15729 case OPC_CMPGDU_LE_QB:
15730 check_dspr2(ctx);
15731 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
15732 tcg_gen_mov_tl(cpu_gpr[ret], t1);
15733 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
15734 tcg_gen_shli_tl(t1, t1, 24);
15735 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
15736 break;
15737 case OPC_CMP_EQ_PH:
15738 check_dsp(ctx);
15739 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
15740 break;
15741 case OPC_CMP_LT_PH:
15742 check_dsp(ctx);
15743 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
15744 break;
15745 case OPC_CMP_LE_PH:
15746 check_dsp(ctx);
15747 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
15748 break;
15749 case OPC_PICK_QB:
15750 check_dsp(ctx);
15751 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15752 break;
15753 case OPC_PICK_PH:
15754 check_dsp(ctx);
15755 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15756 break;
15757 case OPC_PACKRL_PH:
15758 check_dsp(ctx);
15759 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
15760 break;
15762 break;
15763 #ifdef TARGET_MIPS64
15764 case OPC_CMPU_EQ_OB_DSP:
15765 switch (op2) {
15766 case OPC_CMP_EQ_PW:
15767 check_dsp(ctx);
15768 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
15769 break;
15770 case OPC_CMP_LT_PW:
15771 check_dsp(ctx);
15772 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
15773 break;
15774 case OPC_CMP_LE_PW:
15775 check_dsp(ctx);
15776 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
15777 break;
15778 case OPC_CMP_EQ_QH:
15779 check_dsp(ctx);
15780 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
15781 break;
15782 case OPC_CMP_LT_QH:
15783 check_dsp(ctx);
15784 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
15785 break;
15786 case OPC_CMP_LE_QH:
15787 check_dsp(ctx);
15788 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
15789 break;
15790 case OPC_CMPGDU_EQ_OB:
15791 check_dspr2(ctx);
15792 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15793 break;
15794 case OPC_CMPGDU_LT_OB:
15795 check_dspr2(ctx);
15796 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15797 break;
15798 case OPC_CMPGDU_LE_OB:
15799 check_dspr2(ctx);
15800 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15801 break;
15802 case OPC_CMPGU_EQ_OB:
15803 check_dsp(ctx);
15804 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
15805 break;
15806 case OPC_CMPGU_LT_OB:
15807 check_dsp(ctx);
15808 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
15809 break;
15810 case OPC_CMPGU_LE_OB:
15811 check_dsp(ctx);
15812 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
15813 break;
15814 case OPC_CMPU_EQ_OB:
15815 check_dsp(ctx);
15816 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
15817 break;
15818 case OPC_CMPU_LT_OB:
15819 check_dsp(ctx);
15820 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
15821 break;
15822 case OPC_CMPU_LE_OB:
15823 check_dsp(ctx);
15824 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
15825 break;
15826 case OPC_PACKRL_PW:
15827 check_dsp(ctx);
15828 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
15829 break;
15830 case OPC_PICK_OB:
15831 check_dsp(ctx);
15832 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15833 break;
15834 case OPC_PICK_PW:
15835 check_dsp(ctx);
15836 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15837 break;
15838 case OPC_PICK_QH:
15839 check_dsp(ctx);
15840 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15841 break;
15843 break;
15844 #endif
15847 tcg_temp_free(t1);
15848 tcg_temp_free(v1_t);
15849 tcg_temp_free(v2_t);
15851 (void)opn; /* avoid a compiler warning */
15852 MIPS_DEBUG("%s", opn);
15855 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
15856 uint32_t op1, int rt, int rs, int sa)
15858 const char *opn = "mipsdsp append/dappend";
15859 TCGv t0;
15861 check_dspr2(ctx);
15863 if (rt == 0) {
15864 /* Treat as NOP. */
15865 MIPS_DEBUG("NOP");
15866 return;
15869 t0 = tcg_temp_new();
15870 gen_load_gpr(t0, rs);
15872 switch (op1) {
15873 case OPC_APPEND_DSP:
15874 switch (MASK_APPEND(ctx->opcode)) {
15875 case OPC_APPEND:
15876 if (sa != 0) {
15877 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
15879 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15880 break;
15881 case OPC_PREPEND:
15882 if (sa != 0) {
15883 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
15884 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
15885 tcg_gen_shli_tl(t0, t0, 32 - sa);
15886 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15888 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15889 break;
15890 case OPC_BALIGN:
15891 sa &= 3;
15892 if (sa != 0 && sa != 2) {
15893 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
15894 tcg_gen_ext32u_tl(t0, t0);
15895 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
15896 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15898 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15899 break;
15900 default: /* Invalid */
15901 MIPS_INVAL("MASK APPEND");
15902 generate_exception(ctx, EXCP_RI);
15903 break;
15905 break;
15906 #ifdef TARGET_MIPS64
15907 case OPC_DAPPEND_DSP:
15908 switch (MASK_DAPPEND(ctx->opcode)) {
15909 case OPC_DAPPEND:
15910 if (sa != 0) {
15911 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
15913 break;
15914 case OPC_PREPENDD:
15915 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
15916 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
15917 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
15918 break;
15919 case OPC_PREPENDW:
15920 if (sa != 0) {
15921 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
15922 tcg_gen_shli_tl(t0, t0, 64 - sa);
15923 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15925 break;
15926 case OPC_DBALIGN:
15927 sa &= 7;
15928 if (sa != 0 && sa != 2 && sa != 4) {
15929 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
15930 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
15931 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15933 break;
15934 default: /* Invalid */
15935 MIPS_INVAL("MASK DAPPEND");
15936 generate_exception(ctx, EXCP_RI);
15937 break;
15939 break;
15940 #endif
15942 tcg_temp_free(t0);
15943 (void)opn; /* avoid a compiler warning */
15944 MIPS_DEBUG("%s", opn);
15947 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
15948 int ret, int v1, int v2, int check_ret)
15951 const char *opn = "mipsdsp accumulator";
15952 TCGv t0;
15953 TCGv t1;
15954 TCGv v1_t;
15955 TCGv v2_t;
15956 int16_t imm;
15958 if ((ret == 0) && (check_ret == 1)) {
15959 /* Treat as NOP. */
15960 MIPS_DEBUG("NOP");
15961 return;
15964 t0 = tcg_temp_new();
15965 t1 = tcg_temp_new();
15966 v1_t = tcg_temp_new();
15967 v2_t = tcg_temp_new();
15969 gen_load_gpr(v1_t, v1);
15970 gen_load_gpr(v2_t, v2);
15972 switch (op1) {
15973 case OPC_EXTR_W_DSP:
15974 check_dsp(ctx);
15975 switch (op2) {
15976 case OPC_EXTR_W:
15977 tcg_gen_movi_tl(t0, v2);
15978 tcg_gen_movi_tl(t1, v1);
15979 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
15980 break;
15981 case OPC_EXTR_R_W:
15982 tcg_gen_movi_tl(t0, v2);
15983 tcg_gen_movi_tl(t1, v1);
15984 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
15985 break;
15986 case OPC_EXTR_RS_W:
15987 tcg_gen_movi_tl(t0, v2);
15988 tcg_gen_movi_tl(t1, v1);
15989 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
15990 break;
15991 case OPC_EXTR_S_H:
15992 tcg_gen_movi_tl(t0, v2);
15993 tcg_gen_movi_tl(t1, v1);
15994 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15995 break;
15996 case OPC_EXTRV_S_H:
15997 tcg_gen_movi_tl(t0, v2);
15998 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
15999 break;
16000 case OPC_EXTRV_W:
16001 tcg_gen_movi_tl(t0, v2);
16002 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16003 break;
16004 case OPC_EXTRV_R_W:
16005 tcg_gen_movi_tl(t0, v2);
16006 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16007 break;
16008 case OPC_EXTRV_RS_W:
16009 tcg_gen_movi_tl(t0, v2);
16010 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16011 break;
16012 case OPC_EXTP:
16013 tcg_gen_movi_tl(t0, v2);
16014 tcg_gen_movi_tl(t1, v1);
16015 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
16016 break;
16017 case OPC_EXTPV:
16018 tcg_gen_movi_tl(t0, v2);
16019 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
16020 break;
16021 case OPC_EXTPDP:
16022 tcg_gen_movi_tl(t0, v2);
16023 tcg_gen_movi_tl(t1, v1);
16024 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
16025 break;
16026 case OPC_EXTPDPV:
16027 tcg_gen_movi_tl(t0, v2);
16028 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16029 break;
16030 case OPC_SHILO:
16031 imm = (ctx->opcode >> 20) & 0x3F;
16032 tcg_gen_movi_tl(t0, ret);
16033 tcg_gen_movi_tl(t1, imm);
16034 gen_helper_shilo(t0, t1, cpu_env);
16035 break;
16036 case OPC_SHILOV:
16037 tcg_gen_movi_tl(t0, ret);
16038 gen_helper_shilo(t0, v1_t, cpu_env);
16039 break;
16040 case OPC_MTHLIP:
16041 tcg_gen_movi_tl(t0, ret);
16042 gen_helper_mthlip(t0, v1_t, cpu_env);
16043 break;
16044 case OPC_WRDSP:
16045 imm = (ctx->opcode >> 11) & 0x3FF;
16046 tcg_gen_movi_tl(t0, imm);
16047 gen_helper_wrdsp(v1_t, t0, cpu_env);
16048 break;
16049 case OPC_RDDSP:
16050 imm = (ctx->opcode >> 16) & 0x03FF;
16051 tcg_gen_movi_tl(t0, imm);
16052 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
16053 break;
16055 break;
16056 #ifdef TARGET_MIPS64
16057 case OPC_DEXTR_W_DSP:
16058 check_dsp(ctx);
16059 switch (op2) {
16060 case OPC_DMTHLIP:
16061 tcg_gen_movi_tl(t0, ret);
16062 gen_helper_dmthlip(v1_t, t0, cpu_env);
16063 break;
16064 case OPC_DSHILO:
16066 int shift = (ctx->opcode >> 19) & 0x7F;
16067 int ac = (ctx->opcode >> 11) & 0x03;
16068 tcg_gen_movi_tl(t0, shift);
16069 tcg_gen_movi_tl(t1, ac);
16070 gen_helper_dshilo(t0, t1, cpu_env);
16071 break;
16073 case OPC_DSHILOV:
16075 int ac = (ctx->opcode >> 11) & 0x03;
16076 tcg_gen_movi_tl(t0, ac);
16077 gen_helper_dshilo(v1_t, t0, cpu_env);
16078 break;
16080 case OPC_DEXTP:
16081 tcg_gen_movi_tl(t0, v2);
16082 tcg_gen_movi_tl(t1, v1);
16084 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
16085 break;
16086 case OPC_DEXTPV:
16087 tcg_gen_movi_tl(t0, v2);
16088 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
16089 break;
16090 case OPC_DEXTPDP:
16091 tcg_gen_movi_tl(t0, v2);
16092 tcg_gen_movi_tl(t1, v1);
16093 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
16094 break;
16095 case OPC_DEXTPDPV:
16096 tcg_gen_movi_tl(t0, v2);
16097 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16098 break;
16099 case OPC_DEXTR_L:
16100 tcg_gen_movi_tl(t0, v2);
16101 tcg_gen_movi_tl(t1, v1);
16102 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
16103 break;
16104 case OPC_DEXTR_R_L:
16105 tcg_gen_movi_tl(t0, v2);
16106 tcg_gen_movi_tl(t1, v1);
16107 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
16108 break;
16109 case OPC_DEXTR_RS_L:
16110 tcg_gen_movi_tl(t0, v2);
16111 tcg_gen_movi_tl(t1, v1);
16112 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
16113 break;
16114 case OPC_DEXTR_W:
16115 tcg_gen_movi_tl(t0, v2);
16116 tcg_gen_movi_tl(t1, v1);
16117 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
16118 break;
16119 case OPC_DEXTR_R_W:
16120 tcg_gen_movi_tl(t0, v2);
16121 tcg_gen_movi_tl(t1, v1);
16122 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16123 break;
16124 case OPC_DEXTR_RS_W:
16125 tcg_gen_movi_tl(t0, v2);
16126 tcg_gen_movi_tl(t1, v1);
16127 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16128 break;
16129 case OPC_DEXTR_S_H:
16130 tcg_gen_movi_tl(t0, v2);
16131 tcg_gen_movi_tl(t1, v1);
16132 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16133 break;
16134 case OPC_DEXTRV_S_H:
16135 tcg_gen_movi_tl(t0, v2);
16136 tcg_gen_movi_tl(t1, v1);
16137 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16138 break;
16139 case OPC_DEXTRV_L:
16140 tcg_gen_movi_tl(t0, v2);
16141 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16142 break;
16143 case OPC_DEXTRV_R_L:
16144 tcg_gen_movi_tl(t0, v2);
16145 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16146 break;
16147 case OPC_DEXTRV_RS_L:
16148 tcg_gen_movi_tl(t0, v2);
16149 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16150 break;
16151 case OPC_DEXTRV_W:
16152 tcg_gen_movi_tl(t0, v2);
16153 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16154 break;
16155 case OPC_DEXTRV_R_W:
16156 tcg_gen_movi_tl(t0, v2);
16157 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16158 break;
16159 case OPC_DEXTRV_RS_W:
16160 tcg_gen_movi_tl(t0, v2);
16161 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16162 break;
16164 break;
16165 #endif
16168 tcg_temp_free(t0);
16169 tcg_temp_free(t1);
16170 tcg_temp_free(v1_t);
16171 tcg_temp_free(v2_t);
16173 (void)opn; /* avoid a compiler warning */
16174 MIPS_DEBUG("%s", opn);
16177 /* End MIPSDSP functions. */
16179 /* Compact Branches */
16180 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
16181 int rs, int rt, int32_t offset)
16183 int bcond_compute = 0;
16184 TCGv t0 = tcg_temp_new();
16185 TCGv t1 = tcg_temp_new();
16187 if (ctx->hflags & MIPS_HFLAG_BMASK) {
16188 #ifdef MIPS_DEBUG_DISAS
16189 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
16190 "\n", ctx->pc);
16191 #endif
16192 generate_exception(ctx, EXCP_RI);
16193 goto out;
16196 /* Load needed operands and calculate btarget */
16197 switch (opc) {
16198 /* compact branch */
16199 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
16200 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
16201 gen_load_gpr(t0, rs);
16202 gen_load_gpr(t1, rt);
16203 bcond_compute = 1;
16204 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
16205 if (rs <= rt && rs == 0) {
16206 /* OPC_BEQZALC, OPC_BNEZALC */
16207 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
16209 break;
16210 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
16211 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
16212 gen_load_gpr(t0, rs);
16213 gen_load_gpr(t1, rt);
16214 bcond_compute = 1;
16215 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
16216 break;
16217 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
16218 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
16219 if (rs == 0 || rs == rt) {
16220 /* OPC_BLEZALC, OPC_BGEZALC */
16221 /* OPC_BGTZALC, OPC_BLTZALC */
16222 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
16224 gen_load_gpr(t0, rs);
16225 gen_load_gpr(t1, rt);
16226 bcond_compute = 1;
16227 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
16228 break;
16229 case OPC_BC:
16230 case OPC_BALC:
16231 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
16232 break;
16233 case OPC_BEQZC:
16234 case OPC_BNEZC:
16235 if (rs != 0) {
16236 /* OPC_BEQZC, OPC_BNEZC */
16237 gen_load_gpr(t0, rs);
16238 bcond_compute = 1;
16239 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
16240 } else {
16241 /* OPC_JIC, OPC_JIALC */
16242 TCGv tbase = tcg_temp_new();
16243 TCGv toffset = tcg_temp_new();
16245 gen_load_gpr(tbase, rt);
16246 tcg_gen_movi_tl(toffset, offset);
16247 gen_op_addr_add(ctx, btarget, tbase, toffset);
16248 tcg_temp_free(tbase);
16249 tcg_temp_free(toffset);
16251 break;
16252 default:
16253 MIPS_INVAL("Compact branch/jump");
16254 generate_exception(ctx, EXCP_RI);
16255 goto out;
16258 if (bcond_compute == 0) {
16259 /* Uncoditional compact branch */
16260 switch (opc) {
16261 case OPC_JIALC:
16262 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
16263 /* Fallthrough */
16264 case OPC_JIC:
16265 ctx->hflags |= MIPS_HFLAG_BR;
16266 break;
16267 case OPC_BALC:
16268 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
16269 /* Fallthrough */
16270 case OPC_BC:
16271 ctx->hflags |= MIPS_HFLAG_B;
16272 break;
16273 default:
16274 MIPS_INVAL("Compact branch/jump");
16275 generate_exception(ctx, EXCP_RI);
16276 goto out;
16279 /* Generating branch here as compact branches don't have delay slot */
16280 gen_branch(ctx, 4);
16281 } else {
16282 /* Conditional compact branch */
16283 TCGLabel *fs = gen_new_label();
16284 save_cpu_state(ctx, 0);
16286 switch (opc) {
16287 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
16288 if (rs == 0 && rt != 0) {
16289 /* OPC_BLEZALC */
16290 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
16291 } else if (rs != 0 && rt != 0 && rs == rt) {
16292 /* OPC_BGEZALC */
16293 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
16294 } else {
16295 /* OPC_BGEUC */
16296 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
16298 break;
16299 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
16300 if (rs == 0 && rt != 0) {
16301 /* OPC_BGTZALC */
16302 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
16303 } else if (rs != 0 && rt != 0 && rs == rt) {
16304 /* OPC_BLTZALC */
16305 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
16306 } else {
16307 /* OPC_BLTUC */
16308 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
16310 break;
16311 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
16312 if (rs == 0 && rt != 0) {
16313 /* OPC_BLEZC */
16314 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
16315 } else if (rs != 0 && rt != 0 && rs == rt) {
16316 /* OPC_BGEZC */
16317 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
16318 } else {
16319 /* OPC_BGEC */
16320 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
16322 break;
16323 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
16324 if (rs == 0 && rt != 0) {
16325 /* OPC_BGTZC */
16326 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
16327 } else if (rs != 0 && rt != 0 && rs == rt) {
16328 /* OPC_BLTZC */
16329 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
16330 } else {
16331 /* OPC_BLTC */
16332 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
16334 break;
16335 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
16336 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
16337 if (rs >= rt) {
16338 /* OPC_BOVC, OPC_BNVC */
16339 TCGv t2 = tcg_temp_new();
16340 TCGv t3 = tcg_temp_new();
16341 TCGv t4 = tcg_temp_new();
16342 TCGv input_overflow = tcg_temp_new();
16344 gen_load_gpr(t0, rs);
16345 gen_load_gpr(t1, rt);
16346 tcg_gen_ext32s_tl(t2, t0);
16347 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
16348 tcg_gen_ext32s_tl(t3, t1);
16349 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
16350 tcg_gen_or_tl(input_overflow, input_overflow, t4);
16352 tcg_gen_add_tl(t4, t2, t3);
16353 tcg_gen_ext32s_tl(t4, t4);
16354 tcg_gen_xor_tl(t2, t2, t3);
16355 tcg_gen_xor_tl(t3, t4, t3);
16356 tcg_gen_andc_tl(t2, t3, t2);
16357 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
16358 tcg_gen_or_tl(t4, t4, input_overflow);
16359 if (opc == OPC_BOVC) {
16360 /* OPC_BOVC */
16361 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
16362 } else {
16363 /* OPC_BNVC */
16364 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
16366 tcg_temp_free(input_overflow);
16367 tcg_temp_free(t4);
16368 tcg_temp_free(t3);
16369 tcg_temp_free(t2);
16370 } else if (rs < rt && rs == 0) {
16371 /* OPC_BEQZALC, OPC_BNEZALC */
16372 if (opc == OPC_BEQZALC) {
16373 /* OPC_BEQZALC */
16374 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
16375 } else {
16376 /* OPC_BNEZALC */
16377 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
16379 } else {
16380 /* OPC_BEQC, OPC_BNEC */
16381 if (opc == OPC_BEQC) {
16382 /* OPC_BEQC */
16383 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
16384 } else {
16385 /* OPC_BNEC */
16386 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
16389 break;
16390 case OPC_BEQZC:
16391 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
16392 break;
16393 case OPC_BNEZC:
16394 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
16395 break;
16396 default:
16397 MIPS_INVAL("Compact conditional branch/jump");
16398 generate_exception(ctx, EXCP_RI);
16399 goto out;
16402 /* Generating branch here as compact branches don't have delay slot */
16403 gen_goto_tb(ctx, 1, ctx->btarget);
16404 gen_set_label(fs);
16406 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
16407 MIPS_DEBUG("Compact conditional branch");
16410 out:
16411 tcg_temp_free(t0);
16412 tcg_temp_free(t1);
16415 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
16417 int rs, rt, rd, sa;
16418 uint32_t op1, op2;
16420 rs = (ctx->opcode >> 21) & 0x1f;
16421 rt = (ctx->opcode >> 16) & 0x1f;
16422 rd = (ctx->opcode >> 11) & 0x1f;
16423 sa = (ctx->opcode >> 6) & 0x1f;
16425 op1 = MASK_SPECIAL(ctx->opcode);
16426 switch (op1) {
16427 case OPC_LSA:
16428 if (rd != 0) {
16429 int imm2 = extract32(ctx->opcode, 6, 3);
16430 TCGv t0 = tcg_temp_new();
16431 TCGv t1 = tcg_temp_new();
16432 gen_load_gpr(t0, rs);
16433 gen_load_gpr(t1, rt);
16434 tcg_gen_shli_tl(t0, t0, imm2 + 1);
16435 tcg_gen_add_tl(t0, t0, t1);
16436 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
16437 tcg_temp_free(t1);
16438 tcg_temp_free(t0);
16440 break;
16441 case OPC_MULT ... OPC_DIVU:
16442 op2 = MASK_R6_MULDIV(ctx->opcode);
16443 switch (op2) {
16444 case R6_OPC_MUL:
16445 case R6_OPC_MUH:
16446 case R6_OPC_MULU:
16447 case R6_OPC_MUHU:
16448 case R6_OPC_DIV:
16449 case R6_OPC_MOD:
16450 case R6_OPC_DIVU:
16451 case R6_OPC_MODU:
16452 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16453 break;
16454 default:
16455 MIPS_INVAL("special_r6 muldiv");
16456 generate_exception(ctx, EXCP_RI);
16457 break;
16459 break;
16460 case OPC_SELEQZ:
16461 case OPC_SELNEZ:
16462 gen_cond_move(ctx, op1, rd, rs, rt);
16463 break;
16464 case R6_OPC_CLO:
16465 case R6_OPC_CLZ:
16466 if (rt == 0 && sa == 1) {
16467 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16468 We need additionally to check other fields */
16469 gen_cl(ctx, op1, rd, rs);
16470 } else {
16471 generate_exception(ctx, EXCP_RI);
16473 break;
16474 case R6_OPC_SDBBP:
16475 if (ctx->hflags & MIPS_HFLAG_SBRI) {
16476 generate_exception(ctx, EXCP_RI);
16477 } else {
16478 generate_exception(ctx, EXCP_DBp);
16480 break;
16481 #if defined(TARGET_MIPS64)
16482 case OPC_DLSA:
16483 check_mips_64(ctx);
16484 if (rd != 0) {
16485 int imm2 = extract32(ctx->opcode, 6, 3);
16486 TCGv t0 = tcg_temp_new();
16487 TCGv t1 = tcg_temp_new();
16488 gen_load_gpr(t0, rs);
16489 gen_load_gpr(t1, rt);
16490 tcg_gen_shli_tl(t0, t0, imm2 + 1);
16491 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
16492 tcg_temp_free(t1);
16493 tcg_temp_free(t0);
16495 break;
16496 case R6_OPC_DCLO:
16497 case R6_OPC_DCLZ:
16498 if (rt == 0 && sa == 1) {
16499 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16500 We need additionally to check other fields */
16501 check_mips_64(ctx);
16502 gen_cl(ctx, op1, rd, rs);
16503 } else {
16504 generate_exception(ctx, EXCP_RI);
16506 break;
16507 case OPC_DMULT ... OPC_DDIVU:
16508 op2 = MASK_R6_MULDIV(ctx->opcode);
16509 switch (op2) {
16510 case R6_OPC_DMUL:
16511 case R6_OPC_DMUH:
16512 case R6_OPC_DMULU:
16513 case R6_OPC_DMUHU:
16514 case R6_OPC_DDIV:
16515 case R6_OPC_DMOD:
16516 case R6_OPC_DDIVU:
16517 case R6_OPC_DMODU:
16518 check_mips_64(ctx);
16519 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16520 break;
16521 default:
16522 MIPS_INVAL("special_r6 muldiv");
16523 generate_exception(ctx, EXCP_RI);
16524 break;
16526 break;
16527 #endif
16528 default: /* Invalid */
16529 MIPS_INVAL("special_r6");
16530 generate_exception(ctx, EXCP_RI);
16531 break;
16535 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
16537 int rs, rt, rd, sa;
16538 uint32_t op1;
16540 rs = (ctx->opcode >> 21) & 0x1f;
16541 rt = (ctx->opcode >> 16) & 0x1f;
16542 rd = (ctx->opcode >> 11) & 0x1f;
16543 sa = (ctx->opcode >> 6) & 0x1f;
16545 op1 = MASK_SPECIAL(ctx->opcode);
16546 switch (op1) {
16547 case OPC_MOVN: /* Conditional move */
16548 case OPC_MOVZ:
16549 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
16550 INSN_LOONGSON2E | INSN_LOONGSON2F);
16551 gen_cond_move(ctx, op1, rd, rs, rt);
16552 break;
16553 case OPC_MFHI: /* Move from HI/LO */
16554 case OPC_MFLO:
16555 gen_HILO(ctx, op1, rs & 3, rd);
16556 break;
16557 case OPC_MTHI:
16558 case OPC_MTLO: /* Move to HI/LO */
16559 gen_HILO(ctx, op1, rd & 3, rs);
16560 break;
16561 case OPC_MOVCI:
16562 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
16563 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16564 check_cp1_enabled(ctx);
16565 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
16566 (ctx->opcode >> 16) & 1);
16567 } else {
16568 generate_exception_err(ctx, EXCP_CpU, 1);
16570 break;
16571 case OPC_MULT:
16572 case OPC_MULTU:
16573 if (sa) {
16574 check_insn(ctx, INSN_VR54XX);
16575 op1 = MASK_MUL_VR54XX(ctx->opcode);
16576 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
16577 } else {
16578 gen_muldiv(ctx, op1, rd & 3, rs, rt);
16580 break;
16581 case OPC_DIV:
16582 case OPC_DIVU:
16583 gen_muldiv(ctx, op1, 0, rs, rt);
16584 break;
16585 #if defined(TARGET_MIPS64)
16586 case OPC_DMULT ... OPC_DDIVU:
16587 check_insn(ctx, ISA_MIPS3);
16588 check_mips_64(ctx);
16589 gen_muldiv(ctx, op1, 0, rs, rt);
16590 break;
16591 #endif
16592 case OPC_JR:
16593 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
16594 break;
16595 case OPC_SPIM:
16596 #ifdef MIPS_STRICT_STANDARD
16597 MIPS_INVAL("SPIM");
16598 generate_exception(ctx, EXCP_RI);
16599 #else
16600 /* Implemented as RI exception for now. */
16601 MIPS_INVAL("spim (unofficial)");
16602 generate_exception(ctx, EXCP_RI);
16603 #endif
16604 break;
16605 default: /* Invalid */
16606 MIPS_INVAL("special_legacy");
16607 generate_exception(ctx, EXCP_RI);
16608 break;
16612 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
16614 int rs, rt, rd, sa;
16615 uint32_t op1;
16617 rs = (ctx->opcode >> 21) & 0x1f;
16618 rt = (ctx->opcode >> 16) & 0x1f;
16619 rd = (ctx->opcode >> 11) & 0x1f;
16620 sa = (ctx->opcode >> 6) & 0x1f;
16622 op1 = MASK_SPECIAL(ctx->opcode);
16623 switch (op1) {
16624 case OPC_SLL: /* Shift with immediate */
16625 if (sa == 5 && rd == 0 &&
16626 rs == 0 && rt == 0) { /* PAUSE */
16627 if ((ctx->insn_flags & ISA_MIPS32R6) &&
16628 (ctx->hflags & MIPS_HFLAG_BMASK)) {
16629 MIPS_DEBUG("CTI in delay / forbidden slot");
16630 generate_exception(ctx, EXCP_RI);
16631 break;
16634 /* Fallthrough */
16635 case OPC_SRA:
16636 gen_shift_imm(ctx, op1, rd, rt, sa);
16637 break;
16638 case OPC_SRL:
16639 switch ((ctx->opcode >> 21) & 0x1f) {
16640 case 1:
16641 /* rotr is decoded as srl on non-R2 CPUs */
16642 if (ctx->insn_flags & ISA_MIPS32R2) {
16643 op1 = OPC_ROTR;
16645 /* Fallthrough */
16646 case 0:
16647 gen_shift_imm(ctx, op1, rd, rt, sa);
16648 break;
16649 default:
16650 generate_exception(ctx, EXCP_RI);
16651 break;
16653 break;
16654 case OPC_ADD ... OPC_SUBU:
16655 gen_arith(ctx, op1, rd, rs, rt);
16656 break;
16657 case OPC_SLLV: /* Shifts */
16658 case OPC_SRAV:
16659 gen_shift(ctx, op1, rd, rs, rt);
16660 break;
16661 case OPC_SRLV:
16662 switch ((ctx->opcode >> 6) & 0x1f) {
16663 case 1:
16664 /* rotrv is decoded as srlv on non-R2 CPUs */
16665 if (ctx->insn_flags & ISA_MIPS32R2) {
16666 op1 = OPC_ROTRV;
16668 /* Fallthrough */
16669 case 0:
16670 gen_shift(ctx, op1, rd, rs, rt);
16671 break;
16672 default:
16673 generate_exception(ctx, EXCP_RI);
16674 break;
16676 break;
16677 case OPC_SLT: /* Set on less than */
16678 case OPC_SLTU:
16679 gen_slt(ctx, op1, rd, rs, rt);
16680 break;
16681 case OPC_AND: /* Logic*/
16682 case OPC_OR:
16683 case OPC_NOR:
16684 case OPC_XOR:
16685 gen_logic(ctx, op1, rd, rs, rt);
16686 break;
16687 case OPC_JALR:
16688 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
16689 break;
16690 case OPC_TGE ... OPC_TEQ: /* Traps */
16691 case OPC_TNE:
16692 check_insn(ctx, ISA_MIPS2);
16693 gen_trap(ctx, op1, rs, rt, -1);
16694 break;
16695 case OPC_LSA: /* OPC_PMON */
16696 if ((ctx->insn_flags & ISA_MIPS32R6) ||
16697 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
16698 decode_opc_special_r6(env, ctx);
16699 } else {
16700 /* Pmon entry point, also R4010 selsl */
16701 #ifdef MIPS_STRICT_STANDARD
16702 MIPS_INVAL("PMON / selsl");
16703 generate_exception(ctx, EXCP_RI);
16704 #else
16705 gen_helper_0e0i(pmon, sa);
16706 #endif
16708 break;
16709 case OPC_SYSCALL:
16710 generate_exception(ctx, EXCP_SYSCALL);
16711 ctx->bstate = BS_STOP;
16712 break;
16713 case OPC_BREAK:
16714 generate_exception(ctx, EXCP_BREAK);
16715 break;
16716 case OPC_SYNC:
16717 check_insn(ctx, ISA_MIPS2);
16718 /* Treat as NOP. */
16719 break;
16721 #if defined(TARGET_MIPS64)
16722 /* MIPS64 specific opcodes */
16723 case OPC_DSLL:
16724 case OPC_DSRA:
16725 case OPC_DSLL32:
16726 case OPC_DSRA32:
16727 check_insn(ctx, ISA_MIPS3);
16728 check_mips_64(ctx);
16729 gen_shift_imm(ctx, op1, rd, rt, sa);
16730 break;
16731 case OPC_DSRL:
16732 switch ((ctx->opcode >> 21) & 0x1f) {
16733 case 1:
16734 /* drotr is decoded as dsrl on non-R2 CPUs */
16735 if (ctx->insn_flags & ISA_MIPS32R2) {
16736 op1 = OPC_DROTR;
16738 /* Fallthrough */
16739 case 0:
16740 check_insn(ctx, ISA_MIPS3);
16741 check_mips_64(ctx);
16742 gen_shift_imm(ctx, op1, rd, rt, sa);
16743 break;
16744 default:
16745 generate_exception(ctx, EXCP_RI);
16746 break;
16748 break;
16749 case OPC_DSRL32:
16750 switch ((ctx->opcode >> 21) & 0x1f) {
16751 case 1:
16752 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
16753 if (ctx->insn_flags & ISA_MIPS32R2) {
16754 op1 = OPC_DROTR32;
16756 /* Fallthrough */
16757 case 0:
16758 check_insn(ctx, ISA_MIPS3);
16759 check_mips_64(ctx);
16760 gen_shift_imm(ctx, op1, rd, rt, sa);
16761 break;
16762 default:
16763 generate_exception(ctx, EXCP_RI);
16764 break;
16766 break;
16767 case OPC_DADD ... OPC_DSUBU:
16768 check_insn(ctx, ISA_MIPS3);
16769 check_mips_64(ctx);
16770 gen_arith(ctx, op1, rd, rs, rt);
16771 break;
16772 case OPC_DSLLV:
16773 case OPC_DSRAV:
16774 check_insn(ctx, ISA_MIPS3);
16775 check_mips_64(ctx);
16776 gen_shift(ctx, op1, rd, rs, rt);
16777 break;
16778 case OPC_DSRLV:
16779 switch ((ctx->opcode >> 6) & 0x1f) {
16780 case 1:
16781 /* drotrv is decoded as dsrlv on non-R2 CPUs */
16782 if (ctx->insn_flags & ISA_MIPS32R2) {
16783 op1 = OPC_DROTRV;
16785 /* Fallthrough */
16786 case 0:
16787 check_insn(ctx, ISA_MIPS3);
16788 check_mips_64(ctx);
16789 gen_shift(ctx, op1, rd, rs, rt);
16790 break;
16791 default:
16792 generate_exception(ctx, EXCP_RI);
16793 break;
16795 break;
16796 case OPC_DLSA:
16797 if ((ctx->insn_flags & ISA_MIPS32R6) ||
16798 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
16799 decode_opc_special_r6(env, ctx);
16801 break;
16802 #endif
16803 default:
16804 if (ctx->insn_flags & ISA_MIPS32R6) {
16805 decode_opc_special_r6(env, ctx);
16806 } else {
16807 decode_opc_special_legacy(env, ctx);
16812 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
16814 int rs, rt, rd;
16815 uint32_t op1;
16817 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16819 rs = (ctx->opcode >> 21) & 0x1f;
16820 rt = (ctx->opcode >> 16) & 0x1f;
16821 rd = (ctx->opcode >> 11) & 0x1f;
16823 op1 = MASK_SPECIAL2(ctx->opcode);
16824 switch (op1) {
16825 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
16826 case OPC_MSUB ... OPC_MSUBU:
16827 check_insn(ctx, ISA_MIPS32);
16828 gen_muldiv(ctx, op1, rd & 3, rs, rt);
16829 break;
16830 case OPC_MUL:
16831 gen_arith(ctx, op1, rd, rs, rt);
16832 break;
16833 case OPC_DIV_G_2F:
16834 case OPC_DIVU_G_2F:
16835 case OPC_MULT_G_2F:
16836 case OPC_MULTU_G_2F:
16837 case OPC_MOD_G_2F:
16838 case OPC_MODU_G_2F:
16839 check_insn(ctx, INSN_LOONGSON2F);
16840 gen_loongson_integer(ctx, op1, rd, rs, rt);
16841 break;
16842 case OPC_CLO:
16843 case OPC_CLZ:
16844 check_insn(ctx, ISA_MIPS32);
16845 gen_cl(ctx, op1, rd, rs);
16846 break;
16847 case OPC_SDBBP:
16848 /* XXX: not clear which exception should be raised
16849 * when in debug mode...
16851 check_insn(ctx, ISA_MIPS32);
16852 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
16853 generate_exception(ctx, EXCP_DBp);
16854 } else {
16855 generate_exception(ctx, EXCP_DBp);
16857 /* Treat as NOP. */
16858 break;
16859 #if defined(TARGET_MIPS64)
16860 case OPC_DCLO:
16861 case OPC_DCLZ:
16862 check_insn(ctx, ISA_MIPS64);
16863 check_mips_64(ctx);
16864 gen_cl(ctx, op1, rd, rs);
16865 break;
16866 case OPC_DMULT_G_2F:
16867 case OPC_DMULTU_G_2F:
16868 case OPC_DDIV_G_2F:
16869 case OPC_DDIVU_G_2F:
16870 case OPC_DMOD_G_2F:
16871 case OPC_DMODU_G_2F:
16872 check_insn(ctx, INSN_LOONGSON2F);
16873 gen_loongson_integer(ctx, op1, rd, rs, rt);
16874 break;
16875 #endif
16876 default: /* Invalid */
16877 MIPS_INVAL("special2_legacy");
16878 generate_exception(ctx, EXCP_RI);
16879 break;
16883 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
16885 int rs, rt, rd, sa;
16886 uint32_t op1, op2;
16887 int16_t imm;
16889 rs = (ctx->opcode >> 21) & 0x1f;
16890 rt = (ctx->opcode >> 16) & 0x1f;
16891 rd = (ctx->opcode >> 11) & 0x1f;
16892 sa = (ctx->opcode >> 6) & 0x1f;
16893 imm = (int16_t)ctx->opcode >> 7;
16895 op1 = MASK_SPECIAL3(ctx->opcode);
16896 switch (op1) {
16897 case R6_OPC_PREF:
16898 if (rt >= 24) {
16899 /* hint codes 24-31 are reserved and signal RI */
16900 generate_exception(ctx, EXCP_RI);
16902 /* Treat as NOP. */
16903 break;
16904 case R6_OPC_CACHE:
16905 /* Treat as NOP. */
16906 break;
16907 case R6_OPC_SC:
16908 gen_st_cond(ctx, op1, rt, rs, imm);
16909 break;
16910 case R6_OPC_LL:
16911 gen_ld(ctx, op1, rt, rs, imm);
16912 break;
16913 case OPC_BSHFL:
16915 if (rd == 0) {
16916 /* Treat as NOP. */
16917 break;
16919 TCGv t0 = tcg_temp_new();
16920 gen_load_gpr(t0, rt);
16922 op2 = MASK_BSHFL(ctx->opcode);
16923 switch (op2) {
16924 case OPC_ALIGN ... OPC_ALIGN_END:
16925 sa &= 3;
16926 if (sa == 0) {
16927 tcg_gen_mov_tl(cpu_gpr[rd], t0);
16928 } else {
16929 TCGv t1 = tcg_temp_new();
16930 TCGv_i64 t2 = tcg_temp_new_i64();
16931 gen_load_gpr(t1, rs);
16932 tcg_gen_concat_tl_i64(t2, t1, t0);
16933 tcg_gen_shri_i64(t2, t2, 8 * (4 - sa));
16934 #if defined(TARGET_MIPS64)
16935 tcg_gen_ext32s_i64(cpu_gpr[rd], t2);
16936 #else
16937 tcg_gen_trunc_i64_i32(cpu_gpr[rd], t2);
16938 #endif
16939 tcg_temp_free_i64(t2);
16940 tcg_temp_free(t1);
16942 break;
16943 case OPC_BITSWAP:
16944 gen_helper_bitswap(cpu_gpr[rd], t0);
16945 break;
16947 tcg_temp_free(t0);
16949 break;
16950 #if defined(TARGET_MIPS64)
16951 case R6_OPC_SCD:
16952 gen_st_cond(ctx, op1, rt, rs, imm);
16953 break;
16954 case R6_OPC_LLD:
16955 gen_ld(ctx, op1, rt, rs, imm);
16956 break;
16957 case OPC_DBSHFL:
16958 check_mips_64(ctx);
16960 if (rd == 0) {
16961 /* Treat as NOP. */
16962 break;
16964 TCGv t0 = tcg_temp_new();
16965 gen_load_gpr(t0, rt);
16967 op2 = MASK_DBSHFL(ctx->opcode);
16968 switch (op2) {
16969 case OPC_DALIGN ... OPC_DALIGN_END:
16970 sa &= 7;
16971 if (sa == 0) {
16972 tcg_gen_mov_tl(cpu_gpr[rd], t0);
16973 } else {
16974 TCGv t1 = tcg_temp_new();
16975 gen_load_gpr(t1, rs);
16976 tcg_gen_shli_tl(t0, t0, 8 * sa);
16977 tcg_gen_shri_tl(t1, t1, 8 * (8 - sa));
16978 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
16979 tcg_temp_free(t1);
16981 break;
16982 case OPC_DBITSWAP:
16983 gen_helper_dbitswap(cpu_gpr[rd], t0);
16984 break;
16986 tcg_temp_free(t0);
16988 break;
16989 #endif
16990 default: /* Invalid */
16991 MIPS_INVAL("special3_r6");
16992 generate_exception(ctx, EXCP_RI);
16993 break;
16997 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
16999 int rs, rt, rd;
17000 uint32_t op1, op2;
17002 rs = (ctx->opcode >> 21) & 0x1f;
17003 rt = (ctx->opcode >> 16) & 0x1f;
17004 rd = (ctx->opcode >> 11) & 0x1f;
17006 op1 = MASK_SPECIAL3(ctx->opcode);
17007 switch (op1) {
17008 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
17009 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
17010 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
17011 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
17012 * the same mask and op1. */
17013 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
17014 op2 = MASK_ADDUH_QB(ctx->opcode);
17015 switch (op2) {
17016 case OPC_ADDUH_QB:
17017 case OPC_ADDUH_R_QB:
17018 case OPC_ADDQH_PH:
17019 case OPC_ADDQH_R_PH:
17020 case OPC_ADDQH_W:
17021 case OPC_ADDQH_R_W:
17022 case OPC_SUBUH_QB:
17023 case OPC_SUBUH_R_QB:
17024 case OPC_SUBQH_PH:
17025 case OPC_SUBQH_R_PH:
17026 case OPC_SUBQH_W:
17027 case OPC_SUBQH_R_W:
17028 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17029 break;
17030 case OPC_MUL_PH:
17031 case OPC_MUL_S_PH:
17032 case OPC_MULQ_S_W:
17033 case OPC_MULQ_RS_W:
17034 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17035 break;
17036 default:
17037 MIPS_INVAL("MASK ADDUH.QB");
17038 generate_exception(ctx, EXCP_RI);
17039 break;
17041 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
17042 gen_loongson_integer(ctx, op1, rd, rs, rt);
17043 } else {
17044 generate_exception(ctx, EXCP_RI);
17046 break;
17047 case OPC_LX_DSP:
17048 op2 = MASK_LX(ctx->opcode);
17049 switch (op2) {
17050 #if defined(TARGET_MIPS64)
17051 case OPC_LDX:
17052 #endif
17053 case OPC_LBUX:
17054 case OPC_LHX:
17055 case OPC_LWX:
17056 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
17057 break;
17058 default: /* Invalid */
17059 MIPS_INVAL("MASK LX");
17060 generate_exception(ctx, EXCP_RI);
17061 break;
17063 break;
17064 case OPC_ABSQ_S_PH_DSP:
17065 op2 = MASK_ABSQ_S_PH(ctx->opcode);
17066 switch (op2) {
17067 case OPC_ABSQ_S_QB:
17068 case OPC_ABSQ_S_PH:
17069 case OPC_ABSQ_S_W:
17070 case OPC_PRECEQ_W_PHL:
17071 case OPC_PRECEQ_W_PHR:
17072 case OPC_PRECEQU_PH_QBL:
17073 case OPC_PRECEQU_PH_QBR:
17074 case OPC_PRECEQU_PH_QBLA:
17075 case OPC_PRECEQU_PH_QBRA:
17076 case OPC_PRECEU_PH_QBL:
17077 case OPC_PRECEU_PH_QBR:
17078 case OPC_PRECEU_PH_QBLA:
17079 case OPC_PRECEU_PH_QBRA:
17080 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17081 break;
17082 case OPC_BITREV:
17083 case OPC_REPL_QB:
17084 case OPC_REPLV_QB:
17085 case OPC_REPL_PH:
17086 case OPC_REPLV_PH:
17087 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17088 break;
17089 default:
17090 MIPS_INVAL("MASK ABSQ_S.PH");
17091 generate_exception(ctx, EXCP_RI);
17092 break;
17094 break;
17095 case OPC_ADDU_QB_DSP:
17096 op2 = MASK_ADDU_QB(ctx->opcode);
17097 switch (op2) {
17098 case OPC_ADDQ_PH:
17099 case OPC_ADDQ_S_PH:
17100 case OPC_ADDQ_S_W:
17101 case OPC_ADDU_QB:
17102 case OPC_ADDU_S_QB:
17103 case OPC_ADDU_PH:
17104 case OPC_ADDU_S_PH:
17105 case OPC_SUBQ_PH:
17106 case OPC_SUBQ_S_PH:
17107 case OPC_SUBQ_S_W:
17108 case OPC_SUBU_QB:
17109 case OPC_SUBU_S_QB:
17110 case OPC_SUBU_PH:
17111 case OPC_SUBU_S_PH:
17112 case OPC_ADDSC:
17113 case OPC_ADDWC:
17114 case OPC_MODSUB:
17115 case OPC_RADDU_W_QB:
17116 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17117 break;
17118 case OPC_MULEU_S_PH_QBL:
17119 case OPC_MULEU_S_PH_QBR:
17120 case OPC_MULQ_RS_PH:
17121 case OPC_MULEQ_S_W_PHL:
17122 case OPC_MULEQ_S_W_PHR:
17123 case OPC_MULQ_S_PH:
17124 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17125 break;
17126 default: /* Invalid */
17127 MIPS_INVAL("MASK ADDU.QB");
17128 generate_exception(ctx, EXCP_RI);
17129 break;
17132 break;
17133 case OPC_CMPU_EQ_QB_DSP:
17134 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
17135 switch (op2) {
17136 case OPC_PRECR_SRA_PH_W:
17137 case OPC_PRECR_SRA_R_PH_W:
17138 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17139 break;
17140 case OPC_PRECR_QB_PH:
17141 case OPC_PRECRQ_QB_PH:
17142 case OPC_PRECRQ_PH_W:
17143 case OPC_PRECRQ_RS_PH_W:
17144 case OPC_PRECRQU_S_QB_PH:
17145 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17146 break;
17147 case OPC_CMPU_EQ_QB:
17148 case OPC_CMPU_LT_QB:
17149 case OPC_CMPU_LE_QB:
17150 case OPC_CMP_EQ_PH:
17151 case OPC_CMP_LT_PH:
17152 case OPC_CMP_LE_PH:
17153 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17154 break;
17155 case OPC_CMPGU_EQ_QB:
17156 case OPC_CMPGU_LT_QB:
17157 case OPC_CMPGU_LE_QB:
17158 case OPC_CMPGDU_EQ_QB:
17159 case OPC_CMPGDU_LT_QB:
17160 case OPC_CMPGDU_LE_QB:
17161 case OPC_PICK_QB:
17162 case OPC_PICK_PH:
17163 case OPC_PACKRL_PH:
17164 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17165 break;
17166 default: /* Invalid */
17167 MIPS_INVAL("MASK CMPU.EQ.QB");
17168 generate_exception(ctx, EXCP_RI);
17169 break;
17171 break;
17172 case OPC_SHLL_QB_DSP:
17173 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17174 break;
17175 case OPC_DPA_W_PH_DSP:
17176 op2 = MASK_DPA_W_PH(ctx->opcode);
17177 switch (op2) {
17178 case OPC_DPAU_H_QBL:
17179 case OPC_DPAU_H_QBR:
17180 case OPC_DPSU_H_QBL:
17181 case OPC_DPSU_H_QBR:
17182 case OPC_DPA_W_PH:
17183 case OPC_DPAX_W_PH:
17184 case OPC_DPAQ_S_W_PH:
17185 case OPC_DPAQX_S_W_PH:
17186 case OPC_DPAQX_SA_W_PH:
17187 case OPC_DPS_W_PH:
17188 case OPC_DPSX_W_PH:
17189 case OPC_DPSQ_S_W_PH:
17190 case OPC_DPSQX_S_W_PH:
17191 case OPC_DPSQX_SA_W_PH:
17192 case OPC_MULSAQ_S_W_PH:
17193 case OPC_DPAQ_SA_L_W:
17194 case OPC_DPSQ_SA_L_W:
17195 case OPC_MAQ_S_W_PHL:
17196 case OPC_MAQ_S_W_PHR:
17197 case OPC_MAQ_SA_W_PHL:
17198 case OPC_MAQ_SA_W_PHR:
17199 case OPC_MULSA_W_PH:
17200 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17201 break;
17202 default: /* Invalid */
17203 MIPS_INVAL("MASK DPAW.PH");
17204 generate_exception(ctx, EXCP_RI);
17205 break;
17207 break;
17208 case OPC_INSV_DSP:
17209 op2 = MASK_INSV(ctx->opcode);
17210 switch (op2) {
17211 case OPC_INSV:
17212 check_dsp(ctx);
17214 TCGv t0, t1;
17216 if (rt == 0) {
17217 MIPS_DEBUG("NOP");
17218 break;
17221 t0 = tcg_temp_new();
17222 t1 = tcg_temp_new();
17224 gen_load_gpr(t0, rt);
17225 gen_load_gpr(t1, rs);
17227 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
17229 tcg_temp_free(t0);
17230 tcg_temp_free(t1);
17231 break;
17233 default: /* Invalid */
17234 MIPS_INVAL("MASK INSV");
17235 generate_exception(ctx, EXCP_RI);
17236 break;
17238 break;
17239 case OPC_APPEND_DSP:
17240 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17241 break;
17242 case OPC_EXTR_W_DSP:
17243 op2 = MASK_EXTR_W(ctx->opcode);
17244 switch (op2) {
17245 case OPC_EXTR_W:
17246 case OPC_EXTR_R_W:
17247 case OPC_EXTR_RS_W:
17248 case OPC_EXTR_S_H:
17249 case OPC_EXTRV_S_H:
17250 case OPC_EXTRV_W:
17251 case OPC_EXTRV_R_W:
17252 case OPC_EXTRV_RS_W:
17253 case OPC_EXTP:
17254 case OPC_EXTPV:
17255 case OPC_EXTPDP:
17256 case OPC_EXTPDPV:
17257 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17258 break;
17259 case OPC_RDDSP:
17260 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
17261 break;
17262 case OPC_SHILO:
17263 case OPC_SHILOV:
17264 case OPC_MTHLIP:
17265 case OPC_WRDSP:
17266 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17267 break;
17268 default: /* Invalid */
17269 MIPS_INVAL("MASK EXTR.W");
17270 generate_exception(ctx, EXCP_RI);
17271 break;
17273 break;
17274 #if defined(TARGET_MIPS64)
17275 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
17276 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
17277 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
17278 check_insn(ctx, INSN_LOONGSON2E);
17279 gen_loongson_integer(ctx, op1, rd, rs, rt);
17280 break;
17281 case OPC_ABSQ_S_QH_DSP:
17282 op2 = MASK_ABSQ_S_QH(ctx->opcode);
17283 switch (op2) {
17284 case OPC_PRECEQ_L_PWL:
17285 case OPC_PRECEQ_L_PWR:
17286 case OPC_PRECEQ_PW_QHL:
17287 case OPC_PRECEQ_PW_QHR:
17288 case OPC_PRECEQ_PW_QHLA:
17289 case OPC_PRECEQ_PW_QHRA:
17290 case OPC_PRECEQU_QH_OBL:
17291 case OPC_PRECEQU_QH_OBR:
17292 case OPC_PRECEQU_QH_OBLA:
17293 case OPC_PRECEQU_QH_OBRA:
17294 case OPC_PRECEU_QH_OBL:
17295 case OPC_PRECEU_QH_OBR:
17296 case OPC_PRECEU_QH_OBLA:
17297 case OPC_PRECEU_QH_OBRA:
17298 case OPC_ABSQ_S_OB:
17299 case OPC_ABSQ_S_PW:
17300 case OPC_ABSQ_S_QH:
17301 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17302 break;
17303 case OPC_REPL_OB:
17304 case OPC_REPL_PW:
17305 case OPC_REPL_QH:
17306 case OPC_REPLV_OB:
17307 case OPC_REPLV_PW:
17308 case OPC_REPLV_QH:
17309 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17310 break;
17311 default: /* Invalid */
17312 MIPS_INVAL("MASK ABSQ_S.QH");
17313 generate_exception(ctx, EXCP_RI);
17314 break;
17316 break;
17317 case OPC_ADDU_OB_DSP:
17318 op2 = MASK_ADDU_OB(ctx->opcode);
17319 switch (op2) {
17320 case OPC_RADDU_L_OB:
17321 case OPC_SUBQ_PW:
17322 case OPC_SUBQ_S_PW:
17323 case OPC_SUBQ_QH:
17324 case OPC_SUBQ_S_QH:
17325 case OPC_SUBU_OB:
17326 case OPC_SUBU_S_OB:
17327 case OPC_SUBU_QH:
17328 case OPC_SUBU_S_QH:
17329 case OPC_SUBUH_OB:
17330 case OPC_SUBUH_R_OB:
17331 case OPC_ADDQ_PW:
17332 case OPC_ADDQ_S_PW:
17333 case OPC_ADDQ_QH:
17334 case OPC_ADDQ_S_QH:
17335 case OPC_ADDU_OB:
17336 case OPC_ADDU_S_OB:
17337 case OPC_ADDU_QH:
17338 case OPC_ADDU_S_QH:
17339 case OPC_ADDUH_OB:
17340 case OPC_ADDUH_R_OB:
17341 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17342 break;
17343 case OPC_MULEQ_S_PW_QHL:
17344 case OPC_MULEQ_S_PW_QHR:
17345 case OPC_MULEU_S_QH_OBL:
17346 case OPC_MULEU_S_QH_OBR:
17347 case OPC_MULQ_RS_QH:
17348 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17349 break;
17350 default: /* Invalid */
17351 MIPS_INVAL("MASK ADDU.OB");
17352 generate_exception(ctx, EXCP_RI);
17353 break;
17355 break;
17356 case OPC_CMPU_EQ_OB_DSP:
17357 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
17358 switch (op2) {
17359 case OPC_PRECR_SRA_QH_PW:
17360 case OPC_PRECR_SRA_R_QH_PW:
17361 /* Return value is rt. */
17362 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17363 break;
17364 case OPC_PRECR_OB_QH:
17365 case OPC_PRECRQ_OB_QH:
17366 case OPC_PRECRQ_PW_L:
17367 case OPC_PRECRQ_QH_PW:
17368 case OPC_PRECRQ_RS_QH_PW:
17369 case OPC_PRECRQU_S_OB_QH:
17370 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17371 break;
17372 case OPC_CMPU_EQ_OB:
17373 case OPC_CMPU_LT_OB:
17374 case OPC_CMPU_LE_OB:
17375 case OPC_CMP_EQ_QH:
17376 case OPC_CMP_LT_QH:
17377 case OPC_CMP_LE_QH:
17378 case OPC_CMP_EQ_PW:
17379 case OPC_CMP_LT_PW:
17380 case OPC_CMP_LE_PW:
17381 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17382 break;
17383 case OPC_CMPGDU_EQ_OB:
17384 case OPC_CMPGDU_LT_OB:
17385 case OPC_CMPGDU_LE_OB:
17386 case OPC_CMPGU_EQ_OB:
17387 case OPC_CMPGU_LT_OB:
17388 case OPC_CMPGU_LE_OB:
17389 case OPC_PACKRL_PW:
17390 case OPC_PICK_OB:
17391 case OPC_PICK_PW:
17392 case OPC_PICK_QH:
17393 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17394 break;
17395 default: /* Invalid */
17396 MIPS_INVAL("MASK CMPU_EQ.OB");
17397 generate_exception(ctx, EXCP_RI);
17398 break;
17400 break;
17401 case OPC_DAPPEND_DSP:
17402 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17403 break;
17404 case OPC_DEXTR_W_DSP:
17405 op2 = MASK_DEXTR_W(ctx->opcode);
17406 switch (op2) {
17407 case OPC_DEXTP:
17408 case OPC_DEXTPDP:
17409 case OPC_DEXTPDPV:
17410 case OPC_DEXTPV:
17411 case OPC_DEXTR_L:
17412 case OPC_DEXTR_R_L:
17413 case OPC_DEXTR_RS_L:
17414 case OPC_DEXTR_W:
17415 case OPC_DEXTR_R_W:
17416 case OPC_DEXTR_RS_W:
17417 case OPC_DEXTR_S_H:
17418 case OPC_DEXTRV_L:
17419 case OPC_DEXTRV_R_L:
17420 case OPC_DEXTRV_RS_L:
17421 case OPC_DEXTRV_S_H:
17422 case OPC_DEXTRV_W:
17423 case OPC_DEXTRV_R_W:
17424 case OPC_DEXTRV_RS_W:
17425 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17426 break;
17427 case OPC_DMTHLIP:
17428 case OPC_DSHILO:
17429 case OPC_DSHILOV:
17430 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17431 break;
17432 default: /* Invalid */
17433 MIPS_INVAL("MASK EXTR.W");
17434 generate_exception(ctx, EXCP_RI);
17435 break;
17437 break;
17438 case OPC_DPAQ_W_QH_DSP:
17439 op2 = MASK_DPAQ_W_QH(ctx->opcode);
17440 switch (op2) {
17441 case OPC_DPAU_H_OBL:
17442 case OPC_DPAU_H_OBR:
17443 case OPC_DPSU_H_OBL:
17444 case OPC_DPSU_H_OBR:
17445 case OPC_DPA_W_QH:
17446 case OPC_DPAQ_S_W_QH:
17447 case OPC_DPS_W_QH:
17448 case OPC_DPSQ_S_W_QH:
17449 case OPC_MULSAQ_S_W_QH:
17450 case OPC_DPAQ_SA_L_PW:
17451 case OPC_DPSQ_SA_L_PW:
17452 case OPC_MULSAQ_S_L_PW:
17453 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17454 break;
17455 case OPC_MAQ_S_W_QHLL:
17456 case OPC_MAQ_S_W_QHLR:
17457 case OPC_MAQ_S_W_QHRL:
17458 case OPC_MAQ_S_W_QHRR:
17459 case OPC_MAQ_SA_W_QHLL:
17460 case OPC_MAQ_SA_W_QHLR:
17461 case OPC_MAQ_SA_W_QHRL:
17462 case OPC_MAQ_SA_W_QHRR:
17463 case OPC_MAQ_S_L_PWL:
17464 case OPC_MAQ_S_L_PWR:
17465 case OPC_DMADD:
17466 case OPC_DMADDU:
17467 case OPC_DMSUB:
17468 case OPC_DMSUBU:
17469 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17470 break;
17471 default: /* Invalid */
17472 MIPS_INVAL("MASK DPAQ.W.QH");
17473 generate_exception(ctx, EXCP_RI);
17474 break;
17476 break;
17477 case OPC_DINSV_DSP:
17478 op2 = MASK_INSV(ctx->opcode);
17479 switch (op2) {
17480 case OPC_DINSV:
17482 TCGv t0, t1;
17484 if (rt == 0) {
17485 MIPS_DEBUG("NOP");
17486 break;
17488 check_dsp(ctx);
17490 t0 = tcg_temp_new();
17491 t1 = tcg_temp_new();
17493 gen_load_gpr(t0, rt);
17494 gen_load_gpr(t1, rs);
17496 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
17498 tcg_temp_free(t0);
17499 tcg_temp_free(t1);
17500 break;
17502 default: /* Invalid */
17503 MIPS_INVAL("MASK DINSV");
17504 generate_exception(ctx, EXCP_RI);
17505 break;
17507 break;
17508 case OPC_SHLL_OB_DSP:
17509 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17510 break;
17511 #endif
17512 default: /* Invalid */
17513 MIPS_INVAL("special3_legacy");
17514 generate_exception(ctx, EXCP_RI);
17515 break;
17519 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
17521 int rs, rt, rd, sa;
17522 uint32_t op1, op2;
17524 rs = (ctx->opcode >> 21) & 0x1f;
17525 rt = (ctx->opcode >> 16) & 0x1f;
17526 rd = (ctx->opcode >> 11) & 0x1f;
17527 sa = (ctx->opcode >> 6) & 0x1f;
17529 op1 = MASK_SPECIAL3(ctx->opcode);
17530 switch (op1) {
17531 case OPC_EXT:
17532 case OPC_INS:
17533 check_insn(ctx, ISA_MIPS32R2);
17534 gen_bitops(ctx, op1, rt, rs, sa, rd);
17535 break;
17536 case OPC_BSHFL:
17537 op2 = MASK_BSHFL(ctx->opcode);
17538 switch (op2) {
17539 case OPC_ALIGN ... OPC_ALIGN_END:
17540 case OPC_BITSWAP:
17541 check_insn(ctx, ISA_MIPS32R6);
17542 decode_opc_special3_r6(env, ctx);
17543 break;
17544 default:
17545 check_insn(ctx, ISA_MIPS32R2);
17546 gen_bshfl(ctx, op2, rt, rd);
17547 break;
17549 break;
17550 #if defined(TARGET_MIPS64)
17551 case OPC_DEXTM ... OPC_DEXT:
17552 case OPC_DINSM ... OPC_DINS:
17553 check_insn(ctx, ISA_MIPS64R2);
17554 check_mips_64(ctx);
17555 gen_bitops(ctx, op1, rt, rs, sa, rd);
17556 break;
17557 case OPC_DBSHFL:
17558 op2 = MASK_DBSHFL(ctx->opcode);
17559 switch (op2) {
17560 case OPC_DALIGN ... OPC_DALIGN_END:
17561 case OPC_DBITSWAP:
17562 check_insn(ctx, ISA_MIPS32R6);
17563 decode_opc_special3_r6(env, ctx);
17564 break;
17565 default:
17566 check_insn(ctx, ISA_MIPS64R2);
17567 check_mips_64(ctx);
17568 op2 = MASK_DBSHFL(ctx->opcode);
17569 gen_bshfl(ctx, op2, rt, rd);
17570 break;
17572 break;
17573 #endif
17574 case OPC_RDHWR:
17575 gen_rdhwr(ctx, rt, rd);
17576 break;
17577 case OPC_FORK:
17578 check_insn(ctx, ASE_MT);
17580 TCGv t0 = tcg_temp_new();
17581 TCGv t1 = tcg_temp_new();
17583 gen_load_gpr(t0, rt);
17584 gen_load_gpr(t1, rs);
17585 gen_helper_fork(t0, t1);
17586 tcg_temp_free(t0);
17587 tcg_temp_free(t1);
17589 break;
17590 case OPC_YIELD:
17591 check_insn(ctx, ASE_MT);
17593 TCGv t0 = tcg_temp_new();
17595 save_cpu_state(ctx, 1);
17596 gen_load_gpr(t0, rs);
17597 gen_helper_yield(t0, cpu_env, t0);
17598 gen_store_gpr(t0, rd);
17599 tcg_temp_free(t0);
17601 break;
17602 default:
17603 if (ctx->insn_flags & ISA_MIPS32R6) {
17604 decode_opc_special3_r6(env, ctx);
17605 } else {
17606 decode_opc_special3_legacy(env, ctx);
17611 /* MIPS SIMD Architecture (MSA) */
17612 static inline int check_msa_access(DisasContext *ctx)
17614 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
17615 !(ctx->hflags & MIPS_HFLAG_F64))) {
17616 generate_exception(ctx, EXCP_RI);
17617 return 0;
17620 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
17621 if (ctx->insn_flags & ASE_MSA) {
17622 generate_exception(ctx, EXCP_MSADIS);
17623 return 0;
17624 } else {
17625 generate_exception(ctx, EXCP_RI);
17626 return 0;
17629 return 1;
17632 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
17634 /* generates tcg ops to check if any element is 0 */
17635 /* Note this function only works with MSA_WRLEN = 128 */
17636 uint64_t eval_zero_or_big = 0;
17637 uint64_t eval_big = 0;
17638 TCGv_i64 t0 = tcg_temp_new_i64();
17639 TCGv_i64 t1 = tcg_temp_new_i64();
17640 switch (df) {
17641 case DF_BYTE:
17642 eval_zero_or_big = 0x0101010101010101ULL;
17643 eval_big = 0x8080808080808080ULL;
17644 break;
17645 case DF_HALF:
17646 eval_zero_or_big = 0x0001000100010001ULL;
17647 eval_big = 0x8000800080008000ULL;
17648 break;
17649 case DF_WORD:
17650 eval_zero_or_big = 0x0000000100000001ULL;
17651 eval_big = 0x8000000080000000ULL;
17652 break;
17653 case DF_DOUBLE:
17654 eval_zero_or_big = 0x0000000000000001ULL;
17655 eval_big = 0x8000000000000000ULL;
17656 break;
17658 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
17659 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
17660 tcg_gen_andi_i64(t0, t0, eval_big);
17661 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
17662 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
17663 tcg_gen_andi_i64(t1, t1, eval_big);
17664 tcg_gen_or_i64(t0, t0, t1);
17665 /* if all bits are zero then all elements are not zero */
17666 /* if some bit is non-zero then some element is zero */
17667 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
17668 tcg_gen_trunc_i64_tl(tresult, t0);
17669 tcg_temp_free_i64(t0);
17670 tcg_temp_free_i64(t1);
17673 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
17675 uint8_t df = (ctx->opcode >> 21) & 0x3;
17676 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
17677 int64_t s16 = (int16_t)ctx->opcode;
17679 check_msa_access(ctx);
17681 if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
17682 MIPS_DEBUG("CTI in delay / forbidden slot");
17683 generate_exception(ctx, EXCP_RI);
17684 return;
17686 switch (op1) {
17687 case OPC_BZ_V:
17688 case OPC_BNZ_V:
17690 TCGv_i64 t0 = tcg_temp_new_i64();
17691 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
17692 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
17693 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
17694 tcg_gen_trunc_i64_tl(bcond, t0);
17695 tcg_temp_free_i64(t0);
17697 break;
17698 case OPC_BZ_B:
17699 case OPC_BZ_H:
17700 case OPC_BZ_W:
17701 case OPC_BZ_D:
17702 gen_check_zero_element(bcond, df, wt);
17703 break;
17704 case OPC_BNZ_B:
17705 case OPC_BNZ_H:
17706 case OPC_BNZ_W:
17707 case OPC_BNZ_D:
17708 gen_check_zero_element(bcond, df, wt);
17709 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
17710 break;
17713 ctx->btarget = ctx->pc + (s16 << 2) + 4;
17715 ctx->hflags |= MIPS_HFLAG_BC;
17716 ctx->hflags |= MIPS_HFLAG_BDS32;
17719 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
17721 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
17722 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
17723 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17724 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17726 TCGv_i32 twd = tcg_const_i32(wd);
17727 TCGv_i32 tws = tcg_const_i32(ws);
17728 TCGv_i32 ti8 = tcg_const_i32(i8);
17730 switch (MASK_MSA_I8(ctx->opcode)) {
17731 case OPC_ANDI_B:
17732 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
17733 break;
17734 case OPC_ORI_B:
17735 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
17736 break;
17737 case OPC_NORI_B:
17738 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
17739 break;
17740 case OPC_XORI_B:
17741 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
17742 break;
17743 case OPC_BMNZI_B:
17744 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
17745 break;
17746 case OPC_BMZI_B:
17747 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
17748 break;
17749 case OPC_BSELI_B:
17750 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
17751 break;
17752 case OPC_SHF_B:
17753 case OPC_SHF_H:
17754 case OPC_SHF_W:
17756 uint8_t df = (ctx->opcode >> 24) & 0x3;
17757 if (df == DF_DOUBLE) {
17758 generate_exception(ctx, EXCP_RI);
17759 } else {
17760 TCGv_i32 tdf = tcg_const_i32(df);
17761 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
17762 tcg_temp_free_i32(tdf);
17765 break;
17766 default:
17767 MIPS_INVAL("MSA instruction");
17768 generate_exception(ctx, EXCP_RI);
17769 break;
17772 tcg_temp_free_i32(twd);
17773 tcg_temp_free_i32(tws);
17774 tcg_temp_free_i32(ti8);
17777 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
17779 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
17780 uint8_t df = (ctx->opcode >> 21) & 0x3;
17781 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
17782 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
17783 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17784 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17786 TCGv_i32 tdf = tcg_const_i32(df);
17787 TCGv_i32 twd = tcg_const_i32(wd);
17788 TCGv_i32 tws = tcg_const_i32(ws);
17789 TCGv_i32 timm = tcg_temp_new_i32();
17790 tcg_gen_movi_i32(timm, u5);
17792 switch (MASK_MSA_I5(ctx->opcode)) {
17793 case OPC_ADDVI_df:
17794 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
17795 break;
17796 case OPC_SUBVI_df:
17797 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
17798 break;
17799 case OPC_MAXI_S_df:
17800 tcg_gen_movi_i32(timm, s5);
17801 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
17802 break;
17803 case OPC_MAXI_U_df:
17804 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
17805 break;
17806 case OPC_MINI_S_df:
17807 tcg_gen_movi_i32(timm, s5);
17808 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
17809 break;
17810 case OPC_MINI_U_df:
17811 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
17812 break;
17813 case OPC_CEQI_df:
17814 tcg_gen_movi_i32(timm, s5);
17815 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
17816 break;
17817 case OPC_CLTI_S_df:
17818 tcg_gen_movi_i32(timm, s5);
17819 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
17820 break;
17821 case OPC_CLTI_U_df:
17822 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
17823 break;
17824 case OPC_CLEI_S_df:
17825 tcg_gen_movi_i32(timm, s5);
17826 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
17827 break;
17828 case OPC_CLEI_U_df:
17829 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
17830 break;
17831 case OPC_LDI_df:
17833 int32_t s10 = sextract32(ctx->opcode, 11, 10);
17834 tcg_gen_movi_i32(timm, s10);
17835 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
17837 break;
17838 default:
17839 MIPS_INVAL("MSA instruction");
17840 generate_exception(ctx, EXCP_RI);
17841 break;
17844 tcg_temp_free_i32(tdf);
17845 tcg_temp_free_i32(twd);
17846 tcg_temp_free_i32(tws);
17847 tcg_temp_free_i32(timm);
17850 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
17852 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
17853 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
17854 uint32_t df = 0, m = 0;
17855 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17856 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17858 TCGv_i32 tdf;
17859 TCGv_i32 tm;
17860 TCGv_i32 twd;
17861 TCGv_i32 tws;
17863 if ((dfm & 0x40) == 0x00) {
17864 m = dfm & 0x3f;
17865 df = DF_DOUBLE;
17866 } else if ((dfm & 0x60) == 0x40) {
17867 m = dfm & 0x1f;
17868 df = DF_WORD;
17869 } else if ((dfm & 0x70) == 0x60) {
17870 m = dfm & 0x0f;
17871 df = DF_HALF;
17872 } else if ((dfm & 0x78) == 0x70) {
17873 m = dfm & 0x7;
17874 df = DF_BYTE;
17875 } else {
17876 generate_exception(ctx, EXCP_RI);
17877 return;
17880 tdf = tcg_const_i32(df);
17881 tm = tcg_const_i32(m);
17882 twd = tcg_const_i32(wd);
17883 tws = tcg_const_i32(ws);
17885 switch (MASK_MSA_BIT(ctx->opcode)) {
17886 case OPC_SLLI_df:
17887 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
17888 break;
17889 case OPC_SRAI_df:
17890 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
17891 break;
17892 case OPC_SRLI_df:
17893 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
17894 break;
17895 case OPC_BCLRI_df:
17896 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
17897 break;
17898 case OPC_BSETI_df:
17899 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
17900 break;
17901 case OPC_BNEGI_df:
17902 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
17903 break;
17904 case OPC_BINSLI_df:
17905 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
17906 break;
17907 case OPC_BINSRI_df:
17908 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
17909 break;
17910 case OPC_SAT_S_df:
17911 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
17912 break;
17913 case OPC_SAT_U_df:
17914 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
17915 break;
17916 case OPC_SRARI_df:
17917 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
17918 break;
17919 case OPC_SRLRI_df:
17920 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
17921 break;
17922 default:
17923 MIPS_INVAL("MSA instruction");
17924 generate_exception(ctx, EXCP_RI);
17925 break;
17928 tcg_temp_free_i32(tdf);
17929 tcg_temp_free_i32(tm);
17930 tcg_temp_free_i32(twd);
17931 tcg_temp_free_i32(tws);
17934 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
17936 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
17937 uint8_t df = (ctx->opcode >> 21) & 0x3;
17938 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
17939 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17940 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17942 TCGv_i32 tdf = tcg_const_i32(df);
17943 TCGv_i32 twd = tcg_const_i32(wd);
17944 TCGv_i32 tws = tcg_const_i32(ws);
17945 TCGv_i32 twt = tcg_const_i32(wt);
17947 switch (MASK_MSA_3R(ctx->opcode)) {
17948 case OPC_SLL_df:
17949 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
17950 break;
17951 case OPC_ADDV_df:
17952 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
17953 break;
17954 case OPC_CEQ_df:
17955 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
17956 break;
17957 case OPC_ADD_A_df:
17958 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
17959 break;
17960 case OPC_SUBS_S_df:
17961 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
17962 break;
17963 case OPC_MULV_df:
17964 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
17965 break;
17966 case OPC_SLD_df:
17967 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
17968 break;
17969 case OPC_VSHF_df:
17970 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
17971 break;
17972 case OPC_SRA_df:
17973 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
17974 break;
17975 case OPC_SUBV_df:
17976 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
17977 break;
17978 case OPC_ADDS_A_df:
17979 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
17980 break;
17981 case OPC_SUBS_U_df:
17982 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
17983 break;
17984 case OPC_MADDV_df:
17985 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
17986 break;
17987 case OPC_SPLAT_df:
17988 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
17989 break;
17990 case OPC_SRAR_df:
17991 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
17992 break;
17993 case OPC_SRL_df:
17994 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
17995 break;
17996 case OPC_MAX_S_df:
17997 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
17998 break;
17999 case OPC_CLT_S_df:
18000 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
18001 break;
18002 case OPC_ADDS_S_df:
18003 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
18004 break;
18005 case OPC_SUBSUS_U_df:
18006 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
18007 break;
18008 case OPC_MSUBV_df:
18009 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
18010 break;
18011 case OPC_PCKEV_df:
18012 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
18013 break;
18014 case OPC_SRLR_df:
18015 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
18016 break;
18017 case OPC_BCLR_df:
18018 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
18019 break;
18020 case OPC_MAX_U_df:
18021 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
18022 break;
18023 case OPC_CLT_U_df:
18024 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
18025 break;
18026 case OPC_ADDS_U_df:
18027 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
18028 break;
18029 case OPC_SUBSUU_S_df:
18030 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
18031 break;
18032 case OPC_PCKOD_df:
18033 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
18034 break;
18035 case OPC_BSET_df:
18036 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
18037 break;
18038 case OPC_MIN_S_df:
18039 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
18040 break;
18041 case OPC_CLE_S_df:
18042 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
18043 break;
18044 case OPC_AVE_S_df:
18045 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
18046 break;
18047 case OPC_ASUB_S_df:
18048 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
18049 break;
18050 case OPC_DIV_S_df:
18051 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
18052 break;
18053 case OPC_ILVL_df:
18054 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
18055 break;
18056 case OPC_BNEG_df:
18057 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
18058 break;
18059 case OPC_MIN_U_df:
18060 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
18061 break;
18062 case OPC_CLE_U_df:
18063 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
18064 break;
18065 case OPC_AVE_U_df:
18066 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
18067 break;
18068 case OPC_ASUB_U_df:
18069 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
18070 break;
18071 case OPC_DIV_U_df:
18072 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
18073 break;
18074 case OPC_ILVR_df:
18075 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
18076 break;
18077 case OPC_BINSL_df:
18078 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
18079 break;
18080 case OPC_MAX_A_df:
18081 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
18082 break;
18083 case OPC_AVER_S_df:
18084 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
18085 break;
18086 case OPC_MOD_S_df:
18087 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
18088 break;
18089 case OPC_ILVEV_df:
18090 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
18091 break;
18092 case OPC_BINSR_df:
18093 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
18094 break;
18095 case OPC_MIN_A_df:
18096 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
18097 break;
18098 case OPC_AVER_U_df:
18099 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
18100 break;
18101 case OPC_MOD_U_df:
18102 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
18103 break;
18104 case OPC_ILVOD_df:
18105 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
18106 break;
18108 case OPC_DOTP_S_df:
18109 case OPC_DOTP_U_df:
18110 case OPC_DPADD_S_df:
18111 case OPC_DPADD_U_df:
18112 case OPC_DPSUB_S_df:
18113 case OPC_HADD_S_df:
18114 case OPC_DPSUB_U_df:
18115 case OPC_HADD_U_df:
18116 case OPC_HSUB_S_df:
18117 case OPC_HSUB_U_df:
18118 if (df == DF_BYTE) {
18119 generate_exception(ctx, EXCP_RI);
18121 switch (MASK_MSA_3R(ctx->opcode)) {
18122 case OPC_DOTP_S_df:
18123 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
18124 break;
18125 case OPC_DOTP_U_df:
18126 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
18127 break;
18128 case OPC_DPADD_S_df:
18129 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
18130 break;
18131 case OPC_DPADD_U_df:
18132 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
18133 break;
18134 case OPC_DPSUB_S_df:
18135 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
18136 break;
18137 case OPC_HADD_S_df:
18138 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
18139 break;
18140 case OPC_DPSUB_U_df:
18141 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
18142 break;
18143 case OPC_HADD_U_df:
18144 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
18145 break;
18146 case OPC_HSUB_S_df:
18147 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
18148 break;
18149 case OPC_HSUB_U_df:
18150 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
18151 break;
18153 break;
18154 default:
18155 MIPS_INVAL("MSA instruction");
18156 generate_exception(ctx, EXCP_RI);
18157 break;
18159 tcg_temp_free_i32(twd);
18160 tcg_temp_free_i32(tws);
18161 tcg_temp_free_i32(twt);
18162 tcg_temp_free_i32(tdf);
18165 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
18167 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
18168 uint8_t source = (ctx->opcode >> 11) & 0x1f;
18169 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
18170 TCGv telm = tcg_temp_new();
18171 TCGv_i32 tsr = tcg_const_i32(source);
18172 TCGv_i32 tdt = tcg_const_i32(dest);
18174 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
18175 case OPC_CTCMSA:
18176 gen_load_gpr(telm, source);
18177 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
18178 break;
18179 case OPC_CFCMSA:
18180 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
18181 gen_store_gpr(telm, dest);
18182 break;
18183 case OPC_MOVE_V:
18184 gen_helper_msa_move_v(cpu_env, tdt, tsr);
18185 break;
18186 default:
18187 MIPS_INVAL("MSA instruction");
18188 generate_exception(ctx, EXCP_RI);
18189 break;
18192 tcg_temp_free(telm);
18193 tcg_temp_free_i32(tdt);
18194 tcg_temp_free_i32(tsr);
18197 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
18198 uint32_t n)
18200 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18201 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18202 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18204 TCGv_i32 tws = tcg_const_i32(ws);
18205 TCGv_i32 twd = tcg_const_i32(wd);
18206 TCGv_i32 tn = tcg_const_i32(n);
18207 TCGv_i32 tdf = tcg_const_i32(df);
18209 switch (MASK_MSA_ELM(ctx->opcode)) {
18210 case OPC_SLDI_df:
18211 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
18212 break;
18213 case OPC_SPLATI_df:
18214 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
18215 break;
18216 case OPC_INSVE_df:
18217 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
18218 break;
18219 case OPC_COPY_S_df:
18220 case OPC_COPY_U_df:
18221 case OPC_INSERT_df:
18222 #if !defined(TARGET_MIPS64)
18223 /* Double format valid only for MIPS64 */
18224 if (df == DF_DOUBLE) {
18225 generate_exception(ctx, EXCP_RI);
18226 break;
18228 #endif
18229 switch (MASK_MSA_ELM(ctx->opcode)) {
18230 case OPC_COPY_S_df:
18231 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
18232 break;
18233 case OPC_COPY_U_df:
18234 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
18235 break;
18236 case OPC_INSERT_df:
18237 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
18238 break;
18240 break;
18241 default:
18242 MIPS_INVAL("MSA instruction");
18243 generate_exception(ctx, EXCP_RI);
18245 tcg_temp_free_i32(twd);
18246 tcg_temp_free_i32(tws);
18247 tcg_temp_free_i32(tn);
18248 tcg_temp_free_i32(tdf);
18251 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
18253 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
18254 uint32_t df = 0, n = 0;
18256 if ((dfn & 0x30) == 0x00) {
18257 n = dfn & 0x0f;
18258 df = DF_BYTE;
18259 } else if ((dfn & 0x38) == 0x20) {
18260 n = dfn & 0x07;
18261 df = DF_HALF;
18262 } else if ((dfn & 0x3c) == 0x30) {
18263 n = dfn & 0x03;
18264 df = DF_WORD;
18265 } else if ((dfn & 0x3e) == 0x38) {
18266 n = dfn & 0x01;
18267 df = DF_DOUBLE;
18268 } else if (dfn == 0x3E) {
18269 /* CTCMSA, CFCMSA, MOVE.V */
18270 gen_msa_elm_3e(env, ctx);
18271 return;
18272 } else {
18273 generate_exception(ctx, EXCP_RI);
18274 return;
18277 gen_msa_elm_df(env, ctx, df, n);
18280 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
18282 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18283 uint8_t df = (ctx->opcode >> 21) & 0x1;
18284 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18285 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18286 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18288 TCGv_i32 twd = tcg_const_i32(wd);
18289 TCGv_i32 tws = tcg_const_i32(ws);
18290 TCGv_i32 twt = tcg_const_i32(wt);
18291 TCGv_i32 tdf = tcg_temp_new_i32();
18293 /* adjust df value for floating-point instruction */
18294 tcg_gen_movi_i32(tdf, df + 2);
18296 switch (MASK_MSA_3RF(ctx->opcode)) {
18297 case OPC_FCAF_df:
18298 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
18299 break;
18300 case OPC_FADD_df:
18301 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
18302 break;
18303 case OPC_FCUN_df:
18304 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
18305 break;
18306 case OPC_FSUB_df:
18307 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
18308 break;
18309 case OPC_FCOR_df:
18310 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
18311 break;
18312 case OPC_FCEQ_df:
18313 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
18314 break;
18315 case OPC_FMUL_df:
18316 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
18317 break;
18318 case OPC_FCUNE_df:
18319 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
18320 break;
18321 case OPC_FCUEQ_df:
18322 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
18323 break;
18324 case OPC_FDIV_df:
18325 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
18326 break;
18327 case OPC_FCNE_df:
18328 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
18329 break;
18330 case OPC_FCLT_df:
18331 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
18332 break;
18333 case OPC_FMADD_df:
18334 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
18335 break;
18336 case OPC_MUL_Q_df:
18337 tcg_gen_movi_i32(tdf, df + 1);
18338 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
18339 break;
18340 case OPC_FCULT_df:
18341 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
18342 break;
18343 case OPC_FMSUB_df:
18344 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
18345 break;
18346 case OPC_MADD_Q_df:
18347 tcg_gen_movi_i32(tdf, df + 1);
18348 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
18349 break;
18350 case OPC_FCLE_df:
18351 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
18352 break;
18353 case OPC_MSUB_Q_df:
18354 tcg_gen_movi_i32(tdf, df + 1);
18355 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
18356 break;
18357 case OPC_FCULE_df:
18358 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
18359 break;
18360 case OPC_FEXP2_df:
18361 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
18362 break;
18363 case OPC_FSAF_df:
18364 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
18365 break;
18366 case OPC_FEXDO_df:
18367 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
18368 break;
18369 case OPC_FSUN_df:
18370 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
18371 break;
18372 case OPC_FSOR_df:
18373 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
18374 break;
18375 case OPC_FSEQ_df:
18376 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
18377 break;
18378 case OPC_FTQ_df:
18379 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
18380 break;
18381 case OPC_FSUNE_df:
18382 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
18383 break;
18384 case OPC_FSUEQ_df:
18385 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
18386 break;
18387 case OPC_FSNE_df:
18388 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
18389 break;
18390 case OPC_FSLT_df:
18391 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
18392 break;
18393 case OPC_FMIN_df:
18394 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
18395 break;
18396 case OPC_MULR_Q_df:
18397 tcg_gen_movi_i32(tdf, df + 1);
18398 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
18399 break;
18400 case OPC_FSULT_df:
18401 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
18402 break;
18403 case OPC_FMIN_A_df:
18404 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
18405 break;
18406 case OPC_MADDR_Q_df:
18407 tcg_gen_movi_i32(tdf, df + 1);
18408 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
18409 break;
18410 case OPC_FSLE_df:
18411 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
18412 break;
18413 case OPC_FMAX_df:
18414 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
18415 break;
18416 case OPC_MSUBR_Q_df:
18417 tcg_gen_movi_i32(tdf, df + 1);
18418 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
18419 break;
18420 case OPC_FSULE_df:
18421 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
18422 break;
18423 case OPC_FMAX_A_df:
18424 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
18425 break;
18426 default:
18427 MIPS_INVAL("MSA instruction");
18428 generate_exception(ctx, EXCP_RI);
18429 break;
18432 tcg_temp_free_i32(twd);
18433 tcg_temp_free_i32(tws);
18434 tcg_temp_free_i32(twt);
18435 tcg_temp_free_i32(tdf);
18438 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
18440 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18441 (op & (0x7 << 18)))
18442 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18443 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18444 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18445 uint8_t df = (ctx->opcode >> 16) & 0x3;
18446 TCGv_i32 twd = tcg_const_i32(wd);
18447 TCGv_i32 tws = tcg_const_i32(ws);
18448 TCGv_i32 twt = tcg_const_i32(wt);
18449 TCGv_i32 tdf = tcg_const_i32(df);
18451 switch (MASK_MSA_2R(ctx->opcode)) {
18452 case OPC_FILL_df:
18453 #if !defined(TARGET_MIPS64)
18454 /* Double format valid only for MIPS64 */
18455 if (df == DF_DOUBLE) {
18456 generate_exception(ctx, EXCP_RI);
18457 break;
18459 #endif
18460 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
18461 break;
18462 case OPC_PCNT_df:
18463 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
18464 break;
18465 case OPC_NLOC_df:
18466 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
18467 break;
18468 case OPC_NLZC_df:
18469 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
18470 break;
18471 default:
18472 MIPS_INVAL("MSA instruction");
18473 generate_exception(ctx, EXCP_RI);
18474 break;
18477 tcg_temp_free_i32(twd);
18478 tcg_temp_free_i32(tws);
18479 tcg_temp_free_i32(twt);
18480 tcg_temp_free_i32(tdf);
18483 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
18485 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18486 (op & (0xf << 17)))
18487 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18488 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18489 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18490 uint8_t df = (ctx->opcode >> 16) & 0x1;
18491 TCGv_i32 twd = tcg_const_i32(wd);
18492 TCGv_i32 tws = tcg_const_i32(ws);
18493 TCGv_i32 twt = tcg_const_i32(wt);
18494 /* adjust df value for floating-point instruction */
18495 TCGv_i32 tdf = tcg_const_i32(df + 2);
18497 switch (MASK_MSA_2RF(ctx->opcode)) {
18498 case OPC_FCLASS_df:
18499 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
18500 break;
18501 case OPC_FTRUNC_S_df:
18502 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
18503 break;
18504 case OPC_FTRUNC_U_df:
18505 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
18506 break;
18507 case OPC_FSQRT_df:
18508 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
18509 break;
18510 case OPC_FRSQRT_df:
18511 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
18512 break;
18513 case OPC_FRCP_df:
18514 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
18515 break;
18516 case OPC_FRINT_df:
18517 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
18518 break;
18519 case OPC_FLOG2_df:
18520 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
18521 break;
18522 case OPC_FEXUPL_df:
18523 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
18524 break;
18525 case OPC_FEXUPR_df:
18526 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
18527 break;
18528 case OPC_FFQL_df:
18529 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
18530 break;
18531 case OPC_FFQR_df:
18532 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
18533 break;
18534 case OPC_FTINT_S_df:
18535 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
18536 break;
18537 case OPC_FTINT_U_df:
18538 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
18539 break;
18540 case OPC_FFINT_S_df:
18541 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
18542 break;
18543 case OPC_FFINT_U_df:
18544 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
18545 break;
18548 tcg_temp_free_i32(twd);
18549 tcg_temp_free_i32(tws);
18550 tcg_temp_free_i32(twt);
18551 tcg_temp_free_i32(tdf);
18554 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
18556 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
18557 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18558 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18559 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18560 TCGv_i32 twd = tcg_const_i32(wd);
18561 TCGv_i32 tws = tcg_const_i32(ws);
18562 TCGv_i32 twt = tcg_const_i32(wt);
18564 switch (MASK_MSA_VEC(ctx->opcode)) {
18565 case OPC_AND_V:
18566 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
18567 break;
18568 case OPC_OR_V:
18569 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
18570 break;
18571 case OPC_NOR_V:
18572 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
18573 break;
18574 case OPC_XOR_V:
18575 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
18576 break;
18577 case OPC_BMNZ_V:
18578 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
18579 break;
18580 case OPC_BMZ_V:
18581 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
18582 break;
18583 case OPC_BSEL_V:
18584 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
18585 break;
18586 default:
18587 MIPS_INVAL("MSA instruction");
18588 generate_exception(ctx, EXCP_RI);
18589 break;
18592 tcg_temp_free_i32(twd);
18593 tcg_temp_free_i32(tws);
18594 tcg_temp_free_i32(twt);
18597 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
18599 switch (MASK_MSA_VEC(ctx->opcode)) {
18600 case OPC_AND_V:
18601 case OPC_OR_V:
18602 case OPC_NOR_V:
18603 case OPC_XOR_V:
18604 case OPC_BMNZ_V:
18605 case OPC_BMZ_V:
18606 case OPC_BSEL_V:
18607 gen_msa_vec_v(env, ctx);
18608 break;
18609 case OPC_MSA_2R:
18610 gen_msa_2r(env, ctx);
18611 break;
18612 case OPC_MSA_2RF:
18613 gen_msa_2rf(env, ctx);
18614 break;
18615 default:
18616 MIPS_INVAL("MSA instruction");
18617 generate_exception(ctx, EXCP_RI);
18618 break;
18622 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
18624 uint32_t opcode = ctx->opcode;
18625 check_insn(ctx, ASE_MSA);
18626 check_msa_access(ctx);
18628 switch (MASK_MSA_MINOR(opcode)) {
18629 case OPC_MSA_I8_00:
18630 case OPC_MSA_I8_01:
18631 case OPC_MSA_I8_02:
18632 gen_msa_i8(env, ctx);
18633 break;
18634 case OPC_MSA_I5_06:
18635 case OPC_MSA_I5_07:
18636 gen_msa_i5(env, ctx);
18637 break;
18638 case OPC_MSA_BIT_09:
18639 case OPC_MSA_BIT_0A:
18640 gen_msa_bit(env, ctx);
18641 break;
18642 case OPC_MSA_3R_0D:
18643 case OPC_MSA_3R_0E:
18644 case OPC_MSA_3R_0F:
18645 case OPC_MSA_3R_10:
18646 case OPC_MSA_3R_11:
18647 case OPC_MSA_3R_12:
18648 case OPC_MSA_3R_13:
18649 case OPC_MSA_3R_14:
18650 case OPC_MSA_3R_15:
18651 gen_msa_3r(env, ctx);
18652 break;
18653 case OPC_MSA_ELM:
18654 gen_msa_elm(env, ctx);
18655 break;
18656 case OPC_MSA_3RF_1A:
18657 case OPC_MSA_3RF_1B:
18658 case OPC_MSA_3RF_1C:
18659 gen_msa_3rf(env, ctx);
18660 break;
18661 case OPC_MSA_VEC:
18662 gen_msa_vec(env, ctx);
18663 break;
18664 case OPC_LD_B:
18665 case OPC_LD_H:
18666 case OPC_LD_W:
18667 case OPC_LD_D:
18668 case OPC_ST_B:
18669 case OPC_ST_H:
18670 case OPC_ST_W:
18671 case OPC_ST_D:
18673 int32_t s10 = sextract32(ctx->opcode, 16, 10);
18674 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
18675 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18676 uint8_t df = (ctx->opcode >> 0) & 0x3;
18678 TCGv_i32 twd = tcg_const_i32(wd);
18679 TCGv taddr = tcg_temp_new();
18680 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
18682 switch (MASK_MSA_MINOR(opcode)) {
18683 case OPC_LD_B:
18684 gen_helper_msa_ld_b(cpu_env, twd, taddr);
18685 break;
18686 case OPC_LD_H:
18687 gen_helper_msa_ld_h(cpu_env, twd, taddr);
18688 break;
18689 case OPC_LD_W:
18690 gen_helper_msa_ld_w(cpu_env, twd, taddr);
18691 break;
18692 case OPC_LD_D:
18693 gen_helper_msa_ld_d(cpu_env, twd, taddr);
18694 break;
18695 case OPC_ST_B:
18696 gen_helper_msa_st_b(cpu_env, twd, taddr);
18697 break;
18698 case OPC_ST_H:
18699 gen_helper_msa_st_h(cpu_env, twd, taddr);
18700 break;
18701 case OPC_ST_W:
18702 gen_helper_msa_st_w(cpu_env, twd, taddr);
18703 break;
18704 case OPC_ST_D:
18705 gen_helper_msa_st_d(cpu_env, twd, taddr);
18706 break;
18709 tcg_temp_free_i32(twd);
18710 tcg_temp_free(taddr);
18712 break;
18713 default:
18714 MIPS_INVAL("MSA instruction");
18715 generate_exception(ctx, EXCP_RI);
18716 break;
18721 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
18723 int32_t offset;
18724 int rs, rt, rd, sa;
18725 uint32_t op, op1;
18726 int16_t imm;
18728 /* make sure instructions are on a word boundary */
18729 if (ctx->pc & 0x3) {
18730 env->CP0_BadVAddr = ctx->pc;
18731 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
18732 ctx->bstate = BS_STOP;
18733 return;
18736 /* Handle blikely not taken case */
18737 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
18738 TCGLabel *l1 = gen_new_label();
18740 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
18741 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
18742 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
18743 gen_goto_tb(ctx, 1, ctx->pc + 4);
18744 gen_set_label(l1);
18747 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
18748 tcg_gen_debug_insn_start(ctx->pc);
18751 op = MASK_OP_MAJOR(ctx->opcode);
18752 rs = (ctx->opcode >> 21) & 0x1f;
18753 rt = (ctx->opcode >> 16) & 0x1f;
18754 rd = (ctx->opcode >> 11) & 0x1f;
18755 sa = (ctx->opcode >> 6) & 0x1f;
18756 imm = (int16_t)ctx->opcode;
18757 switch (op) {
18758 case OPC_SPECIAL:
18759 decode_opc_special(env, ctx);
18760 break;
18761 case OPC_SPECIAL2:
18762 decode_opc_special2_legacy(env, ctx);
18763 break;
18764 case OPC_SPECIAL3:
18765 decode_opc_special3(env, ctx);
18766 break;
18767 case OPC_REGIMM:
18768 op1 = MASK_REGIMM(ctx->opcode);
18769 switch (op1) {
18770 case OPC_BLTZL: /* REGIMM branches */
18771 case OPC_BGEZL:
18772 case OPC_BLTZALL:
18773 case OPC_BGEZALL:
18774 check_insn(ctx, ISA_MIPS2);
18775 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18776 /* Fallthrough */
18777 case OPC_BLTZ:
18778 case OPC_BGEZ:
18779 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
18780 break;
18781 case OPC_BLTZAL:
18782 case OPC_BGEZAL:
18783 if (ctx->insn_flags & ISA_MIPS32R6) {
18784 if (rs == 0) {
18785 /* OPC_NAL, OPC_BAL */
18786 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
18787 } else {
18788 generate_exception(ctx, EXCP_RI);
18790 } else {
18791 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
18793 break;
18794 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
18795 case OPC_TNEI:
18796 check_insn(ctx, ISA_MIPS2);
18797 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18798 gen_trap(ctx, op1, rs, -1, imm);
18799 break;
18800 case OPC_SYNCI:
18801 check_insn(ctx, ISA_MIPS32R2);
18802 /* Break the TB to be able to sync copied instructions
18803 immediately */
18804 ctx->bstate = BS_STOP;
18805 break;
18806 case OPC_BPOSGE32: /* MIPS DSP branch */
18807 #if defined(TARGET_MIPS64)
18808 case OPC_BPOSGE64:
18809 #endif
18810 check_dsp(ctx);
18811 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
18812 break;
18813 #if defined(TARGET_MIPS64)
18814 case OPC_DAHI:
18815 check_insn(ctx, ISA_MIPS32R6);
18816 check_mips_64(ctx);
18817 if (rs != 0) {
18818 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
18820 MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm);
18821 break;
18822 case OPC_DATI:
18823 check_insn(ctx, ISA_MIPS32R6);
18824 check_mips_64(ctx);
18825 if (rs != 0) {
18826 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
18828 MIPS_DEBUG("dati %s, %04x", regnames[rs], imm);
18829 break;
18830 #endif
18831 default: /* Invalid */
18832 MIPS_INVAL("regimm");
18833 generate_exception(ctx, EXCP_RI);
18834 break;
18836 break;
18837 case OPC_CP0:
18838 check_cp0_enabled(ctx);
18839 op1 = MASK_CP0(ctx->opcode);
18840 switch (op1) {
18841 case OPC_MFC0:
18842 case OPC_MTC0:
18843 case OPC_MFTR:
18844 case OPC_MTTR:
18845 case OPC_MFHC0:
18846 case OPC_MTHC0:
18847 #if defined(TARGET_MIPS64)
18848 case OPC_DMFC0:
18849 case OPC_DMTC0:
18850 #endif
18851 #ifndef CONFIG_USER_ONLY
18852 gen_cp0(env, ctx, op1, rt, rd);
18853 #endif /* !CONFIG_USER_ONLY */
18854 break;
18855 case OPC_C0_FIRST ... OPC_C0_LAST:
18856 #ifndef CONFIG_USER_ONLY
18857 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
18858 #endif /* !CONFIG_USER_ONLY */
18859 break;
18860 case OPC_MFMC0:
18861 #ifndef CONFIG_USER_ONLY
18863 uint32_t op2;
18864 TCGv t0 = tcg_temp_new();
18866 op2 = MASK_MFMC0(ctx->opcode);
18867 switch (op2) {
18868 case OPC_DMT:
18869 check_insn(ctx, ASE_MT);
18870 gen_helper_dmt(t0);
18871 gen_store_gpr(t0, rt);
18872 break;
18873 case OPC_EMT:
18874 check_insn(ctx, ASE_MT);
18875 gen_helper_emt(t0);
18876 gen_store_gpr(t0, rt);
18877 break;
18878 case OPC_DVPE:
18879 check_insn(ctx, ASE_MT);
18880 gen_helper_dvpe(t0, cpu_env);
18881 gen_store_gpr(t0, rt);
18882 break;
18883 case OPC_EVPE:
18884 check_insn(ctx, ASE_MT);
18885 gen_helper_evpe(t0, cpu_env);
18886 gen_store_gpr(t0, rt);
18887 break;
18888 case OPC_DI:
18889 check_insn(ctx, ISA_MIPS32R2);
18890 save_cpu_state(ctx, 1);
18891 gen_helper_di(t0, cpu_env);
18892 gen_store_gpr(t0, rt);
18893 /* Stop translation as we may have switched
18894 the execution mode. */
18895 ctx->bstate = BS_STOP;
18896 break;
18897 case OPC_EI:
18898 check_insn(ctx, ISA_MIPS32R2);
18899 save_cpu_state(ctx, 1);
18900 gen_helper_ei(t0, cpu_env);
18901 gen_store_gpr(t0, rt);
18902 /* Stop translation as we may have switched
18903 the execution mode. */
18904 ctx->bstate = BS_STOP;
18905 break;
18906 default: /* Invalid */
18907 MIPS_INVAL("mfmc0");
18908 generate_exception(ctx, EXCP_RI);
18909 break;
18911 tcg_temp_free(t0);
18913 #endif /* !CONFIG_USER_ONLY */
18914 break;
18915 case OPC_RDPGPR:
18916 check_insn(ctx, ISA_MIPS32R2);
18917 gen_load_srsgpr(rt, rd);
18918 break;
18919 case OPC_WRPGPR:
18920 check_insn(ctx, ISA_MIPS32R2);
18921 gen_store_srsgpr(rt, rd);
18922 break;
18923 default:
18924 MIPS_INVAL("cp0");
18925 generate_exception(ctx, EXCP_RI);
18926 break;
18928 break;
18929 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
18930 if (ctx->insn_flags & ISA_MIPS32R6) {
18931 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
18932 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18933 } else {
18934 /* OPC_ADDI */
18935 /* Arithmetic with immediate opcode */
18936 gen_arith_imm(ctx, op, rt, rs, imm);
18938 break;
18939 case OPC_ADDIU:
18940 gen_arith_imm(ctx, op, rt, rs, imm);
18941 break;
18942 case OPC_SLTI: /* Set on less than with immediate opcode */
18943 case OPC_SLTIU:
18944 gen_slt_imm(ctx, op, rt, rs, imm);
18945 break;
18946 case OPC_ANDI: /* Arithmetic with immediate opcode */
18947 case OPC_LUI: /* OPC_AUI */
18948 case OPC_ORI:
18949 case OPC_XORI:
18950 gen_logic_imm(ctx, op, rt, rs, imm);
18951 break;
18952 case OPC_J ... OPC_JAL: /* Jump */
18953 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
18954 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
18955 break;
18956 /* Branch */
18957 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
18958 if (ctx->insn_flags & ISA_MIPS32R6) {
18959 if (rt == 0) {
18960 generate_exception(ctx, EXCP_RI);
18961 break;
18963 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
18964 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18965 } else {
18966 /* OPC_BLEZL */
18967 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18969 break;
18970 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
18971 if (ctx->insn_flags & ISA_MIPS32R6) {
18972 if (rt == 0) {
18973 generate_exception(ctx, EXCP_RI);
18974 break;
18976 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
18977 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18978 } else {
18979 /* OPC_BGTZL */
18980 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18982 break;
18983 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
18984 if (rt == 0) {
18985 /* OPC_BLEZ */
18986 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18987 } else {
18988 check_insn(ctx, ISA_MIPS32R6);
18989 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
18990 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18992 break;
18993 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
18994 if (rt == 0) {
18995 /* OPC_BGTZ */
18996 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18997 } else {
18998 check_insn(ctx, ISA_MIPS32R6);
18999 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
19000 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19002 break;
19003 case OPC_BEQL:
19004 case OPC_BNEL:
19005 check_insn(ctx, ISA_MIPS2);
19006 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19007 /* Fallthrough */
19008 case OPC_BEQ:
19009 case OPC_BNE:
19010 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19011 break;
19012 case OPC_LL: /* Load and stores */
19013 check_insn(ctx, ISA_MIPS2);
19014 /* Fallthrough */
19015 case OPC_LWL:
19016 case OPC_LWR:
19017 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19018 /* Fallthrough */
19019 case OPC_LB ... OPC_LH:
19020 case OPC_LW ... OPC_LHU:
19021 gen_ld(ctx, op, rt, rs, imm);
19022 break;
19023 case OPC_SWL:
19024 case OPC_SWR:
19025 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19026 /* fall through */
19027 case OPC_SB ... OPC_SH:
19028 case OPC_SW:
19029 gen_st(ctx, op, rt, rs, imm);
19030 break;
19031 case OPC_SC:
19032 check_insn(ctx, ISA_MIPS2);
19033 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19034 gen_st_cond(ctx, op, rt, rs, imm);
19035 break;
19036 case OPC_CACHE:
19037 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19038 check_cp0_enabled(ctx);
19039 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
19040 /* Treat as NOP. */
19041 break;
19042 case OPC_PREF:
19043 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19044 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
19045 /* Treat as NOP. */
19046 break;
19048 /* Floating point (COP1). */
19049 case OPC_LWC1:
19050 case OPC_LDC1:
19051 case OPC_SWC1:
19052 case OPC_SDC1:
19053 gen_cop1_ldst(ctx, op, rt, rs, imm);
19054 break;
19056 case OPC_CP1:
19057 op1 = MASK_CP1(ctx->opcode);
19059 switch (op1) {
19060 case OPC_MFHC1:
19061 case OPC_MTHC1:
19062 check_cp1_enabled(ctx);
19063 check_insn(ctx, ISA_MIPS32R2);
19064 case OPC_MFC1:
19065 case OPC_CFC1:
19066 case OPC_MTC1:
19067 case OPC_CTC1:
19068 check_cp1_enabled(ctx);
19069 gen_cp1(ctx, op1, rt, rd);
19070 break;
19071 #if defined(TARGET_MIPS64)
19072 case OPC_DMFC1:
19073 case OPC_DMTC1:
19074 check_cp1_enabled(ctx);
19075 check_insn(ctx, ISA_MIPS3);
19076 check_mips_64(ctx);
19077 gen_cp1(ctx, op1, rt, rd);
19078 break;
19079 #endif
19080 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
19081 check_cp1_enabled(ctx);
19082 if (ctx->insn_flags & ISA_MIPS32R6) {
19083 /* OPC_BC1EQZ */
19084 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19085 rt, imm << 2);
19086 } else {
19087 /* OPC_BC1ANY2 */
19088 check_cop1x(ctx);
19089 check_insn(ctx, ASE_MIPS3D);
19090 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19091 (rt >> 2) & 0x7, imm << 2);
19093 break;
19094 case OPC_BC1NEZ:
19095 check_cp1_enabled(ctx);
19096 check_insn(ctx, ISA_MIPS32R6);
19097 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19098 rt, imm << 2);
19099 break;
19100 case OPC_BC1ANY4:
19101 check_cp1_enabled(ctx);
19102 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19103 check_cop1x(ctx);
19104 check_insn(ctx, ASE_MIPS3D);
19105 /* fall through */
19106 case OPC_BC1:
19107 check_cp1_enabled(ctx);
19108 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19109 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19110 (rt >> 2) & 0x7, imm << 2);
19111 break;
19112 case OPC_PS_FMT:
19113 check_cp1_enabled(ctx);
19114 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19115 /* fall through */
19116 case OPC_S_FMT:
19117 case OPC_D_FMT:
19118 check_cp1_enabled(ctx);
19119 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19120 (imm >> 8) & 0x7);
19121 break;
19122 case OPC_W_FMT:
19123 case OPC_L_FMT:
19125 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
19126 check_cp1_enabled(ctx);
19127 if (ctx->insn_flags & ISA_MIPS32R6) {
19128 switch (r6_op) {
19129 case R6_OPC_CMP_AF_S:
19130 case R6_OPC_CMP_UN_S:
19131 case R6_OPC_CMP_EQ_S:
19132 case R6_OPC_CMP_UEQ_S:
19133 case R6_OPC_CMP_LT_S:
19134 case R6_OPC_CMP_ULT_S:
19135 case R6_OPC_CMP_LE_S:
19136 case R6_OPC_CMP_ULE_S:
19137 case R6_OPC_CMP_SAF_S:
19138 case R6_OPC_CMP_SUN_S:
19139 case R6_OPC_CMP_SEQ_S:
19140 case R6_OPC_CMP_SEUQ_S:
19141 case R6_OPC_CMP_SLT_S:
19142 case R6_OPC_CMP_SULT_S:
19143 case R6_OPC_CMP_SLE_S:
19144 case R6_OPC_CMP_SULE_S:
19145 case R6_OPC_CMP_OR_S:
19146 case R6_OPC_CMP_UNE_S:
19147 case R6_OPC_CMP_NE_S:
19148 case R6_OPC_CMP_SOR_S:
19149 case R6_OPC_CMP_SUNE_S:
19150 case R6_OPC_CMP_SNE_S:
19151 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19152 break;
19153 case R6_OPC_CMP_AF_D:
19154 case R6_OPC_CMP_UN_D:
19155 case R6_OPC_CMP_EQ_D:
19156 case R6_OPC_CMP_UEQ_D:
19157 case R6_OPC_CMP_LT_D:
19158 case R6_OPC_CMP_ULT_D:
19159 case R6_OPC_CMP_LE_D:
19160 case R6_OPC_CMP_ULE_D:
19161 case R6_OPC_CMP_SAF_D:
19162 case R6_OPC_CMP_SUN_D:
19163 case R6_OPC_CMP_SEQ_D:
19164 case R6_OPC_CMP_SEUQ_D:
19165 case R6_OPC_CMP_SLT_D:
19166 case R6_OPC_CMP_SULT_D:
19167 case R6_OPC_CMP_SLE_D:
19168 case R6_OPC_CMP_SULE_D:
19169 case R6_OPC_CMP_OR_D:
19170 case R6_OPC_CMP_UNE_D:
19171 case R6_OPC_CMP_NE_D:
19172 case R6_OPC_CMP_SOR_D:
19173 case R6_OPC_CMP_SUNE_D:
19174 case R6_OPC_CMP_SNE_D:
19175 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19176 break;
19177 default:
19178 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
19179 rt, rd, sa, (imm >> 8) & 0x7);
19181 break;
19183 } else {
19184 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19185 (imm >> 8) & 0x7);
19187 break;
19189 case OPC_BZ_V:
19190 case OPC_BNZ_V:
19191 case OPC_BZ_B:
19192 case OPC_BZ_H:
19193 case OPC_BZ_W:
19194 case OPC_BZ_D:
19195 case OPC_BNZ_B:
19196 case OPC_BNZ_H:
19197 case OPC_BNZ_W:
19198 case OPC_BNZ_D:
19199 check_insn(ctx, ASE_MSA);
19200 gen_msa_branch(env, ctx, op1);
19201 break;
19202 default:
19203 MIPS_INVAL("cp1");
19204 generate_exception(ctx, EXCP_RI);
19205 break;
19207 break;
19209 /* Compact branches [R6] and COP2 [non-R6] */
19210 case OPC_BC: /* OPC_LWC2 */
19211 case OPC_BALC: /* OPC_SWC2 */
19212 if (ctx->insn_flags & ISA_MIPS32R6) {
19213 /* OPC_BC, OPC_BALC */
19214 gen_compute_compact_branch(ctx, op, 0, 0,
19215 sextract32(ctx->opcode << 2, 0, 28));
19216 } else {
19217 /* OPC_LWC2, OPC_SWC2 */
19218 /* COP2: Not implemented. */
19219 generate_exception_err(ctx, EXCP_CpU, 2);
19221 break;
19222 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
19223 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
19224 if (ctx->insn_flags & ISA_MIPS32R6) {
19225 if (rs != 0) {
19226 /* OPC_BEQZC, OPC_BNEZC */
19227 gen_compute_compact_branch(ctx, op, rs, 0,
19228 sextract32(ctx->opcode << 2, 0, 23));
19229 } else {
19230 /* OPC_JIC, OPC_JIALC */
19231 gen_compute_compact_branch(ctx, op, 0, rt, imm);
19233 } else {
19234 /* OPC_LWC2, OPC_SWC2 */
19235 /* COP2: Not implemented. */
19236 generate_exception_err(ctx, EXCP_CpU, 2);
19238 break;
19239 case OPC_CP2:
19240 check_insn(ctx, INSN_LOONGSON2F);
19241 /* Note that these instructions use different fields. */
19242 gen_loongson_multimedia(ctx, sa, rd, rt);
19243 break;
19245 case OPC_CP3:
19246 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19247 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19248 check_cp1_enabled(ctx);
19249 op1 = MASK_CP3(ctx->opcode);
19250 switch (op1) {
19251 case OPC_LUXC1:
19252 case OPC_SUXC1:
19253 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19254 /* Fallthrough */
19255 case OPC_LWXC1:
19256 case OPC_LDXC1:
19257 case OPC_SWXC1:
19258 case OPC_SDXC1:
19259 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19260 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
19261 break;
19262 case OPC_PREFX:
19263 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19264 /* Treat as NOP. */
19265 break;
19266 case OPC_ALNV_PS:
19267 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19268 /* Fallthrough */
19269 case OPC_MADD_S:
19270 case OPC_MADD_D:
19271 case OPC_MADD_PS:
19272 case OPC_MSUB_S:
19273 case OPC_MSUB_D:
19274 case OPC_MSUB_PS:
19275 case OPC_NMADD_S:
19276 case OPC_NMADD_D:
19277 case OPC_NMADD_PS:
19278 case OPC_NMSUB_S:
19279 case OPC_NMSUB_D:
19280 case OPC_NMSUB_PS:
19281 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19282 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
19283 break;
19284 default:
19285 MIPS_INVAL("cp3");
19286 generate_exception (ctx, EXCP_RI);
19287 break;
19289 } else {
19290 generate_exception_err(ctx, EXCP_CpU, 1);
19292 break;
19294 #if defined(TARGET_MIPS64)
19295 /* MIPS64 opcodes */
19296 case OPC_LDL ... OPC_LDR:
19297 case OPC_LLD:
19298 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19299 /* fall through */
19300 case OPC_LWU:
19301 case OPC_LD:
19302 check_insn(ctx, ISA_MIPS3);
19303 check_mips_64(ctx);
19304 gen_ld(ctx, op, rt, rs, imm);
19305 break;
19306 case OPC_SDL ... OPC_SDR:
19307 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19308 /* fall through */
19309 case OPC_SD:
19310 check_insn(ctx, ISA_MIPS3);
19311 check_mips_64(ctx);
19312 gen_st(ctx, op, rt, rs, imm);
19313 break;
19314 case OPC_SCD:
19315 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19316 check_insn(ctx, ISA_MIPS3);
19317 check_mips_64(ctx);
19318 gen_st_cond(ctx, op, rt, rs, imm);
19319 break;
19320 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
19321 if (ctx->insn_flags & ISA_MIPS32R6) {
19322 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
19323 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19324 } else {
19325 /* OPC_DADDI */
19326 check_insn(ctx, ISA_MIPS3);
19327 check_mips_64(ctx);
19328 gen_arith_imm(ctx, op, rt, rs, imm);
19330 break;
19331 case OPC_DADDIU:
19332 check_insn(ctx, ISA_MIPS3);
19333 check_mips_64(ctx);
19334 gen_arith_imm(ctx, op, rt, rs, imm);
19335 break;
19336 #else
19337 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
19338 if (ctx->insn_flags & ISA_MIPS32R6) {
19339 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19340 } else {
19341 MIPS_INVAL("major opcode");
19342 generate_exception(ctx, EXCP_RI);
19344 break;
19345 #endif
19346 case OPC_DAUI: /* OPC_JALX */
19347 if (ctx->insn_flags & ISA_MIPS32R6) {
19348 #if defined(TARGET_MIPS64)
19349 /* OPC_DAUI */
19350 check_mips_64(ctx);
19351 if (rt != 0) {
19352 TCGv t0 = tcg_temp_new();
19353 gen_load_gpr(t0, rs);
19354 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
19355 tcg_temp_free(t0);
19357 MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm);
19358 #else
19359 generate_exception(ctx, EXCP_RI);
19360 MIPS_INVAL("major opcode");
19361 #endif
19362 } else {
19363 /* OPC_JALX */
19364 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
19365 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19366 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19368 break;
19369 case OPC_MSA: /* OPC_MDMX */
19370 /* MDMX: Not implemented. */
19371 gen_msa(env, ctx);
19372 break;
19373 case OPC_PCREL:
19374 check_insn(ctx, ISA_MIPS32R6);
19375 gen_pcrel(ctx, rs, imm);
19376 break;
19377 default: /* Invalid */
19378 MIPS_INVAL("major opcode");
19379 generate_exception(ctx, EXCP_RI);
19380 break;
19384 static inline void
19385 gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
19386 bool search_pc)
19388 CPUState *cs = CPU(cpu);
19389 CPUMIPSState *env = &cpu->env;
19390 DisasContext ctx;
19391 target_ulong pc_start;
19392 target_ulong next_page_start;
19393 CPUBreakpoint *bp;
19394 int j, lj = -1;
19395 int num_insns;
19396 int max_insns;
19397 int insn_bytes;
19398 int is_slot;
19400 if (search_pc)
19401 qemu_log("search pc %d\n", search_pc);
19403 pc_start = tb->pc;
19404 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
19405 ctx.pc = pc_start;
19406 ctx.saved_pc = -1;
19407 ctx.singlestep_enabled = cs->singlestep_enabled;
19408 ctx.insn_flags = env->insn_flags;
19409 ctx.CP0_Config1 = env->CP0_Config1;
19410 ctx.tb = tb;
19411 ctx.bstate = BS_NONE;
19412 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
19413 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
19414 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
19415 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
19416 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
19417 ctx.PAMask = env->PAMask;
19418 ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
19419 ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
19420 /* Restore delay slot state from the tb context. */
19421 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
19422 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
19423 restore_cpu_state(env, &ctx);
19424 #ifdef CONFIG_USER_ONLY
19425 ctx.mem_idx = MIPS_HFLAG_UM;
19426 #else
19427 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
19428 #endif
19429 ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
19430 MO_UNALN : MO_ALIGN;
19431 num_insns = 0;
19432 max_insns = tb->cflags & CF_COUNT_MASK;
19433 if (max_insns == 0)
19434 max_insns = CF_COUNT_MASK;
19435 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
19436 gen_tb_start(tb);
19437 while (ctx.bstate == BS_NONE) {
19438 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
19439 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
19440 if (bp->pc == ctx.pc) {
19441 save_cpu_state(&ctx, 1);
19442 ctx.bstate = BS_BRANCH;
19443 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
19444 /* Include the breakpoint location or the tb won't
19445 * be flushed when it must be. */
19446 ctx.pc += 4;
19447 goto done_generating;
19452 if (search_pc) {
19453 j = tcg_op_buf_count();
19454 if (lj < j) {
19455 lj++;
19456 while (lj < j)
19457 tcg_ctx.gen_opc_instr_start[lj++] = 0;
19459 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
19460 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
19461 gen_opc_btarget[lj] = ctx.btarget;
19462 tcg_ctx.gen_opc_instr_start[lj] = 1;
19463 tcg_ctx.gen_opc_icount[lj] = num_insns;
19465 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
19466 gen_io_start();
19468 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
19469 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
19470 ctx.opcode = cpu_ldl_code(env, ctx.pc);
19471 insn_bytes = 4;
19472 decode_opc(env, &ctx);
19473 } else if (ctx.insn_flags & ASE_MICROMIPS) {
19474 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19475 insn_bytes = decode_micromips_opc(env, &ctx);
19476 } else if (ctx.insn_flags & ASE_MIPS16) {
19477 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19478 insn_bytes = decode_mips16_opc(env, &ctx);
19479 } else {
19480 generate_exception(&ctx, EXCP_RI);
19481 ctx.bstate = BS_STOP;
19482 break;
19485 if (ctx.hflags & MIPS_HFLAG_BMASK) {
19486 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
19487 MIPS_HFLAG_FBNSLOT))) {
19488 /* force to generate branch as there is neither delay nor
19489 forbidden slot */
19490 is_slot = 1;
19493 if (is_slot) {
19494 gen_branch(&ctx, insn_bytes);
19496 ctx.pc += insn_bytes;
19498 num_insns++;
19500 /* Execute a branch and its delay slot as a single instruction.
19501 This is what GDB expects and is consistent with what the
19502 hardware does (e.g. if a delay slot instruction faults, the
19503 reported PC is the PC of the branch). */
19504 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
19505 break;
19508 if (ctx.pc >= next_page_start) {
19509 break;
19512 if (tcg_op_buf_full()) {
19513 break;
19516 if (num_insns >= max_insns)
19517 break;
19519 if (singlestep)
19520 break;
19522 if (tb->cflags & CF_LAST_IO) {
19523 gen_io_end();
19525 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
19526 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
19527 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
19528 } else {
19529 switch (ctx.bstate) {
19530 case BS_STOP:
19531 gen_goto_tb(&ctx, 0, ctx.pc);
19532 break;
19533 case BS_NONE:
19534 save_cpu_state(&ctx, 0);
19535 gen_goto_tb(&ctx, 0, ctx.pc);
19536 break;
19537 case BS_EXCP:
19538 tcg_gen_exit_tb(0);
19539 break;
19540 case BS_BRANCH:
19541 default:
19542 break;
19545 done_generating:
19546 gen_tb_end(tb, num_insns);
19548 if (search_pc) {
19549 j = tcg_op_buf_count();
19550 lj++;
19551 while (lj <= j)
19552 tcg_ctx.gen_opc_instr_start[lj++] = 0;
19553 } else {
19554 tb->size = ctx.pc - pc_start;
19555 tb->icount = num_insns;
19557 #ifdef DEBUG_DISAS
19558 LOG_DISAS("\n");
19559 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
19560 qemu_log("IN: %s\n", lookup_symbol(pc_start));
19561 log_target_disas(env, pc_start, ctx.pc - pc_start, 0);
19562 qemu_log("\n");
19564 #endif
19567 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
19569 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
19572 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
19574 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
19577 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
19578 int flags)
19580 int i;
19581 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
19583 #define printfpr(fp) \
19584 do { \
19585 if (is_fpu64) \
19586 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19587 " fd:%13g fs:%13g psu: %13g\n", \
19588 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
19589 (double)(fp)->fd, \
19590 (double)(fp)->fs[FP_ENDIAN_IDX], \
19591 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
19592 else { \
19593 fpr_t tmp; \
19594 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
19595 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
19596 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19597 " fd:%13g fs:%13g psu:%13g\n", \
19598 tmp.w[FP_ENDIAN_IDX], tmp.d, \
19599 (double)tmp.fd, \
19600 (double)tmp.fs[FP_ENDIAN_IDX], \
19601 (double)tmp.fs[!FP_ENDIAN_IDX]); \
19603 } while(0)
19606 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
19607 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
19608 get_float_exception_flags(&env->active_fpu.fp_status));
19609 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
19610 fpu_fprintf(f, "%3s: ", fregnames[i]);
19611 printfpr(&env->active_fpu.fpr[i]);
19614 #undef printfpr
19617 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
19618 /* Debug help: The architecture requires 32bit code to maintain proper
19619 sign-extended values on 64bit machines. */
19621 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
19623 static void
19624 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
19625 fprintf_function cpu_fprintf,
19626 int flags)
19628 int i;
19630 if (!SIGN_EXT_P(env->active_tc.PC))
19631 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
19632 if (!SIGN_EXT_P(env->active_tc.HI[0]))
19633 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
19634 if (!SIGN_EXT_P(env->active_tc.LO[0]))
19635 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
19636 if (!SIGN_EXT_P(env->btarget))
19637 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
19639 for (i = 0; i < 32; i++) {
19640 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
19641 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
19644 if (!SIGN_EXT_P(env->CP0_EPC))
19645 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
19646 if (!SIGN_EXT_P(env->lladdr))
19647 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
19649 #endif
19651 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
19652 int flags)
19654 MIPSCPU *cpu = MIPS_CPU(cs);
19655 CPUMIPSState *env = &cpu->env;
19656 int i;
19658 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
19659 " LO=0x" TARGET_FMT_lx " ds %04x "
19660 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
19661 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
19662 env->hflags, env->btarget, env->bcond);
19663 for (i = 0; i < 32; i++) {
19664 if ((i & 3) == 0)
19665 cpu_fprintf(f, "GPR%02d:", i);
19666 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
19667 if ((i & 3) == 3)
19668 cpu_fprintf(f, "\n");
19671 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
19672 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
19673 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
19674 PRIx64 "\n",
19675 env->CP0_Config0, env->CP0_Config1, env->lladdr);
19676 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
19677 env->CP0_Config2, env->CP0_Config3);
19678 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
19679 env->CP0_Config4, env->CP0_Config5);
19680 if (env->hflags & MIPS_HFLAG_FPU)
19681 fpu_dump_state(env, f, cpu_fprintf, flags);
19682 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
19683 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
19684 #endif
19687 void mips_tcg_init(void)
19689 int i;
19690 static int inited;
19692 /* Initialize various static tables. */
19693 if (inited)
19694 return;
19696 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
19697 TCGV_UNUSED(cpu_gpr[0]);
19698 for (i = 1; i < 32; i++)
19699 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
19700 offsetof(CPUMIPSState, active_tc.gpr[i]),
19701 regnames[i]);
19703 for (i = 0; i < 32; i++) {
19704 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
19705 msa_wr_d[i * 2] =
19706 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]);
19707 /* The scalar floating-point unit (FPU) registers are mapped on
19708 * the MSA vector registers. */
19709 fpu_f64[i] = msa_wr_d[i * 2];
19710 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
19711 msa_wr_d[i * 2 + 1] =
19712 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + 1]);
19715 cpu_PC = tcg_global_mem_new(TCG_AREG0,
19716 offsetof(CPUMIPSState, active_tc.PC), "PC");
19717 for (i = 0; i < MIPS_DSP_ACC; i++) {
19718 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
19719 offsetof(CPUMIPSState, active_tc.HI[i]),
19720 regnames_HI[i]);
19721 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
19722 offsetof(CPUMIPSState, active_tc.LO[i]),
19723 regnames_LO[i]);
19725 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
19726 offsetof(CPUMIPSState, active_tc.DSPControl),
19727 "DSPControl");
19728 bcond = tcg_global_mem_new(TCG_AREG0,
19729 offsetof(CPUMIPSState, bcond), "bcond");
19730 btarget = tcg_global_mem_new(TCG_AREG0,
19731 offsetof(CPUMIPSState, btarget), "btarget");
19732 hflags = tcg_global_mem_new_i32(TCG_AREG0,
19733 offsetof(CPUMIPSState, hflags), "hflags");
19735 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
19736 offsetof(CPUMIPSState, active_fpu.fcr0),
19737 "fcr0");
19738 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
19739 offsetof(CPUMIPSState, active_fpu.fcr31),
19740 "fcr31");
19742 inited = 1;
19745 #include "translate_init.c"
19747 MIPSCPU *cpu_mips_init(const char *cpu_model)
19749 MIPSCPU *cpu;
19750 CPUMIPSState *env;
19751 const mips_def_t *def;
19753 def = cpu_mips_find_by_name(cpu_model);
19754 if (!def)
19755 return NULL;
19756 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
19757 env = &cpu->env;
19758 env->cpu_model = def;
19760 #ifndef CONFIG_USER_ONLY
19761 mmu_init(env, def);
19762 #endif
19763 fpu_init(env, def);
19764 mvp_init(env, def);
19766 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
19768 return cpu;
19771 void cpu_state_reset(CPUMIPSState *env)
19773 MIPSCPU *cpu = mips_env_get_cpu(env);
19774 CPUState *cs = CPU(cpu);
19776 /* Reset registers to their default values */
19777 env->CP0_PRid = env->cpu_model->CP0_PRid;
19778 env->CP0_Config0 = env->cpu_model->CP0_Config0;
19779 #ifdef TARGET_WORDS_BIGENDIAN
19780 env->CP0_Config0 |= (1 << CP0C0_BE);
19781 #endif
19782 env->CP0_Config1 = env->cpu_model->CP0_Config1;
19783 env->CP0_Config2 = env->cpu_model->CP0_Config2;
19784 env->CP0_Config3 = env->cpu_model->CP0_Config3;
19785 env->CP0_Config4 = env->cpu_model->CP0_Config4;
19786 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
19787 env->CP0_Config5 = env->cpu_model->CP0_Config5;
19788 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
19789 env->CP0_Config6 = env->cpu_model->CP0_Config6;
19790 env->CP0_Config7 = env->cpu_model->CP0_Config7;
19791 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
19792 << env->cpu_model->CP0_LLAddr_shift;
19793 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
19794 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
19795 env->CCRes = env->cpu_model->CCRes;
19796 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
19797 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
19798 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
19799 env->current_tc = 0;
19800 env->SEGBITS = env->cpu_model->SEGBITS;
19801 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
19802 #if defined(TARGET_MIPS64)
19803 if (env->cpu_model->insn_flags & ISA_MIPS3) {
19804 env->SEGMask |= 3ULL << 62;
19806 #endif
19807 env->PABITS = env->cpu_model->PABITS;
19808 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
19809 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
19810 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
19811 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
19812 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
19813 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
19814 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
19815 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
19816 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
19817 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
19818 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
19819 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
19820 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
19821 env->msair = env->cpu_model->MSAIR;
19822 env->insn_flags = env->cpu_model->insn_flags;
19824 #if defined(CONFIG_USER_ONLY)
19825 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
19826 # ifdef TARGET_MIPS64
19827 /* Enable 64-bit register mode. */
19828 env->CP0_Status |= (1 << CP0St_PX);
19829 # endif
19830 # ifdef TARGET_ABI_MIPSN64
19831 /* Enable 64-bit address mode. */
19832 env->CP0_Status |= (1 << CP0St_UX);
19833 # endif
19834 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
19835 hardware registers. */
19836 env->CP0_HWREna |= 0x0000000F;
19837 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
19838 env->CP0_Status |= (1 << CP0St_CU1);
19840 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
19841 env->CP0_Status |= (1 << CP0St_MX);
19843 # if defined(TARGET_MIPS64)
19844 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
19845 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
19846 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
19847 env->CP0_Status |= (1 << CP0St_FR);
19849 # endif
19850 #else
19851 if (env->hflags & MIPS_HFLAG_BMASK) {
19852 /* If the exception was raised from a delay slot,
19853 come back to the jump. */
19854 env->CP0_ErrorEPC = (env->active_tc.PC
19855 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
19856 } else {
19857 env->CP0_ErrorEPC = env->active_tc.PC;
19859 env->active_tc.PC = (int32_t)0xBFC00000;
19860 env->CP0_Random = env->tlb->nb_tlb - 1;
19861 env->tlb->tlb_in_use = env->tlb->nb_tlb;
19862 env->CP0_Wired = 0;
19863 env->CP0_EBase = (cs->cpu_index & 0x3FF);
19864 if (kvm_enabled()) {
19865 env->CP0_EBase |= 0x40000000;
19866 } else {
19867 env->CP0_EBase |= 0x80000000;
19869 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
19870 /* vectored interrupts not implemented, timer on int 7,
19871 no performance counters. */
19872 env->CP0_IntCtl = 0xe0000000;
19874 int i;
19876 for (i = 0; i < 7; i++) {
19877 env->CP0_WatchLo[i] = 0;
19878 env->CP0_WatchHi[i] = 0x80000000;
19880 env->CP0_WatchLo[7] = 0;
19881 env->CP0_WatchHi[7] = 0;
19883 /* Count register increments in debug mode, EJTAG version 1 */
19884 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
19886 cpu_mips_store_count(env, 1);
19888 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
19889 int i;
19891 /* Only TC0 on VPE 0 starts as active. */
19892 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
19893 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
19894 env->tcs[i].CP0_TCHalt = 1;
19896 env->active_tc.CP0_TCHalt = 1;
19897 cs->halted = 1;
19899 if (cs->cpu_index == 0) {
19900 /* VPE0 starts up enabled. */
19901 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
19902 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
19904 /* TC0 starts up unhalted. */
19905 cs->halted = 0;
19906 env->active_tc.CP0_TCHalt = 0;
19907 env->tcs[0].CP0_TCHalt = 0;
19908 /* With thread 0 active. */
19909 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
19910 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
19913 #endif
19914 if ((env->insn_flags & ISA_MIPS32R6) &&
19915 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
19916 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
19917 env->CP0_Status |= (1 << CP0St_FR);
19920 /* MSA */
19921 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
19922 msa_reset(env);
19925 compute_hflags(env);
19926 restore_rounding_mode(env);
19927 restore_flush_mode(env);
19928 restore_pamask(env);
19929 cs->exception_index = EXCP_NONE;
19932 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
19934 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
19935 env->hflags &= ~MIPS_HFLAG_BMASK;
19936 env->hflags |= gen_opc_hflags[pc_pos];
19937 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
19938 case MIPS_HFLAG_BR:
19939 break;
19940 case MIPS_HFLAG_BC:
19941 case MIPS_HFLAG_BL:
19942 case MIPS_HFLAG_B:
19943 env->btarget = gen_opc_btarget[pc_pos];
19944 break;