block: Forbid bdrv_set_aio_context outside BQL
[qemu.git] / target-mips / translate.c
blobca51149872a208f9413488673285b77e2f02212c
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_MTC0 = (0x04 << 21) | OPC_CP0,
872 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
873 OPC_MFTR = (0x08 << 21) | OPC_CP0,
874 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
875 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
876 OPC_MTTR = (0x0C << 21) | OPC_CP0,
877 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
878 OPC_C0 = (0x10 << 21) | OPC_CP0,
879 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
880 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
883 /* MFMC0 opcodes */
884 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
886 enum {
887 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
888 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
889 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
890 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
891 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
892 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
895 /* Coprocessor 0 (with rs == C0) */
896 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
898 enum {
899 OPC_TLBR = 0x01 | OPC_C0,
900 OPC_TLBWI = 0x02 | OPC_C0,
901 OPC_TLBINV = 0x03 | OPC_C0,
902 OPC_TLBINVF = 0x04 | OPC_C0,
903 OPC_TLBWR = 0x06 | OPC_C0,
904 OPC_TLBP = 0x08 | OPC_C0,
905 OPC_RFE = 0x10 | OPC_C0,
906 OPC_ERET = 0x18 | OPC_C0,
907 OPC_DERET = 0x1F | OPC_C0,
908 OPC_WAIT = 0x20 | OPC_C0,
911 /* Coprocessor 1 (rs field) */
912 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
914 /* Values for the fmt field in FP instructions */
915 enum {
916 /* 0 - 15 are reserved */
917 FMT_S = 16, /* single fp */
918 FMT_D = 17, /* double fp */
919 FMT_E = 18, /* extended fp */
920 FMT_Q = 19, /* quad fp */
921 FMT_W = 20, /* 32-bit fixed */
922 FMT_L = 21, /* 64-bit fixed */
923 FMT_PS = 22, /* paired single fp */
924 /* 23 - 31 are reserved */
927 enum {
928 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
929 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
930 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
931 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
932 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
933 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
934 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
935 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
936 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
937 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
938 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
939 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
940 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
941 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
942 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
943 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
944 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
945 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
946 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
947 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
948 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
949 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
950 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
951 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
952 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
953 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
954 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
955 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
956 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
957 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
960 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
961 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
963 enum {
964 OPC_BC1F = (0x00 << 16) | OPC_BC1,
965 OPC_BC1T = (0x01 << 16) | OPC_BC1,
966 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
967 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
970 enum {
971 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
972 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
975 enum {
976 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
977 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
980 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
982 enum {
983 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
984 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
985 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
986 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
987 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
988 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
989 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
990 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
991 OPC_BC2 = (0x08 << 21) | OPC_CP2,
992 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
993 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
996 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
998 enum {
999 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1000 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1001 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1002 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1003 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1004 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1005 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1006 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1008 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1009 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1010 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1011 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1012 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1013 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1014 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1015 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1018 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1019 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1020 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1021 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1022 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1023 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1024 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1026 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1027 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1028 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1029 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1030 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1031 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1032 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1033 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1035 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1036 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1037 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1038 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1039 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1040 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1042 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1043 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1044 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1045 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1046 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1047 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1049 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1050 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1051 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1052 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1053 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1054 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1056 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1057 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1058 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1059 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1060 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1061 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1063 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1064 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1065 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1066 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1067 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1068 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1070 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1071 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1072 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1073 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1074 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1075 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1077 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1078 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1079 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1080 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1081 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1082 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1084 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1085 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1086 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1087 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1088 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1089 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1093 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1095 enum {
1096 OPC_LWXC1 = 0x00 | OPC_CP3,
1097 OPC_LDXC1 = 0x01 | OPC_CP3,
1098 OPC_LUXC1 = 0x05 | OPC_CP3,
1099 OPC_SWXC1 = 0x08 | OPC_CP3,
1100 OPC_SDXC1 = 0x09 | OPC_CP3,
1101 OPC_SUXC1 = 0x0D | OPC_CP3,
1102 OPC_PREFX = 0x0F | OPC_CP3,
1103 OPC_ALNV_PS = 0x1E | OPC_CP3,
1104 OPC_MADD_S = 0x20 | OPC_CP3,
1105 OPC_MADD_D = 0x21 | OPC_CP3,
1106 OPC_MADD_PS = 0x26 | OPC_CP3,
1107 OPC_MSUB_S = 0x28 | OPC_CP3,
1108 OPC_MSUB_D = 0x29 | OPC_CP3,
1109 OPC_MSUB_PS = 0x2E | OPC_CP3,
1110 OPC_NMADD_S = 0x30 | OPC_CP3,
1111 OPC_NMADD_D = 0x31 | OPC_CP3,
1112 OPC_NMADD_PS= 0x36 | OPC_CP3,
1113 OPC_NMSUB_S = 0x38 | OPC_CP3,
1114 OPC_NMSUB_D = 0x39 | OPC_CP3,
1115 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1118 /* MSA Opcodes */
1119 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1120 enum {
1121 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1122 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1123 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1124 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1125 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1126 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1127 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1128 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1129 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1130 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1131 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1132 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1133 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1134 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1135 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1136 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1137 OPC_MSA_ELM = 0x19 | OPC_MSA,
1138 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1139 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1140 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1141 OPC_MSA_VEC = 0x1E | OPC_MSA,
1143 /* MI10 instruction */
1144 OPC_LD_B = (0x20) | OPC_MSA,
1145 OPC_LD_H = (0x21) | OPC_MSA,
1146 OPC_LD_W = (0x22) | OPC_MSA,
1147 OPC_LD_D = (0x23) | OPC_MSA,
1148 OPC_ST_B = (0x24) | OPC_MSA,
1149 OPC_ST_H = (0x25) | OPC_MSA,
1150 OPC_ST_W = (0x26) | OPC_MSA,
1151 OPC_ST_D = (0x27) | OPC_MSA,
1154 enum {
1155 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1156 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1157 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1158 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1159 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1160 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1161 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1162 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1163 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1164 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1165 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1166 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1167 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1169 /* I8 instruction */
1170 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1171 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1172 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1173 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1174 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1175 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1176 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1177 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1178 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1179 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1181 /* VEC/2R/2RF instruction */
1182 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1183 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1184 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1185 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1186 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1187 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1188 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1190 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1191 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1193 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1194 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1195 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1196 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1197 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1199 /* 2RF instruction df(bit 16) = _w, _d */
1200 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1201 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1202 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1203 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1204 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1205 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1206 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1207 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1208 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1209 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1210 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1211 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1212 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1213 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1214 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1215 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1217 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1218 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1219 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1220 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1221 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1222 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1223 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1224 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1225 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1226 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1227 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1228 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1229 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1230 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1231 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1232 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1233 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1234 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1235 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1236 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1237 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1238 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1239 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1240 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1241 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1242 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1243 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1244 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1245 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1246 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1247 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1248 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1249 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1250 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1251 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1252 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1253 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1254 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1255 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1256 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1257 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1258 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1259 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1260 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1261 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1262 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1263 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1264 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1265 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1266 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1267 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1268 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1269 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1270 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1271 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1272 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1273 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1274 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1275 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1276 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1277 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1278 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1279 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1280 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1282 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1283 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1284 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1285 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1286 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1287 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1288 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1289 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1290 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1291 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1293 /* 3RF instruction _df(bit 21) = _w, _d */
1294 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1295 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1296 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1297 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1298 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1299 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1300 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1301 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1302 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1303 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1304 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1305 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1306 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1307 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1308 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1309 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1310 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1311 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1312 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1313 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1314 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1315 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1316 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1317 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1318 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1319 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1320 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1321 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1322 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1323 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1324 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1325 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1326 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1327 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1328 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1329 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1330 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1331 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1332 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1333 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1334 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1336 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1337 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1338 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1339 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1340 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1341 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1342 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1343 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1344 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1345 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1346 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1347 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1348 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1351 /* global register indices */
1352 static TCGv_ptr cpu_env;
1353 static TCGv cpu_gpr[32], cpu_PC;
1354 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1355 static TCGv cpu_dspctrl, btarget, bcond;
1356 static TCGv_i32 hflags;
1357 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1358 static TCGv_i64 fpu_f64[32];
1359 static TCGv_i64 msa_wr_d[64];
1361 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
1362 static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
1364 #include "exec/gen-icount.h"
1366 #define gen_helper_0e0i(name, arg) do { \
1367 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1368 gen_helper_##name(cpu_env, helper_tmp); \
1369 tcg_temp_free_i32(helper_tmp); \
1370 } while(0)
1372 #define gen_helper_0e1i(name, arg1, arg2) do { \
1373 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1374 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1375 tcg_temp_free_i32(helper_tmp); \
1376 } while(0)
1378 #define gen_helper_1e0i(name, ret, arg1) do { \
1379 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1380 gen_helper_##name(ret, cpu_env, helper_tmp); \
1381 tcg_temp_free_i32(helper_tmp); \
1382 } while(0)
1384 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1385 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1386 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1387 tcg_temp_free_i32(helper_tmp); \
1388 } while(0)
1390 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1391 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1392 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1393 tcg_temp_free_i32(helper_tmp); \
1394 } while(0)
1396 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1397 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1398 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1399 tcg_temp_free_i32(helper_tmp); \
1400 } while(0)
1402 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1403 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1404 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1405 tcg_temp_free_i32(helper_tmp); \
1406 } while(0)
1408 typedef struct DisasContext {
1409 struct TranslationBlock *tb;
1410 target_ulong pc, saved_pc;
1411 uint32_t opcode;
1412 int singlestep_enabled;
1413 int insn_flags;
1414 int32_t CP0_Config1;
1415 /* Routine used to access memory */
1416 int mem_idx;
1417 uint32_t hflags, saved_hflags;
1418 int bstate;
1419 target_ulong btarget;
1420 bool ulri;
1421 int kscrexist;
1422 bool rxi;
1423 int ie;
1424 bool bi;
1425 bool bp;
1426 } DisasContext;
1428 enum {
1429 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1430 * exception condition */
1431 BS_STOP = 1, /* We want to stop translation for any reason */
1432 BS_BRANCH = 2, /* We reached a branch condition */
1433 BS_EXCP = 3, /* We reached an exception condition */
1436 static const char * const regnames[] = {
1437 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1438 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1439 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1440 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1443 static const char * const regnames_HI[] = {
1444 "HI0", "HI1", "HI2", "HI3",
1447 static const char * const regnames_LO[] = {
1448 "LO0", "LO1", "LO2", "LO3",
1451 static const char * const fregnames[] = {
1452 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1453 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1454 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1455 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1458 static const char * const msaregnames[] = {
1459 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1460 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1461 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1462 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1463 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1464 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1465 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1466 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1467 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1468 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1469 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1470 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1471 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1472 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1473 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1474 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1477 #define MIPS_DEBUG(fmt, ...) \
1478 do { \
1479 if (MIPS_DEBUG_DISAS) { \
1480 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1481 TARGET_FMT_lx ": %08x " fmt "\n", \
1482 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
1484 } while (0)
1486 #define LOG_DISAS(...) \
1487 do { \
1488 if (MIPS_DEBUG_DISAS) { \
1489 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1491 } while (0)
1493 #define MIPS_INVAL(op) \
1494 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
1495 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
1497 /* General purpose registers moves. */
1498 static inline void gen_load_gpr (TCGv t, int reg)
1500 if (reg == 0)
1501 tcg_gen_movi_tl(t, 0);
1502 else
1503 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1506 static inline void gen_store_gpr (TCGv t, int reg)
1508 if (reg != 0)
1509 tcg_gen_mov_tl(cpu_gpr[reg], t);
1512 /* Moves to/from shadow registers. */
1513 static inline void gen_load_srsgpr (int from, int to)
1515 TCGv t0 = tcg_temp_new();
1517 if (from == 0)
1518 tcg_gen_movi_tl(t0, 0);
1519 else {
1520 TCGv_i32 t2 = tcg_temp_new_i32();
1521 TCGv_ptr addr = tcg_temp_new_ptr();
1523 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1524 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1525 tcg_gen_andi_i32(t2, t2, 0xf);
1526 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1527 tcg_gen_ext_i32_ptr(addr, t2);
1528 tcg_gen_add_ptr(addr, cpu_env, addr);
1530 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1531 tcg_temp_free_ptr(addr);
1532 tcg_temp_free_i32(t2);
1534 gen_store_gpr(t0, to);
1535 tcg_temp_free(t0);
1538 static inline void gen_store_srsgpr (int from, int to)
1540 if (to != 0) {
1541 TCGv t0 = tcg_temp_new();
1542 TCGv_i32 t2 = tcg_temp_new_i32();
1543 TCGv_ptr addr = tcg_temp_new_ptr();
1545 gen_load_gpr(t0, from);
1546 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1547 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1548 tcg_gen_andi_i32(t2, t2, 0xf);
1549 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1550 tcg_gen_ext_i32_ptr(addr, t2);
1551 tcg_gen_add_ptr(addr, cpu_env, addr);
1553 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1554 tcg_temp_free_ptr(addr);
1555 tcg_temp_free_i32(t2);
1556 tcg_temp_free(t0);
1560 /* Floating point register moves. */
1561 static void gen_load_fpr32(TCGv_i32 t, int reg)
1563 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
1566 static void gen_store_fpr32(TCGv_i32 t, int reg)
1568 TCGv_i64 t64 = tcg_temp_new_i64();
1569 tcg_gen_extu_i32_i64(t64, t);
1570 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1571 tcg_temp_free_i64(t64);
1574 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1576 if (ctx->hflags & MIPS_HFLAG_F64) {
1577 TCGv_i64 t64 = tcg_temp_new_i64();
1578 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
1579 tcg_gen_trunc_i64_i32(t, t64);
1580 tcg_temp_free_i64(t64);
1581 } else {
1582 gen_load_fpr32(t, reg | 1);
1586 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1588 if (ctx->hflags & MIPS_HFLAG_F64) {
1589 TCGv_i64 t64 = tcg_temp_new_i64();
1590 tcg_gen_extu_i32_i64(t64, t);
1591 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1592 tcg_temp_free_i64(t64);
1593 } else {
1594 gen_store_fpr32(t, reg | 1);
1598 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1600 if (ctx->hflags & MIPS_HFLAG_F64) {
1601 tcg_gen_mov_i64(t, fpu_f64[reg]);
1602 } else {
1603 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1607 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1609 if (ctx->hflags & MIPS_HFLAG_F64) {
1610 tcg_gen_mov_i64(fpu_f64[reg], t);
1611 } else {
1612 TCGv_i64 t0;
1613 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1614 t0 = tcg_temp_new_i64();
1615 tcg_gen_shri_i64(t0, t, 32);
1616 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1617 tcg_temp_free_i64(t0);
1621 static inline int get_fp_bit (int cc)
1623 if (cc)
1624 return 24 + cc;
1625 else
1626 return 23;
1629 /* Tests */
1630 static inline void gen_save_pc(target_ulong pc)
1632 tcg_gen_movi_tl(cpu_PC, pc);
1635 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
1637 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1638 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1639 gen_save_pc(ctx->pc);
1640 ctx->saved_pc = ctx->pc;
1642 if (ctx->hflags != ctx->saved_hflags) {
1643 tcg_gen_movi_i32(hflags, ctx->hflags);
1644 ctx->saved_hflags = ctx->hflags;
1645 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1646 case MIPS_HFLAG_BR:
1647 break;
1648 case MIPS_HFLAG_BC:
1649 case MIPS_HFLAG_BL:
1650 case MIPS_HFLAG_B:
1651 tcg_gen_movi_tl(btarget, ctx->btarget);
1652 break;
1657 static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
1659 ctx->saved_hflags = ctx->hflags;
1660 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1661 case MIPS_HFLAG_BR:
1662 break;
1663 case MIPS_HFLAG_BC:
1664 case MIPS_HFLAG_BL:
1665 case MIPS_HFLAG_B:
1666 ctx->btarget = env->btarget;
1667 break;
1671 static inline void
1672 generate_exception_err (DisasContext *ctx, int excp, int err)
1674 TCGv_i32 texcp = tcg_const_i32(excp);
1675 TCGv_i32 terr = tcg_const_i32(err);
1676 save_cpu_state(ctx, 1);
1677 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1678 tcg_temp_free_i32(terr);
1679 tcg_temp_free_i32(texcp);
1682 static inline void
1683 generate_exception (DisasContext *ctx, int excp)
1685 save_cpu_state(ctx, 1);
1686 gen_helper_0e0i(raise_exception, excp);
1689 /* Addresses computation */
1690 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1692 tcg_gen_add_tl(ret, arg0, arg1);
1694 #if defined(TARGET_MIPS64)
1695 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1696 tcg_gen_ext32s_i64(ret, ret);
1698 #endif
1701 /* Addresses computation (translation time) */
1702 static target_long addr_add(DisasContext *ctx, target_long base,
1703 target_long offset)
1705 target_long sum = base + offset;
1707 #if defined(TARGET_MIPS64)
1708 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1709 sum = (int32_t)sum;
1711 #endif
1712 return sum;
1715 static inline void check_cp0_enabled(DisasContext *ctx)
1717 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1718 generate_exception_err(ctx, EXCP_CpU, 0);
1721 static inline void check_cp1_enabled(DisasContext *ctx)
1723 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1724 generate_exception_err(ctx, EXCP_CpU, 1);
1727 /* Verify that the processor is running with COP1X instructions enabled.
1728 This is associated with the nabla symbol in the MIPS32 and MIPS64
1729 opcode tables. */
1731 static inline void check_cop1x(DisasContext *ctx)
1733 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1734 generate_exception(ctx, EXCP_RI);
1737 /* Verify that the processor is running with 64-bit floating-point
1738 operations enabled. */
1740 static inline void check_cp1_64bitmode(DisasContext *ctx)
1742 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1743 generate_exception(ctx, EXCP_RI);
1747 * Verify if floating point register is valid; an operation is not defined
1748 * if bit 0 of any register specification is set and the FR bit in the
1749 * Status register equals zero, since the register numbers specify an
1750 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1751 * in the Status register equals one, both even and odd register numbers
1752 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1754 * Multiple 64 bit wide registers can be checked by calling
1755 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1757 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1759 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1760 generate_exception(ctx, EXCP_RI);
1763 /* Verify that the processor is running with DSP instructions enabled.
1764 This is enabled by CP0 Status register MX(24) bit.
1767 static inline void check_dsp(DisasContext *ctx)
1769 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1770 if (ctx->insn_flags & ASE_DSP) {
1771 generate_exception(ctx, EXCP_DSPDIS);
1772 } else {
1773 generate_exception(ctx, EXCP_RI);
1778 static inline void check_dspr2(DisasContext *ctx)
1780 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1781 if (ctx->insn_flags & ASE_DSP) {
1782 generate_exception(ctx, EXCP_DSPDIS);
1783 } else {
1784 generate_exception(ctx, EXCP_RI);
1789 /* This code generates a "reserved instruction" exception if the
1790 CPU does not support the instruction set corresponding to flags. */
1791 static inline void check_insn(DisasContext *ctx, int flags)
1793 if (unlikely(!(ctx->insn_flags & flags))) {
1794 generate_exception(ctx, EXCP_RI);
1798 /* This code generates a "reserved instruction" exception if the
1799 CPU has corresponding flag set which indicates that the instruction
1800 has been removed. */
1801 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1803 if (unlikely(ctx->insn_flags & flags)) {
1804 generate_exception(ctx, EXCP_RI);
1808 #ifdef TARGET_MIPS64
1809 /* This code generates a "reserved instruction" exception if 64-bit
1810 instructions are not enabled. */
1811 static inline void check_mips_64(DisasContext *ctx)
1813 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1814 generate_exception(ctx, EXCP_RI);
1816 #endif
1818 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1819 calling interface for 32 and 64-bit FPRs. No sense in changing
1820 all callers for gen_load_fpr32 when we need the CTX parameter for
1821 this one use. */
1822 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
1823 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1824 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1825 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1826 int ft, int fs, int cc) \
1828 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1829 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1830 switch (ifmt) { \
1831 case FMT_PS: \
1832 check_cp1_64bitmode(ctx); \
1833 break; \
1834 case FMT_D: \
1835 if (abs) { \
1836 check_cop1x(ctx); \
1838 check_cp1_registers(ctx, fs | ft); \
1839 break; \
1840 case FMT_S: \
1841 if (abs) { \
1842 check_cop1x(ctx); \
1844 break; \
1846 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1847 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1848 switch (n) { \
1849 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1850 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1851 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1852 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1853 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1854 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1855 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1856 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1857 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1858 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1859 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1860 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1861 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1862 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1863 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1864 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1865 default: abort(); \
1867 tcg_temp_free_i##bits (fp0); \
1868 tcg_temp_free_i##bits (fp1); \
1871 FOP_CONDS(, 0, d, FMT_D, 64)
1872 FOP_CONDS(abs, 1, d, FMT_D, 64)
1873 FOP_CONDS(, 0, s, FMT_S, 32)
1874 FOP_CONDS(abs, 1, s, FMT_S, 32)
1875 FOP_CONDS(, 0, ps, FMT_PS, 64)
1876 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1877 #undef FOP_CONDS
1879 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1880 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1881 int ft, int fs, int fd) \
1883 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1884 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1885 if (ifmt == FMT_D) { \
1886 check_cp1_registers(ctx, fs | ft | fd); \
1888 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1889 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1890 switch (n) { \
1891 case 0: \
1892 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1893 break; \
1894 case 1: \
1895 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1896 break; \
1897 case 2: \
1898 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1899 break; \
1900 case 3: \
1901 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1902 break; \
1903 case 4: \
1904 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1905 break; \
1906 case 5: \
1907 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1908 break; \
1909 case 6: \
1910 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1911 break; \
1912 case 7: \
1913 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1914 break; \
1915 case 8: \
1916 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1917 break; \
1918 case 9: \
1919 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1920 break; \
1921 case 10: \
1922 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1923 break; \
1924 case 11: \
1925 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1926 break; \
1927 case 12: \
1928 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1929 break; \
1930 case 13: \
1931 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1932 break; \
1933 case 14: \
1934 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1935 break; \
1936 case 15: \
1937 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1938 break; \
1939 case 17: \
1940 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1941 break; \
1942 case 18: \
1943 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1944 break; \
1945 case 19: \
1946 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1947 break; \
1948 case 25: \
1949 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1950 break; \
1951 case 26: \
1952 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
1953 break; \
1954 case 27: \
1955 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
1956 break; \
1957 default: \
1958 abort(); \
1960 STORE; \
1961 tcg_temp_free_i ## bits (fp0); \
1962 tcg_temp_free_i ## bits (fp1); \
1965 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
1966 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(fp0, fd))
1967 #undef FOP_CONDNS
1968 #undef gen_ldcmp_fpr32
1969 #undef gen_ldcmp_fpr64
1971 /* load/store instructions. */
1972 #ifdef CONFIG_USER_ONLY
1973 #define OP_LD_ATOMIC(insn,fname) \
1974 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1976 TCGv t0 = tcg_temp_new(); \
1977 tcg_gen_mov_tl(t0, arg1); \
1978 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1979 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1980 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
1981 tcg_temp_free(t0); \
1983 #else
1984 #define OP_LD_ATOMIC(insn,fname) \
1985 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1987 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
1989 #endif
1990 OP_LD_ATOMIC(ll,ld32s);
1991 #if defined(TARGET_MIPS64)
1992 OP_LD_ATOMIC(lld,ld64);
1993 #endif
1994 #undef OP_LD_ATOMIC
1996 #ifdef CONFIG_USER_ONLY
1997 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1998 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2000 TCGv t0 = tcg_temp_new(); \
2001 int l1 = gen_new_label(); \
2002 int l2 = gen_new_label(); \
2004 tcg_gen_andi_tl(t0, arg2, almask); \
2005 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2006 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2007 generate_exception(ctx, EXCP_AdES); \
2008 gen_set_label(l1); \
2009 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2010 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2011 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2012 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2013 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2014 gen_helper_0e0i(raise_exception, EXCP_SC); \
2015 gen_set_label(l2); \
2016 tcg_gen_movi_tl(t0, 0); \
2017 gen_store_gpr(t0, rt); \
2018 tcg_temp_free(t0); \
2020 #else
2021 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2022 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2024 TCGv t0 = tcg_temp_new(); \
2025 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
2026 gen_store_gpr(t0, rt); \
2027 tcg_temp_free(t0); \
2029 #endif
2030 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2031 #if defined(TARGET_MIPS64)
2032 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2033 #endif
2034 #undef OP_ST_ATOMIC
2036 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2037 int base, int16_t offset)
2039 if (base == 0) {
2040 tcg_gen_movi_tl(addr, offset);
2041 } else if (offset == 0) {
2042 gen_load_gpr(addr, base);
2043 } else {
2044 tcg_gen_movi_tl(addr, offset);
2045 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2049 static target_ulong pc_relative_pc (DisasContext *ctx)
2051 target_ulong pc = ctx->pc;
2053 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2054 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2056 pc -= branch_bytes;
2059 pc &= ~(target_ulong)3;
2060 return pc;
2063 /* Load */
2064 static void gen_ld(DisasContext *ctx, uint32_t opc,
2065 int rt, int base, int16_t offset)
2067 const char *opn = "ld";
2068 TCGv t0, t1, t2;
2070 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2071 /* Loongson CPU uses a load to zero register for prefetch.
2072 We emulate it as a NOP. On other CPU we must perform the
2073 actual memory access. */
2074 MIPS_DEBUG("NOP");
2075 return;
2078 t0 = tcg_temp_new();
2079 gen_base_offset_addr(ctx, t0, base, offset);
2081 switch (opc) {
2082 #if defined(TARGET_MIPS64)
2083 case OPC_LWU:
2084 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2085 gen_store_gpr(t0, rt);
2086 opn = "lwu";
2087 break;
2088 case OPC_LD:
2089 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2090 gen_store_gpr(t0, rt);
2091 opn = "ld";
2092 break;
2093 case OPC_LLD:
2094 case R6_OPC_LLD:
2095 save_cpu_state(ctx, 1);
2096 op_ld_lld(t0, t0, ctx);
2097 gen_store_gpr(t0, rt);
2098 opn = "lld";
2099 break;
2100 case OPC_LDL:
2101 t1 = tcg_temp_new();
2102 tcg_gen_andi_tl(t1, t0, 7);
2103 #ifndef TARGET_WORDS_BIGENDIAN
2104 tcg_gen_xori_tl(t1, t1, 7);
2105 #endif
2106 tcg_gen_shli_tl(t1, t1, 3);
2107 tcg_gen_andi_tl(t0, t0, ~7);
2108 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2109 tcg_gen_shl_tl(t0, t0, t1);
2110 tcg_gen_xori_tl(t1, t1, 63);
2111 t2 = tcg_const_tl(0x7fffffffffffffffull);
2112 tcg_gen_shr_tl(t2, t2, t1);
2113 gen_load_gpr(t1, rt);
2114 tcg_gen_and_tl(t1, t1, t2);
2115 tcg_temp_free(t2);
2116 tcg_gen_or_tl(t0, t0, t1);
2117 tcg_temp_free(t1);
2118 gen_store_gpr(t0, rt);
2119 opn = "ldl";
2120 break;
2121 case OPC_LDR:
2122 t1 = tcg_temp_new();
2123 tcg_gen_andi_tl(t1, t0, 7);
2124 #ifdef TARGET_WORDS_BIGENDIAN
2125 tcg_gen_xori_tl(t1, t1, 7);
2126 #endif
2127 tcg_gen_shli_tl(t1, t1, 3);
2128 tcg_gen_andi_tl(t0, t0, ~7);
2129 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2130 tcg_gen_shr_tl(t0, t0, t1);
2131 tcg_gen_xori_tl(t1, t1, 63);
2132 t2 = tcg_const_tl(0xfffffffffffffffeull);
2133 tcg_gen_shl_tl(t2, t2, t1);
2134 gen_load_gpr(t1, rt);
2135 tcg_gen_and_tl(t1, t1, t2);
2136 tcg_temp_free(t2);
2137 tcg_gen_or_tl(t0, t0, t1);
2138 tcg_temp_free(t1);
2139 gen_store_gpr(t0, rt);
2140 opn = "ldr";
2141 break;
2142 case OPC_LDPC:
2143 t1 = tcg_const_tl(pc_relative_pc(ctx));
2144 gen_op_addr_add(ctx, t0, t0, t1);
2145 tcg_temp_free(t1);
2146 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2147 gen_store_gpr(t0, rt);
2148 opn = "ldpc";
2149 break;
2150 #endif
2151 case OPC_LWPC:
2152 t1 = tcg_const_tl(pc_relative_pc(ctx));
2153 gen_op_addr_add(ctx, t0, t0, t1);
2154 tcg_temp_free(t1);
2155 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2156 gen_store_gpr(t0, rt);
2157 opn = "lwpc";
2158 break;
2159 case OPC_LW:
2160 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2161 gen_store_gpr(t0, rt);
2162 opn = "lw";
2163 break;
2164 case OPC_LH:
2165 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
2166 gen_store_gpr(t0, rt);
2167 opn = "lh";
2168 break;
2169 case OPC_LHU:
2170 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW);
2171 gen_store_gpr(t0, rt);
2172 opn = "lhu";
2173 break;
2174 case OPC_LB:
2175 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
2176 gen_store_gpr(t0, rt);
2177 opn = "lb";
2178 break;
2179 case OPC_LBU:
2180 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
2181 gen_store_gpr(t0, rt);
2182 opn = "lbu";
2183 break;
2184 case OPC_LWL:
2185 t1 = tcg_temp_new();
2186 tcg_gen_andi_tl(t1, t0, 3);
2187 #ifndef TARGET_WORDS_BIGENDIAN
2188 tcg_gen_xori_tl(t1, t1, 3);
2189 #endif
2190 tcg_gen_shli_tl(t1, t1, 3);
2191 tcg_gen_andi_tl(t0, t0, ~3);
2192 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2193 tcg_gen_shl_tl(t0, t0, t1);
2194 tcg_gen_xori_tl(t1, t1, 31);
2195 t2 = tcg_const_tl(0x7fffffffull);
2196 tcg_gen_shr_tl(t2, t2, t1);
2197 gen_load_gpr(t1, rt);
2198 tcg_gen_and_tl(t1, t1, t2);
2199 tcg_temp_free(t2);
2200 tcg_gen_or_tl(t0, t0, t1);
2201 tcg_temp_free(t1);
2202 tcg_gen_ext32s_tl(t0, t0);
2203 gen_store_gpr(t0, rt);
2204 opn = "lwl";
2205 break;
2206 case OPC_LWR:
2207 t1 = tcg_temp_new();
2208 tcg_gen_andi_tl(t1, t0, 3);
2209 #ifdef TARGET_WORDS_BIGENDIAN
2210 tcg_gen_xori_tl(t1, t1, 3);
2211 #endif
2212 tcg_gen_shli_tl(t1, t1, 3);
2213 tcg_gen_andi_tl(t0, t0, ~3);
2214 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2215 tcg_gen_shr_tl(t0, t0, t1);
2216 tcg_gen_xori_tl(t1, t1, 31);
2217 t2 = tcg_const_tl(0xfffffffeull);
2218 tcg_gen_shl_tl(t2, t2, t1);
2219 gen_load_gpr(t1, rt);
2220 tcg_gen_and_tl(t1, t1, t2);
2221 tcg_temp_free(t2);
2222 tcg_gen_or_tl(t0, t0, t1);
2223 tcg_temp_free(t1);
2224 tcg_gen_ext32s_tl(t0, t0);
2225 gen_store_gpr(t0, rt);
2226 opn = "lwr";
2227 break;
2228 case OPC_LL:
2229 case R6_OPC_LL:
2230 save_cpu_state(ctx, 1);
2231 op_ld_ll(t0, t0, ctx);
2232 gen_store_gpr(t0, rt);
2233 opn = "ll";
2234 break;
2236 (void)opn; /* avoid a compiler warning */
2237 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2238 tcg_temp_free(t0);
2241 /* Store */
2242 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2243 int base, int16_t offset)
2245 const char *opn = "st";
2246 TCGv t0 = tcg_temp_new();
2247 TCGv t1 = tcg_temp_new();
2249 gen_base_offset_addr(ctx, t0, base, offset);
2250 gen_load_gpr(t1, rt);
2251 switch (opc) {
2252 #if defined(TARGET_MIPS64)
2253 case OPC_SD:
2254 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
2255 opn = "sd";
2256 break;
2257 case OPC_SDL:
2258 save_cpu_state(ctx, 1);
2259 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
2260 opn = "sdl";
2261 break;
2262 case OPC_SDR:
2263 save_cpu_state(ctx, 1);
2264 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2265 opn = "sdr";
2266 break;
2267 #endif
2268 case OPC_SW:
2269 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
2270 opn = "sw";
2271 break;
2272 case OPC_SH:
2273 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW);
2274 opn = "sh";
2275 break;
2276 case OPC_SB:
2277 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2278 opn = "sb";
2279 break;
2280 case OPC_SWL:
2281 save_cpu_state(ctx, 1);
2282 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2283 opn = "swl";
2284 break;
2285 case OPC_SWR:
2286 save_cpu_state(ctx, 1);
2287 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2288 opn = "swr";
2289 break;
2291 (void)opn; /* avoid a compiler warning */
2292 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2293 tcg_temp_free(t0);
2294 tcg_temp_free(t1);
2298 /* Store conditional */
2299 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2300 int base, int16_t offset)
2302 const char *opn = "st_cond";
2303 TCGv t0, t1;
2305 #ifdef CONFIG_USER_ONLY
2306 t0 = tcg_temp_local_new();
2307 t1 = tcg_temp_local_new();
2308 #else
2309 t0 = tcg_temp_new();
2310 t1 = tcg_temp_new();
2311 #endif
2312 gen_base_offset_addr(ctx, t0, base, offset);
2313 gen_load_gpr(t1, rt);
2314 switch (opc) {
2315 #if defined(TARGET_MIPS64)
2316 case OPC_SCD:
2317 case R6_OPC_SCD:
2318 save_cpu_state(ctx, 1);
2319 op_st_scd(t1, t0, rt, ctx);
2320 opn = "scd";
2321 break;
2322 #endif
2323 case OPC_SC:
2324 case R6_OPC_SC:
2325 save_cpu_state(ctx, 1);
2326 op_st_sc(t1, t0, rt, ctx);
2327 opn = "sc";
2328 break;
2330 (void)opn; /* avoid a compiler warning */
2331 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2332 tcg_temp_free(t1);
2333 tcg_temp_free(t0);
2336 /* Load and store */
2337 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2338 int base, int16_t offset)
2340 const char *opn = "flt_ldst";
2341 TCGv t0 = tcg_temp_new();
2343 gen_base_offset_addr(ctx, t0, base, offset);
2344 /* Don't do NOP if destination is zero: we must perform the actual
2345 memory access. */
2346 switch (opc) {
2347 case OPC_LWC1:
2349 TCGv_i32 fp0 = tcg_temp_new_i32();
2350 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL);
2351 gen_store_fpr32(fp0, ft);
2352 tcg_temp_free_i32(fp0);
2354 opn = "lwc1";
2355 break;
2356 case OPC_SWC1:
2358 TCGv_i32 fp0 = tcg_temp_new_i32();
2359 gen_load_fpr32(fp0, ft);
2360 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
2361 tcg_temp_free_i32(fp0);
2363 opn = "swc1";
2364 break;
2365 case OPC_LDC1:
2367 TCGv_i64 fp0 = tcg_temp_new_i64();
2368 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
2369 gen_store_fpr64(ctx, fp0, ft);
2370 tcg_temp_free_i64(fp0);
2372 opn = "ldc1";
2373 break;
2374 case OPC_SDC1:
2376 TCGv_i64 fp0 = tcg_temp_new_i64();
2377 gen_load_fpr64(ctx, fp0, ft);
2378 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
2379 tcg_temp_free_i64(fp0);
2381 opn = "sdc1";
2382 break;
2383 default:
2384 MIPS_INVAL(opn);
2385 generate_exception(ctx, EXCP_RI);
2386 goto out;
2388 (void)opn; /* avoid a compiler warning */
2389 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
2390 out:
2391 tcg_temp_free(t0);
2394 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2395 int rs, int16_t imm)
2397 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2398 check_cp1_enabled(ctx);
2399 switch (op) {
2400 case OPC_LDC1:
2401 case OPC_SDC1:
2402 check_insn(ctx, ISA_MIPS2);
2403 /* Fallthrough */
2404 default:
2405 gen_flt_ldst(ctx, op, rt, rs, imm);
2407 } else {
2408 generate_exception_err(ctx, EXCP_CpU, 1);
2412 /* Arithmetic with immediate operand */
2413 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2414 int rt, int rs, int16_t imm)
2416 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2417 const char *opn = "imm arith";
2419 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2420 /* If no destination, treat it as a NOP.
2421 For addi, we must generate the overflow exception when needed. */
2422 MIPS_DEBUG("NOP");
2423 return;
2425 switch (opc) {
2426 case OPC_ADDI:
2428 TCGv t0 = tcg_temp_local_new();
2429 TCGv t1 = tcg_temp_new();
2430 TCGv t2 = tcg_temp_new();
2431 int l1 = gen_new_label();
2433 gen_load_gpr(t1, rs);
2434 tcg_gen_addi_tl(t0, t1, uimm);
2435 tcg_gen_ext32s_tl(t0, t0);
2437 tcg_gen_xori_tl(t1, t1, ~uimm);
2438 tcg_gen_xori_tl(t2, t0, uimm);
2439 tcg_gen_and_tl(t1, t1, t2);
2440 tcg_temp_free(t2);
2441 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2442 tcg_temp_free(t1);
2443 /* operands of same sign, result different sign */
2444 generate_exception(ctx, EXCP_OVERFLOW);
2445 gen_set_label(l1);
2446 tcg_gen_ext32s_tl(t0, t0);
2447 gen_store_gpr(t0, rt);
2448 tcg_temp_free(t0);
2450 opn = "addi";
2451 break;
2452 case OPC_ADDIU:
2453 if (rs != 0) {
2454 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2455 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2456 } else {
2457 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2459 opn = "addiu";
2460 break;
2461 #if defined(TARGET_MIPS64)
2462 case OPC_DADDI:
2464 TCGv t0 = tcg_temp_local_new();
2465 TCGv t1 = tcg_temp_new();
2466 TCGv t2 = tcg_temp_new();
2467 int l1 = gen_new_label();
2469 gen_load_gpr(t1, rs);
2470 tcg_gen_addi_tl(t0, t1, uimm);
2472 tcg_gen_xori_tl(t1, t1, ~uimm);
2473 tcg_gen_xori_tl(t2, t0, uimm);
2474 tcg_gen_and_tl(t1, t1, t2);
2475 tcg_temp_free(t2);
2476 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2477 tcg_temp_free(t1);
2478 /* operands of same sign, result different sign */
2479 generate_exception(ctx, EXCP_OVERFLOW);
2480 gen_set_label(l1);
2481 gen_store_gpr(t0, rt);
2482 tcg_temp_free(t0);
2484 opn = "daddi";
2485 break;
2486 case OPC_DADDIU:
2487 if (rs != 0) {
2488 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2489 } else {
2490 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2492 opn = "daddiu";
2493 break;
2494 #endif
2496 (void)opn; /* avoid a compiler warning */
2497 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2500 /* Logic with immediate operand */
2501 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2502 int rt, int rs, int16_t imm)
2504 target_ulong uimm;
2506 if (rt == 0) {
2507 /* If no destination, treat it as a NOP. */
2508 MIPS_DEBUG("NOP");
2509 return;
2511 uimm = (uint16_t)imm;
2512 switch (opc) {
2513 case OPC_ANDI:
2514 if (likely(rs != 0))
2515 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2516 else
2517 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2518 MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
2519 regnames[rs], uimm);
2520 break;
2521 case OPC_ORI:
2522 if (rs != 0)
2523 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2524 else
2525 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2526 MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
2527 regnames[rs], uimm);
2528 break;
2529 case OPC_XORI:
2530 if (likely(rs != 0))
2531 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2532 else
2533 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2534 MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
2535 regnames[rs], uimm);
2536 break;
2537 case OPC_LUI:
2538 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2539 /* OPC_AUI */
2540 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2541 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2542 MIPS_DEBUG("aui %s, %s, %04x", regnames[rt], regnames[rs], imm);
2543 } else {
2544 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2545 MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
2547 break;
2549 default:
2550 MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
2551 break;
2555 /* Set on less than with immediate operand */
2556 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2557 int rt, int rs, int16_t imm)
2559 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2560 const char *opn = "imm arith";
2561 TCGv t0;
2563 if (rt == 0) {
2564 /* If no destination, treat it as a NOP. */
2565 MIPS_DEBUG("NOP");
2566 return;
2568 t0 = tcg_temp_new();
2569 gen_load_gpr(t0, rs);
2570 switch (opc) {
2571 case OPC_SLTI:
2572 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2573 opn = "slti";
2574 break;
2575 case OPC_SLTIU:
2576 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2577 opn = "sltiu";
2578 break;
2580 (void)opn; /* avoid a compiler warning */
2581 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2582 tcg_temp_free(t0);
2585 /* Shifts with immediate operand */
2586 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2587 int rt, int rs, int16_t imm)
2589 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2590 const char *opn = "imm shift";
2591 TCGv t0;
2593 if (rt == 0) {
2594 /* If no destination, treat it as a NOP. */
2595 MIPS_DEBUG("NOP");
2596 return;
2599 t0 = tcg_temp_new();
2600 gen_load_gpr(t0, rs);
2601 switch (opc) {
2602 case OPC_SLL:
2603 tcg_gen_shli_tl(t0, t0, uimm);
2604 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2605 opn = "sll";
2606 break;
2607 case OPC_SRA:
2608 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2609 opn = "sra";
2610 break;
2611 case OPC_SRL:
2612 if (uimm != 0) {
2613 tcg_gen_ext32u_tl(t0, t0);
2614 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2615 } else {
2616 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2618 opn = "srl";
2619 break;
2620 case OPC_ROTR:
2621 if (uimm != 0) {
2622 TCGv_i32 t1 = tcg_temp_new_i32();
2624 tcg_gen_trunc_tl_i32(t1, t0);
2625 tcg_gen_rotri_i32(t1, t1, uimm);
2626 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2627 tcg_temp_free_i32(t1);
2628 } else {
2629 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2631 opn = "rotr";
2632 break;
2633 #if defined(TARGET_MIPS64)
2634 case OPC_DSLL:
2635 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2636 opn = "dsll";
2637 break;
2638 case OPC_DSRA:
2639 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2640 opn = "dsra";
2641 break;
2642 case OPC_DSRL:
2643 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2644 opn = "dsrl";
2645 break;
2646 case OPC_DROTR:
2647 if (uimm != 0) {
2648 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2649 } else {
2650 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2652 opn = "drotr";
2653 break;
2654 case OPC_DSLL32:
2655 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2656 opn = "dsll32";
2657 break;
2658 case OPC_DSRA32:
2659 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2660 opn = "dsra32";
2661 break;
2662 case OPC_DSRL32:
2663 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2664 opn = "dsrl32";
2665 break;
2666 case OPC_DROTR32:
2667 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2668 opn = "drotr32";
2669 break;
2670 #endif
2672 (void)opn; /* avoid a compiler warning */
2673 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2674 tcg_temp_free(t0);
2677 /* Arithmetic */
2678 static void gen_arith(DisasContext *ctx, uint32_t opc,
2679 int rd, int rs, int rt)
2681 const char *opn = "arith";
2683 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2684 && opc != OPC_DADD && opc != OPC_DSUB) {
2685 /* If no destination, treat it as a NOP.
2686 For add & sub, we must generate the overflow exception when needed. */
2687 MIPS_DEBUG("NOP");
2688 return;
2691 switch (opc) {
2692 case OPC_ADD:
2694 TCGv t0 = tcg_temp_local_new();
2695 TCGv t1 = tcg_temp_new();
2696 TCGv t2 = tcg_temp_new();
2697 int l1 = gen_new_label();
2699 gen_load_gpr(t1, rs);
2700 gen_load_gpr(t2, rt);
2701 tcg_gen_add_tl(t0, t1, t2);
2702 tcg_gen_ext32s_tl(t0, t0);
2703 tcg_gen_xor_tl(t1, t1, t2);
2704 tcg_gen_xor_tl(t2, t0, t2);
2705 tcg_gen_andc_tl(t1, t2, t1);
2706 tcg_temp_free(t2);
2707 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2708 tcg_temp_free(t1);
2709 /* operands of same sign, result different sign */
2710 generate_exception(ctx, EXCP_OVERFLOW);
2711 gen_set_label(l1);
2712 gen_store_gpr(t0, rd);
2713 tcg_temp_free(t0);
2715 opn = "add";
2716 break;
2717 case OPC_ADDU:
2718 if (rs != 0 && rt != 0) {
2719 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2720 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2721 } else if (rs == 0 && rt != 0) {
2722 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2723 } else if (rs != 0 && rt == 0) {
2724 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2725 } else {
2726 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2728 opn = "addu";
2729 break;
2730 case OPC_SUB:
2732 TCGv t0 = tcg_temp_local_new();
2733 TCGv t1 = tcg_temp_new();
2734 TCGv t2 = tcg_temp_new();
2735 int l1 = gen_new_label();
2737 gen_load_gpr(t1, rs);
2738 gen_load_gpr(t2, rt);
2739 tcg_gen_sub_tl(t0, t1, t2);
2740 tcg_gen_ext32s_tl(t0, t0);
2741 tcg_gen_xor_tl(t2, t1, t2);
2742 tcg_gen_xor_tl(t1, t0, t1);
2743 tcg_gen_and_tl(t1, t1, t2);
2744 tcg_temp_free(t2);
2745 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2746 tcg_temp_free(t1);
2747 /* operands of different sign, first operand and result different sign */
2748 generate_exception(ctx, EXCP_OVERFLOW);
2749 gen_set_label(l1);
2750 gen_store_gpr(t0, rd);
2751 tcg_temp_free(t0);
2753 opn = "sub";
2754 break;
2755 case OPC_SUBU:
2756 if (rs != 0 && rt != 0) {
2757 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2758 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2759 } else if (rs == 0 && rt != 0) {
2760 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2761 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2762 } else if (rs != 0 && rt == 0) {
2763 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2764 } else {
2765 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2767 opn = "subu";
2768 break;
2769 #if defined(TARGET_MIPS64)
2770 case OPC_DADD:
2772 TCGv t0 = tcg_temp_local_new();
2773 TCGv t1 = tcg_temp_new();
2774 TCGv t2 = tcg_temp_new();
2775 int l1 = gen_new_label();
2777 gen_load_gpr(t1, rs);
2778 gen_load_gpr(t2, rt);
2779 tcg_gen_add_tl(t0, t1, t2);
2780 tcg_gen_xor_tl(t1, t1, t2);
2781 tcg_gen_xor_tl(t2, t0, t2);
2782 tcg_gen_andc_tl(t1, t2, t1);
2783 tcg_temp_free(t2);
2784 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2785 tcg_temp_free(t1);
2786 /* operands of same sign, result different sign */
2787 generate_exception(ctx, EXCP_OVERFLOW);
2788 gen_set_label(l1);
2789 gen_store_gpr(t0, rd);
2790 tcg_temp_free(t0);
2792 opn = "dadd";
2793 break;
2794 case OPC_DADDU:
2795 if (rs != 0 && rt != 0) {
2796 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2797 } else if (rs == 0 && rt != 0) {
2798 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2799 } else if (rs != 0 && rt == 0) {
2800 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2801 } else {
2802 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2804 opn = "daddu";
2805 break;
2806 case OPC_DSUB:
2808 TCGv t0 = tcg_temp_local_new();
2809 TCGv t1 = tcg_temp_new();
2810 TCGv t2 = tcg_temp_new();
2811 int l1 = gen_new_label();
2813 gen_load_gpr(t1, rs);
2814 gen_load_gpr(t2, rt);
2815 tcg_gen_sub_tl(t0, t1, t2);
2816 tcg_gen_xor_tl(t2, t1, t2);
2817 tcg_gen_xor_tl(t1, t0, t1);
2818 tcg_gen_and_tl(t1, t1, t2);
2819 tcg_temp_free(t2);
2820 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2821 tcg_temp_free(t1);
2822 /* operands of different sign, first operand and result different sign */
2823 generate_exception(ctx, EXCP_OVERFLOW);
2824 gen_set_label(l1);
2825 gen_store_gpr(t0, rd);
2826 tcg_temp_free(t0);
2828 opn = "dsub";
2829 break;
2830 case OPC_DSUBU:
2831 if (rs != 0 && rt != 0) {
2832 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2833 } else if (rs == 0 && rt != 0) {
2834 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2835 } else if (rs != 0 && rt == 0) {
2836 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2837 } else {
2838 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2840 opn = "dsubu";
2841 break;
2842 #endif
2843 case OPC_MUL:
2844 if (likely(rs != 0 && rt != 0)) {
2845 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2846 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2847 } else {
2848 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2850 opn = "mul";
2851 break;
2853 (void)opn; /* avoid a compiler warning */
2854 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2857 /* Conditional move */
2858 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2859 int rd, int rs, int rt)
2861 const char *opn = "cond move";
2862 TCGv t0, t1, t2;
2864 if (rd == 0) {
2865 /* If no destination, treat it as a NOP. */
2866 MIPS_DEBUG("NOP");
2867 return;
2870 t0 = tcg_temp_new();
2871 gen_load_gpr(t0, rt);
2872 t1 = tcg_const_tl(0);
2873 t2 = tcg_temp_new();
2874 gen_load_gpr(t2, rs);
2875 switch (opc) {
2876 case OPC_MOVN:
2877 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2878 opn = "movn";
2879 break;
2880 case OPC_MOVZ:
2881 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2882 opn = "movz";
2883 break;
2884 case OPC_SELNEZ:
2885 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2886 opn = "selnez";
2887 break;
2888 case OPC_SELEQZ:
2889 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2890 opn = "seleqz";
2891 break;
2893 tcg_temp_free(t2);
2894 tcg_temp_free(t1);
2895 tcg_temp_free(t0);
2897 (void)opn; /* avoid a compiler warning */
2898 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2901 /* Logic */
2902 static void gen_logic(DisasContext *ctx, uint32_t opc,
2903 int rd, int rs, int rt)
2905 const char *opn = "logic";
2907 if (rd == 0) {
2908 /* If no destination, treat it as a NOP. */
2909 MIPS_DEBUG("NOP");
2910 return;
2913 switch (opc) {
2914 case OPC_AND:
2915 if (likely(rs != 0 && rt != 0)) {
2916 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2917 } else {
2918 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2920 opn = "and";
2921 break;
2922 case OPC_NOR:
2923 if (rs != 0 && rt != 0) {
2924 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2925 } else if (rs == 0 && rt != 0) {
2926 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2927 } else if (rs != 0 && rt == 0) {
2928 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2929 } else {
2930 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2932 opn = "nor";
2933 break;
2934 case OPC_OR:
2935 if (likely(rs != 0 && rt != 0)) {
2936 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2937 } else if (rs == 0 && rt != 0) {
2938 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2939 } else if (rs != 0 && rt == 0) {
2940 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2941 } else {
2942 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2944 opn = "or";
2945 break;
2946 case OPC_XOR:
2947 if (likely(rs != 0 && rt != 0)) {
2948 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2949 } else if (rs == 0 && rt != 0) {
2950 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2951 } else if (rs != 0 && rt == 0) {
2952 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2953 } else {
2954 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2956 opn = "xor";
2957 break;
2959 (void)opn; /* avoid a compiler warning */
2960 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2963 /* Set on lower than */
2964 static void gen_slt(DisasContext *ctx, uint32_t opc,
2965 int rd, int rs, int rt)
2967 const char *opn = "slt";
2968 TCGv t0, t1;
2970 if (rd == 0) {
2971 /* If no destination, treat it as a NOP. */
2972 MIPS_DEBUG("NOP");
2973 return;
2976 t0 = tcg_temp_new();
2977 t1 = tcg_temp_new();
2978 gen_load_gpr(t0, rs);
2979 gen_load_gpr(t1, rt);
2980 switch (opc) {
2981 case OPC_SLT:
2982 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2983 opn = "slt";
2984 break;
2985 case OPC_SLTU:
2986 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2987 opn = "sltu";
2988 break;
2990 (void)opn; /* avoid a compiler warning */
2991 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2992 tcg_temp_free(t0);
2993 tcg_temp_free(t1);
2996 /* Shifts */
2997 static void gen_shift(DisasContext *ctx, uint32_t opc,
2998 int rd, int rs, int rt)
3000 const char *opn = "shifts";
3001 TCGv t0, t1;
3003 if (rd == 0) {
3004 /* If no destination, treat it as a NOP.
3005 For add & sub, we must generate the overflow exception when needed. */
3006 MIPS_DEBUG("NOP");
3007 return;
3010 t0 = tcg_temp_new();
3011 t1 = tcg_temp_new();
3012 gen_load_gpr(t0, rs);
3013 gen_load_gpr(t1, rt);
3014 switch (opc) {
3015 case OPC_SLLV:
3016 tcg_gen_andi_tl(t0, t0, 0x1f);
3017 tcg_gen_shl_tl(t0, t1, t0);
3018 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3019 opn = "sllv";
3020 break;
3021 case OPC_SRAV:
3022 tcg_gen_andi_tl(t0, t0, 0x1f);
3023 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3024 opn = "srav";
3025 break;
3026 case OPC_SRLV:
3027 tcg_gen_ext32u_tl(t1, t1);
3028 tcg_gen_andi_tl(t0, t0, 0x1f);
3029 tcg_gen_shr_tl(t0, t1, t0);
3030 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3031 opn = "srlv";
3032 break;
3033 case OPC_ROTRV:
3035 TCGv_i32 t2 = tcg_temp_new_i32();
3036 TCGv_i32 t3 = tcg_temp_new_i32();
3038 tcg_gen_trunc_tl_i32(t2, t0);
3039 tcg_gen_trunc_tl_i32(t3, t1);
3040 tcg_gen_andi_i32(t2, t2, 0x1f);
3041 tcg_gen_rotr_i32(t2, t3, t2);
3042 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3043 tcg_temp_free_i32(t2);
3044 tcg_temp_free_i32(t3);
3045 opn = "rotrv";
3047 break;
3048 #if defined(TARGET_MIPS64)
3049 case OPC_DSLLV:
3050 tcg_gen_andi_tl(t0, t0, 0x3f);
3051 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3052 opn = "dsllv";
3053 break;
3054 case OPC_DSRAV:
3055 tcg_gen_andi_tl(t0, t0, 0x3f);
3056 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3057 opn = "dsrav";
3058 break;
3059 case OPC_DSRLV:
3060 tcg_gen_andi_tl(t0, t0, 0x3f);
3061 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3062 opn = "dsrlv";
3063 break;
3064 case OPC_DROTRV:
3065 tcg_gen_andi_tl(t0, t0, 0x3f);
3066 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3067 opn = "drotrv";
3068 break;
3069 #endif
3071 (void)opn; /* avoid a compiler warning */
3072 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3073 tcg_temp_free(t0);
3074 tcg_temp_free(t1);
3077 /* Arithmetic on HI/LO registers */
3078 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3080 const char *opn = "hilo";
3082 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3083 /* Treat as NOP. */
3084 MIPS_DEBUG("NOP");
3085 return;
3088 if (acc != 0) {
3089 check_dsp(ctx);
3092 switch (opc) {
3093 case OPC_MFHI:
3094 #if defined(TARGET_MIPS64)
3095 if (acc != 0) {
3096 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3097 } else
3098 #endif
3100 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3102 opn = "mfhi";
3103 break;
3104 case OPC_MFLO:
3105 #if defined(TARGET_MIPS64)
3106 if (acc != 0) {
3107 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3108 } else
3109 #endif
3111 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3113 opn = "mflo";
3114 break;
3115 case OPC_MTHI:
3116 if (reg != 0) {
3117 #if defined(TARGET_MIPS64)
3118 if (acc != 0) {
3119 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3120 } else
3121 #endif
3123 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3125 } else {
3126 tcg_gen_movi_tl(cpu_HI[acc], 0);
3128 opn = "mthi";
3129 break;
3130 case OPC_MTLO:
3131 if (reg != 0) {
3132 #if defined(TARGET_MIPS64)
3133 if (acc != 0) {
3134 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3135 } else
3136 #endif
3138 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3140 } else {
3141 tcg_gen_movi_tl(cpu_LO[acc], 0);
3143 opn = "mtlo";
3144 break;
3146 (void)opn; /* avoid a compiler warning */
3147 MIPS_DEBUG("%s %s", opn, regnames[reg]);
3150 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3151 TCGMemOp memop)
3153 TCGv t0 = tcg_const_tl(addr);
3154 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3155 gen_store_gpr(t0, reg);
3156 tcg_temp_free(t0);
3159 static inline void gen_pcrel(DisasContext *ctx, int rs, int16_t imm)
3161 target_long offset;
3162 target_long addr;
3164 switch (MASK_OPC_PCREL_TOP2BITS(ctx->opcode)) {
3165 case OPC_ADDIUPC:
3166 if (rs != 0) {
3167 offset = sextract32(ctx->opcode << 2, 0, 21);
3168 addr = addr_add(ctx, ctx->pc, offset);
3169 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3171 break;
3172 case R6_OPC_LWPC:
3173 offset = sextract32(ctx->opcode << 2, 0, 21);
3174 addr = addr_add(ctx, ctx->pc, offset);
3175 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3176 break;
3177 #if defined(TARGET_MIPS64)
3178 case OPC_LWUPC:
3179 check_mips_64(ctx);
3180 offset = sextract32(ctx->opcode << 2, 0, 21);
3181 addr = addr_add(ctx, ctx->pc, offset);
3182 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3183 break;
3184 #endif
3185 default:
3186 switch (MASK_OPC_PCREL_TOP5BITS(ctx->opcode)) {
3187 case OPC_AUIPC:
3188 if (rs != 0) {
3189 offset = imm << 16;
3190 addr = addr_add(ctx, ctx->pc, offset);
3191 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3193 break;
3194 case OPC_ALUIPC:
3195 if (rs != 0) {
3196 offset = imm << 16;
3197 addr = ~0xFFFF & addr_add(ctx, ctx->pc, offset);
3198 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3200 break;
3201 #if defined(TARGET_MIPS64)
3202 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3203 case R6_OPC_LDPC + (1 << 16):
3204 case R6_OPC_LDPC + (2 << 16):
3205 case R6_OPC_LDPC + (3 << 16):
3206 check_mips_64(ctx);
3207 offset = sextract32(ctx->opcode << 3, 0, 21);
3208 addr = addr_add(ctx, (ctx->pc & ~0x7), offset);
3209 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3210 break;
3211 #endif
3212 default:
3213 MIPS_INVAL("OPC_PCREL");
3214 generate_exception(ctx, EXCP_RI);
3215 break;
3217 break;
3221 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3223 const char *opn = "r6 mul/div";
3224 TCGv t0, t1;
3226 if (rd == 0) {
3227 /* Treat as NOP. */
3228 MIPS_DEBUG("NOP");
3229 return;
3232 t0 = tcg_temp_new();
3233 t1 = tcg_temp_new();
3235 gen_load_gpr(t0, rs);
3236 gen_load_gpr(t1, rt);
3238 switch (opc) {
3239 case R6_OPC_DIV:
3241 TCGv t2 = tcg_temp_new();
3242 TCGv t3 = tcg_temp_new();
3243 tcg_gen_ext32s_tl(t0, t0);
3244 tcg_gen_ext32s_tl(t1, t1);
3245 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3246 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3247 tcg_gen_and_tl(t2, t2, t3);
3248 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3249 tcg_gen_or_tl(t2, t2, t3);
3250 tcg_gen_movi_tl(t3, 0);
3251 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3252 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3253 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3254 tcg_temp_free(t3);
3255 tcg_temp_free(t2);
3257 opn = "div";
3258 break;
3259 case R6_OPC_MOD:
3261 TCGv t2 = tcg_temp_new();
3262 TCGv t3 = tcg_temp_new();
3263 tcg_gen_ext32s_tl(t0, t0);
3264 tcg_gen_ext32s_tl(t1, t1);
3265 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3266 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3267 tcg_gen_and_tl(t2, t2, t3);
3268 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3269 tcg_gen_or_tl(t2, t2, t3);
3270 tcg_gen_movi_tl(t3, 0);
3271 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3272 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3273 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3274 tcg_temp_free(t3);
3275 tcg_temp_free(t2);
3277 opn = "mod";
3278 break;
3279 case R6_OPC_DIVU:
3281 TCGv t2 = tcg_const_tl(0);
3282 TCGv t3 = tcg_const_tl(1);
3283 tcg_gen_ext32u_tl(t0, t0);
3284 tcg_gen_ext32u_tl(t1, t1);
3285 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3286 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3287 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3288 tcg_temp_free(t3);
3289 tcg_temp_free(t2);
3291 opn = "divu";
3292 break;
3293 case R6_OPC_MODU:
3295 TCGv t2 = tcg_const_tl(0);
3296 TCGv t3 = tcg_const_tl(1);
3297 tcg_gen_ext32u_tl(t0, t0);
3298 tcg_gen_ext32u_tl(t1, t1);
3299 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3300 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3301 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3302 tcg_temp_free(t3);
3303 tcg_temp_free(t2);
3305 opn = "modu";
3306 break;
3307 case R6_OPC_MUL:
3309 TCGv_i32 t2 = tcg_temp_new_i32();
3310 TCGv_i32 t3 = tcg_temp_new_i32();
3311 tcg_gen_trunc_tl_i32(t2, t0);
3312 tcg_gen_trunc_tl_i32(t3, t1);
3313 tcg_gen_mul_i32(t2, t2, t3);
3314 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3315 tcg_temp_free_i32(t2);
3316 tcg_temp_free_i32(t3);
3318 opn = "mul";
3319 break;
3320 case R6_OPC_MUH:
3322 TCGv_i32 t2 = tcg_temp_new_i32();
3323 TCGv_i32 t3 = tcg_temp_new_i32();
3324 tcg_gen_trunc_tl_i32(t2, t0);
3325 tcg_gen_trunc_tl_i32(t3, t1);
3326 tcg_gen_muls2_i32(t2, t3, t2, t3);
3327 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3328 tcg_temp_free_i32(t2);
3329 tcg_temp_free_i32(t3);
3331 opn = "muh";
3332 break;
3333 case R6_OPC_MULU:
3335 TCGv_i32 t2 = tcg_temp_new_i32();
3336 TCGv_i32 t3 = tcg_temp_new_i32();
3337 tcg_gen_trunc_tl_i32(t2, t0);
3338 tcg_gen_trunc_tl_i32(t3, t1);
3339 tcg_gen_mul_i32(t2, t2, t3);
3340 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3341 tcg_temp_free_i32(t2);
3342 tcg_temp_free_i32(t3);
3344 opn = "mulu";
3345 break;
3346 case R6_OPC_MUHU:
3348 TCGv_i32 t2 = tcg_temp_new_i32();
3349 TCGv_i32 t3 = tcg_temp_new_i32();
3350 tcg_gen_trunc_tl_i32(t2, t0);
3351 tcg_gen_trunc_tl_i32(t3, t1);
3352 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3353 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3354 tcg_temp_free_i32(t2);
3355 tcg_temp_free_i32(t3);
3357 opn = "muhu";
3358 break;
3359 #if defined(TARGET_MIPS64)
3360 case R6_OPC_DDIV:
3362 TCGv t2 = tcg_temp_new();
3363 TCGv t3 = tcg_temp_new();
3364 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3365 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3366 tcg_gen_and_tl(t2, t2, t3);
3367 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3368 tcg_gen_or_tl(t2, t2, t3);
3369 tcg_gen_movi_tl(t3, 0);
3370 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3371 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3372 tcg_temp_free(t3);
3373 tcg_temp_free(t2);
3375 opn = "ddiv";
3376 break;
3377 case R6_OPC_DMOD:
3379 TCGv t2 = tcg_temp_new();
3380 TCGv t3 = tcg_temp_new();
3381 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3382 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3383 tcg_gen_and_tl(t2, t2, t3);
3384 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3385 tcg_gen_or_tl(t2, t2, t3);
3386 tcg_gen_movi_tl(t3, 0);
3387 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3388 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3389 tcg_temp_free(t3);
3390 tcg_temp_free(t2);
3392 opn = "dmod";
3393 break;
3394 case R6_OPC_DDIVU:
3396 TCGv t2 = tcg_const_tl(0);
3397 TCGv t3 = tcg_const_tl(1);
3398 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3399 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3400 tcg_temp_free(t3);
3401 tcg_temp_free(t2);
3403 opn = "ddivu";
3404 break;
3405 case R6_OPC_DMODU:
3407 TCGv t2 = tcg_const_tl(0);
3408 TCGv t3 = tcg_const_tl(1);
3409 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3410 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3411 tcg_temp_free(t3);
3412 tcg_temp_free(t2);
3414 opn = "dmodu";
3415 break;
3416 case R6_OPC_DMUL:
3417 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3418 opn = "dmul";
3419 break;
3420 case R6_OPC_DMUH:
3422 TCGv t2 = tcg_temp_new();
3423 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3424 tcg_temp_free(t2);
3426 opn = "dmuh";
3427 break;
3428 case R6_OPC_DMULU:
3429 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3430 opn = "dmulu";
3431 break;
3432 case R6_OPC_DMUHU:
3434 TCGv t2 = tcg_temp_new();
3435 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3436 tcg_temp_free(t2);
3438 opn = "dmuhu";
3439 break;
3440 #endif
3441 default:
3442 MIPS_INVAL(opn);
3443 generate_exception(ctx, EXCP_RI);
3444 goto out;
3446 (void)opn; /* avoid a compiler warning */
3447 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3448 out:
3449 tcg_temp_free(t0);
3450 tcg_temp_free(t1);
3453 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3454 int acc, int rs, int rt)
3456 const char *opn = "mul/div";
3457 TCGv t0, t1;
3459 t0 = tcg_temp_new();
3460 t1 = tcg_temp_new();
3462 gen_load_gpr(t0, rs);
3463 gen_load_gpr(t1, rt);
3465 if (acc != 0) {
3466 check_dsp(ctx);
3469 switch (opc) {
3470 case OPC_DIV:
3472 TCGv t2 = tcg_temp_new();
3473 TCGv t3 = tcg_temp_new();
3474 tcg_gen_ext32s_tl(t0, t0);
3475 tcg_gen_ext32s_tl(t1, t1);
3476 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3477 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3478 tcg_gen_and_tl(t2, t2, t3);
3479 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3480 tcg_gen_or_tl(t2, t2, t3);
3481 tcg_gen_movi_tl(t3, 0);
3482 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3483 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3484 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3485 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3486 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3487 tcg_temp_free(t3);
3488 tcg_temp_free(t2);
3490 opn = "div";
3491 break;
3492 case OPC_DIVU:
3494 TCGv t2 = tcg_const_tl(0);
3495 TCGv t3 = tcg_const_tl(1);
3496 tcg_gen_ext32u_tl(t0, t0);
3497 tcg_gen_ext32u_tl(t1, t1);
3498 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3499 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3500 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3501 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3502 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3503 tcg_temp_free(t3);
3504 tcg_temp_free(t2);
3506 opn = "divu";
3507 break;
3508 case OPC_MULT:
3510 TCGv_i32 t2 = tcg_temp_new_i32();
3511 TCGv_i32 t3 = tcg_temp_new_i32();
3512 tcg_gen_trunc_tl_i32(t2, t0);
3513 tcg_gen_trunc_tl_i32(t3, t1);
3514 tcg_gen_muls2_i32(t2, t3, t2, t3);
3515 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3516 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3517 tcg_temp_free_i32(t2);
3518 tcg_temp_free_i32(t3);
3520 opn = "mult";
3521 break;
3522 case OPC_MULTU:
3524 TCGv_i32 t2 = tcg_temp_new_i32();
3525 TCGv_i32 t3 = tcg_temp_new_i32();
3526 tcg_gen_trunc_tl_i32(t2, t0);
3527 tcg_gen_trunc_tl_i32(t3, t1);
3528 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3529 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3530 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3531 tcg_temp_free_i32(t2);
3532 tcg_temp_free_i32(t3);
3534 opn = "multu";
3535 break;
3536 #if defined(TARGET_MIPS64)
3537 case OPC_DDIV:
3539 TCGv t2 = tcg_temp_new();
3540 TCGv t3 = tcg_temp_new();
3541 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3542 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3543 tcg_gen_and_tl(t2, t2, t3);
3544 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3545 tcg_gen_or_tl(t2, t2, t3);
3546 tcg_gen_movi_tl(t3, 0);
3547 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3548 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3549 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3550 tcg_temp_free(t3);
3551 tcg_temp_free(t2);
3553 opn = "ddiv";
3554 break;
3555 case OPC_DDIVU:
3557 TCGv t2 = tcg_const_tl(0);
3558 TCGv t3 = tcg_const_tl(1);
3559 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3560 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3561 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3562 tcg_temp_free(t3);
3563 tcg_temp_free(t2);
3565 opn = "ddivu";
3566 break;
3567 case OPC_DMULT:
3568 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3569 opn = "dmult";
3570 break;
3571 case OPC_DMULTU:
3572 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3573 opn = "dmultu";
3574 break;
3575 #endif
3576 case OPC_MADD:
3578 TCGv_i64 t2 = tcg_temp_new_i64();
3579 TCGv_i64 t3 = tcg_temp_new_i64();
3581 tcg_gen_ext_tl_i64(t2, t0);
3582 tcg_gen_ext_tl_i64(t3, t1);
3583 tcg_gen_mul_i64(t2, t2, t3);
3584 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3585 tcg_gen_add_i64(t2, t2, t3);
3586 tcg_temp_free_i64(t3);
3587 tcg_gen_trunc_i64_tl(t0, t2);
3588 tcg_gen_shri_i64(t2, t2, 32);
3589 tcg_gen_trunc_i64_tl(t1, t2);
3590 tcg_temp_free_i64(t2);
3591 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3592 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3594 opn = "madd";
3595 break;
3596 case OPC_MADDU:
3598 TCGv_i64 t2 = tcg_temp_new_i64();
3599 TCGv_i64 t3 = tcg_temp_new_i64();
3601 tcg_gen_ext32u_tl(t0, t0);
3602 tcg_gen_ext32u_tl(t1, t1);
3603 tcg_gen_extu_tl_i64(t2, t0);
3604 tcg_gen_extu_tl_i64(t3, t1);
3605 tcg_gen_mul_i64(t2, t2, t3);
3606 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3607 tcg_gen_add_i64(t2, t2, t3);
3608 tcg_temp_free_i64(t3);
3609 tcg_gen_trunc_i64_tl(t0, t2);
3610 tcg_gen_shri_i64(t2, t2, 32);
3611 tcg_gen_trunc_i64_tl(t1, t2);
3612 tcg_temp_free_i64(t2);
3613 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3614 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3616 opn = "maddu";
3617 break;
3618 case OPC_MSUB:
3620 TCGv_i64 t2 = tcg_temp_new_i64();
3621 TCGv_i64 t3 = tcg_temp_new_i64();
3623 tcg_gen_ext_tl_i64(t2, t0);
3624 tcg_gen_ext_tl_i64(t3, t1);
3625 tcg_gen_mul_i64(t2, t2, t3);
3626 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3627 tcg_gen_sub_i64(t2, t3, t2);
3628 tcg_temp_free_i64(t3);
3629 tcg_gen_trunc_i64_tl(t0, t2);
3630 tcg_gen_shri_i64(t2, t2, 32);
3631 tcg_gen_trunc_i64_tl(t1, t2);
3632 tcg_temp_free_i64(t2);
3633 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3634 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3636 opn = "msub";
3637 break;
3638 case OPC_MSUBU:
3640 TCGv_i64 t2 = tcg_temp_new_i64();
3641 TCGv_i64 t3 = tcg_temp_new_i64();
3643 tcg_gen_ext32u_tl(t0, t0);
3644 tcg_gen_ext32u_tl(t1, t1);
3645 tcg_gen_extu_tl_i64(t2, t0);
3646 tcg_gen_extu_tl_i64(t3, t1);
3647 tcg_gen_mul_i64(t2, t2, t3);
3648 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3649 tcg_gen_sub_i64(t2, t3, t2);
3650 tcg_temp_free_i64(t3);
3651 tcg_gen_trunc_i64_tl(t0, t2);
3652 tcg_gen_shri_i64(t2, t2, 32);
3653 tcg_gen_trunc_i64_tl(t1, t2);
3654 tcg_temp_free_i64(t2);
3655 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3656 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3658 opn = "msubu";
3659 break;
3660 default:
3661 MIPS_INVAL(opn);
3662 generate_exception(ctx, EXCP_RI);
3663 goto out;
3665 (void)opn; /* avoid a compiler warning */
3666 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3667 out:
3668 tcg_temp_free(t0);
3669 tcg_temp_free(t1);
3672 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3673 int rd, int rs, int rt)
3675 const char *opn = "mul vr54xx";
3676 TCGv t0 = tcg_temp_new();
3677 TCGv t1 = tcg_temp_new();
3679 gen_load_gpr(t0, rs);
3680 gen_load_gpr(t1, rt);
3682 switch (opc) {
3683 case OPC_VR54XX_MULS:
3684 gen_helper_muls(t0, cpu_env, t0, t1);
3685 opn = "muls";
3686 break;
3687 case OPC_VR54XX_MULSU:
3688 gen_helper_mulsu(t0, cpu_env, t0, t1);
3689 opn = "mulsu";
3690 break;
3691 case OPC_VR54XX_MACC:
3692 gen_helper_macc(t0, cpu_env, t0, t1);
3693 opn = "macc";
3694 break;
3695 case OPC_VR54XX_MACCU:
3696 gen_helper_maccu(t0, cpu_env, t0, t1);
3697 opn = "maccu";
3698 break;
3699 case OPC_VR54XX_MSAC:
3700 gen_helper_msac(t0, cpu_env, t0, t1);
3701 opn = "msac";
3702 break;
3703 case OPC_VR54XX_MSACU:
3704 gen_helper_msacu(t0, cpu_env, t0, t1);
3705 opn = "msacu";
3706 break;
3707 case OPC_VR54XX_MULHI:
3708 gen_helper_mulhi(t0, cpu_env, t0, t1);
3709 opn = "mulhi";
3710 break;
3711 case OPC_VR54XX_MULHIU:
3712 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3713 opn = "mulhiu";
3714 break;
3715 case OPC_VR54XX_MULSHI:
3716 gen_helper_mulshi(t0, cpu_env, t0, t1);
3717 opn = "mulshi";
3718 break;
3719 case OPC_VR54XX_MULSHIU:
3720 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3721 opn = "mulshiu";
3722 break;
3723 case OPC_VR54XX_MACCHI:
3724 gen_helper_macchi(t0, cpu_env, t0, t1);
3725 opn = "macchi";
3726 break;
3727 case OPC_VR54XX_MACCHIU:
3728 gen_helper_macchiu(t0, cpu_env, t0, t1);
3729 opn = "macchiu";
3730 break;
3731 case OPC_VR54XX_MSACHI:
3732 gen_helper_msachi(t0, cpu_env, t0, t1);
3733 opn = "msachi";
3734 break;
3735 case OPC_VR54XX_MSACHIU:
3736 gen_helper_msachiu(t0, cpu_env, t0, t1);
3737 opn = "msachiu";
3738 break;
3739 default:
3740 MIPS_INVAL("mul vr54xx");
3741 generate_exception(ctx, EXCP_RI);
3742 goto out;
3744 gen_store_gpr(t0, rd);
3745 (void)opn; /* avoid a compiler warning */
3746 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3748 out:
3749 tcg_temp_free(t0);
3750 tcg_temp_free(t1);
3753 static void gen_cl (DisasContext *ctx, uint32_t opc,
3754 int rd, int rs)
3756 const char *opn = "CLx";
3757 TCGv t0;
3759 if (rd == 0) {
3760 /* Treat as NOP. */
3761 MIPS_DEBUG("NOP");
3762 return;
3764 t0 = tcg_temp_new();
3765 gen_load_gpr(t0, rs);
3766 switch (opc) {
3767 case OPC_CLO:
3768 case R6_OPC_CLO:
3769 gen_helper_clo(cpu_gpr[rd], t0);
3770 opn = "clo";
3771 break;
3772 case OPC_CLZ:
3773 case R6_OPC_CLZ:
3774 gen_helper_clz(cpu_gpr[rd], t0);
3775 opn = "clz";
3776 break;
3777 #if defined(TARGET_MIPS64)
3778 case OPC_DCLO:
3779 case R6_OPC_DCLO:
3780 gen_helper_dclo(cpu_gpr[rd], t0);
3781 opn = "dclo";
3782 break;
3783 case OPC_DCLZ:
3784 case R6_OPC_DCLZ:
3785 gen_helper_dclz(cpu_gpr[rd], t0);
3786 opn = "dclz";
3787 break;
3788 #endif
3790 (void)opn; /* avoid a compiler warning */
3791 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3792 tcg_temp_free(t0);
3795 /* Godson integer instructions */
3796 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3797 int rd, int rs, int rt)
3799 const char *opn = "loongson";
3800 TCGv t0, t1;
3802 if (rd == 0) {
3803 /* Treat as NOP. */
3804 MIPS_DEBUG("NOP");
3805 return;
3808 switch (opc) {
3809 case OPC_MULT_G_2E:
3810 case OPC_MULT_G_2F:
3811 case OPC_MULTU_G_2E:
3812 case OPC_MULTU_G_2F:
3813 #if defined(TARGET_MIPS64)
3814 case OPC_DMULT_G_2E:
3815 case OPC_DMULT_G_2F:
3816 case OPC_DMULTU_G_2E:
3817 case OPC_DMULTU_G_2F:
3818 #endif
3819 t0 = tcg_temp_new();
3820 t1 = tcg_temp_new();
3821 break;
3822 default:
3823 t0 = tcg_temp_local_new();
3824 t1 = tcg_temp_local_new();
3825 break;
3828 gen_load_gpr(t0, rs);
3829 gen_load_gpr(t1, rt);
3831 switch (opc) {
3832 case OPC_MULT_G_2E:
3833 case OPC_MULT_G_2F:
3834 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3835 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3836 opn = "mult.g";
3837 break;
3838 case OPC_MULTU_G_2E:
3839 case OPC_MULTU_G_2F:
3840 tcg_gen_ext32u_tl(t0, t0);
3841 tcg_gen_ext32u_tl(t1, t1);
3842 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3843 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3844 opn = "multu.g";
3845 break;
3846 case OPC_DIV_G_2E:
3847 case OPC_DIV_G_2F:
3849 int l1 = gen_new_label();
3850 int l2 = gen_new_label();
3851 int l3 = gen_new_label();
3852 tcg_gen_ext32s_tl(t0, t0);
3853 tcg_gen_ext32s_tl(t1, t1);
3854 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3855 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3856 tcg_gen_br(l3);
3857 gen_set_label(l1);
3858 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3859 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3860 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3861 tcg_gen_br(l3);
3862 gen_set_label(l2);
3863 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3864 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3865 gen_set_label(l3);
3867 opn = "div.g";
3868 break;
3869 case OPC_DIVU_G_2E:
3870 case OPC_DIVU_G_2F:
3872 int l1 = gen_new_label();
3873 int l2 = gen_new_label();
3874 tcg_gen_ext32u_tl(t0, t0);
3875 tcg_gen_ext32u_tl(t1, t1);
3876 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3877 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3878 tcg_gen_br(l2);
3879 gen_set_label(l1);
3880 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3881 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3882 gen_set_label(l2);
3884 opn = "divu.g";
3885 break;
3886 case OPC_MOD_G_2E:
3887 case OPC_MOD_G_2F:
3889 int l1 = gen_new_label();
3890 int l2 = gen_new_label();
3891 int l3 = gen_new_label();
3892 tcg_gen_ext32u_tl(t0, t0);
3893 tcg_gen_ext32u_tl(t1, t1);
3894 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3895 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3896 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3897 gen_set_label(l1);
3898 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3899 tcg_gen_br(l3);
3900 gen_set_label(l2);
3901 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3902 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3903 gen_set_label(l3);
3905 opn = "mod.g";
3906 break;
3907 case OPC_MODU_G_2E:
3908 case OPC_MODU_G_2F:
3910 int l1 = gen_new_label();
3911 int l2 = gen_new_label();
3912 tcg_gen_ext32u_tl(t0, t0);
3913 tcg_gen_ext32u_tl(t1, t1);
3914 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3915 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3916 tcg_gen_br(l2);
3917 gen_set_label(l1);
3918 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3919 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3920 gen_set_label(l2);
3922 opn = "modu.g";
3923 break;
3924 #if defined(TARGET_MIPS64)
3925 case OPC_DMULT_G_2E:
3926 case OPC_DMULT_G_2F:
3927 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3928 opn = "dmult.g";
3929 break;
3930 case OPC_DMULTU_G_2E:
3931 case OPC_DMULTU_G_2F:
3932 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3933 opn = "dmultu.g";
3934 break;
3935 case OPC_DDIV_G_2E:
3936 case OPC_DDIV_G_2F:
3938 int l1 = gen_new_label();
3939 int l2 = gen_new_label();
3940 int l3 = gen_new_label();
3941 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3942 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3943 tcg_gen_br(l3);
3944 gen_set_label(l1);
3945 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3946 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3947 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3948 tcg_gen_br(l3);
3949 gen_set_label(l2);
3950 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3951 gen_set_label(l3);
3953 opn = "ddiv.g";
3954 break;
3955 case OPC_DDIVU_G_2E:
3956 case OPC_DDIVU_G_2F:
3958 int l1 = gen_new_label();
3959 int l2 = gen_new_label();
3960 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3961 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3962 tcg_gen_br(l2);
3963 gen_set_label(l1);
3964 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3965 gen_set_label(l2);
3967 opn = "ddivu.g";
3968 break;
3969 case OPC_DMOD_G_2E:
3970 case OPC_DMOD_G_2F:
3972 int l1 = gen_new_label();
3973 int l2 = gen_new_label();
3974 int l3 = gen_new_label();
3975 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3976 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3977 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3978 gen_set_label(l1);
3979 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3980 tcg_gen_br(l3);
3981 gen_set_label(l2);
3982 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3983 gen_set_label(l3);
3985 opn = "dmod.g";
3986 break;
3987 case OPC_DMODU_G_2E:
3988 case OPC_DMODU_G_2F:
3990 int l1 = gen_new_label();
3991 int 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_remu_tl(cpu_gpr[rd], t0, t1);
3997 gen_set_label(l2);
3999 opn = "dmodu.g";
4000 break;
4001 #endif
4004 (void)opn; /* avoid a compiler warning */
4005 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
4006 tcg_temp_free(t0);
4007 tcg_temp_free(t1);
4010 /* Loongson multimedia instructions */
4011 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4013 const char *opn = "loongson_cp2";
4014 uint32_t opc, shift_max;
4015 TCGv_i64 t0, t1;
4017 opc = MASK_LMI(ctx->opcode);
4018 switch (opc) {
4019 case OPC_ADD_CP2:
4020 case OPC_SUB_CP2:
4021 case OPC_DADD_CP2:
4022 case OPC_DSUB_CP2:
4023 t0 = tcg_temp_local_new_i64();
4024 t1 = tcg_temp_local_new_i64();
4025 break;
4026 default:
4027 t0 = tcg_temp_new_i64();
4028 t1 = tcg_temp_new_i64();
4029 break;
4032 gen_load_fpr64(ctx, t0, rs);
4033 gen_load_fpr64(ctx, t1, rt);
4035 #define LMI_HELPER(UP, LO) \
4036 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
4037 #define LMI_HELPER_1(UP, LO) \
4038 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
4039 #define LMI_DIRECT(UP, LO, OP) \
4040 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
4042 switch (opc) {
4043 LMI_HELPER(PADDSH, paddsh);
4044 LMI_HELPER(PADDUSH, paddush);
4045 LMI_HELPER(PADDH, paddh);
4046 LMI_HELPER(PADDW, paddw);
4047 LMI_HELPER(PADDSB, paddsb);
4048 LMI_HELPER(PADDUSB, paddusb);
4049 LMI_HELPER(PADDB, paddb);
4051 LMI_HELPER(PSUBSH, psubsh);
4052 LMI_HELPER(PSUBUSH, psubush);
4053 LMI_HELPER(PSUBH, psubh);
4054 LMI_HELPER(PSUBW, psubw);
4055 LMI_HELPER(PSUBSB, psubsb);
4056 LMI_HELPER(PSUBUSB, psubusb);
4057 LMI_HELPER(PSUBB, psubb);
4059 LMI_HELPER(PSHUFH, pshufh);
4060 LMI_HELPER(PACKSSWH, packsswh);
4061 LMI_HELPER(PACKSSHB, packsshb);
4062 LMI_HELPER(PACKUSHB, packushb);
4064 LMI_HELPER(PUNPCKLHW, punpcklhw);
4065 LMI_HELPER(PUNPCKHHW, punpckhhw);
4066 LMI_HELPER(PUNPCKLBH, punpcklbh);
4067 LMI_HELPER(PUNPCKHBH, punpckhbh);
4068 LMI_HELPER(PUNPCKLWD, punpcklwd);
4069 LMI_HELPER(PUNPCKHWD, punpckhwd);
4071 LMI_HELPER(PAVGH, pavgh);
4072 LMI_HELPER(PAVGB, pavgb);
4073 LMI_HELPER(PMAXSH, pmaxsh);
4074 LMI_HELPER(PMINSH, pminsh);
4075 LMI_HELPER(PMAXUB, pmaxub);
4076 LMI_HELPER(PMINUB, pminub);
4078 LMI_HELPER(PCMPEQW, pcmpeqw);
4079 LMI_HELPER(PCMPGTW, pcmpgtw);
4080 LMI_HELPER(PCMPEQH, pcmpeqh);
4081 LMI_HELPER(PCMPGTH, pcmpgth);
4082 LMI_HELPER(PCMPEQB, pcmpeqb);
4083 LMI_HELPER(PCMPGTB, pcmpgtb);
4085 LMI_HELPER(PSLLW, psllw);
4086 LMI_HELPER(PSLLH, psllh);
4087 LMI_HELPER(PSRLW, psrlw);
4088 LMI_HELPER(PSRLH, psrlh);
4089 LMI_HELPER(PSRAW, psraw);
4090 LMI_HELPER(PSRAH, psrah);
4092 LMI_HELPER(PMULLH, pmullh);
4093 LMI_HELPER(PMULHH, pmulhh);
4094 LMI_HELPER(PMULHUH, pmulhuh);
4095 LMI_HELPER(PMADDHW, pmaddhw);
4097 LMI_HELPER(PASUBUB, pasubub);
4098 LMI_HELPER_1(BIADD, biadd);
4099 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4101 LMI_DIRECT(PADDD, paddd, add);
4102 LMI_DIRECT(PSUBD, psubd, sub);
4103 LMI_DIRECT(XOR_CP2, xor, xor);
4104 LMI_DIRECT(NOR_CP2, nor, nor);
4105 LMI_DIRECT(AND_CP2, and, and);
4106 LMI_DIRECT(PANDN, pandn, andc);
4107 LMI_DIRECT(OR, or, or);
4109 case OPC_PINSRH_0:
4110 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4111 opn = "pinsrh_0";
4112 break;
4113 case OPC_PINSRH_1:
4114 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4115 opn = "pinsrh_1";
4116 break;
4117 case OPC_PINSRH_2:
4118 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4119 opn = "pinsrh_2";
4120 break;
4121 case OPC_PINSRH_3:
4122 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4123 opn = "pinsrh_3";
4124 break;
4126 case OPC_PEXTRH:
4127 tcg_gen_andi_i64(t1, t1, 3);
4128 tcg_gen_shli_i64(t1, t1, 4);
4129 tcg_gen_shr_i64(t0, t0, t1);
4130 tcg_gen_ext16u_i64(t0, t0);
4131 opn = "pextrh";
4132 break;
4134 case OPC_ADDU_CP2:
4135 tcg_gen_add_i64(t0, t0, t1);
4136 tcg_gen_ext32s_i64(t0, t0);
4137 opn = "addu";
4138 break;
4139 case OPC_SUBU_CP2:
4140 tcg_gen_sub_i64(t0, t0, t1);
4141 tcg_gen_ext32s_i64(t0, t0);
4142 opn = "addu";
4143 break;
4145 case OPC_SLL_CP2:
4146 opn = "sll";
4147 shift_max = 32;
4148 goto do_shift;
4149 case OPC_SRL_CP2:
4150 opn = "srl";
4151 shift_max = 32;
4152 goto do_shift;
4153 case OPC_SRA_CP2:
4154 opn = "sra";
4155 shift_max = 32;
4156 goto do_shift;
4157 case OPC_DSLL_CP2:
4158 opn = "dsll";
4159 shift_max = 64;
4160 goto do_shift;
4161 case OPC_DSRL_CP2:
4162 opn = "dsrl";
4163 shift_max = 64;
4164 goto do_shift;
4165 case OPC_DSRA_CP2:
4166 opn = "dsra";
4167 shift_max = 64;
4168 goto do_shift;
4169 do_shift:
4170 /* Make sure shift count isn't TCG undefined behaviour. */
4171 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4173 switch (opc) {
4174 case OPC_SLL_CP2:
4175 case OPC_DSLL_CP2:
4176 tcg_gen_shl_i64(t0, t0, t1);
4177 break;
4178 case OPC_SRA_CP2:
4179 case OPC_DSRA_CP2:
4180 /* Since SRA is UndefinedResult without sign-extended inputs,
4181 we can treat SRA and DSRA the same. */
4182 tcg_gen_sar_i64(t0, t0, t1);
4183 break;
4184 case OPC_SRL_CP2:
4185 /* We want to shift in zeros for SRL; zero-extend first. */
4186 tcg_gen_ext32u_i64(t0, t0);
4187 /* FALLTHRU */
4188 case OPC_DSRL_CP2:
4189 tcg_gen_shr_i64(t0, t0, t1);
4190 break;
4193 if (shift_max == 32) {
4194 tcg_gen_ext32s_i64(t0, t0);
4197 /* Shifts larger than MAX produce zero. */
4198 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4199 tcg_gen_neg_i64(t1, t1);
4200 tcg_gen_and_i64(t0, t0, t1);
4201 break;
4203 case OPC_ADD_CP2:
4204 case OPC_DADD_CP2:
4206 TCGv_i64 t2 = tcg_temp_new_i64();
4207 int lab = gen_new_label();
4209 tcg_gen_mov_i64(t2, t0);
4210 tcg_gen_add_i64(t0, t1, t2);
4211 if (opc == OPC_ADD_CP2) {
4212 tcg_gen_ext32s_i64(t0, t0);
4214 tcg_gen_xor_i64(t1, t1, t2);
4215 tcg_gen_xor_i64(t2, t2, t0);
4216 tcg_gen_andc_i64(t1, t2, t1);
4217 tcg_temp_free_i64(t2);
4218 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4219 generate_exception(ctx, EXCP_OVERFLOW);
4220 gen_set_label(lab);
4222 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
4223 break;
4226 case OPC_SUB_CP2:
4227 case OPC_DSUB_CP2:
4229 TCGv_i64 t2 = tcg_temp_new_i64();
4230 int lab = gen_new_label();
4232 tcg_gen_mov_i64(t2, t0);
4233 tcg_gen_sub_i64(t0, t1, t2);
4234 if (opc == OPC_SUB_CP2) {
4235 tcg_gen_ext32s_i64(t0, t0);
4237 tcg_gen_xor_i64(t1, t1, t2);
4238 tcg_gen_xor_i64(t2, t2, t0);
4239 tcg_gen_and_i64(t1, t1, t2);
4240 tcg_temp_free_i64(t2);
4241 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4242 generate_exception(ctx, EXCP_OVERFLOW);
4243 gen_set_label(lab);
4245 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
4246 break;
4249 case OPC_PMULUW:
4250 tcg_gen_ext32u_i64(t0, t0);
4251 tcg_gen_ext32u_i64(t1, t1);
4252 tcg_gen_mul_i64(t0, t0, t1);
4253 opn = "pmuluw";
4254 break;
4256 case OPC_SEQU_CP2:
4257 case OPC_SEQ_CP2:
4258 case OPC_SLTU_CP2:
4259 case OPC_SLT_CP2:
4260 case OPC_SLEU_CP2:
4261 case OPC_SLE_CP2:
4262 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4263 FD field is the CC field? */
4264 default:
4265 MIPS_INVAL(opn);
4266 generate_exception(ctx, EXCP_RI);
4267 return;
4270 #undef LMI_HELPER
4271 #undef LMI_DIRECT
4273 gen_store_fpr64(ctx, t0, rd);
4275 (void)opn; /* avoid a compiler warning */
4276 MIPS_DEBUG("%s %s, %s, %s", opn,
4277 fregnames[rd], fregnames[rs], fregnames[rt]);
4278 tcg_temp_free_i64(t0);
4279 tcg_temp_free_i64(t1);
4282 /* Traps */
4283 static void gen_trap (DisasContext *ctx, uint32_t opc,
4284 int rs, int rt, int16_t imm)
4286 int cond;
4287 TCGv t0 = tcg_temp_new();
4288 TCGv t1 = tcg_temp_new();
4290 cond = 0;
4291 /* Load needed operands */
4292 switch (opc) {
4293 case OPC_TEQ:
4294 case OPC_TGE:
4295 case OPC_TGEU:
4296 case OPC_TLT:
4297 case OPC_TLTU:
4298 case OPC_TNE:
4299 /* Compare two registers */
4300 if (rs != rt) {
4301 gen_load_gpr(t0, rs);
4302 gen_load_gpr(t1, rt);
4303 cond = 1;
4305 break;
4306 case OPC_TEQI:
4307 case OPC_TGEI:
4308 case OPC_TGEIU:
4309 case OPC_TLTI:
4310 case OPC_TLTIU:
4311 case OPC_TNEI:
4312 /* Compare register to immediate */
4313 if (rs != 0 || imm != 0) {
4314 gen_load_gpr(t0, rs);
4315 tcg_gen_movi_tl(t1, (int32_t)imm);
4316 cond = 1;
4318 break;
4320 if (cond == 0) {
4321 switch (opc) {
4322 case OPC_TEQ: /* rs == rs */
4323 case OPC_TEQI: /* r0 == 0 */
4324 case OPC_TGE: /* rs >= rs */
4325 case OPC_TGEI: /* r0 >= 0 */
4326 case OPC_TGEU: /* rs >= rs unsigned */
4327 case OPC_TGEIU: /* r0 >= 0 unsigned */
4328 /* Always trap */
4329 generate_exception(ctx, EXCP_TRAP);
4330 break;
4331 case OPC_TLT: /* rs < rs */
4332 case OPC_TLTI: /* r0 < 0 */
4333 case OPC_TLTU: /* rs < rs unsigned */
4334 case OPC_TLTIU: /* r0 < 0 unsigned */
4335 case OPC_TNE: /* rs != rs */
4336 case OPC_TNEI: /* r0 != 0 */
4337 /* Never trap: treat as NOP. */
4338 break;
4340 } else {
4341 int l1 = gen_new_label();
4343 switch (opc) {
4344 case OPC_TEQ:
4345 case OPC_TEQI:
4346 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4347 break;
4348 case OPC_TGE:
4349 case OPC_TGEI:
4350 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4351 break;
4352 case OPC_TGEU:
4353 case OPC_TGEIU:
4354 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4355 break;
4356 case OPC_TLT:
4357 case OPC_TLTI:
4358 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4359 break;
4360 case OPC_TLTU:
4361 case OPC_TLTIU:
4362 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4363 break;
4364 case OPC_TNE:
4365 case OPC_TNEI:
4366 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4367 break;
4369 generate_exception(ctx, EXCP_TRAP);
4370 gen_set_label(l1);
4372 tcg_temp_free(t0);
4373 tcg_temp_free(t1);
4376 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4378 TranslationBlock *tb;
4379 tb = ctx->tb;
4380 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
4381 likely(!ctx->singlestep_enabled)) {
4382 tcg_gen_goto_tb(n);
4383 gen_save_pc(dest);
4384 tcg_gen_exit_tb((uintptr_t)tb + n);
4385 } else {
4386 gen_save_pc(dest);
4387 if (ctx->singlestep_enabled) {
4388 save_cpu_state(ctx, 0);
4389 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
4391 tcg_gen_exit_tb(0);
4395 /* Branches (before delay slot) */
4396 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4397 int insn_bytes,
4398 int rs, int rt, int32_t offset,
4399 int delayslot_size)
4401 target_ulong btgt = -1;
4402 int blink = 0;
4403 int bcond_compute = 0;
4404 TCGv t0 = tcg_temp_new();
4405 TCGv t1 = tcg_temp_new();
4407 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4408 #ifdef MIPS_DEBUG_DISAS
4409 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4410 TARGET_FMT_lx "\n", ctx->pc);
4411 #endif
4412 generate_exception(ctx, EXCP_RI);
4413 goto out;
4416 /* Load needed operands */
4417 switch (opc) {
4418 case OPC_BEQ:
4419 case OPC_BEQL:
4420 case OPC_BNE:
4421 case OPC_BNEL:
4422 /* Compare two registers */
4423 if (rs != rt) {
4424 gen_load_gpr(t0, rs);
4425 gen_load_gpr(t1, rt);
4426 bcond_compute = 1;
4428 btgt = ctx->pc + insn_bytes + offset;
4429 break;
4430 case OPC_BGEZ:
4431 case OPC_BGEZAL:
4432 case OPC_BGEZALL:
4433 case OPC_BGEZL:
4434 case OPC_BGTZ:
4435 case OPC_BGTZL:
4436 case OPC_BLEZ:
4437 case OPC_BLEZL:
4438 case OPC_BLTZ:
4439 case OPC_BLTZAL:
4440 case OPC_BLTZALL:
4441 case OPC_BLTZL:
4442 /* Compare to zero */
4443 if (rs != 0) {
4444 gen_load_gpr(t0, rs);
4445 bcond_compute = 1;
4447 btgt = ctx->pc + insn_bytes + offset;
4448 break;
4449 case OPC_BPOSGE32:
4450 #if defined(TARGET_MIPS64)
4451 case OPC_BPOSGE64:
4452 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4453 #else
4454 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4455 #endif
4456 bcond_compute = 1;
4457 btgt = ctx->pc + insn_bytes + offset;
4458 break;
4459 case OPC_J:
4460 case OPC_JAL:
4461 case OPC_JALX:
4462 /* Jump to immediate */
4463 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4464 break;
4465 case OPC_JR:
4466 case OPC_JALR:
4467 /* Jump to register */
4468 if (offset != 0 && offset != 16) {
4469 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4470 others are reserved. */
4471 MIPS_INVAL("jump hint");
4472 generate_exception(ctx, EXCP_RI);
4473 goto out;
4475 gen_load_gpr(btarget, rs);
4476 break;
4477 default:
4478 MIPS_INVAL("branch/jump");
4479 generate_exception(ctx, EXCP_RI);
4480 goto out;
4482 if (bcond_compute == 0) {
4483 /* No condition to be computed */
4484 switch (opc) {
4485 case OPC_BEQ: /* rx == rx */
4486 case OPC_BEQL: /* rx == rx likely */
4487 case OPC_BGEZ: /* 0 >= 0 */
4488 case OPC_BGEZL: /* 0 >= 0 likely */
4489 case OPC_BLEZ: /* 0 <= 0 */
4490 case OPC_BLEZL: /* 0 <= 0 likely */
4491 /* Always take */
4492 ctx->hflags |= MIPS_HFLAG_B;
4493 MIPS_DEBUG("balways");
4494 break;
4495 case OPC_BGEZAL: /* 0 >= 0 */
4496 case OPC_BGEZALL: /* 0 >= 0 likely */
4497 /* Always take and link */
4498 blink = 31;
4499 ctx->hflags |= MIPS_HFLAG_B;
4500 MIPS_DEBUG("balways and link");
4501 break;
4502 case OPC_BNE: /* rx != rx */
4503 case OPC_BGTZ: /* 0 > 0 */
4504 case OPC_BLTZ: /* 0 < 0 */
4505 /* Treat as NOP. */
4506 MIPS_DEBUG("bnever (NOP)");
4507 goto out;
4508 case OPC_BLTZAL: /* 0 < 0 */
4509 /* Handle as an unconditional branch to get correct delay
4510 slot checking. */
4511 blink = 31;
4512 btgt = ctx->pc + insn_bytes + delayslot_size;
4513 ctx->hflags |= MIPS_HFLAG_B;
4514 MIPS_DEBUG("bnever and link");
4515 break;
4516 case OPC_BLTZALL: /* 0 < 0 likely */
4517 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4518 /* Skip the instruction in the delay slot */
4519 MIPS_DEBUG("bnever, link and skip");
4520 ctx->pc += 4;
4521 goto out;
4522 case OPC_BNEL: /* rx != rx likely */
4523 case OPC_BGTZL: /* 0 > 0 likely */
4524 case OPC_BLTZL: /* 0 < 0 likely */
4525 /* Skip the instruction in the delay slot */
4526 MIPS_DEBUG("bnever and skip");
4527 ctx->pc += 4;
4528 goto out;
4529 case OPC_J:
4530 ctx->hflags |= MIPS_HFLAG_B;
4531 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
4532 break;
4533 case OPC_JALX:
4534 ctx->hflags |= MIPS_HFLAG_BX;
4535 /* Fallthrough */
4536 case OPC_JAL:
4537 blink = 31;
4538 ctx->hflags |= MIPS_HFLAG_B;
4539 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
4540 break;
4541 case OPC_JR:
4542 ctx->hflags |= MIPS_HFLAG_BR;
4543 MIPS_DEBUG("jr %s", regnames[rs]);
4544 break;
4545 case OPC_JALR:
4546 blink = rt;
4547 ctx->hflags |= MIPS_HFLAG_BR;
4548 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
4549 break;
4550 default:
4551 MIPS_INVAL("branch/jump");
4552 generate_exception(ctx, EXCP_RI);
4553 goto out;
4555 } else {
4556 switch (opc) {
4557 case OPC_BEQ:
4558 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4559 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
4560 regnames[rs], regnames[rt], btgt);
4561 goto not_likely;
4562 case OPC_BEQL:
4563 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4564 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
4565 regnames[rs], regnames[rt], btgt);
4566 goto likely;
4567 case OPC_BNE:
4568 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4569 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
4570 regnames[rs], regnames[rt], btgt);
4571 goto not_likely;
4572 case OPC_BNEL:
4573 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4574 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
4575 regnames[rs], regnames[rt], btgt);
4576 goto likely;
4577 case OPC_BGEZ:
4578 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4579 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4580 goto not_likely;
4581 case OPC_BGEZL:
4582 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4583 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4584 goto likely;
4585 case OPC_BGEZAL:
4586 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4587 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4588 blink = 31;
4589 goto not_likely;
4590 case OPC_BGEZALL:
4591 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4592 blink = 31;
4593 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4594 goto likely;
4595 case OPC_BGTZ:
4596 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4597 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4598 goto not_likely;
4599 case OPC_BGTZL:
4600 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4601 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4602 goto likely;
4603 case OPC_BLEZ:
4604 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4605 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4606 goto not_likely;
4607 case OPC_BLEZL:
4608 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4609 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4610 goto likely;
4611 case OPC_BLTZ:
4612 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4613 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4614 goto not_likely;
4615 case OPC_BLTZL:
4616 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4617 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4618 goto likely;
4619 case OPC_BPOSGE32:
4620 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4621 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
4622 goto not_likely;
4623 #if defined(TARGET_MIPS64)
4624 case OPC_BPOSGE64:
4625 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4626 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
4627 goto not_likely;
4628 #endif
4629 case OPC_BLTZAL:
4630 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4631 blink = 31;
4632 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4633 not_likely:
4634 ctx->hflags |= MIPS_HFLAG_BC;
4635 break;
4636 case OPC_BLTZALL:
4637 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4638 blink = 31;
4639 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4640 likely:
4641 ctx->hflags |= MIPS_HFLAG_BL;
4642 break;
4643 default:
4644 MIPS_INVAL("conditional branch/jump");
4645 generate_exception(ctx, EXCP_RI);
4646 goto out;
4649 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
4650 blink, ctx->hflags, btgt);
4652 ctx->btarget = btgt;
4654 switch (delayslot_size) {
4655 case 2:
4656 ctx->hflags |= MIPS_HFLAG_BDS16;
4657 break;
4658 case 4:
4659 ctx->hflags |= MIPS_HFLAG_BDS32;
4660 break;
4663 if (blink > 0) {
4664 int post_delay = insn_bytes + delayslot_size;
4665 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4667 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4670 out:
4671 if (insn_bytes == 2)
4672 ctx->hflags |= MIPS_HFLAG_B16;
4673 tcg_temp_free(t0);
4674 tcg_temp_free(t1);
4677 /* special3 bitfield operations */
4678 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4679 int rs, int lsb, int msb)
4681 TCGv t0 = tcg_temp_new();
4682 TCGv t1 = tcg_temp_new();
4684 gen_load_gpr(t1, rs);
4685 switch (opc) {
4686 case OPC_EXT:
4687 if (lsb + msb > 31)
4688 goto fail;
4689 tcg_gen_shri_tl(t0, t1, lsb);
4690 if (msb != 31) {
4691 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
4692 } else {
4693 tcg_gen_ext32s_tl(t0, t0);
4695 break;
4696 #if defined(TARGET_MIPS64)
4697 case OPC_DEXTM:
4698 tcg_gen_shri_tl(t0, t1, lsb);
4699 if (msb != 31) {
4700 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
4702 break;
4703 case OPC_DEXTU:
4704 tcg_gen_shri_tl(t0, t1, lsb + 32);
4705 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4706 break;
4707 case OPC_DEXT:
4708 tcg_gen_shri_tl(t0, t1, lsb);
4709 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4710 break;
4711 #endif
4712 case OPC_INS:
4713 if (lsb > msb)
4714 goto fail;
4715 gen_load_gpr(t0, rt);
4716 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4717 tcg_gen_ext32s_tl(t0, t0);
4718 break;
4719 #if defined(TARGET_MIPS64)
4720 case OPC_DINSM:
4721 gen_load_gpr(t0, rt);
4722 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb + 32 - lsb + 1);
4723 break;
4724 case OPC_DINSU:
4725 gen_load_gpr(t0, rt);
4726 tcg_gen_deposit_tl(t0, t0, t1, lsb + 32, msb - lsb + 1);
4727 break;
4728 case OPC_DINS:
4729 gen_load_gpr(t0, rt);
4730 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4731 break;
4732 #endif
4733 default:
4734 fail:
4735 MIPS_INVAL("bitops");
4736 generate_exception(ctx, EXCP_RI);
4737 tcg_temp_free(t0);
4738 tcg_temp_free(t1);
4739 return;
4741 gen_store_gpr(t0, rt);
4742 tcg_temp_free(t0);
4743 tcg_temp_free(t1);
4746 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4748 TCGv t0;
4750 if (rd == 0) {
4751 /* If no destination, treat it as a NOP. */
4752 MIPS_DEBUG("NOP");
4753 return;
4756 t0 = tcg_temp_new();
4757 gen_load_gpr(t0, rt);
4758 switch (op2) {
4759 case OPC_WSBH:
4761 TCGv t1 = tcg_temp_new();
4763 tcg_gen_shri_tl(t1, t0, 8);
4764 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4765 tcg_gen_shli_tl(t0, t0, 8);
4766 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4767 tcg_gen_or_tl(t0, t0, t1);
4768 tcg_temp_free(t1);
4769 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4771 break;
4772 case OPC_SEB:
4773 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4774 break;
4775 case OPC_SEH:
4776 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4777 break;
4778 #if defined(TARGET_MIPS64)
4779 case OPC_DSBH:
4781 TCGv t1 = tcg_temp_new();
4783 tcg_gen_shri_tl(t1, t0, 8);
4784 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4785 tcg_gen_shli_tl(t0, t0, 8);
4786 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4787 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4788 tcg_temp_free(t1);
4790 break;
4791 case OPC_DSHD:
4793 TCGv t1 = tcg_temp_new();
4795 tcg_gen_shri_tl(t1, t0, 16);
4796 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4797 tcg_gen_shli_tl(t0, t0, 16);
4798 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4799 tcg_gen_or_tl(t0, t0, t1);
4800 tcg_gen_shri_tl(t1, t0, 32);
4801 tcg_gen_shli_tl(t0, t0, 32);
4802 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4803 tcg_temp_free(t1);
4805 break;
4806 #endif
4807 default:
4808 MIPS_INVAL("bsfhl");
4809 generate_exception(ctx, EXCP_RI);
4810 tcg_temp_free(t0);
4811 return;
4813 tcg_temp_free(t0);
4816 #ifndef CONFIG_USER_ONLY
4817 /* CP0 (MMU and control) */
4818 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4820 TCGv_i32 t0 = tcg_temp_new_i32();
4822 tcg_gen_ld_i32(t0, cpu_env, off);
4823 tcg_gen_ext_i32_tl(arg, t0);
4824 tcg_temp_free_i32(t0);
4827 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4829 tcg_gen_ld_tl(arg, cpu_env, off);
4830 tcg_gen_ext32s_tl(arg, arg);
4833 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4835 TCGv_i32 t0 = tcg_temp_new_i32();
4837 tcg_gen_trunc_tl_i32(t0, arg);
4838 tcg_gen_st_i32(t0, cpu_env, off);
4839 tcg_temp_free_i32(t0);
4842 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
4844 tcg_gen_ext32s_tl(arg, arg);
4845 tcg_gen_st_tl(arg, cpu_env, off);
4848 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
4850 if (ctx->insn_flags & ISA_MIPS32R6) {
4851 tcg_gen_movi_tl(arg, 0);
4852 } else {
4853 tcg_gen_movi_tl(arg, ~0);
4857 #define CP0_CHECK(c) \
4858 do { \
4859 if (!(c)) { \
4860 goto cp0_unimplemented; \
4862 } while (0)
4864 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4866 const char *rn = "invalid";
4868 if (sel != 0)
4869 check_insn(ctx, ISA_MIPS32);
4871 switch (reg) {
4872 case 0:
4873 switch (sel) {
4874 case 0:
4875 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4876 rn = "Index";
4877 break;
4878 case 1:
4879 CP0_CHECK(ctx->insn_flags & ASE_MT);
4880 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4881 rn = "MVPControl";
4882 break;
4883 case 2:
4884 CP0_CHECK(ctx->insn_flags & ASE_MT);
4885 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4886 rn = "MVPConf0";
4887 break;
4888 case 3:
4889 CP0_CHECK(ctx->insn_flags & ASE_MT);
4890 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4891 rn = "MVPConf1";
4892 break;
4893 default:
4894 goto cp0_unimplemented;
4896 break;
4897 case 1:
4898 switch (sel) {
4899 case 0:
4900 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
4901 gen_helper_mfc0_random(arg, cpu_env);
4902 rn = "Random";
4903 break;
4904 case 1:
4905 CP0_CHECK(ctx->insn_flags & ASE_MT);
4906 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4907 rn = "VPEControl";
4908 break;
4909 case 2:
4910 CP0_CHECK(ctx->insn_flags & ASE_MT);
4911 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
4912 rn = "VPEConf0";
4913 break;
4914 case 3:
4915 CP0_CHECK(ctx->insn_flags & ASE_MT);
4916 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
4917 rn = "VPEConf1";
4918 break;
4919 case 4:
4920 CP0_CHECK(ctx->insn_flags & ASE_MT);
4921 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
4922 rn = "YQMask";
4923 break;
4924 case 5:
4925 CP0_CHECK(ctx->insn_flags & ASE_MT);
4926 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
4927 rn = "VPESchedule";
4928 break;
4929 case 6:
4930 CP0_CHECK(ctx->insn_flags & ASE_MT);
4931 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4932 rn = "VPEScheFBack";
4933 break;
4934 case 7:
4935 CP0_CHECK(ctx->insn_flags & ASE_MT);
4936 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
4937 rn = "VPEOpt";
4938 break;
4939 default:
4940 goto cp0_unimplemented;
4942 break;
4943 case 2:
4944 switch (sel) {
4945 case 0:
4946 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
4947 #if defined(TARGET_MIPS64)
4948 if (ctx->rxi) {
4949 TCGv tmp = tcg_temp_new();
4950 tcg_gen_andi_tl(tmp, arg, (3ull << CP0EnLo_XI));
4951 tcg_gen_shri_tl(tmp, tmp, 32);
4952 tcg_gen_or_tl(arg, arg, tmp);
4953 tcg_temp_free(tmp);
4955 #endif
4956 tcg_gen_ext32s_tl(arg, arg);
4957 rn = "EntryLo0";
4958 break;
4959 case 1:
4960 CP0_CHECK(ctx->insn_flags & ASE_MT);
4961 gen_helper_mfc0_tcstatus(arg, cpu_env);
4962 rn = "TCStatus";
4963 break;
4964 case 2:
4965 CP0_CHECK(ctx->insn_flags & ASE_MT);
4966 gen_helper_mfc0_tcbind(arg, cpu_env);
4967 rn = "TCBind";
4968 break;
4969 case 3:
4970 CP0_CHECK(ctx->insn_flags & ASE_MT);
4971 gen_helper_mfc0_tcrestart(arg, cpu_env);
4972 rn = "TCRestart";
4973 break;
4974 case 4:
4975 CP0_CHECK(ctx->insn_flags & ASE_MT);
4976 gen_helper_mfc0_tchalt(arg, cpu_env);
4977 rn = "TCHalt";
4978 break;
4979 case 5:
4980 CP0_CHECK(ctx->insn_flags & ASE_MT);
4981 gen_helper_mfc0_tccontext(arg, cpu_env);
4982 rn = "TCContext";
4983 break;
4984 case 6:
4985 CP0_CHECK(ctx->insn_flags & ASE_MT);
4986 gen_helper_mfc0_tcschedule(arg, cpu_env);
4987 rn = "TCSchedule";
4988 break;
4989 case 7:
4990 CP0_CHECK(ctx->insn_flags & ASE_MT);
4991 gen_helper_mfc0_tcschefback(arg, cpu_env);
4992 rn = "TCScheFBack";
4993 break;
4994 default:
4995 goto cp0_unimplemented;
4997 break;
4998 case 3:
4999 switch (sel) {
5000 case 0:
5001 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
5002 #if defined(TARGET_MIPS64)
5003 if (ctx->rxi) {
5004 TCGv tmp = tcg_temp_new();
5005 tcg_gen_andi_tl(tmp, arg, (3ull << CP0EnLo_XI));
5006 tcg_gen_shri_tl(tmp, tmp, 32);
5007 tcg_gen_or_tl(arg, arg, tmp);
5008 tcg_temp_free(tmp);
5010 #endif
5011 tcg_gen_ext32s_tl(arg, arg);
5012 rn = "EntryLo1";
5013 break;
5014 default:
5015 goto cp0_unimplemented;
5017 break;
5018 case 4:
5019 switch (sel) {
5020 case 0:
5021 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5022 tcg_gen_ext32s_tl(arg, arg);
5023 rn = "Context";
5024 break;
5025 case 1:
5026 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5027 rn = "ContextConfig";
5028 goto cp0_unimplemented;
5029 // break;
5030 case 2:
5031 CP0_CHECK(ctx->ulri);
5032 tcg_gen_ld32s_tl(arg, cpu_env,
5033 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5034 rn = "UserLocal";
5035 break;
5036 default:
5037 goto cp0_unimplemented;
5039 break;
5040 case 5:
5041 switch (sel) {
5042 case 0:
5043 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5044 rn = "PageMask";
5045 break;
5046 case 1:
5047 check_insn(ctx, ISA_MIPS32R2);
5048 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5049 rn = "PageGrain";
5050 break;
5051 default:
5052 goto cp0_unimplemented;
5054 break;
5055 case 6:
5056 switch (sel) {
5057 case 0:
5058 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5059 rn = "Wired";
5060 break;
5061 case 1:
5062 check_insn(ctx, ISA_MIPS32R2);
5063 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5064 rn = "SRSConf0";
5065 break;
5066 case 2:
5067 check_insn(ctx, ISA_MIPS32R2);
5068 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5069 rn = "SRSConf1";
5070 break;
5071 case 3:
5072 check_insn(ctx, ISA_MIPS32R2);
5073 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5074 rn = "SRSConf2";
5075 break;
5076 case 4:
5077 check_insn(ctx, ISA_MIPS32R2);
5078 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5079 rn = "SRSConf3";
5080 break;
5081 case 5:
5082 check_insn(ctx, ISA_MIPS32R2);
5083 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5084 rn = "SRSConf4";
5085 break;
5086 default:
5087 goto cp0_unimplemented;
5089 break;
5090 case 7:
5091 switch (sel) {
5092 case 0:
5093 check_insn(ctx, ISA_MIPS32R2);
5094 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5095 rn = "HWREna";
5096 break;
5097 default:
5098 goto cp0_unimplemented;
5100 break;
5101 case 8:
5102 switch (sel) {
5103 case 0:
5104 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5105 tcg_gen_ext32s_tl(arg, arg);
5106 rn = "BadVAddr";
5107 break;
5108 case 1:
5109 CP0_CHECK(ctx->bi);
5110 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5111 rn = "BadInstr";
5112 break;
5113 case 2:
5114 CP0_CHECK(ctx->bp);
5115 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5116 rn = "BadInstrP";
5117 break;
5118 default:
5119 goto cp0_unimplemented;
5121 break;
5122 case 9:
5123 switch (sel) {
5124 case 0:
5125 /* Mark as an IO operation because we read the time. */
5126 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5127 gen_io_start();
5129 gen_helper_mfc0_count(arg, cpu_env);
5130 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5131 gen_io_end();
5133 /* Break the TB to be able to take timer interrupts immediately
5134 after reading count. */
5135 ctx->bstate = BS_STOP;
5136 rn = "Count";
5137 break;
5138 /* 6,7 are implementation dependent */
5139 default:
5140 goto cp0_unimplemented;
5142 break;
5143 case 10:
5144 switch (sel) {
5145 case 0:
5146 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5147 tcg_gen_ext32s_tl(arg, arg);
5148 rn = "EntryHi";
5149 break;
5150 default:
5151 goto cp0_unimplemented;
5153 break;
5154 case 11:
5155 switch (sel) {
5156 case 0:
5157 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5158 rn = "Compare";
5159 break;
5160 /* 6,7 are implementation dependent */
5161 default:
5162 goto cp0_unimplemented;
5164 break;
5165 case 12:
5166 switch (sel) {
5167 case 0:
5168 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5169 rn = "Status";
5170 break;
5171 case 1:
5172 check_insn(ctx, ISA_MIPS32R2);
5173 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5174 rn = "IntCtl";
5175 break;
5176 case 2:
5177 check_insn(ctx, ISA_MIPS32R2);
5178 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5179 rn = "SRSCtl";
5180 break;
5181 case 3:
5182 check_insn(ctx, ISA_MIPS32R2);
5183 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5184 rn = "SRSMap";
5185 break;
5186 default:
5187 goto cp0_unimplemented;
5189 break;
5190 case 13:
5191 switch (sel) {
5192 case 0:
5193 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5194 rn = "Cause";
5195 break;
5196 default:
5197 goto cp0_unimplemented;
5199 break;
5200 case 14:
5201 switch (sel) {
5202 case 0:
5203 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5204 tcg_gen_ext32s_tl(arg, arg);
5205 rn = "EPC";
5206 break;
5207 default:
5208 goto cp0_unimplemented;
5210 break;
5211 case 15:
5212 switch (sel) {
5213 case 0:
5214 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5215 rn = "PRid";
5216 break;
5217 case 1:
5218 check_insn(ctx, ISA_MIPS32R2);
5219 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5220 rn = "EBase";
5221 break;
5222 default:
5223 goto cp0_unimplemented;
5225 break;
5226 case 16:
5227 switch (sel) {
5228 case 0:
5229 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5230 rn = "Config";
5231 break;
5232 case 1:
5233 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5234 rn = "Config1";
5235 break;
5236 case 2:
5237 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5238 rn = "Config2";
5239 break;
5240 case 3:
5241 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5242 rn = "Config3";
5243 break;
5244 case 4:
5245 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5246 rn = "Config4";
5247 break;
5248 case 5:
5249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5250 rn = "Config5";
5251 break;
5252 /* 6,7 are implementation dependent */
5253 case 6:
5254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5255 rn = "Config6";
5256 break;
5257 case 7:
5258 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5259 rn = "Config7";
5260 break;
5261 default:
5262 goto cp0_unimplemented;
5264 break;
5265 case 17:
5266 switch (sel) {
5267 case 0:
5268 gen_helper_mfc0_lladdr(arg, cpu_env);
5269 rn = "LLAddr";
5270 break;
5271 default:
5272 goto cp0_unimplemented;
5274 break;
5275 case 18:
5276 switch (sel) {
5277 case 0 ... 7:
5278 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5279 rn = "WatchLo";
5280 break;
5281 default:
5282 goto cp0_unimplemented;
5284 break;
5285 case 19:
5286 switch (sel) {
5287 case 0 ...7:
5288 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5289 rn = "WatchHi";
5290 break;
5291 default:
5292 goto cp0_unimplemented;
5294 break;
5295 case 20:
5296 switch (sel) {
5297 case 0:
5298 #if defined(TARGET_MIPS64)
5299 check_insn(ctx, ISA_MIPS3);
5300 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5301 tcg_gen_ext32s_tl(arg, arg);
5302 rn = "XContext";
5303 break;
5304 #endif
5305 default:
5306 goto cp0_unimplemented;
5308 break;
5309 case 21:
5310 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5311 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5312 switch (sel) {
5313 case 0:
5314 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5315 rn = "Framemask";
5316 break;
5317 default:
5318 goto cp0_unimplemented;
5320 break;
5321 case 22:
5322 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5323 rn = "'Diagnostic"; /* implementation dependent */
5324 break;
5325 case 23:
5326 switch (sel) {
5327 case 0:
5328 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5329 rn = "Debug";
5330 break;
5331 case 1:
5332 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5333 rn = "TraceControl";
5334 // break;
5335 case 2:
5336 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5337 rn = "TraceControl2";
5338 // break;
5339 case 3:
5340 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5341 rn = "UserTraceData";
5342 // break;
5343 case 4:
5344 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5345 rn = "TraceBPC";
5346 // break;
5347 default:
5348 goto cp0_unimplemented;
5350 break;
5351 case 24:
5352 switch (sel) {
5353 case 0:
5354 /* EJTAG support */
5355 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5356 tcg_gen_ext32s_tl(arg, arg);
5357 rn = "DEPC";
5358 break;
5359 default:
5360 goto cp0_unimplemented;
5362 break;
5363 case 25:
5364 switch (sel) {
5365 case 0:
5366 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5367 rn = "Performance0";
5368 break;
5369 case 1:
5370 // gen_helper_mfc0_performance1(arg);
5371 rn = "Performance1";
5372 // break;
5373 case 2:
5374 // gen_helper_mfc0_performance2(arg);
5375 rn = "Performance2";
5376 // break;
5377 case 3:
5378 // gen_helper_mfc0_performance3(arg);
5379 rn = "Performance3";
5380 // break;
5381 case 4:
5382 // gen_helper_mfc0_performance4(arg);
5383 rn = "Performance4";
5384 // break;
5385 case 5:
5386 // gen_helper_mfc0_performance5(arg);
5387 rn = "Performance5";
5388 // break;
5389 case 6:
5390 // gen_helper_mfc0_performance6(arg);
5391 rn = "Performance6";
5392 // break;
5393 case 7:
5394 // gen_helper_mfc0_performance7(arg);
5395 rn = "Performance7";
5396 // break;
5397 default:
5398 goto cp0_unimplemented;
5400 break;
5401 case 26:
5402 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5403 rn = "ECC";
5404 break;
5405 case 27:
5406 switch (sel) {
5407 case 0 ... 3:
5408 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5409 rn = "CacheErr";
5410 break;
5411 default:
5412 goto cp0_unimplemented;
5414 break;
5415 case 28:
5416 switch (sel) {
5417 case 0:
5418 case 2:
5419 case 4:
5420 case 6:
5421 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
5422 rn = "TagLo";
5423 break;
5424 case 1:
5425 case 3:
5426 case 5:
5427 case 7:
5428 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5429 rn = "DataLo";
5430 break;
5431 default:
5432 goto cp0_unimplemented;
5434 break;
5435 case 29:
5436 switch (sel) {
5437 case 0:
5438 case 2:
5439 case 4:
5440 case 6:
5441 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5442 rn = "TagHi";
5443 break;
5444 case 1:
5445 case 3:
5446 case 5:
5447 case 7:
5448 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5449 rn = "DataHi";
5450 break;
5451 default:
5452 goto cp0_unimplemented;
5454 break;
5455 case 30:
5456 switch (sel) {
5457 case 0:
5458 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5459 tcg_gen_ext32s_tl(arg, arg);
5460 rn = "ErrorEPC";
5461 break;
5462 default:
5463 goto cp0_unimplemented;
5465 break;
5466 case 31:
5467 switch (sel) {
5468 case 0:
5469 /* EJTAG support */
5470 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5471 rn = "DESAVE";
5472 break;
5473 case 2 ... 7:
5474 CP0_CHECK(ctx->kscrexist & (1 << sel));
5475 tcg_gen_ld_tl(arg, cpu_env,
5476 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5477 tcg_gen_ext32s_tl(arg, arg);
5478 rn = "KScratch";
5479 break;
5480 default:
5481 goto cp0_unimplemented;
5483 break;
5484 default:
5485 goto cp0_unimplemented;
5487 (void)rn; /* avoid a compiler warning */
5488 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5489 return;
5491 cp0_unimplemented:
5492 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5493 gen_mfc0_unimplemented(ctx, arg);
5496 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5498 const char *rn = "invalid";
5500 if (sel != 0)
5501 check_insn(ctx, ISA_MIPS32);
5503 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5504 gen_io_start();
5507 switch (reg) {
5508 case 0:
5509 switch (sel) {
5510 case 0:
5511 gen_helper_mtc0_index(cpu_env, arg);
5512 rn = "Index";
5513 break;
5514 case 1:
5515 CP0_CHECK(ctx->insn_flags & ASE_MT);
5516 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5517 rn = "MVPControl";
5518 break;
5519 case 2:
5520 CP0_CHECK(ctx->insn_flags & ASE_MT);
5521 /* ignored */
5522 rn = "MVPConf0";
5523 break;
5524 case 3:
5525 CP0_CHECK(ctx->insn_flags & ASE_MT);
5526 /* ignored */
5527 rn = "MVPConf1";
5528 break;
5529 default:
5530 goto cp0_unimplemented;
5532 break;
5533 case 1:
5534 switch (sel) {
5535 case 0:
5536 /* ignored */
5537 rn = "Random";
5538 break;
5539 case 1:
5540 CP0_CHECK(ctx->insn_flags & ASE_MT);
5541 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5542 rn = "VPEControl";
5543 break;
5544 case 2:
5545 CP0_CHECK(ctx->insn_flags & ASE_MT);
5546 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5547 rn = "VPEConf0";
5548 break;
5549 case 3:
5550 CP0_CHECK(ctx->insn_flags & ASE_MT);
5551 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5552 rn = "VPEConf1";
5553 break;
5554 case 4:
5555 CP0_CHECK(ctx->insn_flags & ASE_MT);
5556 gen_helper_mtc0_yqmask(cpu_env, arg);
5557 rn = "YQMask";
5558 break;
5559 case 5:
5560 CP0_CHECK(ctx->insn_flags & ASE_MT);
5561 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5562 rn = "VPESchedule";
5563 break;
5564 case 6:
5565 CP0_CHECK(ctx->insn_flags & ASE_MT);
5566 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5567 rn = "VPEScheFBack";
5568 break;
5569 case 7:
5570 CP0_CHECK(ctx->insn_flags & ASE_MT);
5571 gen_helper_mtc0_vpeopt(cpu_env, arg);
5572 rn = "VPEOpt";
5573 break;
5574 default:
5575 goto cp0_unimplemented;
5577 break;
5578 case 2:
5579 switch (sel) {
5580 case 0:
5581 gen_helper_mtc0_entrylo0(cpu_env, arg);
5582 rn = "EntryLo0";
5583 break;
5584 case 1:
5585 CP0_CHECK(ctx->insn_flags & ASE_MT);
5586 gen_helper_mtc0_tcstatus(cpu_env, arg);
5587 rn = "TCStatus";
5588 break;
5589 case 2:
5590 CP0_CHECK(ctx->insn_flags & ASE_MT);
5591 gen_helper_mtc0_tcbind(cpu_env, arg);
5592 rn = "TCBind";
5593 break;
5594 case 3:
5595 CP0_CHECK(ctx->insn_flags & ASE_MT);
5596 gen_helper_mtc0_tcrestart(cpu_env, arg);
5597 rn = "TCRestart";
5598 break;
5599 case 4:
5600 CP0_CHECK(ctx->insn_flags & ASE_MT);
5601 gen_helper_mtc0_tchalt(cpu_env, arg);
5602 rn = "TCHalt";
5603 break;
5604 case 5:
5605 CP0_CHECK(ctx->insn_flags & ASE_MT);
5606 gen_helper_mtc0_tccontext(cpu_env, arg);
5607 rn = "TCContext";
5608 break;
5609 case 6:
5610 CP0_CHECK(ctx->insn_flags & ASE_MT);
5611 gen_helper_mtc0_tcschedule(cpu_env, arg);
5612 rn = "TCSchedule";
5613 break;
5614 case 7:
5615 CP0_CHECK(ctx->insn_flags & ASE_MT);
5616 gen_helper_mtc0_tcschefback(cpu_env, arg);
5617 rn = "TCScheFBack";
5618 break;
5619 default:
5620 goto cp0_unimplemented;
5622 break;
5623 case 3:
5624 switch (sel) {
5625 case 0:
5626 gen_helper_mtc0_entrylo1(cpu_env, arg);
5627 rn = "EntryLo1";
5628 break;
5629 default:
5630 goto cp0_unimplemented;
5632 break;
5633 case 4:
5634 switch (sel) {
5635 case 0:
5636 gen_helper_mtc0_context(cpu_env, arg);
5637 rn = "Context";
5638 break;
5639 case 1:
5640 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5641 rn = "ContextConfig";
5642 goto cp0_unimplemented;
5643 // break;
5644 case 2:
5645 CP0_CHECK(ctx->ulri);
5646 tcg_gen_st_tl(arg, cpu_env,
5647 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5648 rn = "UserLocal";
5649 break;
5650 default:
5651 goto cp0_unimplemented;
5653 break;
5654 case 5:
5655 switch (sel) {
5656 case 0:
5657 gen_helper_mtc0_pagemask(cpu_env, arg);
5658 rn = "PageMask";
5659 break;
5660 case 1:
5661 check_insn(ctx, ISA_MIPS32R2);
5662 gen_helper_mtc0_pagegrain(cpu_env, arg);
5663 rn = "PageGrain";
5664 break;
5665 default:
5666 goto cp0_unimplemented;
5668 break;
5669 case 6:
5670 switch (sel) {
5671 case 0:
5672 gen_helper_mtc0_wired(cpu_env, arg);
5673 rn = "Wired";
5674 break;
5675 case 1:
5676 check_insn(ctx, ISA_MIPS32R2);
5677 gen_helper_mtc0_srsconf0(cpu_env, arg);
5678 rn = "SRSConf0";
5679 break;
5680 case 2:
5681 check_insn(ctx, ISA_MIPS32R2);
5682 gen_helper_mtc0_srsconf1(cpu_env, arg);
5683 rn = "SRSConf1";
5684 break;
5685 case 3:
5686 check_insn(ctx, ISA_MIPS32R2);
5687 gen_helper_mtc0_srsconf2(cpu_env, arg);
5688 rn = "SRSConf2";
5689 break;
5690 case 4:
5691 check_insn(ctx, ISA_MIPS32R2);
5692 gen_helper_mtc0_srsconf3(cpu_env, arg);
5693 rn = "SRSConf3";
5694 break;
5695 case 5:
5696 check_insn(ctx, ISA_MIPS32R2);
5697 gen_helper_mtc0_srsconf4(cpu_env, arg);
5698 rn = "SRSConf4";
5699 break;
5700 default:
5701 goto cp0_unimplemented;
5703 break;
5704 case 7:
5705 switch (sel) {
5706 case 0:
5707 check_insn(ctx, ISA_MIPS32R2);
5708 gen_helper_mtc0_hwrena(cpu_env, arg);
5709 ctx->bstate = BS_STOP;
5710 rn = "HWREna";
5711 break;
5712 default:
5713 goto cp0_unimplemented;
5715 break;
5716 case 8:
5717 switch (sel) {
5718 case 0:
5719 /* ignored */
5720 rn = "BadVAddr";
5721 break;
5722 case 1:
5723 /* ignored */
5724 rn = "BadInstr";
5725 break;
5726 case 2:
5727 /* ignored */
5728 rn = "BadInstrP";
5729 break;
5730 default:
5731 goto cp0_unimplemented;
5733 break;
5734 case 9:
5735 switch (sel) {
5736 case 0:
5737 gen_helper_mtc0_count(cpu_env, arg);
5738 rn = "Count";
5739 break;
5740 /* 6,7 are implementation dependent */
5741 default:
5742 goto cp0_unimplemented;
5744 break;
5745 case 10:
5746 switch (sel) {
5747 case 0:
5748 gen_helper_mtc0_entryhi(cpu_env, arg);
5749 rn = "EntryHi";
5750 break;
5751 default:
5752 goto cp0_unimplemented;
5754 break;
5755 case 11:
5756 switch (sel) {
5757 case 0:
5758 gen_helper_mtc0_compare(cpu_env, arg);
5759 rn = "Compare";
5760 break;
5761 /* 6,7 are implementation dependent */
5762 default:
5763 goto cp0_unimplemented;
5765 break;
5766 case 12:
5767 switch (sel) {
5768 case 0:
5769 save_cpu_state(ctx, 1);
5770 gen_helper_mtc0_status(cpu_env, arg);
5771 /* BS_STOP isn't good enough here, hflags may have changed. */
5772 gen_save_pc(ctx->pc + 4);
5773 ctx->bstate = BS_EXCP;
5774 rn = "Status";
5775 break;
5776 case 1:
5777 check_insn(ctx, ISA_MIPS32R2);
5778 gen_helper_mtc0_intctl(cpu_env, arg);
5779 /* Stop translation as we may have switched the execution mode */
5780 ctx->bstate = BS_STOP;
5781 rn = "IntCtl";
5782 break;
5783 case 2:
5784 check_insn(ctx, ISA_MIPS32R2);
5785 gen_helper_mtc0_srsctl(cpu_env, arg);
5786 /* Stop translation as we may have switched the execution mode */
5787 ctx->bstate = BS_STOP;
5788 rn = "SRSCtl";
5789 break;
5790 case 3:
5791 check_insn(ctx, ISA_MIPS32R2);
5792 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5793 /* Stop translation as we may have switched the execution mode */
5794 ctx->bstate = BS_STOP;
5795 rn = "SRSMap";
5796 break;
5797 default:
5798 goto cp0_unimplemented;
5800 break;
5801 case 13:
5802 switch (sel) {
5803 case 0:
5804 save_cpu_state(ctx, 1);
5805 gen_helper_mtc0_cause(cpu_env, arg);
5806 rn = "Cause";
5807 break;
5808 default:
5809 goto cp0_unimplemented;
5811 break;
5812 case 14:
5813 switch (sel) {
5814 case 0:
5815 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
5816 rn = "EPC";
5817 break;
5818 default:
5819 goto cp0_unimplemented;
5821 break;
5822 case 15:
5823 switch (sel) {
5824 case 0:
5825 /* ignored */
5826 rn = "PRid";
5827 break;
5828 case 1:
5829 check_insn(ctx, ISA_MIPS32R2);
5830 gen_helper_mtc0_ebase(cpu_env, arg);
5831 rn = "EBase";
5832 break;
5833 default:
5834 goto cp0_unimplemented;
5836 break;
5837 case 16:
5838 switch (sel) {
5839 case 0:
5840 gen_helper_mtc0_config0(cpu_env, arg);
5841 rn = "Config";
5842 /* Stop translation as we may have switched the execution mode */
5843 ctx->bstate = BS_STOP;
5844 break;
5845 case 1:
5846 /* ignored, read only */
5847 rn = "Config1";
5848 break;
5849 case 2:
5850 gen_helper_mtc0_config2(cpu_env, arg);
5851 rn = "Config2";
5852 /* Stop translation as we may have switched the execution mode */
5853 ctx->bstate = BS_STOP;
5854 break;
5855 case 3:
5856 gen_helper_mtc0_config3(cpu_env, arg);
5857 rn = "Config3";
5858 /* Stop translation as we may have switched the execution mode */
5859 ctx->bstate = BS_STOP;
5860 break;
5861 case 4:
5862 gen_helper_mtc0_config4(cpu_env, arg);
5863 rn = "Config4";
5864 ctx->bstate = BS_STOP;
5865 break;
5866 case 5:
5867 gen_helper_mtc0_config5(cpu_env, arg);
5868 rn = "Config5";
5869 /* Stop translation as we may have switched the execution mode */
5870 ctx->bstate = BS_STOP;
5871 break;
5872 /* 6,7 are implementation dependent */
5873 case 6:
5874 /* ignored */
5875 rn = "Config6";
5876 break;
5877 case 7:
5878 /* ignored */
5879 rn = "Config7";
5880 break;
5881 default:
5882 rn = "Invalid config selector";
5883 goto cp0_unimplemented;
5885 break;
5886 case 17:
5887 switch (sel) {
5888 case 0:
5889 gen_helper_mtc0_lladdr(cpu_env, arg);
5890 rn = "LLAddr";
5891 break;
5892 default:
5893 goto cp0_unimplemented;
5895 break;
5896 case 18:
5897 switch (sel) {
5898 case 0 ... 7:
5899 gen_helper_0e1i(mtc0_watchlo, arg, sel);
5900 rn = "WatchLo";
5901 break;
5902 default:
5903 goto cp0_unimplemented;
5905 break;
5906 case 19:
5907 switch (sel) {
5908 case 0 ... 7:
5909 gen_helper_0e1i(mtc0_watchhi, arg, sel);
5910 rn = "WatchHi";
5911 break;
5912 default:
5913 goto cp0_unimplemented;
5915 break;
5916 case 20:
5917 switch (sel) {
5918 case 0:
5919 #if defined(TARGET_MIPS64)
5920 check_insn(ctx, ISA_MIPS3);
5921 gen_helper_mtc0_xcontext(cpu_env, arg);
5922 rn = "XContext";
5923 break;
5924 #endif
5925 default:
5926 goto cp0_unimplemented;
5928 break;
5929 case 21:
5930 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5931 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5932 switch (sel) {
5933 case 0:
5934 gen_helper_mtc0_framemask(cpu_env, arg);
5935 rn = "Framemask";
5936 break;
5937 default:
5938 goto cp0_unimplemented;
5940 break;
5941 case 22:
5942 /* ignored */
5943 rn = "Diagnostic"; /* implementation dependent */
5944 break;
5945 case 23:
5946 switch (sel) {
5947 case 0:
5948 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
5949 /* BS_STOP isn't good enough here, hflags may have changed. */
5950 gen_save_pc(ctx->pc + 4);
5951 ctx->bstate = BS_EXCP;
5952 rn = "Debug";
5953 break;
5954 case 1:
5955 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
5956 rn = "TraceControl";
5957 /* Stop translation as we may have switched the execution mode */
5958 ctx->bstate = BS_STOP;
5959 // break;
5960 case 2:
5961 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
5962 rn = "TraceControl2";
5963 /* Stop translation as we may have switched the execution mode */
5964 ctx->bstate = BS_STOP;
5965 // break;
5966 case 3:
5967 /* Stop translation as we may have switched the execution mode */
5968 ctx->bstate = BS_STOP;
5969 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
5970 rn = "UserTraceData";
5971 /* Stop translation as we may have switched the execution mode */
5972 ctx->bstate = BS_STOP;
5973 // break;
5974 case 4:
5975 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
5976 /* Stop translation as we may have switched the execution mode */
5977 ctx->bstate = BS_STOP;
5978 rn = "TraceBPC";
5979 // break;
5980 default:
5981 goto cp0_unimplemented;
5983 break;
5984 case 24:
5985 switch (sel) {
5986 case 0:
5987 /* EJTAG support */
5988 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
5989 rn = "DEPC";
5990 break;
5991 default:
5992 goto cp0_unimplemented;
5994 break;
5995 case 25:
5996 switch (sel) {
5997 case 0:
5998 gen_helper_mtc0_performance0(cpu_env, arg);
5999 rn = "Performance0";
6000 break;
6001 case 1:
6002 // gen_helper_mtc0_performance1(arg);
6003 rn = "Performance1";
6004 // break;
6005 case 2:
6006 // gen_helper_mtc0_performance2(arg);
6007 rn = "Performance2";
6008 // break;
6009 case 3:
6010 // gen_helper_mtc0_performance3(arg);
6011 rn = "Performance3";
6012 // break;
6013 case 4:
6014 // gen_helper_mtc0_performance4(arg);
6015 rn = "Performance4";
6016 // break;
6017 case 5:
6018 // gen_helper_mtc0_performance5(arg);
6019 rn = "Performance5";
6020 // break;
6021 case 6:
6022 // gen_helper_mtc0_performance6(arg);
6023 rn = "Performance6";
6024 // break;
6025 case 7:
6026 // gen_helper_mtc0_performance7(arg);
6027 rn = "Performance7";
6028 // break;
6029 default:
6030 goto cp0_unimplemented;
6032 break;
6033 case 26:
6034 /* ignored */
6035 rn = "ECC";
6036 break;
6037 case 27:
6038 switch (sel) {
6039 case 0 ... 3:
6040 /* ignored */
6041 rn = "CacheErr";
6042 break;
6043 default:
6044 goto cp0_unimplemented;
6046 break;
6047 case 28:
6048 switch (sel) {
6049 case 0:
6050 case 2:
6051 case 4:
6052 case 6:
6053 gen_helper_mtc0_taglo(cpu_env, arg);
6054 rn = "TagLo";
6055 break;
6056 case 1:
6057 case 3:
6058 case 5:
6059 case 7:
6060 gen_helper_mtc0_datalo(cpu_env, arg);
6061 rn = "DataLo";
6062 break;
6063 default:
6064 goto cp0_unimplemented;
6066 break;
6067 case 29:
6068 switch (sel) {
6069 case 0:
6070 case 2:
6071 case 4:
6072 case 6:
6073 gen_helper_mtc0_taghi(cpu_env, arg);
6074 rn = "TagHi";
6075 break;
6076 case 1:
6077 case 3:
6078 case 5:
6079 case 7:
6080 gen_helper_mtc0_datahi(cpu_env, arg);
6081 rn = "DataHi";
6082 break;
6083 default:
6084 rn = "invalid sel";
6085 goto cp0_unimplemented;
6087 break;
6088 case 30:
6089 switch (sel) {
6090 case 0:
6091 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
6092 rn = "ErrorEPC";
6093 break;
6094 default:
6095 goto cp0_unimplemented;
6097 break;
6098 case 31:
6099 switch (sel) {
6100 case 0:
6101 /* EJTAG support */
6102 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6103 rn = "DESAVE";
6104 break;
6105 case 2 ... 7:
6106 CP0_CHECK(ctx->kscrexist & (1 << sel));
6107 tcg_gen_st_tl(arg, cpu_env,
6108 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6109 rn = "KScratch";
6110 break;
6111 default:
6112 goto cp0_unimplemented;
6114 /* Stop translation as we may have switched the execution mode */
6115 ctx->bstate = BS_STOP;
6116 break;
6117 default:
6118 goto cp0_unimplemented;
6120 (void)rn; /* avoid a compiler warning */
6121 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6122 /* For simplicity assume that all writes can cause interrupts. */
6123 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6124 gen_io_end();
6125 ctx->bstate = BS_STOP;
6127 return;
6129 cp0_unimplemented:
6130 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6133 #if defined(TARGET_MIPS64)
6134 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6136 const char *rn = "invalid";
6138 if (sel != 0)
6139 check_insn(ctx, ISA_MIPS64);
6141 switch (reg) {
6142 case 0:
6143 switch (sel) {
6144 case 0:
6145 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6146 rn = "Index";
6147 break;
6148 case 1:
6149 CP0_CHECK(ctx->insn_flags & ASE_MT);
6150 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6151 rn = "MVPControl";
6152 break;
6153 case 2:
6154 CP0_CHECK(ctx->insn_flags & ASE_MT);
6155 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6156 rn = "MVPConf0";
6157 break;
6158 case 3:
6159 CP0_CHECK(ctx->insn_flags & ASE_MT);
6160 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6161 rn = "MVPConf1";
6162 break;
6163 default:
6164 goto cp0_unimplemented;
6166 break;
6167 case 1:
6168 switch (sel) {
6169 case 0:
6170 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6171 gen_helper_mfc0_random(arg, cpu_env);
6172 rn = "Random";
6173 break;
6174 case 1:
6175 CP0_CHECK(ctx->insn_flags & ASE_MT);
6176 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6177 rn = "VPEControl";
6178 break;
6179 case 2:
6180 CP0_CHECK(ctx->insn_flags & ASE_MT);
6181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6182 rn = "VPEConf0";
6183 break;
6184 case 3:
6185 CP0_CHECK(ctx->insn_flags & ASE_MT);
6186 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6187 rn = "VPEConf1";
6188 break;
6189 case 4:
6190 CP0_CHECK(ctx->insn_flags & ASE_MT);
6191 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6192 rn = "YQMask";
6193 break;
6194 case 5:
6195 CP0_CHECK(ctx->insn_flags & ASE_MT);
6196 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6197 rn = "VPESchedule";
6198 break;
6199 case 6:
6200 CP0_CHECK(ctx->insn_flags & ASE_MT);
6201 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6202 rn = "VPEScheFBack";
6203 break;
6204 case 7:
6205 CP0_CHECK(ctx->insn_flags & ASE_MT);
6206 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6207 rn = "VPEOpt";
6208 break;
6209 default:
6210 goto cp0_unimplemented;
6212 break;
6213 case 2:
6214 switch (sel) {
6215 case 0:
6216 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6217 rn = "EntryLo0";
6218 break;
6219 case 1:
6220 CP0_CHECK(ctx->insn_flags & ASE_MT);
6221 gen_helper_mfc0_tcstatus(arg, cpu_env);
6222 rn = "TCStatus";
6223 break;
6224 case 2:
6225 CP0_CHECK(ctx->insn_flags & ASE_MT);
6226 gen_helper_mfc0_tcbind(arg, cpu_env);
6227 rn = "TCBind";
6228 break;
6229 case 3:
6230 CP0_CHECK(ctx->insn_flags & ASE_MT);
6231 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6232 rn = "TCRestart";
6233 break;
6234 case 4:
6235 CP0_CHECK(ctx->insn_flags & ASE_MT);
6236 gen_helper_dmfc0_tchalt(arg, cpu_env);
6237 rn = "TCHalt";
6238 break;
6239 case 5:
6240 CP0_CHECK(ctx->insn_flags & ASE_MT);
6241 gen_helper_dmfc0_tccontext(arg, cpu_env);
6242 rn = "TCContext";
6243 break;
6244 case 6:
6245 CP0_CHECK(ctx->insn_flags & ASE_MT);
6246 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6247 rn = "TCSchedule";
6248 break;
6249 case 7:
6250 CP0_CHECK(ctx->insn_flags & ASE_MT);
6251 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6252 rn = "TCScheFBack";
6253 break;
6254 default:
6255 goto cp0_unimplemented;
6257 break;
6258 case 3:
6259 switch (sel) {
6260 case 0:
6261 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6262 rn = "EntryLo1";
6263 break;
6264 default:
6265 goto cp0_unimplemented;
6267 break;
6268 case 4:
6269 switch (sel) {
6270 case 0:
6271 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6272 rn = "Context";
6273 break;
6274 case 1:
6275 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6276 rn = "ContextConfig";
6277 goto cp0_unimplemented;
6278 // break;
6279 case 2:
6280 CP0_CHECK(ctx->ulri);
6281 tcg_gen_ld_tl(arg, cpu_env,
6282 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6283 rn = "UserLocal";
6284 break;
6285 default:
6286 goto cp0_unimplemented;
6288 break;
6289 case 5:
6290 switch (sel) {
6291 case 0:
6292 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6293 rn = "PageMask";
6294 break;
6295 case 1:
6296 check_insn(ctx, ISA_MIPS32R2);
6297 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6298 rn = "PageGrain";
6299 break;
6300 default:
6301 goto cp0_unimplemented;
6303 break;
6304 case 6:
6305 switch (sel) {
6306 case 0:
6307 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6308 rn = "Wired";
6309 break;
6310 case 1:
6311 check_insn(ctx, ISA_MIPS32R2);
6312 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6313 rn = "SRSConf0";
6314 break;
6315 case 2:
6316 check_insn(ctx, ISA_MIPS32R2);
6317 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6318 rn = "SRSConf1";
6319 break;
6320 case 3:
6321 check_insn(ctx, ISA_MIPS32R2);
6322 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6323 rn = "SRSConf2";
6324 break;
6325 case 4:
6326 check_insn(ctx, ISA_MIPS32R2);
6327 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6328 rn = "SRSConf3";
6329 break;
6330 case 5:
6331 check_insn(ctx, ISA_MIPS32R2);
6332 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6333 rn = "SRSConf4";
6334 break;
6335 default:
6336 goto cp0_unimplemented;
6338 break;
6339 case 7:
6340 switch (sel) {
6341 case 0:
6342 check_insn(ctx, ISA_MIPS32R2);
6343 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6344 rn = "HWREna";
6345 break;
6346 default:
6347 goto cp0_unimplemented;
6349 break;
6350 case 8:
6351 switch (sel) {
6352 case 0:
6353 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6354 rn = "BadVAddr";
6355 break;
6356 case 1:
6357 CP0_CHECK(ctx->bi);
6358 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6359 rn = "BadInstr";
6360 break;
6361 case 2:
6362 CP0_CHECK(ctx->bp);
6363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6364 rn = "BadInstrP";
6365 break;
6366 default:
6367 goto cp0_unimplemented;
6369 break;
6370 case 9:
6371 switch (sel) {
6372 case 0:
6373 /* Mark as an IO operation because we read the time. */
6374 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6375 gen_io_start();
6377 gen_helper_mfc0_count(arg, cpu_env);
6378 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6379 gen_io_end();
6381 /* Break the TB to be able to take timer interrupts immediately
6382 after reading count. */
6383 ctx->bstate = BS_STOP;
6384 rn = "Count";
6385 break;
6386 /* 6,7 are implementation dependent */
6387 default:
6388 goto cp0_unimplemented;
6390 break;
6391 case 10:
6392 switch (sel) {
6393 case 0:
6394 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6395 rn = "EntryHi";
6396 break;
6397 default:
6398 goto cp0_unimplemented;
6400 break;
6401 case 11:
6402 switch (sel) {
6403 case 0:
6404 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6405 rn = "Compare";
6406 break;
6407 /* 6,7 are implementation dependent */
6408 default:
6409 goto cp0_unimplemented;
6411 break;
6412 case 12:
6413 switch (sel) {
6414 case 0:
6415 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6416 rn = "Status";
6417 break;
6418 case 1:
6419 check_insn(ctx, ISA_MIPS32R2);
6420 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6421 rn = "IntCtl";
6422 break;
6423 case 2:
6424 check_insn(ctx, ISA_MIPS32R2);
6425 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6426 rn = "SRSCtl";
6427 break;
6428 case 3:
6429 check_insn(ctx, ISA_MIPS32R2);
6430 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6431 rn = "SRSMap";
6432 break;
6433 default:
6434 goto cp0_unimplemented;
6436 break;
6437 case 13:
6438 switch (sel) {
6439 case 0:
6440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6441 rn = "Cause";
6442 break;
6443 default:
6444 goto cp0_unimplemented;
6446 break;
6447 case 14:
6448 switch (sel) {
6449 case 0:
6450 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6451 rn = "EPC";
6452 break;
6453 default:
6454 goto cp0_unimplemented;
6456 break;
6457 case 15:
6458 switch (sel) {
6459 case 0:
6460 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6461 rn = "PRid";
6462 break;
6463 case 1:
6464 check_insn(ctx, ISA_MIPS32R2);
6465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6466 rn = "EBase";
6467 break;
6468 default:
6469 goto cp0_unimplemented;
6471 break;
6472 case 16:
6473 switch (sel) {
6474 case 0:
6475 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6476 rn = "Config";
6477 break;
6478 case 1:
6479 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6480 rn = "Config1";
6481 break;
6482 case 2:
6483 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6484 rn = "Config2";
6485 break;
6486 case 3:
6487 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6488 rn = "Config3";
6489 break;
6490 case 4:
6491 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6492 rn = "Config4";
6493 break;
6494 case 5:
6495 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6496 rn = "Config5";
6497 break;
6498 /* 6,7 are implementation dependent */
6499 case 6:
6500 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6501 rn = "Config6";
6502 break;
6503 case 7:
6504 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6505 rn = "Config7";
6506 break;
6507 default:
6508 goto cp0_unimplemented;
6510 break;
6511 case 17:
6512 switch (sel) {
6513 case 0:
6514 gen_helper_dmfc0_lladdr(arg, cpu_env);
6515 rn = "LLAddr";
6516 break;
6517 default:
6518 goto cp0_unimplemented;
6520 break;
6521 case 18:
6522 switch (sel) {
6523 case 0 ... 7:
6524 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6525 rn = "WatchLo";
6526 break;
6527 default:
6528 goto cp0_unimplemented;
6530 break;
6531 case 19:
6532 switch (sel) {
6533 case 0 ... 7:
6534 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6535 rn = "WatchHi";
6536 break;
6537 default:
6538 goto cp0_unimplemented;
6540 break;
6541 case 20:
6542 switch (sel) {
6543 case 0:
6544 check_insn(ctx, ISA_MIPS3);
6545 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6546 rn = "XContext";
6547 break;
6548 default:
6549 goto cp0_unimplemented;
6551 break;
6552 case 21:
6553 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6554 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6555 switch (sel) {
6556 case 0:
6557 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6558 rn = "Framemask";
6559 break;
6560 default:
6561 goto cp0_unimplemented;
6563 break;
6564 case 22:
6565 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6566 rn = "'Diagnostic"; /* implementation dependent */
6567 break;
6568 case 23:
6569 switch (sel) {
6570 case 0:
6571 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6572 rn = "Debug";
6573 break;
6574 case 1:
6575 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6576 rn = "TraceControl";
6577 // break;
6578 case 2:
6579 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6580 rn = "TraceControl2";
6581 // break;
6582 case 3:
6583 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6584 rn = "UserTraceData";
6585 // break;
6586 case 4:
6587 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6588 rn = "TraceBPC";
6589 // break;
6590 default:
6591 goto cp0_unimplemented;
6593 break;
6594 case 24:
6595 switch (sel) {
6596 case 0:
6597 /* EJTAG support */
6598 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6599 rn = "DEPC";
6600 break;
6601 default:
6602 goto cp0_unimplemented;
6604 break;
6605 case 25:
6606 switch (sel) {
6607 case 0:
6608 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6609 rn = "Performance0";
6610 break;
6611 case 1:
6612 // gen_helper_dmfc0_performance1(arg);
6613 rn = "Performance1";
6614 // break;
6615 case 2:
6616 // gen_helper_dmfc0_performance2(arg);
6617 rn = "Performance2";
6618 // break;
6619 case 3:
6620 // gen_helper_dmfc0_performance3(arg);
6621 rn = "Performance3";
6622 // break;
6623 case 4:
6624 // gen_helper_dmfc0_performance4(arg);
6625 rn = "Performance4";
6626 // break;
6627 case 5:
6628 // gen_helper_dmfc0_performance5(arg);
6629 rn = "Performance5";
6630 // break;
6631 case 6:
6632 // gen_helper_dmfc0_performance6(arg);
6633 rn = "Performance6";
6634 // break;
6635 case 7:
6636 // gen_helper_dmfc0_performance7(arg);
6637 rn = "Performance7";
6638 // break;
6639 default:
6640 goto cp0_unimplemented;
6642 break;
6643 case 26:
6644 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6645 rn = "ECC";
6646 break;
6647 case 27:
6648 switch (sel) {
6649 /* ignored */
6650 case 0 ... 3:
6651 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6652 rn = "CacheErr";
6653 break;
6654 default:
6655 goto cp0_unimplemented;
6657 break;
6658 case 28:
6659 switch (sel) {
6660 case 0:
6661 case 2:
6662 case 4:
6663 case 6:
6664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
6665 rn = "TagLo";
6666 break;
6667 case 1:
6668 case 3:
6669 case 5:
6670 case 7:
6671 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6672 rn = "DataLo";
6673 break;
6674 default:
6675 goto cp0_unimplemented;
6677 break;
6678 case 29:
6679 switch (sel) {
6680 case 0:
6681 case 2:
6682 case 4:
6683 case 6:
6684 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6685 rn = "TagHi";
6686 break;
6687 case 1:
6688 case 3:
6689 case 5:
6690 case 7:
6691 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6692 rn = "DataHi";
6693 break;
6694 default:
6695 goto cp0_unimplemented;
6697 break;
6698 case 30:
6699 switch (sel) {
6700 case 0:
6701 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6702 rn = "ErrorEPC";
6703 break;
6704 default:
6705 goto cp0_unimplemented;
6707 break;
6708 case 31:
6709 switch (sel) {
6710 case 0:
6711 /* EJTAG support */
6712 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6713 rn = "DESAVE";
6714 break;
6715 case 2 ... 7:
6716 CP0_CHECK(ctx->kscrexist & (1 << sel));
6717 tcg_gen_ld_tl(arg, cpu_env,
6718 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6719 rn = "KScratch";
6720 break;
6721 default:
6722 goto cp0_unimplemented;
6724 break;
6725 default:
6726 goto cp0_unimplemented;
6728 (void)rn; /* avoid a compiler warning */
6729 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6730 return;
6732 cp0_unimplemented:
6733 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6734 gen_mfc0_unimplemented(ctx, arg);
6737 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6739 const char *rn = "invalid";
6741 if (sel != 0)
6742 check_insn(ctx, ISA_MIPS64);
6744 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6745 gen_io_start();
6748 switch (reg) {
6749 case 0:
6750 switch (sel) {
6751 case 0:
6752 gen_helper_mtc0_index(cpu_env, arg);
6753 rn = "Index";
6754 break;
6755 case 1:
6756 CP0_CHECK(ctx->insn_flags & ASE_MT);
6757 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6758 rn = "MVPControl";
6759 break;
6760 case 2:
6761 CP0_CHECK(ctx->insn_flags & ASE_MT);
6762 /* ignored */
6763 rn = "MVPConf0";
6764 break;
6765 case 3:
6766 CP0_CHECK(ctx->insn_flags & ASE_MT);
6767 /* ignored */
6768 rn = "MVPConf1";
6769 break;
6770 default:
6771 goto cp0_unimplemented;
6773 break;
6774 case 1:
6775 switch (sel) {
6776 case 0:
6777 /* ignored */
6778 rn = "Random";
6779 break;
6780 case 1:
6781 CP0_CHECK(ctx->insn_flags & ASE_MT);
6782 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6783 rn = "VPEControl";
6784 break;
6785 case 2:
6786 CP0_CHECK(ctx->insn_flags & ASE_MT);
6787 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6788 rn = "VPEConf0";
6789 break;
6790 case 3:
6791 CP0_CHECK(ctx->insn_flags & ASE_MT);
6792 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6793 rn = "VPEConf1";
6794 break;
6795 case 4:
6796 CP0_CHECK(ctx->insn_flags & ASE_MT);
6797 gen_helper_mtc0_yqmask(cpu_env, arg);
6798 rn = "YQMask";
6799 break;
6800 case 5:
6801 CP0_CHECK(ctx->insn_flags & ASE_MT);
6802 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6803 rn = "VPESchedule";
6804 break;
6805 case 6:
6806 CP0_CHECK(ctx->insn_flags & ASE_MT);
6807 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6808 rn = "VPEScheFBack";
6809 break;
6810 case 7:
6811 CP0_CHECK(ctx->insn_flags & ASE_MT);
6812 gen_helper_mtc0_vpeopt(cpu_env, arg);
6813 rn = "VPEOpt";
6814 break;
6815 default:
6816 goto cp0_unimplemented;
6818 break;
6819 case 2:
6820 switch (sel) {
6821 case 0:
6822 gen_helper_dmtc0_entrylo0(cpu_env, arg);
6823 rn = "EntryLo0";
6824 break;
6825 case 1:
6826 CP0_CHECK(ctx->insn_flags & ASE_MT);
6827 gen_helper_mtc0_tcstatus(cpu_env, arg);
6828 rn = "TCStatus";
6829 break;
6830 case 2:
6831 CP0_CHECK(ctx->insn_flags & ASE_MT);
6832 gen_helper_mtc0_tcbind(cpu_env, arg);
6833 rn = "TCBind";
6834 break;
6835 case 3:
6836 CP0_CHECK(ctx->insn_flags & ASE_MT);
6837 gen_helper_mtc0_tcrestart(cpu_env, arg);
6838 rn = "TCRestart";
6839 break;
6840 case 4:
6841 CP0_CHECK(ctx->insn_flags & ASE_MT);
6842 gen_helper_mtc0_tchalt(cpu_env, arg);
6843 rn = "TCHalt";
6844 break;
6845 case 5:
6846 CP0_CHECK(ctx->insn_flags & ASE_MT);
6847 gen_helper_mtc0_tccontext(cpu_env, arg);
6848 rn = "TCContext";
6849 break;
6850 case 6:
6851 CP0_CHECK(ctx->insn_flags & ASE_MT);
6852 gen_helper_mtc0_tcschedule(cpu_env, arg);
6853 rn = "TCSchedule";
6854 break;
6855 case 7:
6856 CP0_CHECK(ctx->insn_flags & ASE_MT);
6857 gen_helper_mtc0_tcschefback(cpu_env, arg);
6858 rn = "TCScheFBack";
6859 break;
6860 default:
6861 goto cp0_unimplemented;
6863 break;
6864 case 3:
6865 switch (sel) {
6866 case 0:
6867 gen_helper_dmtc0_entrylo1(cpu_env, arg);
6868 rn = "EntryLo1";
6869 break;
6870 default:
6871 goto cp0_unimplemented;
6873 break;
6874 case 4:
6875 switch (sel) {
6876 case 0:
6877 gen_helper_mtc0_context(cpu_env, arg);
6878 rn = "Context";
6879 break;
6880 case 1:
6881 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
6882 rn = "ContextConfig";
6883 goto cp0_unimplemented;
6884 // break;
6885 case 2:
6886 CP0_CHECK(ctx->ulri);
6887 tcg_gen_st_tl(arg, cpu_env,
6888 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6889 rn = "UserLocal";
6890 break;
6891 default:
6892 goto cp0_unimplemented;
6894 break;
6895 case 5:
6896 switch (sel) {
6897 case 0:
6898 gen_helper_mtc0_pagemask(cpu_env, arg);
6899 rn = "PageMask";
6900 break;
6901 case 1:
6902 check_insn(ctx, ISA_MIPS32R2);
6903 gen_helper_mtc0_pagegrain(cpu_env, arg);
6904 rn = "PageGrain";
6905 break;
6906 default:
6907 goto cp0_unimplemented;
6909 break;
6910 case 6:
6911 switch (sel) {
6912 case 0:
6913 gen_helper_mtc0_wired(cpu_env, arg);
6914 rn = "Wired";
6915 break;
6916 case 1:
6917 check_insn(ctx, ISA_MIPS32R2);
6918 gen_helper_mtc0_srsconf0(cpu_env, arg);
6919 rn = "SRSConf0";
6920 break;
6921 case 2:
6922 check_insn(ctx, ISA_MIPS32R2);
6923 gen_helper_mtc0_srsconf1(cpu_env, arg);
6924 rn = "SRSConf1";
6925 break;
6926 case 3:
6927 check_insn(ctx, ISA_MIPS32R2);
6928 gen_helper_mtc0_srsconf2(cpu_env, arg);
6929 rn = "SRSConf2";
6930 break;
6931 case 4:
6932 check_insn(ctx, ISA_MIPS32R2);
6933 gen_helper_mtc0_srsconf3(cpu_env, arg);
6934 rn = "SRSConf3";
6935 break;
6936 case 5:
6937 check_insn(ctx, ISA_MIPS32R2);
6938 gen_helper_mtc0_srsconf4(cpu_env, arg);
6939 rn = "SRSConf4";
6940 break;
6941 default:
6942 goto cp0_unimplemented;
6944 break;
6945 case 7:
6946 switch (sel) {
6947 case 0:
6948 check_insn(ctx, ISA_MIPS32R2);
6949 gen_helper_mtc0_hwrena(cpu_env, arg);
6950 ctx->bstate = BS_STOP;
6951 rn = "HWREna";
6952 break;
6953 default:
6954 goto cp0_unimplemented;
6956 break;
6957 case 8:
6958 switch (sel) {
6959 case 0:
6960 /* ignored */
6961 rn = "BadVAddr";
6962 break;
6963 case 1:
6964 /* ignored */
6965 rn = "BadInstr";
6966 break;
6967 case 2:
6968 /* ignored */
6969 rn = "BadInstrP";
6970 break;
6971 default:
6972 goto cp0_unimplemented;
6974 break;
6975 case 9:
6976 switch (sel) {
6977 case 0:
6978 gen_helper_mtc0_count(cpu_env, arg);
6979 rn = "Count";
6980 break;
6981 /* 6,7 are implementation dependent */
6982 default:
6983 goto cp0_unimplemented;
6985 /* Stop translation as we may have switched the execution mode */
6986 ctx->bstate = BS_STOP;
6987 break;
6988 case 10:
6989 switch (sel) {
6990 case 0:
6991 gen_helper_mtc0_entryhi(cpu_env, arg);
6992 rn = "EntryHi";
6993 break;
6994 default:
6995 goto cp0_unimplemented;
6997 break;
6998 case 11:
6999 switch (sel) {
7000 case 0:
7001 gen_helper_mtc0_compare(cpu_env, arg);
7002 rn = "Compare";
7003 break;
7004 /* 6,7 are implementation dependent */
7005 default:
7006 goto cp0_unimplemented;
7008 /* Stop translation as we may have switched the execution mode */
7009 ctx->bstate = BS_STOP;
7010 break;
7011 case 12:
7012 switch (sel) {
7013 case 0:
7014 save_cpu_state(ctx, 1);
7015 gen_helper_mtc0_status(cpu_env, arg);
7016 /* BS_STOP isn't good enough here, hflags may have changed. */
7017 gen_save_pc(ctx->pc + 4);
7018 ctx->bstate = BS_EXCP;
7019 rn = "Status";
7020 break;
7021 case 1:
7022 check_insn(ctx, ISA_MIPS32R2);
7023 gen_helper_mtc0_intctl(cpu_env, arg);
7024 /* Stop translation as we may have switched the execution mode */
7025 ctx->bstate = BS_STOP;
7026 rn = "IntCtl";
7027 break;
7028 case 2:
7029 check_insn(ctx, ISA_MIPS32R2);
7030 gen_helper_mtc0_srsctl(cpu_env, arg);
7031 /* Stop translation as we may have switched the execution mode */
7032 ctx->bstate = BS_STOP;
7033 rn = "SRSCtl";
7034 break;
7035 case 3:
7036 check_insn(ctx, ISA_MIPS32R2);
7037 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7038 /* Stop translation as we may have switched the execution mode */
7039 ctx->bstate = BS_STOP;
7040 rn = "SRSMap";
7041 break;
7042 default:
7043 goto cp0_unimplemented;
7045 break;
7046 case 13:
7047 switch (sel) {
7048 case 0:
7049 save_cpu_state(ctx, 1);
7050 /* Mark as an IO operation because we may trigger a software
7051 interrupt. */
7052 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7053 gen_io_start();
7055 gen_helper_mtc0_cause(cpu_env, arg);
7056 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7057 gen_io_end();
7059 /* Stop translation as we may have triggered an intetrupt */
7060 ctx->bstate = BS_STOP;
7061 rn = "Cause";
7062 break;
7063 default:
7064 goto cp0_unimplemented;
7066 break;
7067 case 14:
7068 switch (sel) {
7069 case 0:
7070 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7071 rn = "EPC";
7072 break;
7073 default:
7074 goto cp0_unimplemented;
7076 break;
7077 case 15:
7078 switch (sel) {
7079 case 0:
7080 /* ignored */
7081 rn = "PRid";
7082 break;
7083 case 1:
7084 check_insn(ctx, ISA_MIPS32R2);
7085 gen_helper_mtc0_ebase(cpu_env, arg);
7086 rn = "EBase";
7087 break;
7088 default:
7089 goto cp0_unimplemented;
7091 break;
7092 case 16:
7093 switch (sel) {
7094 case 0:
7095 gen_helper_mtc0_config0(cpu_env, arg);
7096 rn = "Config";
7097 /* Stop translation as we may have switched the execution mode */
7098 ctx->bstate = BS_STOP;
7099 break;
7100 case 1:
7101 /* ignored, read only */
7102 rn = "Config1";
7103 break;
7104 case 2:
7105 gen_helper_mtc0_config2(cpu_env, arg);
7106 rn = "Config2";
7107 /* Stop translation as we may have switched the execution mode */
7108 ctx->bstate = BS_STOP;
7109 break;
7110 case 3:
7111 gen_helper_mtc0_config3(cpu_env, arg);
7112 rn = "Config3";
7113 /* Stop translation as we may have switched the execution mode */
7114 ctx->bstate = BS_STOP;
7115 break;
7116 case 4:
7117 /* currently ignored */
7118 rn = "Config4";
7119 break;
7120 case 5:
7121 gen_helper_mtc0_config5(cpu_env, arg);
7122 rn = "Config5";
7123 /* Stop translation as we may have switched the execution mode */
7124 ctx->bstate = BS_STOP;
7125 break;
7126 /* 6,7 are implementation dependent */
7127 default:
7128 rn = "Invalid config selector";
7129 goto cp0_unimplemented;
7131 break;
7132 case 17:
7133 switch (sel) {
7134 case 0:
7135 gen_helper_mtc0_lladdr(cpu_env, arg);
7136 rn = "LLAddr";
7137 break;
7138 default:
7139 goto cp0_unimplemented;
7141 break;
7142 case 18:
7143 switch (sel) {
7144 case 0 ... 7:
7145 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7146 rn = "WatchLo";
7147 break;
7148 default:
7149 goto cp0_unimplemented;
7151 break;
7152 case 19:
7153 switch (sel) {
7154 case 0 ... 7:
7155 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7156 rn = "WatchHi";
7157 break;
7158 default:
7159 goto cp0_unimplemented;
7161 break;
7162 case 20:
7163 switch (sel) {
7164 case 0:
7165 check_insn(ctx, ISA_MIPS3);
7166 gen_helper_mtc0_xcontext(cpu_env, arg);
7167 rn = "XContext";
7168 break;
7169 default:
7170 goto cp0_unimplemented;
7172 break;
7173 case 21:
7174 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7175 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7176 switch (sel) {
7177 case 0:
7178 gen_helper_mtc0_framemask(cpu_env, arg);
7179 rn = "Framemask";
7180 break;
7181 default:
7182 goto cp0_unimplemented;
7184 break;
7185 case 22:
7186 /* ignored */
7187 rn = "Diagnostic"; /* implementation dependent */
7188 break;
7189 case 23:
7190 switch (sel) {
7191 case 0:
7192 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7193 /* BS_STOP isn't good enough here, hflags may have changed. */
7194 gen_save_pc(ctx->pc + 4);
7195 ctx->bstate = BS_EXCP;
7196 rn = "Debug";
7197 break;
7198 case 1:
7199 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7200 /* Stop translation as we may have switched the execution mode */
7201 ctx->bstate = BS_STOP;
7202 rn = "TraceControl";
7203 // break;
7204 case 2:
7205 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7206 /* Stop translation as we may have switched the execution mode */
7207 ctx->bstate = BS_STOP;
7208 rn = "TraceControl2";
7209 // break;
7210 case 3:
7211 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7212 /* Stop translation as we may have switched the execution mode */
7213 ctx->bstate = BS_STOP;
7214 rn = "UserTraceData";
7215 // break;
7216 case 4:
7217 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7218 /* Stop translation as we may have switched the execution mode */
7219 ctx->bstate = BS_STOP;
7220 rn = "TraceBPC";
7221 // break;
7222 default:
7223 goto cp0_unimplemented;
7225 break;
7226 case 24:
7227 switch (sel) {
7228 case 0:
7229 /* EJTAG support */
7230 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7231 rn = "DEPC";
7232 break;
7233 default:
7234 goto cp0_unimplemented;
7236 break;
7237 case 25:
7238 switch (sel) {
7239 case 0:
7240 gen_helper_mtc0_performance0(cpu_env, arg);
7241 rn = "Performance0";
7242 break;
7243 case 1:
7244 // gen_helper_mtc0_performance1(cpu_env, arg);
7245 rn = "Performance1";
7246 // break;
7247 case 2:
7248 // gen_helper_mtc0_performance2(cpu_env, arg);
7249 rn = "Performance2";
7250 // break;
7251 case 3:
7252 // gen_helper_mtc0_performance3(cpu_env, arg);
7253 rn = "Performance3";
7254 // break;
7255 case 4:
7256 // gen_helper_mtc0_performance4(cpu_env, arg);
7257 rn = "Performance4";
7258 // break;
7259 case 5:
7260 // gen_helper_mtc0_performance5(cpu_env, arg);
7261 rn = "Performance5";
7262 // break;
7263 case 6:
7264 // gen_helper_mtc0_performance6(cpu_env, arg);
7265 rn = "Performance6";
7266 // break;
7267 case 7:
7268 // gen_helper_mtc0_performance7(cpu_env, arg);
7269 rn = "Performance7";
7270 // break;
7271 default:
7272 goto cp0_unimplemented;
7274 break;
7275 case 26:
7276 /* ignored */
7277 rn = "ECC";
7278 break;
7279 case 27:
7280 switch (sel) {
7281 case 0 ... 3:
7282 /* ignored */
7283 rn = "CacheErr";
7284 break;
7285 default:
7286 goto cp0_unimplemented;
7288 break;
7289 case 28:
7290 switch (sel) {
7291 case 0:
7292 case 2:
7293 case 4:
7294 case 6:
7295 gen_helper_mtc0_taglo(cpu_env, arg);
7296 rn = "TagLo";
7297 break;
7298 case 1:
7299 case 3:
7300 case 5:
7301 case 7:
7302 gen_helper_mtc0_datalo(cpu_env, arg);
7303 rn = "DataLo";
7304 break;
7305 default:
7306 goto cp0_unimplemented;
7308 break;
7309 case 29:
7310 switch (sel) {
7311 case 0:
7312 case 2:
7313 case 4:
7314 case 6:
7315 gen_helper_mtc0_taghi(cpu_env, arg);
7316 rn = "TagHi";
7317 break;
7318 case 1:
7319 case 3:
7320 case 5:
7321 case 7:
7322 gen_helper_mtc0_datahi(cpu_env, arg);
7323 rn = "DataHi";
7324 break;
7325 default:
7326 rn = "invalid sel";
7327 goto cp0_unimplemented;
7329 break;
7330 case 30:
7331 switch (sel) {
7332 case 0:
7333 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7334 rn = "ErrorEPC";
7335 break;
7336 default:
7337 goto cp0_unimplemented;
7339 break;
7340 case 31:
7341 switch (sel) {
7342 case 0:
7343 /* EJTAG support */
7344 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7345 rn = "DESAVE";
7346 break;
7347 case 2 ... 7:
7348 CP0_CHECK(ctx->kscrexist & (1 << sel));
7349 tcg_gen_st_tl(arg, cpu_env,
7350 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7351 rn = "KScratch";
7352 break;
7353 default:
7354 goto cp0_unimplemented;
7356 /* Stop translation as we may have switched the execution mode */
7357 ctx->bstate = BS_STOP;
7358 break;
7359 default:
7360 goto cp0_unimplemented;
7362 (void)rn; /* avoid a compiler warning */
7363 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7364 /* For simplicity assume that all writes can cause interrupts. */
7365 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7366 gen_io_end();
7367 ctx->bstate = BS_STOP;
7369 return;
7371 cp0_unimplemented:
7372 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7374 #endif /* TARGET_MIPS64 */
7376 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7377 int u, int sel, int h)
7379 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7380 TCGv t0 = tcg_temp_local_new();
7382 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7383 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7384 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7385 tcg_gen_movi_tl(t0, -1);
7386 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7387 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7388 tcg_gen_movi_tl(t0, -1);
7389 else if (u == 0) {
7390 switch (rt) {
7391 case 1:
7392 switch (sel) {
7393 case 1:
7394 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7395 break;
7396 case 2:
7397 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7398 break;
7399 default:
7400 goto die;
7401 break;
7403 break;
7404 case 2:
7405 switch (sel) {
7406 case 1:
7407 gen_helper_mftc0_tcstatus(t0, cpu_env);
7408 break;
7409 case 2:
7410 gen_helper_mftc0_tcbind(t0, cpu_env);
7411 break;
7412 case 3:
7413 gen_helper_mftc0_tcrestart(t0, cpu_env);
7414 break;
7415 case 4:
7416 gen_helper_mftc0_tchalt(t0, cpu_env);
7417 break;
7418 case 5:
7419 gen_helper_mftc0_tccontext(t0, cpu_env);
7420 break;
7421 case 6:
7422 gen_helper_mftc0_tcschedule(t0, cpu_env);
7423 break;
7424 case 7:
7425 gen_helper_mftc0_tcschefback(t0, cpu_env);
7426 break;
7427 default:
7428 gen_mfc0(ctx, t0, rt, sel);
7429 break;
7431 break;
7432 case 10:
7433 switch (sel) {
7434 case 0:
7435 gen_helper_mftc0_entryhi(t0, cpu_env);
7436 break;
7437 default:
7438 gen_mfc0(ctx, t0, rt, sel);
7439 break;
7441 case 12:
7442 switch (sel) {
7443 case 0:
7444 gen_helper_mftc0_status(t0, cpu_env);
7445 break;
7446 default:
7447 gen_mfc0(ctx, t0, rt, sel);
7448 break;
7450 case 13:
7451 switch (sel) {
7452 case 0:
7453 gen_helper_mftc0_cause(t0, cpu_env);
7454 break;
7455 default:
7456 goto die;
7457 break;
7459 break;
7460 case 14:
7461 switch (sel) {
7462 case 0:
7463 gen_helper_mftc0_epc(t0, cpu_env);
7464 break;
7465 default:
7466 goto die;
7467 break;
7469 break;
7470 case 15:
7471 switch (sel) {
7472 case 1:
7473 gen_helper_mftc0_ebase(t0, cpu_env);
7474 break;
7475 default:
7476 goto die;
7477 break;
7479 break;
7480 case 16:
7481 switch (sel) {
7482 case 0 ... 7:
7483 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7484 break;
7485 default:
7486 goto die;
7487 break;
7489 break;
7490 case 23:
7491 switch (sel) {
7492 case 0:
7493 gen_helper_mftc0_debug(t0, cpu_env);
7494 break;
7495 default:
7496 gen_mfc0(ctx, t0, rt, sel);
7497 break;
7499 break;
7500 default:
7501 gen_mfc0(ctx, t0, rt, sel);
7503 } else switch (sel) {
7504 /* GPR registers. */
7505 case 0:
7506 gen_helper_1e0i(mftgpr, t0, rt);
7507 break;
7508 /* Auxiliary CPU registers */
7509 case 1:
7510 switch (rt) {
7511 case 0:
7512 gen_helper_1e0i(mftlo, t0, 0);
7513 break;
7514 case 1:
7515 gen_helper_1e0i(mfthi, t0, 0);
7516 break;
7517 case 2:
7518 gen_helper_1e0i(mftacx, t0, 0);
7519 break;
7520 case 4:
7521 gen_helper_1e0i(mftlo, t0, 1);
7522 break;
7523 case 5:
7524 gen_helper_1e0i(mfthi, t0, 1);
7525 break;
7526 case 6:
7527 gen_helper_1e0i(mftacx, t0, 1);
7528 break;
7529 case 8:
7530 gen_helper_1e0i(mftlo, t0, 2);
7531 break;
7532 case 9:
7533 gen_helper_1e0i(mfthi, t0, 2);
7534 break;
7535 case 10:
7536 gen_helper_1e0i(mftacx, t0, 2);
7537 break;
7538 case 12:
7539 gen_helper_1e0i(mftlo, t0, 3);
7540 break;
7541 case 13:
7542 gen_helper_1e0i(mfthi, t0, 3);
7543 break;
7544 case 14:
7545 gen_helper_1e0i(mftacx, t0, 3);
7546 break;
7547 case 16:
7548 gen_helper_mftdsp(t0, cpu_env);
7549 break;
7550 default:
7551 goto die;
7553 break;
7554 /* Floating point (COP1). */
7555 case 2:
7556 /* XXX: For now we support only a single FPU context. */
7557 if (h == 0) {
7558 TCGv_i32 fp0 = tcg_temp_new_i32();
7560 gen_load_fpr32(fp0, rt);
7561 tcg_gen_ext_i32_tl(t0, fp0);
7562 tcg_temp_free_i32(fp0);
7563 } else {
7564 TCGv_i32 fp0 = tcg_temp_new_i32();
7566 gen_load_fpr32h(ctx, fp0, rt);
7567 tcg_gen_ext_i32_tl(t0, fp0);
7568 tcg_temp_free_i32(fp0);
7570 break;
7571 case 3:
7572 /* XXX: For now we support only a single FPU context. */
7573 gen_helper_1e0i(cfc1, t0, rt);
7574 break;
7575 /* COP2: Not implemented. */
7576 case 4:
7577 case 5:
7578 /* fall through */
7579 default:
7580 goto die;
7582 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7583 gen_store_gpr(t0, rd);
7584 tcg_temp_free(t0);
7585 return;
7587 die:
7588 tcg_temp_free(t0);
7589 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7590 generate_exception(ctx, EXCP_RI);
7593 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7594 int u, int sel, int h)
7596 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7597 TCGv t0 = tcg_temp_local_new();
7599 gen_load_gpr(t0, rt);
7600 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7601 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7602 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7603 /* NOP */ ;
7604 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7605 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7606 /* NOP */ ;
7607 else if (u == 0) {
7608 switch (rd) {
7609 case 1:
7610 switch (sel) {
7611 case 1:
7612 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7613 break;
7614 case 2:
7615 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7616 break;
7617 default:
7618 goto die;
7619 break;
7621 break;
7622 case 2:
7623 switch (sel) {
7624 case 1:
7625 gen_helper_mttc0_tcstatus(cpu_env, t0);
7626 break;
7627 case 2:
7628 gen_helper_mttc0_tcbind(cpu_env, t0);
7629 break;
7630 case 3:
7631 gen_helper_mttc0_tcrestart(cpu_env, t0);
7632 break;
7633 case 4:
7634 gen_helper_mttc0_tchalt(cpu_env, t0);
7635 break;
7636 case 5:
7637 gen_helper_mttc0_tccontext(cpu_env, t0);
7638 break;
7639 case 6:
7640 gen_helper_mttc0_tcschedule(cpu_env, t0);
7641 break;
7642 case 7:
7643 gen_helper_mttc0_tcschefback(cpu_env, t0);
7644 break;
7645 default:
7646 gen_mtc0(ctx, t0, rd, sel);
7647 break;
7649 break;
7650 case 10:
7651 switch (sel) {
7652 case 0:
7653 gen_helper_mttc0_entryhi(cpu_env, t0);
7654 break;
7655 default:
7656 gen_mtc0(ctx, t0, rd, sel);
7657 break;
7659 case 12:
7660 switch (sel) {
7661 case 0:
7662 gen_helper_mttc0_status(cpu_env, t0);
7663 break;
7664 default:
7665 gen_mtc0(ctx, t0, rd, sel);
7666 break;
7668 case 13:
7669 switch (sel) {
7670 case 0:
7671 gen_helper_mttc0_cause(cpu_env, t0);
7672 break;
7673 default:
7674 goto die;
7675 break;
7677 break;
7678 case 15:
7679 switch (sel) {
7680 case 1:
7681 gen_helper_mttc0_ebase(cpu_env, t0);
7682 break;
7683 default:
7684 goto die;
7685 break;
7687 break;
7688 case 23:
7689 switch (sel) {
7690 case 0:
7691 gen_helper_mttc0_debug(cpu_env, t0);
7692 break;
7693 default:
7694 gen_mtc0(ctx, t0, rd, sel);
7695 break;
7697 break;
7698 default:
7699 gen_mtc0(ctx, t0, rd, sel);
7701 } else switch (sel) {
7702 /* GPR registers. */
7703 case 0:
7704 gen_helper_0e1i(mttgpr, t0, rd);
7705 break;
7706 /* Auxiliary CPU registers */
7707 case 1:
7708 switch (rd) {
7709 case 0:
7710 gen_helper_0e1i(mttlo, t0, 0);
7711 break;
7712 case 1:
7713 gen_helper_0e1i(mtthi, t0, 0);
7714 break;
7715 case 2:
7716 gen_helper_0e1i(mttacx, t0, 0);
7717 break;
7718 case 4:
7719 gen_helper_0e1i(mttlo, t0, 1);
7720 break;
7721 case 5:
7722 gen_helper_0e1i(mtthi, t0, 1);
7723 break;
7724 case 6:
7725 gen_helper_0e1i(mttacx, t0, 1);
7726 break;
7727 case 8:
7728 gen_helper_0e1i(mttlo, t0, 2);
7729 break;
7730 case 9:
7731 gen_helper_0e1i(mtthi, t0, 2);
7732 break;
7733 case 10:
7734 gen_helper_0e1i(mttacx, t0, 2);
7735 break;
7736 case 12:
7737 gen_helper_0e1i(mttlo, t0, 3);
7738 break;
7739 case 13:
7740 gen_helper_0e1i(mtthi, t0, 3);
7741 break;
7742 case 14:
7743 gen_helper_0e1i(mttacx, t0, 3);
7744 break;
7745 case 16:
7746 gen_helper_mttdsp(cpu_env, t0);
7747 break;
7748 default:
7749 goto die;
7751 break;
7752 /* Floating point (COP1). */
7753 case 2:
7754 /* XXX: For now we support only a single FPU context. */
7755 if (h == 0) {
7756 TCGv_i32 fp0 = tcg_temp_new_i32();
7758 tcg_gen_trunc_tl_i32(fp0, t0);
7759 gen_store_fpr32(fp0, rd);
7760 tcg_temp_free_i32(fp0);
7761 } else {
7762 TCGv_i32 fp0 = tcg_temp_new_i32();
7764 tcg_gen_trunc_tl_i32(fp0, t0);
7765 gen_store_fpr32h(ctx, fp0, rd);
7766 tcg_temp_free_i32(fp0);
7768 break;
7769 case 3:
7770 /* XXX: For now we support only a single FPU context. */
7771 save_cpu_state(ctx, 1);
7773 TCGv_i32 fs_tmp = tcg_const_i32(rd);
7775 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7776 tcg_temp_free_i32(fs_tmp);
7778 /* Stop translation as we may have changed hflags */
7779 ctx->bstate = BS_STOP;
7780 break;
7781 /* COP2: Not implemented. */
7782 case 4:
7783 case 5:
7784 /* fall through */
7785 default:
7786 goto die;
7788 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7789 tcg_temp_free(t0);
7790 return;
7792 die:
7793 tcg_temp_free(t0);
7794 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7795 generate_exception(ctx, EXCP_RI);
7798 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
7800 const char *opn = "ldst";
7802 check_cp0_enabled(ctx);
7803 switch (opc) {
7804 case OPC_MFC0:
7805 if (rt == 0) {
7806 /* Treat as NOP. */
7807 return;
7809 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7810 opn = "mfc0";
7811 break;
7812 case OPC_MTC0:
7814 TCGv t0 = tcg_temp_new();
7816 gen_load_gpr(t0, rt);
7817 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
7818 tcg_temp_free(t0);
7820 opn = "mtc0";
7821 break;
7822 #if defined(TARGET_MIPS64)
7823 case OPC_DMFC0:
7824 check_insn(ctx, ISA_MIPS3);
7825 if (rt == 0) {
7826 /* Treat as NOP. */
7827 return;
7829 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7830 opn = "dmfc0";
7831 break;
7832 case OPC_DMTC0:
7833 check_insn(ctx, ISA_MIPS3);
7835 TCGv t0 = tcg_temp_new();
7837 gen_load_gpr(t0, rt);
7838 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
7839 tcg_temp_free(t0);
7841 opn = "dmtc0";
7842 break;
7843 #endif
7844 case OPC_MFTR:
7845 check_insn(ctx, ASE_MT);
7846 if (rd == 0) {
7847 /* Treat as NOP. */
7848 return;
7850 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
7851 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
7852 opn = "mftr";
7853 break;
7854 case OPC_MTTR:
7855 check_insn(ctx, ASE_MT);
7856 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
7857 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
7858 opn = "mttr";
7859 break;
7860 case OPC_TLBWI:
7861 opn = "tlbwi";
7862 if (!env->tlb->helper_tlbwi)
7863 goto die;
7864 gen_helper_tlbwi(cpu_env);
7865 break;
7866 case OPC_TLBINV:
7867 opn = "tlbinv";
7868 if (ctx->ie >= 2) {
7869 if (!env->tlb->helper_tlbinv) {
7870 goto die;
7872 gen_helper_tlbinv(cpu_env);
7873 } /* treat as nop if TLBINV not supported */
7874 break;
7875 case OPC_TLBINVF:
7876 opn = "tlbinvf";
7877 if (ctx->ie >= 2) {
7878 if (!env->tlb->helper_tlbinvf) {
7879 goto die;
7881 gen_helper_tlbinvf(cpu_env);
7882 } /* treat as nop if TLBINV not supported */
7883 break;
7884 case OPC_TLBWR:
7885 opn = "tlbwr";
7886 if (!env->tlb->helper_tlbwr)
7887 goto die;
7888 gen_helper_tlbwr(cpu_env);
7889 break;
7890 case OPC_TLBP:
7891 opn = "tlbp";
7892 if (!env->tlb->helper_tlbp)
7893 goto die;
7894 gen_helper_tlbp(cpu_env);
7895 break;
7896 case OPC_TLBR:
7897 opn = "tlbr";
7898 if (!env->tlb->helper_tlbr)
7899 goto die;
7900 gen_helper_tlbr(cpu_env);
7901 break;
7902 case OPC_ERET:
7903 opn = "eret";
7904 check_insn(ctx, ISA_MIPS2);
7905 if ((ctx->insn_flags & ISA_MIPS32R6) &&
7906 (ctx->hflags & MIPS_HFLAG_BMASK)) {
7907 MIPS_DEBUG("CTI in delay / forbidden slot");
7908 goto die;
7910 gen_helper_eret(cpu_env);
7911 ctx->bstate = BS_EXCP;
7912 break;
7913 case OPC_DERET:
7914 opn = "deret";
7915 check_insn(ctx, ISA_MIPS32);
7916 if ((ctx->insn_flags & ISA_MIPS32R6) &&
7917 (ctx->hflags & MIPS_HFLAG_BMASK)) {
7918 MIPS_DEBUG("CTI in delay / forbidden slot");
7919 goto die;
7921 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7922 MIPS_INVAL(opn);
7923 generate_exception(ctx, EXCP_RI);
7924 } else {
7925 gen_helper_deret(cpu_env);
7926 ctx->bstate = BS_EXCP;
7928 break;
7929 case OPC_WAIT:
7930 opn = "wait";
7931 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
7932 if ((ctx->insn_flags & ISA_MIPS32R6) &&
7933 (ctx->hflags & MIPS_HFLAG_BMASK)) {
7934 MIPS_DEBUG("CTI in delay / forbidden slot");
7935 goto die;
7937 /* If we get an exception, we want to restart at next instruction */
7938 ctx->pc += 4;
7939 save_cpu_state(ctx, 1);
7940 ctx->pc -= 4;
7941 gen_helper_wait(cpu_env);
7942 ctx->bstate = BS_EXCP;
7943 break;
7944 default:
7945 die:
7946 MIPS_INVAL(opn);
7947 generate_exception(ctx, EXCP_RI);
7948 return;
7950 (void)opn; /* avoid a compiler warning */
7951 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
7953 #endif /* !CONFIG_USER_ONLY */
7955 /* CP1 Branches (before delay slot) */
7956 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
7957 int32_t cc, int32_t offset)
7959 target_ulong btarget;
7960 const char *opn = "cp1 cond branch";
7961 TCGv_i32 t0 = tcg_temp_new_i32();
7963 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
7964 MIPS_DEBUG("CTI in delay / forbidden slot");
7965 generate_exception(ctx, EXCP_RI);
7966 goto out;
7969 if (cc != 0)
7970 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
7972 btarget = ctx->pc + 4 + offset;
7974 switch (op) {
7975 case OPC_BC1F:
7976 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7977 tcg_gen_not_i32(t0, t0);
7978 tcg_gen_andi_i32(t0, t0, 1);
7979 tcg_gen_extu_i32_tl(bcond, t0);
7980 opn = "bc1f";
7981 goto not_likely;
7982 case OPC_BC1FL:
7983 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7984 tcg_gen_not_i32(t0, t0);
7985 tcg_gen_andi_i32(t0, t0, 1);
7986 tcg_gen_extu_i32_tl(bcond, t0);
7987 opn = "bc1fl";
7988 goto likely;
7989 case OPC_BC1T:
7990 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7991 tcg_gen_andi_i32(t0, t0, 1);
7992 tcg_gen_extu_i32_tl(bcond, t0);
7993 opn = "bc1t";
7994 goto not_likely;
7995 case OPC_BC1TL:
7996 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7997 tcg_gen_andi_i32(t0, t0, 1);
7998 tcg_gen_extu_i32_tl(bcond, t0);
7999 opn = "bc1tl";
8000 likely:
8001 ctx->hflags |= MIPS_HFLAG_BL;
8002 break;
8003 case OPC_BC1FANY2:
8005 TCGv_i32 t1 = tcg_temp_new_i32();
8006 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8007 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8008 tcg_gen_nand_i32(t0, t0, t1);
8009 tcg_temp_free_i32(t1);
8010 tcg_gen_andi_i32(t0, t0, 1);
8011 tcg_gen_extu_i32_tl(bcond, t0);
8013 opn = "bc1any2f";
8014 goto not_likely;
8015 case OPC_BC1TANY2:
8017 TCGv_i32 t1 = tcg_temp_new_i32();
8018 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8019 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8020 tcg_gen_or_i32(t0, t0, t1);
8021 tcg_temp_free_i32(t1);
8022 tcg_gen_andi_i32(t0, t0, 1);
8023 tcg_gen_extu_i32_tl(bcond, t0);
8025 opn = "bc1any2t";
8026 goto not_likely;
8027 case OPC_BC1FANY4:
8029 TCGv_i32 t1 = tcg_temp_new_i32();
8030 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8031 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8032 tcg_gen_and_i32(t0, t0, t1);
8033 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8034 tcg_gen_and_i32(t0, t0, t1);
8035 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8036 tcg_gen_nand_i32(t0, t0, t1);
8037 tcg_temp_free_i32(t1);
8038 tcg_gen_andi_i32(t0, t0, 1);
8039 tcg_gen_extu_i32_tl(bcond, t0);
8041 opn = "bc1any4f";
8042 goto not_likely;
8043 case OPC_BC1TANY4:
8045 TCGv_i32 t1 = tcg_temp_new_i32();
8046 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8047 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8048 tcg_gen_or_i32(t0, t0, t1);
8049 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8050 tcg_gen_or_i32(t0, t0, t1);
8051 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8052 tcg_gen_or_i32(t0, t0, t1);
8053 tcg_temp_free_i32(t1);
8054 tcg_gen_andi_i32(t0, t0, 1);
8055 tcg_gen_extu_i32_tl(bcond, t0);
8057 opn = "bc1any4t";
8058 not_likely:
8059 ctx->hflags |= MIPS_HFLAG_BC;
8060 break;
8061 default:
8062 MIPS_INVAL(opn);
8063 generate_exception (ctx, EXCP_RI);
8064 goto out;
8066 (void)opn; /* avoid a compiler warning */
8067 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8068 ctx->hflags, btarget);
8069 ctx->btarget = btarget;
8070 ctx->hflags |= MIPS_HFLAG_BDS32;
8071 out:
8072 tcg_temp_free_i32(t0);
8075 /* R6 CP1 Branches */
8076 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8077 int32_t ft, int32_t offset)
8079 target_ulong btarget;
8080 const char *opn = "cp1 cond branch";
8081 TCGv_i64 t0 = tcg_temp_new_i64();
8083 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8084 #ifdef MIPS_DEBUG_DISAS
8085 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8086 "\n", ctx->pc);
8087 #endif
8088 generate_exception(ctx, EXCP_RI);
8089 goto out;
8092 gen_load_fpr64(ctx, t0, ft);
8093 tcg_gen_andi_i64(t0, t0, 1);
8095 btarget = addr_add(ctx, ctx->pc + 4, offset);
8097 switch (op) {
8098 case OPC_BC1EQZ:
8099 tcg_gen_xori_i64(t0, t0, 1);
8100 opn = "bc1eqz";
8101 ctx->hflags |= MIPS_HFLAG_BC;
8102 break;
8103 case OPC_BC1NEZ:
8104 /* t0 already set */
8105 opn = "bc1nez";
8106 ctx->hflags |= MIPS_HFLAG_BC;
8107 break;
8108 default:
8109 MIPS_INVAL(opn);
8110 generate_exception(ctx, EXCP_RI);
8111 goto out;
8114 tcg_gen_trunc_i64_tl(bcond, t0);
8116 (void)opn; /* avoid a compiler warning */
8117 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8118 ctx->hflags, btarget);
8119 ctx->btarget = btarget;
8120 ctx->hflags |= MIPS_HFLAG_BDS32;
8122 out:
8123 tcg_temp_free_i64(t0);
8126 /* Coprocessor 1 (FPU) */
8128 #define FOP(func, fmt) (((fmt) << 21) | (func))
8130 enum fopcode {
8131 OPC_ADD_S = FOP(0, FMT_S),
8132 OPC_SUB_S = FOP(1, FMT_S),
8133 OPC_MUL_S = FOP(2, FMT_S),
8134 OPC_DIV_S = FOP(3, FMT_S),
8135 OPC_SQRT_S = FOP(4, FMT_S),
8136 OPC_ABS_S = FOP(5, FMT_S),
8137 OPC_MOV_S = FOP(6, FMT_S),
8138 OPC_NEG_S = FOP(7, FMT_S),
8139 OPC_ROUND_L_S = FOP(8, FMT_S),
8140 OPC_TRUNC_L_S = FOP(9, FMT_S),
8141 OPC_CEIL_L_S = FOP(10, FMT_S),
8142 OPC_FLOOR_L_S = FOP(11, FMT_S),
8143 OPC_ROUND_W_S = FOP(12, FMT_S),
8144 OPC_TRUNC_W_S = FOP(13, FMT_S),
8145 OPC_CEIL_W_S = FOP(14, FMT_S),
8146 OPC_FLOOR_W_S = FOP(15, FMT_S),
8147 OPC_SEL_S = FOP(16, FMT_S),
8148 OPC_MOVCF_S = FOP(17, FMT_S),
8149 OPC_MOVZ_S = FOP(18, FMT_S),
8150 OPC_MOVN_S = FOP(19, FMT_S),
8151 OPC_SELEQZ_S = FOP(20, FMT_S),
8152 OPC_RECIP_S = FOP(21, FMT_S),
8153 OPC_RSQRT_S = FOP(22, FMT_S),
8154 OPC_SELNEZ_S = FOP(23, FMT_S),
8155 OPC_MADDF_S = FOP(24, FMT_S),
8156 OPC_MSUBF_S = FOP(25, FMT_S),
8157 OPC_RINT_S = FOP(26, FMT_S),
8158 OPC_CLASS_S = FOP(27, FMT_S),
8159 OPC_MIN_S = FOP(28, FMT_S),
8160 OPC_RECIP2_S = FOP(28, FMT_S),
8161 OPC_MINA_S = FOP(29, FMT_S),
8162 OPC_RECIP1_S = FOP(29, FMT_S),
8163 OPC_MAX_S = FOP(30, FMT_S),
8164 OPC_RSQRT1_S = FOP(30, FMT_S),
8165 OPC_MAXA_S = FOP(31, FMT_S),
8166 OPC_RSQRT2_S = FOP(31, FMT_S),
8167 OPC_CVT_D_S = FOP(33, FMT_S),
8168 OPC_CVT_W_S = FOP(36, FMT_S),
8169 OPC_CVT_L_S = FOP(37, FMT_S),
8170 OPC_CVT_PS_S = FOP(38, FMT_S),
8171 OPC_CMP_F_S = FOP (48, FMT_S),
8172 OPC_CMP_UN_S = FOP (49, FMT_S),
8173 OPC_CMP_EQ_S = FOP (50, FMT_S),
8174 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8175 OPC_CMP_OLT_S = FOP (52, FMT_S),
8176 OPC_CMP_ULT_S = FOP (53, FMT_S),
8177 OPC_CMP_OLE_S = FOP (54, FMT_S),
8178 OPC_CMP_ULE_S = FOP (55, FMT_S),
8179 OPC_CMP_SF_S = FOP (56, FMT_S),
8180 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8181 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8182 OPC_CMP_NGL_S = FOP (59, FMT_S),
8183 OPC_CMP_LT_S = FOP (60, FMT_S),
8184 OPC_CMP_NGE_S = FOP (61, FMT_S),
8185 OPC_CMP_LE_S = FOP (62, FMT_S),
8186 OPC_CMP_NGT_S = FOP (63, FMT_S),
8188 OPC_ADD_D = FOP(0, FMT_D),
8189 OPC_SUB_D = FOP(1, FMT_D),
8190 OPC_MUL_D = FOP(2, FMT_D),
8191 OPC_DIV_D = FOP(3, FMT_D),
8192 OPC_SQRT_D = FOP(4, FMT_D),
8193 OPC_ABS_D = FOP(5, FMT_D),
8194 OPC_MOV_D = FOP(6, FMT_D),
8195 OPC_NEG_D = FOP(7, FMT_D),
8196 OPC_ROUND_L_D = FOP(8, FMT_D),
8197 OPC_TRUNC_L_D = FOP(9, FMT_D),
8198 OPC_CEIL_L_D = FOP(10, FMT_D),
8199 OPC_FLOOR_L_D = FOP(11, FMT_D),
8200 OPC_ROUND_W_D = FOP(12, FMT_D),
8201 OPC_TRUNC_W_D = FOP(13, FMT_D),
8202 OPC_CEIL_W_D = FOP(14, FMT_D),
8203 OPC_FLOOR_W_D = FOP(15, FMT_D),
8204 OPC_SEL_D = FOP(16, FMT_D),
8205 OPC_MOVCF_D = FOP(17, FMT_D),
8206 OPC_MOVZ_D = FOP(18, FMT_D),
8207 OPC_MOVN_D = FOP(19, FMT_D),
8208 OPC_SELEQZ_D = FOP(20, FMT_D),
8209 OPC_RECIP_D = FOP(21, FMT_D),
8210 OPC_RSQRT_D = FOP(22, FMT_D),
8211 OPC_SELNEZ_D = FOP(23, FMT_D),
8212 OPC_MADDF_D = FOP(24, FMT_D),
8213 OPC_MSUBF_D = FOP(25, FMT_D),
8214 OPC_RINT_D = FOP(26, FMT_D),
8215 OPC_CLASS_D = FOP(27, FMT_D),
8216 OPC_MIN_D = FOP(28, FMT_D),
8217 OPC_RECIP2_D = FOP(28, FMT_D),
8218 OPC_MINA_D = FOP(29, FMT_D),
8219 OPC_RECIP1_D = FOP(29, FMT_D),
8220 OPC_MAX_D = FOP(30, FMT_D),
8221 OPC_RSQRT1_D = FOP(30, FMT_D),
8222 OPC_MAXA_D = FOP(31, FMT_D),
8223 OPC_RSQRT2_D = FOP(31, FMT_D),
8224 OPC_CVT_S_D = FOP(32, FMT_D),
8225 OPC_CVT_W_D = FOP(36, FMT_D),
8226 OPC_CVT_L_D = FOP(37, FMT_D),
8227 OPC_CMP_F_D = FOP (48, FMT_D),
8228 OPC_CMP_UN_D = FOP (49, FMT_D),
8229 OPC_CMP_EQ_D = FOP (50, FMT_D),
8230 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8231 OPC_CMP_OLT_D = FOP (52, FMT_D),
8232 OPC_CMP_ULT_D = FOP (53, FMT_D),
8233 OPC_CMP_OLE_D = FOP (54, FMT_D),
8234 OPC_CMP_ULE_D = FOP (55, FMT_D),
8235 OPC_CMP_SF_D = FOP (56, FMT_D),
8236 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8237 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8238 OPC_CMP_NGL_D = FOP (59, FMT_D),
8239 OPC_CMP_LT_D = FOP (60, FMT_D),
8240 OPC_CMP_NGE_D = FOP (61, FMT_D),
8241 OPC_CMP_LE_D = FOP (62, FMT_D),
8242 OPC_CMP_NGT_D = FOP (63, FMT_D),
8244 OPC_CVT_S_W = FOP(32, FMT_W),
8245 OPC_CVT_D_W = FOP(33, FMT_W),
8246 OPC_CVT_S_L = FOP(32, FMT_L),
8247 OPC_CVT_D_L = FOP(33, FMT_L),
8248 OPC_CVT_PS_PW = FOP(38, FMT_W),
8250 OPC_ADD_PS = FOP(0, FMT_PS),
8251 OPC_SUB_PS = FOP(1, FMT_PS),
8252 OPC_MUL_PS = FOP(2, FMT_PS),
8253 OPC_DIV_PS = FOP(3, FMT_PS),
8254 OPC_ABS_PS = FOP(5, FMT_PS),
8255 OPC_MOV_PS = FOP(6, FMT_PS),
8256 OPC_NEG_PS = FOP(7, FMT_PS),
8257 OPC_MOVCF_PS = FOP(17, FMT_PS),
8258 OPC_MOVZ_PS = FOP(18, FMT_PS),
8259 OPC_MOVN_PS = FOP(19, FMT_PS),
8260 OPC_ADDR_PS = FOP(24, FMT_PS),
8261 OPC_MULR_PS = FOP(26, FMT_PS),
8262 OPC_RECIP2_PS = FOP(28, FMT_PS),
8263 OPC_RECIP1_PS = FOP(29, FMT_PS),
8264 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8265 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8267 OPC_CVT_S_PU = FOP(32, FMT_PS),
8268 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8269 OPC_CVT_S_PL = FOP(40, FMT_PS),
8270 OPC_PLL_PS = FOP(44, FMT_PS),
8271 OPC_PLU_PS = FOP(45, FMT_PS),
8272 OPC_PUL_PS = FOP(46, FMT_PS),
8273 OPC_PUU_PS = FOP(47, FMT_PS),
8274 OPC_CMP_F_PS = FOP (48, FMT_PS),
8275 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8276 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8277 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8278 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8279 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8280 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8281 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8282 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8283 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8284 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8285 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8286 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8287 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8288 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8289 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8292 enum r6_f_cmp_op {
8293 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8294 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8295 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8296 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8297 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8298 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8299 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8300 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8301 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8302 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8303 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8304 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8305 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8306 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8307 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8308 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8309 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8310 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8311 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8312 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8313 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8314 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8316 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8317 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8318 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8319 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8320 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8321 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8322 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8323 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8324 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8325 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8326 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8327 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8328 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8329 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8330 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8331 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8332 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8333 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8334 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8335 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8336 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8337 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8339 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8341 const char *opn = "cp1 move";
8342 TCGv t0 = tcg_temp_new();
8344 switch (opc) {
8345 case OPC_MFC1:
8347 TCGv_i32 fp0 = tcg_temp_new_i32();
8349 gen_load_fpr32(fp0, fs);
8350 tcg_gen_ext_i32_tl(t0, fp0);
8351 tcg_temp_free_i32(fp0);
8353 gen_store_gpr(t0, rt);
8354 opn = "mfc1";
8355 break;
8356 case OPC_MTC1:
8357 gen_load_gpr(t0, rt);
8359 TCGv_i32 fp0 = tcg_temp_new_i32();
8361 tcg_gen_trunc_tl_i32(fp0, t0);
8362 gen_store_fpr32(fp0, fs);
8363 tcg_temp_free_i32(fp0);
8365 opn = "mtc1";
8366 break;
8367 case OPC_CFC1:
8368 gen_helper_1e0i(cfc1, t0, fs);
8369 gen_store_gpr(t0, rt);
8370 opn = "cfc1";
8371 break;
8372 case OPC_CTC1:
8373 gen_load_gpr(t0, rt);
8374 save_cpu_state(ctx, 1);
8376 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8378 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8379 tcg_temp_free_i32(fs_tmp);
8381 /* Stop translation as we may have changed hflags */
8382 ctx->bstate = BS_STOP;
8383 opn = "ctc1";
8384 break;
8385 #if defined(TARGET_MIPS64)
8386 case OPC_DMFC1:
8387 gen_load_fpr64(ctx, t0, fs);
8388 gen_store_gpr(t0, rt);
8389 opn = "dmfc1";
8390 break;
8391 case OPC_DMTC1:
8392 gen_load_gpr(t0, rt);
8393 gen_store_fpr64(ctx, t0, fs);
8394 opn = "dmtc1";
8395 break;
8396 #endif
8397 case OPC_MFHC1:
8399 TCGv_i32 fp0 = tcg_temp_new_i32();
8401 gen_load_fpr32h(ctx, fp0, fs);
8402 tcg_gen_ext_i32_tl(t0, fp0);
8403 tcg_temp_free_i32(fp0);
8405 gen_store_gpr(t0, rt);
8406 opn = "mfhc1";
8407 break;
8408 case OPC_MTHC1:
8409 gen_load_gpr(t0, rt);
8411 TCGv_i32 fp0 = tcg_temp_new_i32();
8413 tcg_gen_trunc_tl_i32(fp0, t0);
8414 gen_store_fpr32h(ctx, fp0, fs);
8415 tcg_temp_free_i32(fp0);
8417 opn = "mthc1";
8418 break;
8419 default:
8420 MIPS_INVAL(opn);
8421 generate_exception (ctx, EXCP_RI);
8422 goto out;
8424 (void)opn; /* avoid a compiler warning */
8425 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
8427 out:
8428 tcg_temp_free(t0);
8431 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8433 int l1;
8434 TCGCond cond;
8435 TCGv_i32 t0;
8437 if (rd == 0) {
8438 /* Treat as NOP. */
8439 return;
8442 if (tf)
8443 cond = TCG_COND_EQ;
8444 else
8445 cond = TCG_COND_NE;
8447 l1 = gen_new_label();
8448 t0 = tcg_temp_new_i32();
8449 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8450 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8451 tcg_temp_free_i32(t0);
8452 if (rs == 0) {
8453 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8454 } else {
8455 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8457 gen_set_label(l1);
8460 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
8462 int cond;
8463 TCGv_i32 t0 = tcg_temp_new_i32();
8464 int l1 = gen_new_label();
8466 if (tf)
8467 cond = TCG_COND_EQ;
8468 else
8469 cond = TCG_COND_NE;
8471 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8472 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8473 gen_load_fpr32(t0, fs);
8474 gen_store_fpr32(t0, fd);
8475 gen_set_label(l1);
8476 tcg_temp_free_i32(t0);
8479 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8481 int cond;
8482 TCGv_i32 t0 = tcg_temp_new_i32();
8483 TCGv_i64 fp0;
8484 int l1 = gen_new_label();
8486 if (tf)
8487 cond = TCG_COND_EQ;
8488 else
8489 cond = TCG_COND_NE;
8491 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8492 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8493 tcg_temp_free_i32(t0);
8494 fp0 = tcg_temp_new_i64();
8495 gen_load_fpr64(ctx, fp0, fs);
8496 gen_store_fpr64(ctx, fp0, fd);
8497 tcg_temp_free_i64(fp0);
8498 gen_set_label(l1);
8501 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8502 int cc, int tf)
8504 int cond;
8505 TCGv_i32 t0 = tcg_temp_new_i32();
8506 int l1 = gen_new_label();
8507 int l2 = gen_new_label();
8509 if (tf)
8510 cond = TCG_COND_EQ;
8511 else
8512 cond = TCG_COND_NE;
8514 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8515 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8516 gen_load_fpr32(t0, fs);
8517 gen_store_fpr32(t0, fd);
8518 gen_set_label(l1);
8520 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8521 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8522 gen_load_fpr32h(ctx, t0, fs);
8523 gen_store_fpr32h(ctx, t0, fd);
8524 tcg_temp_free_i32(t0);
8525 gen_set_label(l2);
8528 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8529 int fs)
8531 TCGv_i32 t1 = tcg_const_i32(0);
8532 TCGv_i32 fp0 = tcg_temp_new_i32();
8533 TCGv_i32 fp1 = tcg_temp_new_i32();
8534 TCGv_i32 fp2 = tcg_temp_new_i32();
8535 gen_load_fpr32(fp0, fd);
8536 gen_load_fpr32(fp1, ft);
8537 gen_load_fpr32(fp2, fs);
8539 switch (op1) {
8540 case OPC_SEL_S:
8541 tcg_gen_andi_i32(fp0, fp0, 1);
8542 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8543 break;
8544 case OPC_SELEQZ_S:
8545 tcg_gen_andi_i32(fp1, fp1, 1);
8546 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8547 break;
8548 case OPC_SELNEZ_S:
8549 tcg_gen_andi_i32(fp1, fp1, 1);
8550 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8551 break;
8552 default:
8553 MIPS_INVAL("gen_sel_s");
8554 generate_exception (ctx, EXCP_RI);
8555 break;
8558 gen_store_fpr32(fp0, fd);
8559 tcg_temp_free_i32(fp2);
8560 tcg_temp_free_i32(fp1);
8561 tcg_temp_free_i32(fp0);
8562 tcg_temp_free_i32(t1);
8565 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8566 int fs)
8568 TCGv_i64 t1 = tcg_const_i64(0);
8569 TCGv_i64 fp0 = tcg_temp_new_i64();
8570 TCGv_i64 fp1 = tcg_temp_new_i64();
8571 TCGv_i64 fp2 = tcg_temp_new_i64();
8572 gen_load_fpr64(ctx, fp0, fd);
8573 gen_load_fpr64(ctx, fp1, ft);
8574 gen_load_fpr64(ctx, fp2, fs);
8576 switch (op1) {
8577 case OPC_SEL_D:
8578 tcg_gen_andi_i64(fp0, fp0, 1);
8579 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8580 break;
8581 case OPC_SELEQZ_D:
8582 tcg_gen_andi_i64(fp1, fp1, 1);
8583 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8584 break;
8585 case OPC_SELNEZ_D:
8586 tcg_gen_andi_i64(fp1, fp1, 1);
8587 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8588 break;
8589 default:
8590 MIPS_INVAL("gen_sel_d");
8591 generate_exception (ctx, EXCP_RI);
8592 break;
8595 gen_store_fpr64(ctx, fp0, fd);
8596 tcg_temp_free_i64(fp2);
8597 tcg_temp_free_i64(fp1);
8598 tcg_temp_free_i64(fp0);
8599 tcg_temp_free_i64(t1);
8602 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8603 int ft, int fs, int fd, int cc)
8605 const char *opn = "farith";
8606 const char *condnames[] = {
8607 "c.f",
8608 "c.un",
8609 "c.eq",
8610 "c.ueq",
8611 "c.olt",
8612 "c.ult",
8613 "c.ole",
8614 "c.ule",
8615 "c.sf",
8616 "c.ngle",
8617 "c.seq",
8618 "c.ngl",
8619 "c.lt",
8620 "c.nge",
8621 "c.le",
8622 "c.ngt",
8624 const char *condnames_abs[] = {
8625 "cabs.f",
8626 "cabs.un",
8627 "cabs.eq",
8628 "cabs.ueq",
8629 "cabs.olt",
8630 "cabs.ult",
8631 "cabs.ole",
8632 "cabs.ule",
8633 "cabs.sf",
8634 "cabs.ngle",
8635 "cabs.seq",
8636 "cabs.ngl",
8637 "cabs.lt",
8638 "cabs.nge",
8639 "cabs.le",
8640 "cabs.ngt",
8642 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
8643 uint32_t func = ctx->opcode & 0x3f;
8645 switch (op1) {
8646 case OPC_ADD_S:
8648 TCGv_i32 fp0 = tcg_temp_new_i32();
8649 TCGv_i32 fp1 = tcg_temp_new_i32();
8651 gen_load_fpr32(fp0, fs);
8652 gen_load_fpr32(fp1, ft);
8653 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
8654 tcg_temp_free_i32(fp1);
8655 gen_store_fpr32(fp0, fd);
8656 tcg_temp_free_i32(fp0);
8658 opn = "add.s";
8659 optype = BINOP;
8660 break;
8661 case OPC_SUB_S:
8663 TCGv_i32 fp0 = tcg_temp_new_i32();
8664 TCGv_i32 fp1 = tcg_temp_new_i32();
8666 gen_load_fpr32(fp0, fs);
8667 gen_load_fpr32(fp1, ft);
8668 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
8669 tcg_temp_free_i32(fp1);
8670 gen_store_fpr32(fp0, fd);
8671 tcg_temp_free_i32(fp0);
8673 opn = "sub.s";
8674 optype = BINOP;
8675 break;
8676 case OPC_MUL_S:
8678 TCGv_i32 fp0 = tcg_temp_new_i32();
8679 TCGv_i32 fp1 = tcg_temp_new_i32();
8681 gen_load_fpr32(fp0, fs);
8682 gen_load_fpr32(fp1, ft);
8683 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
8684 tcg_temp_free_i32(fp1);
8685 gen_store_fpr32(fp0, fd);
8686 tcg_temp_free_i32(fp0);
8688 opn = "mul.s";
8689 optype = BINOP;
8690 break;
8691 case OPC_DIV_S:
8693 TCGv_i32 fp0 = tcg_temp_new_i32();
8694 TCGv_i32 fp1 = tcg_temp_new_i32();
8696 gen_load_fpr32(fp0, fs);
8697 gen_load_fpr32(fp1, ft);
8698 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
8699 tcg_temp_free_i32(fp1);
8700 gen_store_fpr32(fp0, fd);
8701 tcg_temp_free_i32(fp0);
8703 opn = "div.s";
8704 optype = BINOP;
8705 break;
8706 case OPC_SQRT_S:
8708 TCGv_i32 fp0 = tcg_temp_new_i32();
8710 gen_load_fpr32(fp0, fs);
8711 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
8712 gen_store_fpr32(fp0, fd);
8713 tcg_temp_free_i32(fp0);
8715 opn = "sqrt.s";
8716 break;
8717 case OPC_ABS_S:
8719 TCGv_i32 fp0 = tcg_temp_new_i32();
8721 gen_load_fpr32(fp0, fs);
8722 gen_helper_float_abs_s(fp0, fp0);
8723 gen_store_fpr32(fp0, fd);
8724 tcg_temp_free_i32(fp0);
8726 opn = "abs.s";
8727 break;
8728 case OPC_MOV_S:
8730 TCGv_i32 fp0 = tcg_temp_new_i32();
8732 gen_load_fpr32(fp0, fs);
8733 gen_store_fpr32(fp0, fd);
8734 tcg_temp_free_i32(fp0);
8736 opn = "mov.s";
8737 break;
8738 case OPC_NEG_S:
8740 TCGv_i32 fp0 = tcg_temp_new_i32();
8742 gen_load_fpr32(fp0, fs);
8743 gen_helper_float_chs_s(fp0, fp0);
8744 gen_store_fpr32(fp0, fd);
8745 tcg_temp_free_i32(fp0);
8747 opn = "neg.s";
8748 break;
8749 case OPC_ROUND_L_S:
8750 check_cp1_64bitmode(ctx);
8752 TCGv_i32 fp32 = tcg_temp_new_i32();
8753 TCGv_i64 fp64 = tcg_temp_new_i64();
8755 gen_load_fpr32(fp32, fs);
8756 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
8757 tcg_temp_free_i32(fp32);
8758 gen_store_fpr64(ctx, fp64, fd);
8759 tcg_temp_free_i64(fp64);
8761 opn = "round.l.s";
8762 break;
8763 case OPC_TRUNC_L_S:
8764 check_cp1_64bitmode(ctx);
8766 TCGv_i32 fp32 = tcg_temp_new_i32();
8767 TCGv_i64 fp64 = tcg_temp_new_i64();
8769 gen_load_fpr32(fp32, fs);
8770 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
8771 tcg_temp_free_i32(fp32);
8772 gen_store_fpr64(ctx, fp64, fd);
8773 tcg_temp_free_i64(fp64);
8775 opn = "trunc.l.s";
8776 break;
8777 case OPC_CEIL_L_S:
8778 check_cp1_64bitmode(ctx);
8780 TCGv_i32 fp32 = tcg_temp_new_i32();
8781 TCGv_i64 fp64 = tcg_temp_new_i64();
8783 gen_load_fpr32(fp32, fs);
8784 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
8785 tcg_temp_free_i32(fp32);
8786 gen_store_fpr64(ctx, fp64, fd);
8787 tcg_temp_free_i64(fp64);
8789 opn = "ceil.l.s";
8790 break;
8791 case OPC_FLOOR_L_S:
8792 check_cp1_64bitmode(ctx);
8794 TCGv_i32 fp32 = tcg_temp_new_i32();
8795 TCGv_i64 fp64 = tcg_temp_new_i64();
8797 gen_load_fpr32(fp32, fs);
8798 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
8799 tcg_temp_free_i32(fp32);
8800 gen_store_fpr64(ctx, fp64, fd);
8801 tcg_temp_free_i64(fp64);
8803 opn = "floor.l.s";
8804 break;
8805 case OPC_ROUND_W_S:
8807 TCGv_i32 fp0 = tcg_temp_new_i32();
8809 gen_load_fpr32(fp0, fs);
8810 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
8811 gen_store_fpr32(fp0, fd);
8812 tcg_temp_free_i32(fp0);
8814 opn = "round.w.s";
8815 break;
8816 case OPC_TRUNC_W_S:
8818 TCGv_i32 fp0 = tcg_temp_new_i32();
8820 gen_load_fpr32(fp0, fs);
8821 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
8822 gen_store_fpr32(fp0, fd);
8823 tcg_temp_free_i32(fp0);
8825 opn = "trunc.w.s";
8826 break;
8827 case OPC_CEIL_W_S:
8829 TCGv_i32 fp0 = tcg_temp_new_i32();
8831 gen_load_fpr32(fp0, fs);
8832 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
8833 gen_store_fpr32(fp0, fd);
8834 tcg_temp_free_i32(fp0);
8836 opn = "ceil.w.s";
8837 break;
8838 case OPC_FLOOR_W_S:
8840 TCGv_i32 fp0 = tcg_temp_new_i32();
8842 gen_load_fpr32(fp0, fs);
8843 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
8844 gen_store_fpr32(fp0, fd);
8845 tcg_temp_free_i32(fp0);
8847 opn = "floor.w.s";
8848 break;
8849 case OPC_SEL_S:
8850 check_insn(ctx, ISA_MIPS32R6);
8851 gen_sel_s(ctx, op1, fd, ft, fs);
8852 opn = "sel.s";
8853 break;
8854 case OPC_SELEQZ_S:
8855 check_insn(ctx, ISA_MIPS32R6);
8856 gen_sel_s(ctx, op1, fd, ft, fs);
8857 opn = "seleqz.s";
8858 break;
8859 case OPC_SELNEZ_S:
8860 check_insn(ctx, ISA_MIPS32R6);
8861 gen_sel_s(ctx, op1, fd, ft, fs);
8862 opn = "selnez.s";
8863 break;
8864 case OPC_MOVCF_S:
8865 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8866 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
8867 opn = "movcf.s";
8868 break;
8869 case OPC_MOVZ_S:
8870 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8872 int l1 = gen_new_label();
8873 TCGv_i32 fp0;
8875 if (ft != 0) {
8876 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8878 fp0 = tcg_temp_new_i32();
8879 gen_load_fpr32(fp0, fs);
8880 gen_store_fpr32(fp0, fd);
8881 tcg_temp_free_i32(fp0);
8882 gen_set_label(l1);
8884 opn = "movz.s";
8885 break;
8886 case OPC_MOVN_S:
8887 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8889 int l1 = gen_new_label();
8890 TCGv_i32 fp0;
8892 if (ft != 0) {
8893 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8894 fp0 = tcg_temp_new_i32();
8895 gen_load_fpr32(fp0, fs);
8896 gen_store_fpr32(fp0, fd);
8897 tcg_temp_free_i32(fp0);
8898 gen_set_label(l1);
8901 opn = "movn.s";
8902 break;
8903 case OPC_RECIP_S:
8904 check_cop1x(ctx);
8906 TCGv_i32 fp0 = tcg_temp_new_i32();
8908 gen_load_fpr32(fp0, fs);
8909 gen_helper_float_recip_s(fp0, cpu_env, fp0);
8910 gen_store_fpr32(fp0, fd);
8911 tcg_temp_free_i32(fp0);
8913 opn = "recip.s";
8914 break;
8915 case OPC_RSQRT_S:
8916 check_cop1x(ctx);
8918 TCGv_i32 fp0 = tcg_temp_new_i32();
8920 gen_load_fpr32(fp0, fs);
8921 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
8922 gen_store_fpr32(fp0, fd);
8923 tcg_temp_free_i32(fp0);
8925 opn = "rsqrt.s";
8926 break;
8927 case OPC_MADDF_S:
8928 check_insn(ctx, ISA_MIPS32R6);
8930 TCGv_i32 fp0 = tcg_temp_new_i32();
8931 TCGv_i32 fp1 = tcg_temp_new_i32();
8932 TCGv_i32 fp2 = tcg_temp_new_i32();
8933 gen_load_fpr32(fp0, fs);
8934 gen_load_fpr32(fp1, ft);
8935 gen_load_fpr32(fp2, fd);
8936 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
8937 gen_store_fpr32(fp2, fd);
8938 tcg_temp_free_i32(fp2);
8939 tcg_temp_free_i32(fp1);
8940 tcg_temp_free_i32(fp0);
8941 opn = "maddf.s";
8943 break;
8944 case OPC_MSUBF_S:
8945 check_insn(ctx, ISA_MIPS32R6);
8947 TCGv_i32 fp0 = tcg_temp_new_i32();
8948 TCGv_i32 fp1 = tcg_temp_new_i32();
8949 TCGv_i32 fp2 = tcg_temp_new_i32();
8950 gen_load_fpr32(fp0, fs);
8951 gen_load_fpr32(fp1, ft);
8952 gen_load_fpr32(fp2, fd);
8953 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
8954 gen_store_fpr32(fp2, fd);
8955 tcg_temp_free_i32(fp2);
8956 tcg_temp_free_i32(fp1);
8957 tcg_temp_free_i32(fp0);
8958 opn = "msubf.s";
8960 break;
8961 case OPC_RINT_S:
8962 check_insn(ctx, ISA_MIPS32R6);
8964 TCGv_i32 fp0 = tcg_temp_new_i32();
8965 gen_load_fpr32(fp0, fs);
8966 gen_helper_float_rint_s(fp0, cpu_env, fp0);
8967 gen_store_fpr32(fp0, fd);
8968 tcg_temp_free_i32(fp0);
8969 opn = "rint.s";
8971 break;
8972 case OPC_CLASS_S:
8973 check_insn(ctx, ISA_MIPS32R6);
8975 TCGv_i32 fp0 = tcg_temp_new_i32();
8976 gen_load_fpr32(fp0, fs);
8977 gen_helper_float_class_s(fp0, fp0);
8978 gen_store_fpr32(fp0, fd);
8979 tcg_temp_free_i32(fp0);
8980 opn = "class.s";
8982 break;
8983 case OPC_MIN_S: /* OPC_RECIP2_S */
8984 if (ctx->insn_flags & ISA_MIPS32R6) {
8985 /* OPC_MIN_S */
8986 TCGv_i32 fp0 = tcg_temp_new_i32();
8987 TCGv_i32 fp1 = tcg_temp_new_i32();
8988 TCGv_i32 fp2 = tcg_temp_new_i32();
8989 gen_load_fpr32(fp0, fs);
8990 gen_load_fpr32(fp1, ft);
8991 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
8992 gen_store_fpr32(fp2, fd);
8993 tcg_temp_free_i32(fp2);
8994 tcg_temp_free_i32(fp1);
8995 tcg_temp_free_i32(fp0);
8996 opn = "min.s";
8997 } else {
8998 /* OPC_RECIP2_S */
8999 check_cp1_64bitmode(ctx);
9001 TCGv_i32 fp0 = tcg_temp_new_i32();
9002 TCGv_i32 fp1 = tcg_temp_new_i32();
9004 gen_load_fpr32(fp0, fs);
9005 gen_load_fpr32(fp1, ft);
9006 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9007 tcg_temp_free_i32(fp1);
9008 gen_store_fpr32(fp0, fd);
9009 tcg_temp_free_i32(fp0);
9011 opn = "recip2.s";
9013 break;
9014 case OPC_MINA_S: /* OPC_RECIP1_S */
9015 if (ctx->insn_flags & ISA_MIPS32R6) {
9016 /* OPC_MINA_S */
9017 TCGv_i32 fp0 = tcg_temp_new_i32();
9018 TCGv_i32 fp1 = tcg_temp_new_i32();
9019 TCGv_i32 fp2 = tcg_temp_new_i32();
9020 gen_load_fpr32(fp0, fs);
9021 gen_load_fpr32(fp1, ft);
9022 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9023 gen_store_fpr32(fp2, fd);
9024 tcg_temp_free_i32(fp2);
9025 tcg_temp_free_i32(fp1);
9026 tcg_temp_free_i32(fp0);
9027 opn = "mina.s";
9028 } else {
9029 /* OPC_RECIP1_S */
9030 check_cp1_64bitmode(ctx);
9032 TCGv_i32 fp0 = tcg_temp_new_i32();
9034 gen_load_fpr32(fp0, fs);
9035 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9036 gen_store_fpr32(fp0, fd);
9037 tcg_temp_free_i32(fp0);
9039 opn = "recip1.s";
9041 break;
9042 case OPC_MAX_S: /* OPC_RSQRT1_S */
9043 if (ctx->insn_flags & ISA_MIPS32R6) {
9044 /* OPC_MAX_S */
9045 TCGv_i32 fp0 = tcg_temp_new_i32();
9046 TCGv_i32 fp1 = tcg_temp_new_i32();
9047 gen_load_fpr32(fp0, fs);
9048 gen_load_fpr32(fp1, ft);
9049 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9050 gen_store_fpr32(fp1, fd);
9051 tcg_temp_free_i32(fp1);
9052 tcg_temp_free_i32(fp0);
9053 opn = "max.s";
9054 } else {
9055 /* OPC_RSQRT1_S */
9056 check_cp1_64bitmode(ctx);
9058 TCGv_i32 fp0 = tcg_temp_new_i32();
9060 gen_load_fpr32(fp0, fs);
9061 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9062 gen_store_fpr32(fp0, fd);
9063 tcg_temp_free_i32(fp0);
9065 opn = "rsqrt1.s";
9067 break;
9068 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9069 if (ctx->insn_flags & ISA_MIPS32R6) {
9070 /* OPC_MAXA_S */
9071 TCGv_i32 fp0 = tcg_temp_new_i32();
9072 TCGv_i32 fp1 = tcg_temp_new_i32();
9073 gen_load_fpr32(fp0, fs);
9074 gen_load_fpr32(fp1, ft);
9075 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9076 gen_store_fpr32(fp1, fd);
9077 tcg_temp_free_i32(fp1);
9078 tcg_temp_free_i32(fp0);
9079 opn = "maxa.s";
9080 } else {
9081 /* OPC_RSQRT2_S */
9082 check_cp1_64bitmode(ctx);
9084 TCGv_i32 fp0 = tcg_temp_new_i32();
9085 TCGv_i32 fp1 = tcg_temp_new_i32();
9087 gen_load_fpr32(fp0, fs);
9088 gen_load_fpr32(fp1, ft);
9089 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9090 tcg_temp_free_i32(fp1);
9091 gen_store_fpr32(fp0, fd);
9092 tcg_temp_free_i32(fp0);
9094 opn = "rsqrt2.s";
9096 break;
9097 case OPC_CVT_D_S:
9098 check_cp1_registers(ctx, fd);
9100 TCGv_i32 fp32 = tcg_temp_new_i32();
9101 TCGv_i64 fp64 = tcg_temp_new_i64();
9103 gen_load_fpr32(fp32, fs);
9104 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9105 tcg_temp_free_i32(fp32);
9106 gen_store_fpr64(ctx, fp64, fd);
9107 tcg_temp_free_i64(fp64);
9109 opn = "cvt.d.s";
9110 break;
9111 case OPC_CVT_W_S:
9113 TCGv_i32 fp0 = tcg_temp_new_i32();
9115 gen_load_fpr32(fp0, fs);
9116 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
9117 gen_store_fpr32(fp0, fd);
9118 tcg_temp_free_i32(fp0);
9120 opn = "cvt.w.s";
9121 break;
9122 case OPC_CVT_L_S:
9123 check_cp1_64bitmode(ctx);
9125 TCGv_i32 fp32 = tcg_temp_new_i32();
9126 TCGv_i64 fp64 = tcg_temp_new_i64();
9128 gen_load_fpr32(fp32, fs);
9129 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
9130 tcg_temp_free_i32(fp32);
9131 gen_store_fpr64(ctx, fp64, fd);
9132 tcg_temp_free_i64(fp64);
9134 opn = "cvt.l.s";
9135 break;
9136 case OPC_CVT_PS_S:
9137 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9138 check_cp1_64bitmode(ctx);
9140 TCGv_i64 fp64 = tcg_temp_new_i64();
9141 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9142 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9144 gen_load_fpr32(fp32_0, fs);
9145 gen_load_fpr32(fp32_1, ft);
9146 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9147 tcg_temp_free_i32(fp32_1);
9148 tcg_temp_free_i32(fp32_0);
9149 gen_store_fpr64(ctx, fp64, fd);
9150 tcg_temp_free_i64(fp64);
9152 opn = "cvt.ps.s";
9153 break;
9154 case OPC_CMP_F_S:
9155 case OPC_CMP_UN_S:
9156 case OPC_CMP_EQ_S:
9157 case OPC_CMP_UEQ_S:
9158 case OPC_CMP_OLT_S:
9159 case OPC_CMP_ULT_S:
9160 case OPC_CMP_OLE_S:
9161 case OPC_CMP_ULE_S:
9162 case OPC_CMP_SF_S:
9163 case OPC_CMP_NGLE_S:
9164 case OPC_CMP_SEQ_S:
9165 case OPC_CMP_NGL_S:
9166 case OPC_CMP_LT_S:
9167 case OPC_CMP_NGE_S:
9168 case OPC_CMP_LE_S:
9169 case OPC_CMP_NGT_S:
9170 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9171 if (ctx->opcode & (1 << 6)) {
9172 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9173 opn = condnames_abs[func-48];
9174 } else {
9175 gen_cmp_s(ctx, func-48, ft, fs, cc);
9176 opn = condnames[func-48];
9178 break;
9179 case OPC_ADD_D:
9180 check_cp1_registers(ctx, fs | ft | fd);
9182 TCGv_i64 fp0 = tcg_temp_new_i64();
9183 TCGv_i64 fp1 = tcg_temp_new_i64();
9185 gen_load_fpr64(ctx, fp0, fs);
9186 gen_load_fpr64(ctx, fp1, ft);
9187 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9188 tcg_temp_free_i64(fp1);
9189 gen_store_fpr64(ctx, fp0, fd);
9190 tcg_temp_free_i64(fp0);
9192 opn = "add.d";
9193 optype = BINOP;
9194 break;
9195 case OPC_SUB_D:
9196 check_cp1_registers(ctx, fs | ft | fd);
9198 TCGv_i64 fp0 = tcg_temp_new_i64();
9199 TCGv_i64 fp1 = tcg_temp_new_i64();
9201 gen_load_fpr64(ctx, fp0, fs);
9202 gen_load_fpr64(ctx, fp1, ft);
9203 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9204 tcg_temp_free_i64(fp1);
9205 gen_store_fpr64(ctx, fp0, fd);
9206 tcg_temp_free_i64(fp0);
9208 opn = "sub.d";
9209 optype = BINOP;
9210 break;
9211 case OPC_MUL_D:
9212 check_cp1_registers(ctx, fs | ft | fd);
9214 TCGv_i64 fp0 = tcg_temp_new_i64();
9215 TCGv_i64 fp1 = tcg_temp_new_i64();
9217 gen_load_fpr64(ctx, fp0, fs);
9218 gen_load_fpr64(ctx, fp1, ft);
9219 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9220 tcg_temp_free_i64(fp1);
9221 gen_store_fpr64(ctx, fp0, fd);
9222 tcg_temp_free_i64(fp0);
9224 opn = "mul.d";
9225 optype = BINOP;
9226 break;
9227 case OPC_DIV_D:
9228 check_cp1_registers(ctx, fs | ft | fd);
9230 TCGv_i64 fp0 = tcg_temp_new_i64();
9231 TCGv_i64 fp1 = tcg_temp_new_i64();
9233 gen_load_fpr64(ctx, fp0, fs);
9234 gen_load_fpr64(ctx, fp1, ft);
9235 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9236 tcg_temp_free_i64(fp1);
9237 gen_store_fpr64(ctx, fp0, fd);
9238 tcg_temp_free_i64(fp0);
9240 opn = "div.d";
9241 optype = BINOP;
9242 break;
9243 case OPC_SQRT_D:
9244 check_cp1_registers(ctx, fs | fd);
9246 TCGv_i64 fp0 = tcg_temp_new_i64();
9248 gen_load_fpr64(ctx, fp0, fs);
9249 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9250 gen_store_fpr64(ctx, fp0, fd);
9251 tcg_temp_free_i64(fp0);
9253 opn = "sqrt.d";
9254 break;
9255 case OPC_ABS_D:
9256 check_cp1_registers(ctx, fs | fd);
9258 TCGv_i64 fp0 = tcg_temp_new_i64();
9260 gen_load_fpr64(ctx, fp0, fs);
9261 gen_helper_float_abs_d(fp0, fp0);
9262 gen_store_fpr64(ctx, fp0, fd);
9263 tcg_temp_free_i64(fp0);
9265 opn = "abs.d";
9266 break;
9267 case OPC_MOV_D:
9268 check_cp1_registers(ctx, fs | fd);
9270 TCGv_i64 fp0 = tcg_temp_new_i64();
9272 gen_load_fpr64(ctx, fp0, fs);
9273 gen_store_fpr64(ctx, fp0, fd);
9274 tcg_temp_free_i64(fp0);
9276 opn = "mov.d";
9277 break;
9278 case OPC_NEG_D:
9279 check_cp1_registers(ctx, fs | fd);
9281 TCGv_i64 fp0 = tcg_temp_new_i64();
9283 gen_load_fpr64(ctx, fp0, fs);
9284 gen_helper_float_chs_d(fp0, fp0);
9285 gen_store_fpr64(ctx, fp0, fd);
9286 tcg_temp_free_i64(fp0);
9288 opn = "neg.d";
9289 break;
9290 case OPC_ROUND_L_D:
9291 check_cp1_64bitmode(ctx);
9293 TCGv_i64 fp0 = tcg_temp_new_i64();
9295 gen_load_fpr64(ctx, fp0, fs);
9296 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
9297 gen_store_fpr64(ctx, fp0, fd);
9298 tcg_temp_free_i64(fp0);
9300 opn = "round.l.d";
9301 break;
9302 case OPC_TRUNC_L_D:
9303 check_cp1_64bitmode(ctx);
9305 TCGv_i64 fp0 = tcg_temp_new_i64();
9307 gen_load_fpr64(ctx, fp0, fs);
9308 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
9309 gen_store_fpr64(ctx, fp0, fd);
9310 tcg_temp_free_i64(fp0);
9312 opn = "trunc.l.d";
9313 break;
9314 case OPC_CEIL_L_D:
9315 check_cp1_64bitmode(ctx);
9317 TCGv_i64 fp0 = tcg_temp_new_i64();
9319 gen_load_fpr64(ctx, fp0, fs);
9320 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
9321 gen_store_fpr64(ctx, fp0, fd);
9322 tcg_temp_free_i64(fp0);
9324 opn = "ceil.l.d";
9325 break;
9326 case OPC_FLOOR_L_D:
9327 check_cp1_64bitmode(ctx);
9329 TCGv_i64 fp0 = tcg_temp_new_i64();
9331 gen_load_fpr64(ctx, fp0, fs);
9332 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
9333 gen_store_fpr64(ctx, fp0, fd);
9334 tcg_temp_free_i64(fp0);
9336 opn = "floor.l.d";
9337 break;
9338 case OPC_ROUND_W_D:
9339 check_cp1_registers(ctx, fs);
9341 TCGv_i32 fp32 = tcg_temp_new_i32();
9342 TCGv_i64 fp64 = tcg_temp_new_i64();
9344 gen_load_fpr64(ctx, fp64, fs);
9345 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
9346 tcg_temp_free_i64(fp64);
9347 gen_store_fpr32(fp32, fd);
9348 tcg_temp_free_i32(fp32);
9350 opn = "round.w.d";
9351 break;
9352 case OPC_TRUNC_W_D:
9353 check_cp1_registers(ctx, fs);
9355 TCGv_i32 fp32 = tcg_temp_new_i32();
9356 TCGv_i64 fp64 = tcg_temp_new_i64();
9358 gen_load_fpr64(ctx, fp64, fs);
9359 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
9360 tcg_temp_free_i64(fp64);
9361 gen_store_fpr32(fp32, fd);
9362 tcg_temp_free_i32(fp32);
9364 opn = "trunc.w.d";
9365 break;
9366 case OPC_CEIL_W_D:
9367 check_cp1_registers(ctx, fs);
9369 TCGv_i32 fp32 = tcg_temp_new_i32();
9370 TCGv_i64 fp64 = tcg_temp_new_i64();
9372 gen_load_fpr64(ctx, fp64, fs);
9373 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
9374 tcg_temp_free_i64(fp64);
9375 gen_store_fpr32(fp32, fd);
9376 tcg_temp_free_i32(fp32);
9378 opn = "ceil.w.d";
9379 break;
9380 case OPC_FLOOR_W_D:
9381 check_cp1_registers(ctx, fs);
9383 TCGv_i32 fp32 = tcg_temp_new_i32();
9384 TCGv_i64 fp64 = tcg_temp_new_i64();
9386 gen_load_fpr64(ctx, fp64, fs);
9387 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
9388 tcg_temp_free_i64(fp64);
9389 gen_store_fpr32(fp32, fd);
9390 tcg_temp_free_i32(fp32);
9392 opn = "floor.w.d";
9393 break;
9394 case OPC_SEL_D:
9395 check_insn(ctx, ISA_MIPS32R6);
9396 gen_sel_d(ctx, op1, fd, ft, fs);
9397 opn = "sel.d";
9398 break;
9399 case OPC_SELEQZ_D:
9400 check_insn(ctx, ISA_MIPS32R6);
9401 gen_sel_d(ctx, op1, fd, ft, fs);
9402 opn = "seleqz.d";
9403 break;
9404 case OPC_SELNEZ_D:
9405 check_insn(ctx, ISA_MIPS32R6);
9406 gen_sel_d(ctx, op1, fd, ft, fs);
9407 opn = "selnez.d";
9408 break;
9409 case OPC_MOVCF_D:
9410 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9411 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9412 opn = "movcf.d";
9413 break;
9414 case OPC_MOVZ_D:
9415 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9417 int l1 = gen_new_label();
9418 TCGv_i64 fp0;
9420 if (ft != 0) {
9421 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9423 fp0 = tcg_temp_new_i64();
9424 gen_load_fpr64(ctx, fp0, fs);
9425 gen_store_fpr64(ctx, fp0, fd);
9426 tcg_temp_free_i64(fp0);
9427 gen_set_label(l1);
9429 opn = "movz.d";
9430 break;
9431 case OPC_MOVN_D:
9432 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9434 int l1 = gen_new_label();
9435 TCGv_i64 fp0;
9437 if (ft != 0) {
9438 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9439 fp0 = tcg_temp_new_i64();
9440 gen_load_fpr64(ctx, fp0, fs);
9441 gen_store_fpr64(ctx, fp0, fd);
9442 tcg_temp_free_i64(fp0);
9443 gen_set_label(l1);
9446 opn = "movn.d";
9447 break;
9448 case OPC_RECIP_D:
9449 check_cp1_64bitmode(ctx);
9451 TCGv_i64 fp0 = tcg_temp_new_i64();
9453 gen_load_fpr64(ctx, fp0, fs);
9454 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9455 gen_store_fpr64(ctx, fp0, fd);
9456 tcg_temp_free_i64(fp0);
9458 opn = "recip.d";
9459 break;
9460 case OPC_RSQRT_D:
9461 check_cp1_64bitmode(ctx);
9463 TCGv_i64 fp0 = tcg_temp_new_i64();
9465 gen_load_fpr64(ctx, fp0, fs);
9466 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9467 gen_store_fpr64(ctx, fp0, fd);
9468 tcg_temp_free_i64(fp0);
9470 opn = "rsqrt.d";
9471 break;
9472 case OPC_MADDF_D:
9473 check_insn(ctx, ISA_MIPS32R6);
9475 TCGv_i64 fp0 = tcg_temp_new_i64();
9476 TCGv_i64 fp1 = tcg_temp_new_i64();
9477 TCGv_i64 fp2 = tcg_temp_new_i64();
9478 gen_load_fpr64(ctx, fp0, fs);
9479 gen_load_fpr64(ctx, fp1, ft);
9480 gen_load_fpr64(ctx, fp2, fd);
9481 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9482 gen_store_fpr64(ctx, fp2, fd);
9483 tcg_temp_free_i64(fp2);
9484 tcg_temp_free_i64(fp1);
9485 tcg_temp_free_i64(fp0);
9486 opn = "maddf.d";
9488 break;
9489 case OPC_MSUBF_D:
9490 check_insn(ctx, ISA_MIPS32R6);
9492 TCGv_i64 fp0 = tcg_temp_new_i64();
9493 TCGv_i64 fp1 = tcg_temp_new_i64();
9494 TCGv_i64 fp2 = tcg_temp_new_i64();
9495 gen_load_fpr64(ctx, fp0, fs);
9496 gen_load_fpr64(ctx, fp1, ft);
9497 gen_load_fpr64(ctx, fp2, fd);
9498 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9499 gen_store_fpr64(ctx, fp2, fd);
9500 tcg_temp_free_i64(fp2);
9501 tcg_temp_free_i64(fp1);
9502 tcg_temp_free_i64(fp0);
9503 opn = "msubf.d";
9505 break;
9506 case OPC_RINT_D:
9507 check_insn(ctx, ISA_MIPS32R6);
9509 TCGv_i64 fp0 = tcg_temp_new_i64();
9510 gen_load_fpr64(ctx, fp0, fs);
9511 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9512 gen_store_fpr64(ctx, fp0, fd);
9513 tcg_temp_free_i64(fp0);
9514 opn = "rint.d";
9516 break;
9517 case OPC_CLASS_D:
9518 check_insn(ctx, ISA_MIPS32R6);
9520 TCGv_i64 fp0 = tcg_temp_new_i64();
9521 gen_load_fpr64(ctx, fp0, fs);
9522 gen_helper_float_class_d(fp0, fp0);
9523 gen_store_fpr64(ctx, fp0, fd);
9524 tcg_temp_free_i64(fp0);
9525 opn = "class.d";
9527 break;
9528 case OPC_MIN_D: /* OPC_RECIP2_D */
9529 if (ctx->insn_flags & ISA_MIPS32R6) {
9530 /* OPC_MIN_D */
9531 TCGv_i64 fp0 = tcg_temp_new_i64();
9532 TCGv_i64 fp1 = tcg_temp_new_i64();
9533 gen_load_fpr64(ctx, fp0, fs);
9534 gen_load_fpr64(ctx, fp1, ft);
9535 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9536 gen_store_fpr64(ctx, fp1, fd);
9537 tcg_temp_free_i64(fp1);
9538 tcg_temp_free_i64(fp0);
9539 opn = "min.d";
9540 } else {
9541 /* OPC_RECIP2_D */
9542 check_cp1_64bitmode(ctx);
9544 TCGv_i64 fp0 = tcg_temp_new_i64();
9545 TCGv_i64 fp1 = tcg_temp_new_i64();
9547 gen_load_fpr64(ctx, fp0, fs);
9548 gen_load_fpr64(ctx, fp1, ft);
9549 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9550 tcg_temp_free_i64(fp1);
9551 gen_store_fpr64(ctx, fp0, fd);
9552 tcg_temp_free_i64(fp0);
9554 opn = "recip2.d";
9556 break;
9557 case OPC_MINA_D: /* OPC_RECIP1_D */
9558 if (ctx->insn_flags & ISA_MIPS32R6) {
9559 /* OPC_MINA_D */
9560 TCGv_i64 fp0 = tcg_temp_new_i64();
9561 TCGv_i64 fp1 = tcg_temp_new_i64();
9562 gen_load_fpr64(ctx, fp0, fs);
9563 gen_load_fpr64(ctx, fp1, ft);
9564 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9565 gen_store_fpr64(ctx, fp1, fd);
9566 tcg_temp_free_i64(fp1);
9567 tcg_temp_free_i64(fp0);
9568 opn = "mina.d";
9569 } else {
9570 /* OPC_RECIP1_D */
9571 check_cp1_64bitmode(ctx);
9573 TCGv_i64 fp0 = tcg_temp_new_i64();
9575 gen_load_fpr64(ctx, fp0, fs);
9576 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9577 gen_store_fpr64(ctx, fp0, fd);
9578 tcg_temp_free_i64(fp0);
9580 opn = "recip1.d";
9582 break;
9583 case OPC_MAX_D: /* OPC_RSQRT1_D */
9584 if (ctx->insn_flags & ISA_MIPS32R6) {
9585 /* OPC_MAX_D */
9586 TCGv_i64 fp0 = tcg_temp_new_i64();
9587 TCGv_i64 fp1 = tcg_temp_new_i64();
9588 gen_load_fpr64(ctx, fp0, fs);
9589 gen_load_fpr64(ctx, fp1, ft);
9590 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9591 gen_store_fpr64(ctx, fp1, fd);
9592 tcg_temp_free_i64(fp1);
9593 tcg_temp_free_i64(fp0);
9594 opn = "max.d";
9595 } else {
9596 /* OPC_RSQRT1_D */
9597 check_cp1_64bitmode(ctx);
9599 TCGv_i64 fp0 = tcg_temp_new_i64();
9601 gen_load_fpr64(ctx, fp0, fs);
9602 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9603 gen_store_fpr64(ctx, fp0, fd);
9604 tcg_temp_free_i64(fp0);
9606 opn = "rsqrt1.d";
9608 break;
9609 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9610 if (ctx->insn_flags & ISA_MIPS32R6) {
9611 /* OPC_MAXA_D */
9612 TCGv_i64 fp0 = tcg_temp_new_i64();
9613 TCGv_i64 fp1 = tcg_temp_new_i64();
9614 gen_load_fpr64(ctx, fp0, fs);
9615 gen_load_fpr64(ctx, fp1, ft);
9616 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9617 gen_store_fpr64(ctx, fp1, fd);
9618 tcg_temp_free_i64(fp1);
9619 tcg_temp_free_i64(fp0);
9620 opn = "maxa.d";
9621 } else {
9622 /* OPC_RSQRT2_D */
9623 check_cp1_64bitmode(ctx);
9625 TCGv_i64 fp0 = tcg_temp_new_i64();
9626 TCGv_i64 fp1 = tcg_temp_new_i64();
9628 gen_load_fpr64(ctx, fp0, fs);
9629 gen_load_fpr64(ctx, fp1, ft);
9630 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9631 tcg_temp_free_i64(fp1);
9632 gen_store_fpr64(ctx, fp0, fd);
9633 tcg_temp_free_i64(fp0);
9635 opn = "rsqrt2.d";
9637 break;
9638 case OPC_CMP_F_D:
9639 case OPC_CMP_UN_D:
9640 case OPC_CMP_EQ_D:
9641 case OPC_CMP_UEQ_D:
9642 case OPC_CMP_OLT_D:
9643 case OPC_CMP_ULT_D:
9644 case OPC_CMP_OLE_D:
9645 case OPC_CMP_ULE_D:
9646 case OPC_CMP_SF_D:
9647 case OPC_CMP_NGLE_D:
9648 case OPC_CMP_SEQ_D:
9649 case OPC_CMP_NGL_D:
9650 case OPC_CMP_LT_D:
9651 case OPC_CMP_NGE_D:
9652 case OPC_CMP_LE_D:
9653 case OPC_CMP_NGT_D:
9654 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9655 if (ctx->opcode & (1 << 6)) {
9656 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9657 opn = condnames_abs[func-48];
9658 } else {
9659 gen_cmp_d(ctx, func-48, ft, fs, cc);
9660 opn = condnames[func-48];
9662 break;
9663 case OPC_CVT_S_D:
9664 check_cp1_registers(ctx, fs);
9666 TCGv_i32 fp32 = tcg_temp_new_i32();
9667 TCGv_i64 fp64 = tcg_temp_new_i64();
9669 gen_load_fpr64(ctx, fp64, fs);
9670 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
9671 tcg_temp_free_i64(fp64);
9672 gen_store_fpr32(fp32, fd);
9673 tcg_temp_free_i32(fp32);
9675 opn = "cvt.s.d";
9676 break;
9677 case OPC_CVT_W_D:
9678 check_cp1_registers(ctx, fs);
9680 TCGv_i32 fp32 = tcg_temp_new_i32();
9681 TCGv_i64 fp64 = tcg_temp_new_i64();
9683 gen_load_fpr64(ctx, fp64, fs);
9684 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
9685 tcg_temp_free_i64(fp64);
9686 gen_store_fpr32(fp32, fd);
9687 tcg_temp_free_i32(fp32);
9689 opn = "cvt.w.d";
9690 break;
9691 case OPC_CVT_L_D:
9692 check_cp1_64bitmode(ctx);
9694 TCGv_i64 fp0 = tcg_temp_new_i64();
9696 gen_load_fpr64(ctx, fp0, fs);
9697 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
9698 gen_store_fpr64(ctx, fp0, fd);
9699 tcg_temp_free_i64(fp0);
9701 opn = "cvt.l.d";
9702 break;
9703 case OPC_CVT_S_W:
9705 TCGv_i32 fp0 = tcg_temp_new_i32();
9707 gen_load_fpr32(fp0, fs);
9708 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
9709 gen_store_fpr32(fp0, fd);
9710 tcg_temp_free_i32(fp0);
9712 opn = "cvt.s.w";
9713 break;
9714 case OPC_CVT_D_W:
9715 check_cp1_registers(ctx, fd);
9717 TCGv_i32 fp32 = tcg_temp_new_i32();
9718 TCGv_i64 fp64 = tcg_temp_new_i64();
9720 gen_load_fpr32(fp32, fs);
9721 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
9722 tcg_temp_free_i32(fp32);
9723 gen_store_fpr64(ctx, fp64, fd);
9724 tcg_temp_free_i64(fp64);
9726 opn = "cvt.d.w";
9727 break;
9728 case OPC_CVT_S_L:
9729 check_cp1_64bitmode(ctx);
9731 TCGv_i32 fp32 = tcg_temp_new_i32();
9732 TCGv_i64 fp64 = tcg_temp_new_i64();
9734 gen_load_fpr64(ctx, fp64, fs);
9735 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
9736 tcg_temp_free_i64(fp64);
9737 gen_store_fpr32(fp32, fd);
9738 tcg_temp_free_i32(fp32);
9740 opn = "cvt.s.l";
9741 break;
9742 case OPC_CVT_D_L:
9743 check_cp1_64bitmode(ctx);
9745 TCGv_i64 fp0 = tcg_temp_new_i64();
9747 gen_load_fpr64(ctx, fp0, fs);
9748 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
9749 gen_store_fpr64(ctx, fp0, fd);
9750 tcg_temp_free_i64(fp0);
9752 opn = "cvt.d.l";
9753 break;
9754 case OPC_CVT_PS_PW:
9755 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9756 check_cp1_64bitmode(ctx);
9758 TCGv_i64 fp0 = tcg_temp_new_i64();
9760 gen_load_fpr64(ctx, fp0, fs);
9761 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
9762 gen_store_fpr64(ctx, fp0, fd);
9763 tcg_temp_free_i64(fp0);
9765 opn = "cvt.ps.pw";
9766 break;
9767 case OPC_ADD_PS:
9768 check_cp1_64bitmode(ctx);
9770 TCGv_i64 fp0 = tcg_temp_new_i64();
9771 TCGv_i64 fp1 = tcg_temp_new_i64();
9773 gen_load_fpr64(ctx, fp0, fs);
9774 gen_load_fpr64(ctx, fp1, ft);
9775 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
9776 tcg_temp_free_i64(fp1);
9777 gen_store_fpr64(ctx, fp0, fd);
9778 tcg_temp_free_i64(fp0);
9780 opn = "add.ps";
9781 break;
9782 case OPC_SUB_PS:
9783 check_cp1_64bitmode(ctx);
9785 TCGv_i64 fp0 = tcg_temp_new_i64();
9786 TCGv_i64 fp1 = tcg_temp_new_i64();
9788 gen_load_fpr64(ctx, fp0, fs);
9789 gen_load_fpr64(ctx, fp1, ft);
9790 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
9791 tcg_temp_free_i64(fp1);
9792 gen_store_fpr64(ctx, fp0, fd);
9793 tcg_temp_free_i64(fp0);
9795 opn = "sub.ps";
9796 break;
9797 case OPC_MUL_PS:
9798 check_cp1_64bitmode(ctx);
9800 TCGv_i64 fp0 = tcg_temp_new_i64();
9801 TCGv_i64 fp1 = tcg_temp_new_i64();
9803 gen_load_fpr64(ctx, fp0, fs);
9804 gen_load_fpr64(ctx, fp1, ft);
9805 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
9806 tcg_temp_free_i64(fp1);
9807 gen_store_fpr64(ctx, fp0, fd);
9808 tcg_temp_free_i64(fp0);
9810 opn = "mul.ps";
9811 break;
9812 case OPC_ABS_PS:
9813 check_cp1_64bitmode(ctx);
9815 TCGv_i64 fp0 = tcg_temp_new_i64();
9817 gen_load_fpr64(ctx, fp0, fs);
9818 gen_helper_float_abs_ps(fp0, fp0);
9819 gen_store_fpr64(ctx, fp0, fd);
9820 tcg_temp_free_i64(fp0);
9822 opn = "abs.ps";
9823 break;
9824 case OPC_MOV_PS:
9825 check_cp1_64bitmode(ctx);
9827 TCGv_i64 fp0 = tcg_temp_new_i64();
9829 gen_load_fpr64(ctx, fp0, fs);
9830 gen_store_fpr64(ctx, fp0, fd);
9831 tcg_temp_free_i64(fp0);
9833 opn = "mov.ps";
9834 break;
9835 case OPC_NEG_PS:
9836 check_cp1_64bitmode(ctx);
9838 TCGv_i64 fp0 = tcg_temp_new_i64();
9840 gen_load_fpr64(ctx, fp0, fs);
9841 gen_helper_float_chs_ps(fp0, fp0);
9842 gen_store_fpr64(ctx, fp0, fd);
9843 tcg_temp_free_i64(fp0);
9845 opn = "neg.ps";
9846 break;
9847 case OPC_MOVCF_PS:
9848 check_cp1_64bitmode(ctx);
9849 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9850 opn = "movcf.ps";
9851 break;
9852 case OPC_MOVZ_PS:
9853 check_cp1_64bitmode(ctx);
9855 int l1 = gen_new_label();
9856 TCGv_i64 fp0;
9858 if (ft != 0)
9859 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9860 fp0 = tcg_temp_new_i64();
9861 gen_load_fpr64(ctx, fp0, fs);
9862 gen_store_fpr64(ctx, fp0, fd);
9863 tcg_temp_free_i64(fp0);
9864 gen_set_label(l1);
9866 opn = "movz.ps";
9867 break;
9868 case OPC_MOVN_PS:
9869 check_cp1_64bitmode(ctx);
9871 int l1 = gen_new_label();
9872 TCGv_i64 fp0;
9874 if (ft != 0) {
9875 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9876 fp0 = tcg_temp_new_i64();
9877 gen_load_fpr64(ctx, fp0, fs);
9878 gen_store_fpr64(ctx, fp0, fd);
9879 tcg_temp_free_i64(fp0);
9880 gen_set_label(l1);
9883 opn = "movn.ps";
9884 break;
9885 case OPC_ADDR_PS:
9886 check_cp1_64bitmode(ctx);
9888 TCGv_i64 fp0 = tcg_temp_new_i64();
9889 TCGv_i64 fp1 = tcg_temp_new_i64();
9891 gen_load_fpr64(ctx, fp0, ft);
9892 gen_load_fpr64(ctx, fp1, fs);
9893 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
9894 tcg_temp_free_i64(fp1);
9895 gen_store_fpr64(ctx, fp0, fd);
9896 tcg_temp_free_i64(fp0);
9898 opn = "addr.ps";
9899 break;
9900 case OPC_MULR_PS:
9901 check_cp1_64bitmode(ctx);
9903 TCGv_i64 fp0 = tcg_temp_new_i64();
9904 TCGv_i64 fp1 = tcg_temp_new_i64();
9906 gen_load_fpr64(ctx, fp0, ft);
9907 gen_load_fpr64(ctx, fp1, fs);
9908 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
9909 tcg_temp_free_i64(fp1);
9910 gen_store_fpr64(ctx, fp0, fd);
9911 tcg_temp_free_i64(fp0);
9913 opn = "mulr.ps";
9914 break;
9915 case OPC_RECIP2_PS:
9916 check_cp1_64bitmode(ctx);
9918 TCGv_i64 fp0 = tcg_temp_new_i64();
9919 TCGv_i64 fp1 = tcg_temp_new_i64();
9921 gen_load_fpr64(ctx, fp0, fs);
9922 gen_load_fpr64(ctx, fp1, ft);
9923 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
9924 tcg_temp_free_i64(fp1);
9925 gen_store_fpr64(ctx, fp0, fd);
9926 tcg_temp_free_i64(fp0);
9928 opn = "recip2.ps";
9929 break;
9930 case OPC_RECIP1_PS:
9931 check_cp1_64bitmode(ctx);
9933 TCGv_i64 fp0 = tcg_temp_new_i64();
9935 gen_load_fpr64(ctx, fp0, fs);
9936 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
9937 gen_store_fpr64(ctx, fp0, fd);
9938 tcg_temp_free_i64(fp0);
9940 opn = "recip1.ps";
9941 break;
9942 case OPC_RSQRT1_PS:
9943 check_cp1_64bitmode(ctx);
9945 TCGv_i64 fp0 = tcg_temp_new_i64();
9947 gen_load_fpr64(ctx, fp0, fs);
9948 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
9949 gen_store_fpr64(ctx, fp0, fd);
9950 tcg_temp_free_i64(fp0);
9952 opn = "rsqrt1.ps";
9953 break;
9954 case OPC_RSQRT2_PS:
9955 check_cp1_64bitmode(ctx);
9957 TCGv_i64 fp0 = tcg_temp_new_i64();
9958 TCGv_i64 fp1 = tcg_temp_new_i64();
9960 gen_load_fpr64(ctx, fp0, fs);
9961 gen_load_fpr64(ctx, fp1, ft);
9962 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
9963 tcg_temp_free_i64(fp1);
9964 gen_store_fpr64(ctx, fp0, fd);
9965 tcg_temp_free_i64(fp0);
9967 opn = "rsqrt2.ps";
9968 break;
9969 case OPC_CVT_S_PU:
9970 check_cp1_64bitmode(ctx);
9972 TCGv_i32 fp0 = tcg_temp_new_i32();
9974 gen_load_fpr32h(ctx, fp0, fs);
9975 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
9976 gen_store_fpr32(fp0, fd);
9977 tcg_temp_free_i32(fp0);
9979 opn = "cvt.s.pu";
9980 break;
9981 case OPC_CVT_PW_PS:
9982 check_cp1_64bitmode(ctx);
9984 TCGv_i64 fp0 = tcg_temp_new_i64();
9986 gen_load_fpr64(ctx, fp0, fs);
9987 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
9988 gen_store_fpr64(ctx, fp0, fd);
9989 tcg_temp_free_i64(fp0);
9991 opn = "cvt.pw.ps";
9992 break;
9993 case OPC_CVT_S_PL:
9994 check_cp1_64bitmode(ctx);
9996 TCGv_i32 fp0 = tcg_temp_new_i32();
9998 gen_load_fpr32(fp0, fs);
9999 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10000 gen_store_fpr32(fp0, fd);
10001 tcg_temp_free_i32(fp0);
10003 opn = "cvt.s.pl";
10004 break;
10005 case OPC_PLL_PS:
10006 check_cp1_64bitmode(ctx);
10008 TCGv_i32 fp0 = tcg_temp_new_i32();
10009 TCGv_i32 fp1 = tcg_temp_new_i32();
10011 gen_load_fpr32(fp0, fs);
10012 gen_load_fpr32(fp1, ft);
10013 gen_store_fpr32h(ctx, fp0, fd);
10014 gen_store_fpr32(fp1, fd);
10015 tcg_temp_free_i32(fp0);
10016 tcg_temp_free_i32(fp1);
10018 opn = "pll.ps";
10019 break;
10020 case OPC_PLU_PS:
10021 check_cp1_64bitmode(ctx);
10023 TCGv_i32 fp0 = tcg_temp_new_i32();
10024 TCGv_i32 fp1 = tcg_temp_new_i32();
10026 gen_load_fpr32(fp0, fs);
10027 gen_load_fpr32h(ctx, fp1, ft);
10028 gen_store_fpr32(fp1, fd);
10029 gen_store_fpr32h(ctx, fp0, fd);
10030 tcg_temp_free_i32(fp0);
10031 tcg_temp_free_i32(fp1);
10033 opn = "plu.ps";
10034 break;
10035 case OPC_PUL_PS:
10036 check_cp1_64bitmode(ctx);
10038 TCGv_i32 fp0 = tcg_temp_new_i32();
10039 TCGv_i32 fp1 = tcg_temp_new_i32();
10041 gen_load_fpr32h(ctx, fp0, fs);
10042 gen_load_fpr32(fp1, ft);
10043 gen_store_fpr32(fp1, fd);
10044 gen_store_fpr32h(ctx, fp0, fd);
10045 tcg_temp_free_i32(fp0);
10046 tcg_temp_free_i32(fp1);
10048 opn = "pul.ps";
10049 break;
10050 case OPC_PUU_PS:
10051 check_cp1_64bitmode(ctx);
10053 TCGv_i32 fp0 = tcg_temp_new_i32();
10054 TCGv_i32 fp1 = tcg_temp_new_i32();
10056 gen_load_fpr32h(ctx, fp0, fs);
10057 gen_load_fpr32h(ctx, fp1, ft);
10058 gen_store_fpr32(fp1, fd);
10059 gen_store_fpr32h(ctx, fp0, fd);
10060 tcg_temp_free_i32(fp0);
10061 tcg_temp_free_i32(fp1);
10063 opn = "puu.ps";
10064 break;
10065 case OPC_CMP_F_PS:
10066 case OPC_CMP_UN_PS:
10067 case OPC_CMP_EQ_PS:
10068 case OPC_CMP_UEQ_PS:
10069 case OPC_CMP_OLT_PS:
10070 case OPC_CMP_ULT_PS:
10071 case OPC_CMP_OLE_PS:
10072 case OPC_CMP_ULE_PS:
10073 case OPC_CMP_SF_PS:
10074 case OPC_CMP_NGLE_PS:
10075 case OPC_CMP_SEQ_PS:
10076 case OPC_CMP_NGL_PS:
10077 case OPC_CMP_LT_PS:
10078 case OPC_CMP_NGE_PS:
10079 case OPC_CMP_LE_PS:
10080 case OPC_CMP_NGT_PS:
10081 if (ctx->opcode & (1 << 6)) {
10082 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10083 opn = condnames_abs[func-48];
10084 } else {
10085 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10086 opn = condnames[func-48];
10088 break;
10089 default:
10090 MIPS_INVAL(opn);
10091 generate_exception (ctx, EXCP_RI);
10092 return;
10094 (void)opn; /* avoid a compiler warning */
10095 switch (optype) {
10096 case BINOP:
10097 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
10098 break;
10099 case CMPOP:
10100 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
10101 break;
10102 default:
10103 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
10104 break;
10108 /* Coprocessor 3 (FPU) */
10109 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10110 int fd, int fs, int base, int index)
10112 const char *opn = "extended float load/store";
10113 int store = 0;
10114 TCGv t0 = tcg_temp_new();
10116 if (base == 0) {
10117 gen_load_gpr(t0, index);
10118 } else if (index == 0) {
10119 gen_load_gpr(t0, base);
10120 } else {
10121 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10123 /* Don't do NOP if destination is zero: we must perform the actual
10124 memory access. */
10125 switch (opc) {
10126 case OPC_LWXC1:
10127 check_cop1x(ctx);
10129 TCGv_i32 fp0 = tcg_temp_new_i32();
10131 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10132 tcg_gen_trunc_tl_i32(fp0, t0);
10133 gen_store_fpr32(fp0, fd);
10134 tcg_temp_free_i32(fp0);
10136 opn = "lwxc1";
10137 break;
10138 case OPC_LDXC1:
10139 check_cop1x(ctx);
10140 check_cp1_registers(ctx, fd);
10142 TCGv_i64 fp0 = tcg_temp_new_i64();
10143 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10144 gen_store_fpr64(ctx, fp0, fd);
10145 tcg_temp_free_i64(fp0);
10147 opn = "ldxc1";
10148 break;
10149 case OPC_LUXC1:
10150 check_cp1_64bitmode(ctx);
10151 tcg_gen_andi_tl(t0, t0, ~0x7);
10153 TCGv_i64 fp0 = tcg_temp_new_i64();
10155 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10156 gen_store_fpr64(ctx, fp0, fd);
10157 tcg_temp_free_i64(fp0);
10159 opn = "luxc1";
10160 break;
10161 case OPC_SWXC1:
10162 check_cop1x(ctx);
10164 TCGv_i32 fp0 = tcg_temp_new_i32();
10165 gen_load_fpr32(fp0, fs);
10166 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10167 tcg_temp_free_i32(fp0);
10169 opn = "swxc1";
10170 store = 1;
10171 break;
10172 case OPC_SDXC1:
10173 check_cop1x(ctx);
10174 check_cp1_registers(ctx, fs);
10176 TCGv_i64 fp0 = tcg_temp_new_i64();
10177 gen_load_fpr64(ctx, fp0, fs);
10178 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10179 tcg_temp_free_i64(fp0);
10181 opn = "sdxc1";
10182 store = 1;
10183 break;
10184 case OPC_SUXC1:
10185 check_cp1_64bitmode(ctx);
10186 tcg_gen_andi_tl(t0, t0, ~0x7);
10188 TCGv_i64 fp0 = tcg_temp_new_i64();
10189 gen_load_fpr64(ctx, fp0, fs);
10190 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10191 tcg_temp_free_i64(fp0);
10193 opn = "suxc1";
10194 store = 1;
10195 break;
10197 tcg_temp_free(t0);
10198 (void)opn; (void)store; /* avoid compiler warnings */
10199 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
10200 regnames[index], regnames[base]);
10203 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10204 int fd, int fr, int fs, int ft)
10206 const char *opn = "flt3_arith";
10208 switch (opc) {
10209 case OPC_ALNV_PS:
10210 check_cp1_64bitmode(ctx);
10212 TCGv t0 = tcg_temp_local_new();
10213 TCGv_i32 fp = tcg_temp_new_i32();
10214 TCGv_i32 fph = tcg_temp_new_i32();
10215 int l1 = gen_new_label();
10216 int l2 = gen_new_label();
10218 gen_load_gpr(t0, fr);
10219 tcg_gen_andi_tl(t0, t0, 0x7);
10221 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10222 gen_load_fpr32(fp, fs);
10223 gen_load_fpr32h(ctx, fph, fs);
10224 gen_store_fpr32(fp, fd);
10225 gen_store_fpr32h(ctx, fph, fd);
10226 tcg_gen_br(l2);
10227 gen_set_label(l1);
10228 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10229 tcg_temp_free(t0);
10230 #ifdef TARGET_WORDS_BIGENDIAN
10231 gen_load_fpr32(fp, fs);
10232 gen_load_fpr32h(ctx, fph, ft);
10233 gen_store_fpr32h(ctx, fp, fd);
10234 gen_store_fpr32(fph, fd);
10235 #else
10236 gen_load_fpr32h(ctx, fph, fs);
10237 gen_load_fpr32(fp, ft);
10238 gen_store_fpr32(fph, fd);
10239 gen_store_fpr32h(ctx, fp, fd);
10240 #endif
10241 gen_set_label(l2);
10242 tcg_temp_free_i32(fp);
10243 tcg_temp_free_i32(fph);
10245 opn = "alnv.ps";
10246 break;
10247 case OPC_MADD_S:
10248 check_cop1x(ctx);
10250 TCGv_i32 fp0 = tcg_temp_new_i32();
10251 TCGv_i32 fp1 = tcg_temp_new_i32();
10252 TCGv_i32 fp2 = tcg_temp_new_i32();
10254 gen_load_fpr32(fp0, fs);
10255 gen_load_fpr32(fp1, ft);
10256 gen_load_fpr32(fp2, fr);
10257 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10258 tcg_temp_free_i32(fp0);
10259 tcg_temp_free_i32(fp1);
10260 gen_store_fpr32(fp2, fd);
10261 tcg_temp_free_i32(fp2);
10263 opn = "madd.s";
10264 break;
10265 case OPC_MADD_D:
10266 check_cop1x(ctx);
10267 check_cp1_registers(ctx, fd | fs | ft | fr);
10269 TCGv_i64 fp0 = tcg_temp_new_i64();
10270 TCGv_i64 fp1 = tcg_temp_new_i64();
10271 TCGv_i64 fp2 = tcg_temp_new_i64();
10273 gen_load_fpr64(ctx, fp0, fs);
10274 gen_load_fpr64(ctx, fp1, ft);
10275 gen_load_fpr64(ctx, fp2, fr);
10276 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10277 tcg_temp_free_i64(fp0);
10278 tcg_temp_free_i64(fp1);
10279 gen_store_fpr64(ctx, fp2, fd);
10280 tcg_temp_free_i64(fp2);
10282 opn = "madd.d";
10283 break;
10284 case OPC_MADD_PS:
10285 check_cp1_64bitmode(ctx);
10287 TCGv_i64 fp0 = tcg_temp_new_i64();
10288 TCGv_i64 fp1 = tcg_temp_new_i64();
10289 TCGv_i64 fp2 = tcg_temp_new_i64();
10291 gen_load_fpr64(ctx, fp0, fs);
10292 gen_load_fpr64(ctx, fp1, ft);
10293 gen_load_fpr64(ctx, fp2, fr);
10294 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10295 tcg_temp_free_i64(fp0);
10296 tcg_temp_free_i64(fp1);
10297 gen_store_fpr64(ctx, fp2, fd);
10298 tcg_temp_free_i64(fp2);
10300 opn = "madd.ps";
10301 break;
10302 case OPC_MSUB_S:
10303 check_cop1x(ctx);
10305 TCGv_i32 fp0 = tcg_temp_new_i32();
10306 TCGv_i32 fp1 = tcg_temp_new_i32();
10307 TCGv_i32 fp2 = tcg_temp_new_i32();
10309 gen_load_fpr32(fp0, fs);
10310 gen_load_fpr32(fp1, ft);
10311 gen_load_fpr32(fp2, fr);
10312 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10313 tcg_temp_free_i32(fp0);
10314 tcg_temp_free_i32(fp1);
10315 gen_store_fpr32(fp2, fd);
10316 tcg_temp_free_i32(fp2);
10318 opn = "msub.s";
10319 break;
10320 case OPC_MSUB_D:
10321 check_cop1x(ctx);
10322 check_cp1_registers(ctx, fd | fs | ft | fr);
10324 TCGv_i64 fp0 = tcg_temp_new_i64();
10325 TCGv_i64 fp1 = tcg_temp_new_i64();
10326 TCGv_i64 fp2 = tcg_temp_new_i64();
10328 gen_load_fpr64(ctx, fp0, fs);
10329 gen_load_fpr64(ctx, fp1, ft);
10330 gen_load_fpr64(ctx, fp2, fr);
10331 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10332 tcg_temp_free_i64(fp0);
10333 tcg_temp_free_i64(fp1);
10334 gen_store_fpr64(ctx, fp2, fd);
10335 tcg_temp_free_i64(fp2);
10337 opn = "msub.d";
10338 break;
10339 case OPC_MSUB_PS:
10340 check_cp1_64bitmode(ctx);
10342 TCGv_i64 fp0 = tcg_temp_new_i64();
10343 TCGv_i64 fp1 = tcg_temp_new_i64();
10344 TCGv_i64 fp2 = tcg_temp_new_i64();
10346 gen_load_fpr64(ctx, fp0, fs);
10347 gen_load_fpr64(ctx, fp1, ft);
10348 gen_load_fpr64(ctx, fp2, fr);
10349 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10350 tcg_temp_free_i64(fp0);
10351 tcg_temp_free_i64(fp1);
10352 gen_store_fpr64(ctx, fp2, fd);
10353 tcg_temp_free_i64(fp2);
10355 opn = "msub.ps";
10356 break;
10357 case OPC_NMADD_S:
10358 check_cop1x(ctx);
10360 TCGv_i32 fp0 = tcg_temp_new_i32();
10361 TCGv_i32 fp1 = tcg_temp_new_i32();
10362 TCGv_i32 fp2 = tcg_temp_new_i32();
10364 gen_load_fpr32(fp0, fs);
10365 gen_load_fpr32(fp1, ft);
10366 gen_load_fpr32(fp2, fr);
10367 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10368 tcg_temp_free_i32(fp0);
10369 tcg_temp_free_i32(fp1);
10370 gen_store_fpr32(fp2, fd);
10371 tcg_temp_free_i32(fp2);
10373 opn = "nmadd.s";
10374 break;
10375 case OPC_NMADD_D:
10376 check_cop1x(ctx);
10377 check_cp1_registers(ctx, fd | fs | ft | fr);
10379 TCGv_i64 fp0 = tcg_temp_new_i64();
10380 TCGv_i64 fp1 = tcg_temp_new_i64();
10381 TCGv_i64 fp2 = tcg_temp_new_i64();
10383 gen_load_fpr64(ctx, fp0, fs);
10384 gen_load_fpr64(ctx, fp1, ft);
10385 gen_load_fpr64(ctx, fp2, fr);
10386 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10387 tcg_temp_free_i64(fp0);
10388 tcg_temp_free_i64(fp1);
10389 gen_store_fpr64(ctx, fp2, fd);
10390 tcg_temp_free_i64(fp2);
10392 opn = "nmadd.d";
10393 break;
10394 case OPC_NMADD_PS:
10395 check_cp1_64bitmode(ctx);
10397 TCGv_i64 fp0 = tcg_temp_new_i64();
10398 TCGv_i64 fp1 = tcg_temp_new_i64();
10399 TCGv_i64 fp2 = tcg_temp_new_i64();
10401 gen_load_fpr64(ctx, fp0, fs);
10402 gen_load_fpr64(ctx, fp1, ft);
10403 gen_load_fpr64(ctx, fp2, fr);
10404 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10405 tcg_temp_free_i64(fp0);
10406 tcg_temp_free_i64(fp1);
10407 gen_store_fpr64(ctx, fp2, fd);
10408 tcg_temp_free_i64(fp2);
10410 opn = "nmadd.ps";
10411 break;
10412 case OPC_NMSUB_S:
10413 check_cop1x(ctx);
10415 TCGv_i32 fp0 = tcg_temp_new_i32();
10416 TCGv_i32 fp1 = tcg_temp_new_i32();
10417 TCGv_i32 fp2 = tcg_temp_new_i32();
10419 gen_load_fpr32(fp0, fs);
10420 gen_load_fpr32(fp1, ft);
10421 gen_load_fpr32(fp2, fr);
10422 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10423 tcg_temp_free_i32(fp0);
10424 tcg_temp_free_i32(fp1);
10425 gen_store_fpr32(fp2, fd);
10426 tcg_temp_free_i32(fp2);
10428 opn = "nmsub.s";
10429 break;
10430 case OPC_NMSUB_D:
10431 check_cop1x(ctx);
10432 check_cp1_registers(ctx, fd | fs | ft | fr);
10434 TCGv_i64 fp0 = tcg_temp_new_i64();
10435 TCGv_i64 fp1 = tcg_temp_new_i64();
10436 TCGv_i64 fp2 = tcg_temp_new_i64();
10438 gen_load_fpr64(ctx, fp0, fs);
10439 gen_load_fpr64(ctx, fp1, ft);
10440 gen_load_fpr64(ctx, fp2, fr);
10441 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10442 tcg_temp_free_i64(fp0);
10443 tcg_temp_free_i64(fp1);
10444 gen_store_fpr64(ctx, fp2, fd);
10445 tcg_temp_free_i64(fp2);
10447 opn = "nmsub.d";
10448 break;
10449 case OPC_NMSUB_PS:
10450 check_cp1_64bitmode(ctx);
10452 TCGv_i64 fp0 = tcg_temp_new_i64();
10453 TCGv_i64 fp1 = tcg_temp_new_i64();
10454 TCGv_i64 fp2 = tcg_temp_new_i64();
10456 gen_load_fpr64(ctx, fp0, fs);
10457 gen_load_fpr64(ctx, fp1, ft);
10458 gen_load_fpr64(ctx, fp2, fr);
10459 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10460 tcg_temp_free_i64(fp0);
10461 tcg_temp_free_i64(fp1);
10462 gen_store_fpr64(ctx, fp2, fd);
10463 tcg_temp_free_i64(fp2);
10465 opn = "nmsub.ps";
10466 break;
10467 default:
10468 MIPS_INVAL(opn);
10469 generate_exception (ctx, EXCP_RI);
10470 return;
10472 (void)opn; /* avoid a compiler warning */
10473 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
10474 fregnames[fs], fregnames[ft]);
10477 static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
10479 TCGv t0;
10481 #if !defined(CONFIG_USER_ONLY)
10482 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10483 Therefore only check the ISA in system mode. */
10484 check_insn(ctx, ISA_MIPS32R2);
10485 #endif
10486 t0 = tcg_temp_new();
10488 switch (rd) {
10489 case 0:
10490 save_cpu_state(ctx, 1);
10491 gen_helper_rdhwr_cpunum(t0, cpu_env);
10492 gen_store_gpr(t0, rt);
10493 break;
10494 case 1:
10495 save_cpu_state(ctx, 1);
10496 gen_helper_rdhwr_synci_step(t0, cpu_env);
10497 gen_store_gpr(t0, rt);
10498 break;
10499 case 2:
10500 save_cpu_state(ctx, 1);
10501 gen_helper_rdhwr_cc(t0, cpu_env);
10502 gen_store_gpr(t0, rt);
10503 break;
10504 case 3:
10505 save_cpu_state(ctx, 1);
10506 gen_helper_rdhwr_ccres(t0, cpu_env);
10507 gen_store_gpr(t0, rt);
10508 break;
10509 case 29:
10510 #if defined(CONFIG_USER_ONLY)
10511 tcg_gen_ld_tl(t0, cpu_env,
10512 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10513 gen_store_gpr(t0, rt);
10514 break;
10515 #else
10516 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10517 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10518 tcg_gen_ld_tl(t0, cpu_env,
10519 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10520 gen_store_gpr(t0, rt);
10521 } else {
10522 generate_exception(ctx, EXCP_RI);
10524 break;
10525 #endif
10526 default: /* Invalid */
10527 MIPS_INVAL("rdhwr");
10528 generate_exception(ctx, EXCP_RI);
10529 break;
10531 tcg_temp_free(t0);
10534 static void gen_branch(DisasContext *ctx, int insn_bytes)
10536 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10537 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10538 /* Branches completion */
10539 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10540 ctx->bstate = BS_BRANCH;
10541 save_cpu_state(ctx, 0);
10542 /* FIXME: Need to clear can_do_io. */
10543 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10544 case MIPS_HFLAG_FBNSLOT:
10545 MIPS_DEBUG("forbidden slot");
10546 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10547 break;
10548 case MIPS_HFLAG_B:
10549 /* unconditional branch */
10550 MIPS_DEBUG("unconditional branch");
10551 if (proc_hflags & MIPS_HFLAG_BX) {
10552 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10554 gen_goto_tb(ctx, 0, ctx->btarget);
10555 break;
10556 case MIPS_HFLAG_BL:
10557 /* blikely taken case */
10558 MIPS_DEBUG("blikely branch taken");
10559 gen_goto_tb(ctx, 0, ctx->btarget);
10560 break;
10561 case MIPS_HFLAG_BC:
10562 /* Conditional branch */
10563 MIPS_DEBUG("conditional branch");
10565 int l1 = gen_new_label();
10567 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10568 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10569 gen_set_label(l1);
10570 gen_goto_tb(ctx, 0, ctx->btarget);
10572 break;
10573 case MIPS_HFLAG_BR:
10574 /* unconditional branch to register */
10575 MIPS_DEBUG("branch to register");
10576 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10577 TCGv t0 = tcg_temp_new();
10578 TCGv_i32 t1 = tcg_temp_new_i32();
10580 tcg_gen_andi_tl(t0, btarget, 0x1);
10581 tcg_gen_trunc_tl_i32(t1, t0);
10582 tcg_temp_free(t0);
10583 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10584 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10585 tcg_gen_or_i32(hflags, hflags, t1);
10586 tcg_temp_free_i32(t1);
10588 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10589 } else {
10590 tcg_gen_mov_tl(cpu_PC, btarget);
10592 if (ctx->singlestep_enabled) {
10593 save_cpu_state(ctx, 0);
10594 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
10596 tcg_gen_exit_tb(0);
10597 break;
10598 default:
10599 MIPS_DEBUG("unknown branch");
10600 break;
10605 /* ISA extensions (ASEs) */
10606 /* MIPS16 extension to MIPS32 */
10608 /* MIPS16 major opcodes */
10609 enum {
10610 M16_OPC_ADDIUSP = 0x00,
10611 M16_OPC_ADDIUPC = 0x01,
10612 M16_OPC_B = 0x02,
10613 M16_OPC_JAL = 0x03,
10614 M16_OPC_BEQZ = 0x04,
10615 M16_OPC_BNEQZ = 0x05,
10616 M16_OPC_SHIFT = 0x06,
10617 M16_OPC_LD = 0x07,
10618 M16_OPC_RRIA = 0x08,
10619 M16_OPC_ADDIU8 = 0x09,
10620 M16_OPC_SLTI = 0x0a,
10621 M16_OPC_SLTIU = 0x0b,
10622 M16_OPC_I8 = 0x0c,
10623 M16_OPC_LI = 0x0d,
10624 M16_OPC_CMPI = 0x0e,
10625 M16_OPC_SD = 0x0f,
10626 M16_OPC_LB = 0x10,
10627 M16_OPC_LH = 0x11,
10628 M16_OPC_LWSP = 0x12,
10629 M16_OPC_LW = 0x13,
10630 M16_OPC_LBU = 0x14,
10631 M16_OPC_LHU = 0x15,
10632 M16_OPC_LWPC = 0x16,
10633 M16_OPC_LWU = 0x17,
10634 M16_OPC_SB = 0x18,
10635 M16_OPC_SH = 0x19,
10636 M16_OPC_SWSP = 0x1a,
10637 M16_OPC_SW = 0x1b,
10638 M16_OPC_RRR = 0x1c,
10639 M16_OPC_RR = 0x1d,
10640 M16_OPC_EXTEND = 0x1e,
10641 M16_OPC_I64 = 0x1f
10644 /* I8 funct field */
10645 enum {
10646 I8_BTEQZ = 0x0,
10647 I8_BTNEZ = 0x1,
10648 I8_SWRASP = 0x2,
10649 I8_ADJSP = 0x3,
10650 I8_SVRS = 0x4,
10651 I8_MOV32R = 0x5,
10652 I8_MOVR32 = 0x7
10655 /* RRR f field */
10656 enum {
10657 RRR_DADDU = 0x0,
10658 RRR_ADDU = 0x1,
10659 RRR_DSUBU = 0x2,
10660 RRR_SUBU = 0x3
10663 /* RR funct field */
10664 enum {
10665 RR_JR = 0x00,
10666 RR_SDBBP = 0x01,
10667 RR_SLT = 0x02,
10668 RR_SLTU = 0x03,
10669 RR_SLLV = 0x04,
10670 RR_BREAK = 0x05,
10671 RR_SRLV = 0x06,
10672 RR_SRAV = 0x07,
10673 RR_DSRL = 0x08,
10674 RR_CMP = 0x0a,
10675 RR_NEG = 0x0b,
10676 RR_AND = 0x0c,
10677 RR_OR = 0x0d,
10678 RR_XOR = 0x0e,
10679 RR_NOT = 0x0f,
10680 RR_MFHI = 0x10,
10681 RR_CNVT = 0x11,
10682 RR_MFLO = 0x12,
10683 RR_DSRA = 0x13,
10684 RR_DSLLV = 0x14,
10685 RR_DSRLV = 0x16,
10686 RR_DSRAV = 0x17,
10687 RR_MULT = 0x18,
10688 RR_MULTU = 0x19,
10689 RR_DIV = 0x1a,
10690 RR_DIVU = 0x1b,
10691 RR_DMULT = 0x1c,
10692 RR_DMULTU = 0x1d,
10693 RR_DDIV = 0x1e,
10694 RR_DDIVU = 0x1f
10697 /* I64 funct field */
10698 enum {
10699 I64_LDSP = 0x0,
10700 I64_SDSP = 0x1,
10701 I64_SDRASP = 0x2,
10702 I64_DADJSP = 0x3,
10703 I64_LDPC = 0x4,
10704 I64_DADDIU5 = 0x5,
10705 I64_DADDIUPC = 0x6,
10706 I64_DADDIUSP = 0x7
10709 /* RR ry field for CNVT */
10710 enum {
10711 RR_RY_CNVT_ZEB = 0x0,
10712 RR_RY_CNVT_ZEH = 0x1,
10713 RR_RY_CNVT_ZEW = 0x2,
10714 RR_RY_CNVT_SEB = 0x4,
10715 RR_RY_CNVT_SEH = 0x5,
10716 RR_RY_CNVT_SEW = 0x6,
10719 static int xlat (int r)
10721 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10723 return map[r];
10726 static void gen_mips16_save (DisasContext *ctx,
10727 int xsregs, int aregs,
10728 int do_ra, int do_s0, int do_s1,
10729 int framesize)
10731 TCGv t0 = tcg_temp_new();
10732 TCGv t1 = tcg_temp_new();
10733 TCGv t2 = tcg_temp_new();
10734 int args, astatic;
10736 switch (aregs) {
10737 case 0:
10738 case 1:
10739 case 2:
10740 case 3:
10741 case 11:
10742 args = 0;
10743 break;
10744 case 4:
10745 case 5:
10746 case 6:
10747 case 7:
10748 args = 1;
10749 break;
10750 case 8:
10751 case 9:
10752 case 10:
10753 args = 2;
10754 break;
10755 case 12:
10756 case 13:
10757 args = 3;
10758 break;
10759 case 14:
10760 args = 4;
10761 break;
10762 default:
10763 generate_exception(ctx, EXCP_RI);
10764 return;
10767 switch (args) {
10768 case 4:
10769 gen_base_offset_addr(ctx, t0, 29, 12);
10770 gen_load_gpr(t1, 7);
10771 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10772 /* Fall through */
10773 case 3:
10774 gen_base_offset_addr(ctx, t0, 29, 8);
10775 gen_load_gpr(t1, 6);
10776 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10777 /* Fall through */
10778 case 2:
10779 gen_base_offset_addr(ctx, t0, 29, 4);
10780 gen_load_gpr(t1, 5);
10781 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10782 /* Fall through */
10783 case 1:
10784 gen_base_offset_addr(ctx, t0, 29, 0);
10785 gen_load_gpr(t1, 4);
10786 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10789 gen_load_gpr(t0, 29);
10791 #define DECR_AND_STORE(reg) do { \
10792 tcg_gen_movi_tl(t2, -4); \
10793 gen_op_addr_add(ctx, t0, t0, t2); \
10794 gen_load_gpr(t1, reg); \
10795 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
10796 } while (0)
10798 if (do_ra) {
10799 DECR_AND_STORE(31);
10802 switch (xsregs) {
10803 case 7:
10804 DECR_AND_STORE(30);
10805 /* Fall through */
10806 case 6:
10807 DECR_AND_STORE(23);
10808 /* Fall through */
10809 case 5:
10810 DECR_AND_STORE(22);
10811 /* Fall through */
10812 case 4:
10813 DECR_AND_STORE(21);
10814 /* Fall through */
10815 case 3:
10816 DECR_AND_STORE(20);
10817 /* Fall through */
10818 case 2:
10819 DECR_AND_STORE(19);
10820 /* Fall through */
10821 case 1:
10822 DECR_AND_STORE(18);
10825 if (do_s1) {
10826 DECR_AND_STORE(17);
10828 if (do_s0) {
10829 DECR_AND_STORE(16);
10832 switch (aregs) {
10833 case 0:
10834 case 4:
10835 case 8:
10836 case 12:
10837 case 14:
10838 astatic = 0;
10839 break;
10840 case 1:
10841 case 5:
10842 case 9:
10843 case 13:
10844 astatic = 1;
10845 break;
10846 case 2:
10847 case 6:
10848 case 10:
10849 astatic = 2;
10850 break;
10851 case 3:
10852 case 7:
10853 astatic = 3;
10854 break;
10855 case 11:
10856 astatic = 4;
10857 break;
10858 default:
10859 generate_exception(ctx, EXCP_RI);
10860 return;
10863 if (astatic > 0) {
10864 DECR_AND_STORE(7);
10865 if (astatic > 1) {
10866 DECR_AND_STORE(6);
10867 if (astatic > 2) {
10868 DECR_AND_STORE(5);
10869 if (astatic > 3) {
10870 DECR_AND_STORE(4);
10875 #undef DECR_AND_STORE
10877 tcg_gen_movi_tl(t2, -framesize);
10878 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
10879 tcg_temp_free(t0);
10880 tcg_temp_free(t1);
10881 tcg_temp_free(t2);
10884 static void gen_mips16_restore (DisasContext *ctx,
10885 int xsregs, int aregs,
10886 int do_ra, int do_s0, int do_s1,
10887 int framesize)
10889 int astatic;
10890 TCGv t0 = tcg_temp_new();
10891 TCGv t1 = tcg_temp_new();
10892 TCGv t2 = tcg_temp_new();
10894 tcg_gen_movi_tl(t2, framesize);
10895 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
10897 #define DECR_AND_LOAD(reg) do { \
10898 tcg_gen_movi_tl(t2, -4); \
10899 gen_op_addr_add(ctx, t0, t0, t2); \
10900 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
10901 gen_store_gpr(t1, reg); \
10902 } while (0)
10904 if (do_ra) {
10905 DECR_AND_LOAD(31);
10908 switch (xsregs) {
10909 case 7:
10910 DECR_AND_LOAD(30);
10911 /* Fall through */
10912 case 6:
10913 DECR_AND_LOAD(23);
10914 /* Fall through */
10915 case 5:
10916 DECR_AND_LOAD(22);
10917 /* Fall through */
10918 case 4:
10919 DECR_AND_LOAD(21);
10920 /* Fall through */
10921 case 3:
10922 DECR_AND_LOAD(20);
10923 /* Fall through */
10924 case 2:
10925 DECR_AND_LOAD(19);
10926 /* Fall through */
10927 case 1:
10928 DECR_AND_LOAD(18);
10931 if (do_s1) {
10932 DECR_AND_LOAD(17);
10934 if (do_s0) {
10935 DECR_AND_LOAD(16);
10938 switch (aregs) {
10939 case 0:
10940 case 4:
10941 case 8:
10942 case 12:
10943 case 14:
10944 astatic = 0;
10945 break;
10946 case 1:
10947 case 5:
10948 case 9:
10949 case 13:
10950 astatic = 1;
10951 break;
10952 case 2:
10953 case 6:
10954 case 10:
10955 astatic = 2;
10956 break;
10957 case 3:
10958 case 7:
10959 astatic = 3;
10960 break;
10961 case 11:
10962 astatic = 4;
10963 break;
10964 default:
10965 generate_exception(ctx, EXCP_RI);
10966 return;
10969 if (astatic > 0) {
10970 DECR_AND_LOAD(7);
10971 if (astatic > 1) {
10972 DECR_AND_LOAD(6);
10973 if (astatic > 2) {
10974 DECR_AND_LOAD(5);
10975 if (astatic > 3) {
10976 DECR_AND_LOAD(4);
10981 #undef DECR_AND_LOAD
10983 tcg_gen_movi_tl(t2, framesize);
10984 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
10985 tcg_temp_free(t0);
10986 tcg_temp_free(t1);
10987 tcg_temp_free(t2);
10990 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
10991 int is_64_bit, int extended)
10993 TCGv t0;
10995 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10996 generate_exception(ctx, EXCP_RI);
10997 return;
11000 t0 = tcg_temp_new();
11002 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11003 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11004 if (!is_64_bit) {
11005 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11008 tcg_temp_free(t0);
11011 #if defined(TARGET_MIPS64)
11012 static void decode_i64_mips16 (DisasContext *ctx,
11013 int ry, int funct, int16_t offset,
11014 int extended)
11016 switch (funct) {
11017 case I64_LDSP:
11018 check_insn(ctx, ISA_MIPS3);
11019 check_mips_64(ctx);
11020 offset = extended ? offset : offset << 3;
11021 gen_ld(ctx, OPC_LD, ry, 29, offset);
11022 break;
11023 case I64_SDSP:
11024 check_insn(ctx, ISA_MIPS3);
11025 check_mips_64(ctx);
11026 offset = extended ? offset : offset << 3;
11027 gen_st(ctx, OPC_SD, ry, 29, offset);
11028 break;
11029 case I64_SDRASP:
11030 check_insn(ctx, ISA_MIPS3);
11031 check_mips_64(ctx);
11032 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11033 gen_st(ctx, OPC_SD, 31, 29, offset);
11034 break;
11035 case I64_DADJSP:
11036 check_insn(ctx, ISA_MIPS3);
11037 check_mips_64(ctx);
11038 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11039 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11040 break;
11041 case I64_LDPC:
11042 check_insn(ctx, ISA_MIPS3);
11043 check_mips_64(ctx);
11044 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11045 generate_exception(ctx, EXCP_RI);
11046 } else {
11047 offset = extended ? offset : offset << 3;
11048 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11050 break;
11051 case I64_DADDIU5:
11052 check_insn(ctx, ISA_MIPS3);
11053 check_mips_64(ctx);
11054 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11055 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11056 break;
11057 case I64_DADDIUPC:
11058 check_insn(ctx, ISA_MIPS3);
11059 check_mips_64(ctx);
11060 offset = extended ? offset : offset << 2;
11061 gen_addiupc(ctx, ry, offset, 1, extended);
11062 break;
11063 case I64_DADDIUSP:
11064 check_insn(ctx, ISA_MIPS3);
11065 check_mips_64(ctx);
11066 offset = extended ? offset : offset << 2;
11067 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11068 break;
11071 #endif
11073 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11075 int extend = cpu_lduw_code(env, ctx->pc + 2);
11076 int op, rx, ry, funct, sa;
11077 int16_t imm, offset;
11079 ctx->opcode = (ctx->opcode << 16) | extend;
11080 op = (ctx->opcode >> 11) & 0x1f;
11081 sa = (ctx->opcode >> 22) & 0x1f;
11082 funct = (ctx->opcode >> 8) & 0x7;
11083 rx = xlat((ctx->opcode >> 8) & 0x7);
11084 ry = xlat((ctx->opcode >> 5) & 0x7);
11085 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11086 | ((ctx->opcode >> 21) & 0x3f) << 5
11087 | (ctx->opcode & 0x1f));
11089 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11090 counterparts. */
11091 switch (op) {
11092 case M16_OPC_ADDIUSP:
11093 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11094 break;
11095 case M16_OPC_ADDIUPC:
11096 gen_addiupc(ctx, rx, imm, 0, 1);
11097 break;
11098 case M16_OPC_B:
11099 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11100 /* No delay slot, so just process as a normal instruction */
11101 break;
11102 case M16_OPC_BEQZ:
11103 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11104 /* No delay slot, so just process as a normal instruction */
11105 break;
11106 case M16_OPC_BNEQZ:
11107 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11108 /* No delay slot, so just process as a normal instruction */
11109 break;
11110 case M16_OPC_SHIFT:
11111 switch (ctx->opcode & 0x3) {
11112 case 0x0:
11113 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11114 break;
11115 case 0x1:
11116 #if defined(TARGET_MIPS64)
11117 check_mips_64(ctx);
11118 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11119 #else
11120 generate_exception(ctx, EXCP_RI);
11121 #endif
11122 break;
11123 case 0x2:
11124 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11125 break;
11126 case 0x3:
11127 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11128 break;
11130 break;
11131 #if defined(TARGET_MIPS64)
11132 case M16_OPC_LD:
11133 check_insn(ctx, ISA_MIPS3);
11134 check_mips_64(ctx);
11135 gen_ld(ctx, OPC_LD, ry, rx, offset);
11136 break;
11137 #endif
11138 case M16_OPC_RRIA:
11139 imm = ctx->opcode & 0xf;
11140 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11141 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11142 imm = (int16_t) (imm << 1) >> 1;
11143 if ((ctx->opcode >> 4) & 0x1) {
11144 #if defined(TARGET_MIPS64)
11145 check_mips_64(ctx);
11146 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11147 #else
11148 generate_exception(ctx, EXCP_RI);
11149 #endif
11150 } else {
11151 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11153 break;
11154 case M16_OPC_ADDIU8:
11155 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11156 break;
11157 case M16_OPC_SLTI:
11158 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11159 break;
11160 case M16_OPC_SLTIU:
11161 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11162 break;
11163 case M16_OPC_I8:
11164 switch (funct) {
11165 case I8_BTEQZ:
11166 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11167 break;
11168 case I8_BTNEZ:
11169 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11170 break;
11171 case I8_SWRASP:
11172 gen_st(ctx, OPC_SW, 31, 29, imm);
11173 break;
11174 case I8_ADJSP:
11175 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11176 break;
11177 case I8_SVRS:
11178 check_insn(ctx, ISA_MIPS32);
11180 int xsregs = (ctx->opcode >> 24) & 0x7;
11181 int aregs = (ctx->opcode >> 16) & 0xf;
11182 int do_ra = (ctx->opcode >> 6) & 0x1;
11183 int do_s0 = (ctx->opcode >> 5) & 0x1;
11184 int do_s1 = (ctx->opcode >> 4) & 0x1;
11185 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11186 | (ctx->opcode & 0xf)) << 3;
11188 if (ctx->opcode & (1 << 7)) {
11189 gen_mips16_save(ctx, xsregs, aregs,
11190 do_ra, do_s0, do_s1,
11191 framesize);
11192 } else {
11193 gen_mips16_restore(ctx, xsregs, aregs,
11194 do_ra, do_s0, do_s1,
11195 framesize);
11198 break;
11199 default:
11200 generate_exception(ctx, EXCP_RI);
11201 break;
11203 break;
11204 case M16_OPC_LI:
11205 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11206 break;
11207 case M16_OPC_CMPI:
11208 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11209 break;
11210 #if defined(TARGET_MIPS64)
11211 case M16_OPC_SD:
11212 check_insn(ctx, ISA_MIPS3);
11213 check_mips_64(ctx);
11214 gen_st(ctx, OPC_SD, ry, rx, offset);
11215 break;
11216 #endif
11217 case M16_OPC_LB:
11218 gen_ld(ctx, OPC_LB, ry, rx, offset);
11219 break;
11220 case M16_OPC_LH:
11221 gen_ld(ctx, OPC_LH, ry, rx, offset);
11222 break;
11223 case M16_OPC_LWSP:
11224 gen_ld(ctx, OPC_LW, rx, 29, offset);
11225 break;
11226 case M16_OPC_LW:
11227 gen_ld(ctx, OPC_LW, ry, rx, offset);
11228 break;
11229 case M16_OPC_LBU:
11230 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11231 break;
11232 case M16_OPC_LHU:
11233 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11234 break;
11235 case M16_OPC_LWPC:
11236 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11237 break;
11238 #if defined(TARGET_MIPS64)
11239 case M16_OPC_LWU:
11240 check_insn(ctx, ISA_MIPS3);
11241 check_mips_64(ctx);
11242 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11243 break;
11244 #endif
11245 case M16_OPC_SB:
11246 gen_st(ctx, OPC_SB, ry, rx, offset);
11247 break;
11248 case M16_OPC_SH:
11249 gen_st(ctx, OPC_SH, ry, rx, offset);
11250 break;
11251 case M16_OPC_SWSP:
11252 gen_st(ctx, OPC_SW, rx, 29, offset);
11253 break;
11254 case M16_OPC_SW:
11255 gen_st(ctx, OPC_SW, ry, rx, offset);
11256 break;
11257 #if defined(TARGET_MIPS64)
11258 case M16_OPC_I64:
11259 decode_i64_mips16(ctx, ry, funct, offset, 1);
11260 break;
11261 #endif
11262 default:
11263 generate_exception(ctx, EXCP_RI);
11264 break;
11267 return 4;
11270 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11272 int rx, ry;
11273 int sa;
11274 int op, cnvt_op, op1, offset;
11275 int funct;
11276 int n_bytes;
11278 op = (ctx->opcode >> 11) & 0x1f;
11279 sa = (ctx->opcode >> 2) & 0x7;
11280 sa = sa == 0 ? 8 : sa;
11281 rx = xlat((ctx->opcode >> 8) & 0x7);
11282 cnvt_op = (ctx->opcode >> 5) & 0x7;
11283 ry = xlat((ctx->opcode >> 5) & 0x7);
11284 op1 = offset = ctx->opcode & 0x1f;
11286 n_bytes = 2;
11288 switch (op) {
11289 case M16_OPC_ADDIUSP:
11291 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11293 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11295 break;
11296 case M16_OPC_ADDIUPC:
11297 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11298 break;
11299 case M16_OPC_B:
11300 offset = (ctx->opcode & 0x7ff) << 1;
11301 offset = (int16_t)(offset << 4) >> 4;
11302 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11303 /* No delay slot, so just process as a normal instruction */
11304 break;
11305 case M16_OPC_JAL:
11306 offset = cpu_lduw_code(env, ctx->pc + 2);
11307 offset = (((ctx->opcode & 0x1f) << 21)
11308 | ((ctx->opcode >> 5) & 0x1f) << 16
11309 | offset) << 2;
11310 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11311 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11312 n_bytes = 4;
11313 break;
11314 case M16_OPC_BEQZ:
11315 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11316 ((int8_t)ctx->opcode) << 1, 0);
11317 /* No delay slot, so just process as a normal instruction */
11318 break;
11319 case M16_OPC_BNEQZ:
11320 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11321 ((int8_t)ctx->opcode) << 1, 0);
11322 /* No delay slot, so just process as a normal instruction */
11323 break;
11324 case M16_OPC_SHIFT:
11325 switch (ctx->opcode & 0x3) {
11326 case 0x0:
11327 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11328 break;
11329 case 0x1:
11330 #if defined(TARGET_MIPS64)
11331 check_insn(ctx, ISA_MIPS3);
11332 check_mips_64(ctx);
11333 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11334 #else
11335 generate_exception(ctx, EXCP_RI);
11336 #endif
11337 break;
11338 case 0x2:
11339 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11340 break;
11341 case 0x3:
11342 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11343 break;
11345 break;
11346 #if defined(TARGET_MIPS64)
11347 case M16_OPC_LD:
11348 check_insn(ctx, ISA_MIPS3);
11349 check_mips_64(ctx);
11350 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
11351 break;
11352 #endif
11353 case M16_OPC_RRIA:
11355 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
11357 if ((ctx->opcode >> 4) & 1) {
11358 #if defined(TARGET_MIPS64)
11359 check_insn(ctx, ISA_MIPS3);
11360 check_mips_64(ctx);
11361 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11362 #else
11363 generate_exception(ctx, EXCP_RI);
11364 #endif
11365 } else {
11366 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11369 break;
11370 case M16_OPC_ADDIU8:
11372 int16_t imm = (int8_t) ctx->opcode;
11374 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11376 break;
11377 case M16_OPC_SLTI:
11379 int16_t imm = (uint8_t) ctx->opcode;
11380 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11382 break;
11383 case M16_OPC_SLTIU:
11385 int16_t imm = (uint8_t) ctx->opcode;
11386 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11388 break;
11389 case M16_OPC_I8:
11391 int reg32;
11393 funct = (ctx->opcode >> 8) & 0x7;
11394 switch (funct) {
11395 case I8_BTEQZ:
11396 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
11397 ((int8_t)ctx->opcode) << 1, 0);
11398 break;
11399 case I8_BTNEZ:
11400 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
11401 ((int8_t)ctx->opcode) << 1, 0);
11402 break;
11403 case I8_SWRASP:
11404 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
11405 break;
11406 case I8_ADJSP:
11407 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
11408 ((int8_t)ctx->opcode) << 3);
11409 break;
11410 case I8_SVRS:
11411 check_insn(ctx, ISA_MIPS32);
11413 int do_ra = ctx->opcode & (1 << 6);
11414 int do_s0 = ctx->opcode & (1 << 5);
11415 int do_s1 = ctx->opcode & (1 << 4);
11416 int framesize = ctx->opcode & 0xf;
11418 if (framesize == 0) {
11419 framesize = 128;
11420 } else {
11421 framesize = framesize << 3;
11424 if (ctx->opcode & (1 << 7)) {
11425 gen_mips16_save(ctx, 0, 0,
11426 do_ra, do_s0, do_s1, framesize);
11427 } else {
11428 gen_mips16_restore(ctx, 0, 0,
11429 do_ra, do_s0, do_s1, framesize);
11432 break;
11433 case I8_MOV32R:
11435 int rz = xlat(ctx->opcode & 0x7);
11437 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
11438 ((ctx->opcode >> 5) & 0x7);
11439 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
11441 break;
11442 case I8_MOVR32:
11443 reg32 = ctx->opcode & 0x1f;
11444 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
11445 break;
11446 default:
11447 generate_exception(ctx, EXCP_RI);
11448 break;
11451 break;
11452 case M16_OPC_LI:
11454 int16_t imm = (uint8_t) ctx->opcode;
11456 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
11458 break;
11459 case M16_OPC_CMPI:
11461 int16_t imm = (uint8_t) ctx->opcode;
11462 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
11464 break;
11465 #if defined(TARGET_MIPS64)
11466 case M16_OPC_SD:
11467 check_insn(ctx, ISA_MIPS3);
11468 check_mips_64(ctx);
11469 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
11470 break;
11471 #endif
11472 case M16_OPC_LB:
11473 gen_ld(ctx, OPC_LB, ry, rx, offset);
11474 break;
11475 case M16_OPC_LH:
11476 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
11477 break;
11478 case M16_OPC_LWSP:
11479 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11480 break;
11481 case M16_OPC_LW:
11482 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
11483 break;
11484 case M16_OPC_LBU:
11485 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11486 break;
11487 case M16_OPC_LHU:
11488 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
11489 break;
11490 case M16_OPC_LWPC:
11491 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
11492 break;
11493 #if defined (TARGET_MIPS64)
11494 case M16_OPC_LWU:
11495 check_insn(ctx, ISA_MIPS3);
11496 check_mips_64(ctx);
11497 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
11498 break;
11499 #endif
11500 case M16_OPC_SB:
11501 gen_st(ctx, OPC_SB, ry, rx, offset);
11502 break;
11503 case M16_OPC_SH:
11504 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
11505 break;
11506 case M16_OPC_SWSP:
11507 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11508 break;
11509 case M16_OPC_SW:
11510 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
11511 break;
11512 case M16_OPC_RRR:
11514 int rz = xlat((ctx->opcode >> 2) & 0x7);
11515 int mips32_op;
11517 switch (ctx->opcode & 0x3) {
11518 case RRR_ADDU:
11519 mips32_op = OPC_ADDU;
11520 break;
11521 case RRR_SUBU:
11522 mips32_op = OPC_SUBU;
11523 break;
11524 #if defined(TARGET_MIPS64)
11525 case RRR_DADDU:
11526 mips32_op = OPC_DADDU;
11527 check_insn(ctx, ISA_MIPS3);
11528 check_mips_64(ctx);
11529 break;
11530 case RRR_DSUBU:
11531 mips32_op = OPC_DSUBU;
11532 check_insn(ctx, ISA_MIPS3);
11533 check_mips_64(ctx);
11534 break;
11535 #endif
11536 default:
11537 generate_exception(ctx, EXCP_RI);
11538 goto done;
11541 gen_arith(ctx, mips32_op, rz, rx, ry);
11542 done:
11545 break;
11546 case M16_OPC_RR:
11547 switch (op1) {
11548 case RR_JR:
11550 int nd = (ctx->opcode >> 7) & 0x1;
11551 int link = (ctx->opcode >> 6) & 0x1;
11552 int ra = (ctx->opcode >> 5) & 0x1;
11554 if (nd) {
11555 check_insn(ctx, ISA_MIPS32);
11558 if (link) {
11559 op = OPC_JALR;
11560 } else {
11561 op = OPC_JR;
11564 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
11565 (nd ? 0 : 2));
11567 break;
11568 case RR_SDBBP:
11569 /* XXX: not clear which exception should be raised
11570 * when in debug mode...
11572 check_insn(ctx, ISA_MIPS32);
11573 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11574 generate_exception(ctx, EXCP_DBp);
11575 } else {
11576 generate_exception(ctx, EXCP_DBp);
11578 break;
11579 case RR_SLT:
11580 gen_slt(ctx, OPC_SLT, 24, rx, ry);
11581 break;
11582 case RR_SLTU:
11583 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
11584 break;
11585 case RR_BREAK:
11586 generate_exception(ctx, EXCP_BREAK);
11587 break;
11588 case RR_SLLV:
11589 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
11590 break;
11591 case RR_SRLV:
11592 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
11593 break;
11594 case RR_SRAV:
11595 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
11596 break;
11597 #if defined (TARGET_MIPS64)
11598 case RR_DSRL:
11599 check_insn(ctx, ISA_MIPS3);
11600 check_mips_64(ctx);
11601 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
11602 break;
11603 #endif
11604 case RR_CMP:
11605 gen_logic(ctx, OPC_XOR, 24, rx, ry);
11606 break;
11607 case RR_NEG:
11608 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
11609 break;
11610 case RR_AND:
11611 gen_logic(ctx, OPC_AND, rx, rx, ry);
11612 break;
11613 case RR_OR:
11614 gen_logic(ctx, OPC_OR, rx, rx, ry);
11615 break;
11616 case RR_XOR:
11617 gen_logic(ctx, OPC_XOR, rx, rx, ry);
11618 break;
11619 case RR_NOT:
11620 gen_logic(ctx, OPC_NOR, rx, ry, 0);
11621 break;
11622 case RR_MFHI:
11623 gen_HILO(ctx, OPC_MFHI, 0, rx);
11624 break;
11625 case RR_CNVT:
11626 check_insn(ctx, ISA_MIPS32);
11627 switch (cnvt_op) {
11628 case RR_RY_CNVT_ZEB:
11629 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11630 break;
11631 case RR_RY_CNVT_ZEH:
11632 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11633 break;
11634 case RR_RY_CNVT_SEB:
11635 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11636 break;
11637 case RR_RY_CNVT_SEH:
11638 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11639 break;
11640 #if defined (TARGET_MIPS64)
11641 case RR_RY_CNVT_ZEW:
11642 check_insn(ctx, ISA_MIPS64);
11643 check_mips_64(ctx);
11644 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11645 break;
11646 case RR_RY_CNVT_SEW:
11647 check_insn(ctx, ISA_MIPS64);
11648 check_mips_64(ctx);
11649 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11650 break;
11651 #endif
11652 default:
11653 generate_exception(ctx, EXCP_RI);
11654 break;
11656 break;
11657 case RR_MFLO:
11658 gen_HILO(ctx, OPC_MFLO, 0, rx);
11659 break;
11660 #if defined (TARGET_MIPS64)
11661 case RR_DSRA:
11662 check_insn(ctx, ISA_MIPS3);
11663 check_mips_64(ctx);
11664 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
11665 break;
11666 case RR_DSLLV:
11667 check_insn(ctx, ISA_MIPS3);
11668 check_mips_64(ctx);
11669 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
11670 break;
11671 case RR_DSRLV:
11672 check_insn(ctx, ISA_MIPS3);
11673 check_mips_64(ctx);
11674 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
11675 break;
11676 case RR_DSRAV:
11677 check_insn(ctx, ISA_MIPS3);
11678 check_mips_64(ctx);
11679 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
11680 break;
11681 #endif
11682 case RR_MULT:
11683 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
11684 break;
11685 case RR_MULTU:
11686 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
11687 break;
11688 case RR_DIV:
11689 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
11690 break;
11691 case RR_DIVU:
11692 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
11693 break;
11694 #if defined (TARGET_MIPS64)
11695 case RR_DMULT:
11696 check_insn(ctx, ISA_MIPS3);
11697 check_mips_64(ctx);
11698 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
11699 break;
11700 case RR_DMULTU:
11701 check_insn(ctx, ISA_MIPS3);
11702 check_mips_64(ctx);
11703 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
11704 break;
11705 case RR_DDIV:
11706 check_insn(ctx, ISA_MIPS3);
11707 check_mips_64(ctx);
11708 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
11709 break;
11710 case RR_DDIVU:
11711 check_insn(ctx, ISA_MIPS3);
11712 check_mips_64(ctx);
11713 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
11714 break;
11715 #endif
11716 default:
11717 generate_exception(ctx, EXCP_RI);
11718 break;
11720 break;
11721 case M16_OPC_EXTEND:
11722 decode_extended_mips16_opc(env, ctx);
11723 n_bytes = 4;
11724 break;
11725 #if defined(TARGET_MIPS64)
11726 case M16_OPC_I64:
11727 funct = (ctx->opcode >> 8) & 0x7;
11728 decode_i64_mips16(ctx, ry, funct, offset, 0);
11729 break;
11730 #endif
11731 default:
11732 generate_exception(ctx, EXCP_RI);
11733 break;
11736 return n_bytes;
11739 /* microMIPS extension to MIPS32/MIPS64 */
11742 * microMIPS32/microMIPS64 major opcodes
11744 * 1. MIPS Architecture for Programmers Volume II-B:
11745 * The microMIPS32 Instruction Set (Revision 3.05)
11747 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
11749 * 2. MIPS Architecture For Programmers Volume II-A:
11750 * The MIPS64 Instruction Set (Revision 3.51)
11753 enum {
11754 POOL32A = 0x00,
11755 POOL16A = 0x01,
11756 LBU16 = 0x02,
11757 MOVE16 = 0x03,
11758 ADDI32 = 0x04,
11759 LBU32 = 0x05,
11760 SB32 = 0x06,
11761 LB32 = 0x07,
11763 POOL32B = 0x08,
11764 POOL16B = 0x09,
11765 LHU16 = 0x0a,
11766 ANDI16 = 0x0b,
11767 ADDIU32 = 0x0c,
11768 LHU32 = 0x0d,
11769 SH32 = 0x0e,
11770 LH32 = 0x0f,
11772 POOL32I = 0x10,
11773 POOL16C = 0x11,
11774 LWSP16 = 0x12,
11775 POOL16D = 0x13,
11776 ORI32 = 0x14,
11777 POOL32F = 0x15,
11778 POOL32S = 0x16, /* MIPS64 */
11779 DADDIU32 = 0x17, /* MIPS64 */
11781 /* 0x1f is reserved */
11782 POOL32C = 0x18,
11783 LWGP16 = 0x19,
11784 LW16 = 0x1a,
11785 POOL16E = 0x1b,
11786 XORI32 = 0x1c,
11787 JALS32 = 0x1d,
11788 ADDIUPC = 0x1e,
11790 /* 0x20 is reserved */
11791 RES_20 = 0x20,
11792 POOL16F = 0x21,
11793 SB16 = 0x22,
11794 BEQZ16 = 0x23,
11795 SLTI32 = 0x24,
11796 BEQ32 = 0x25,
11797 SWC132 = 0x26,
11798 LWC132 = 0x27,
11800 /* 0x28 and 0x29 are reserved */
11801 RES_28 = 0x28,
11802 RES_29 = 0x29,
11803 SH16 = 0x2a,
11804 BNEZ16 = 0x2b,
11805 SLTIU32 = 0x2c,
11806 BNE32 = 0x2d,
11807 SDC132 = 0x2e,
11808 LDC132 = 0x2f,
11810 /* 0x30 and 0x31 are reserved */
11811 RES_30 = 0x30,
11812 RES_31 = 0x31,
11813 SWSP16 = 0x32,
11814 B16 = 0x33,
11815 ANDI32 = 0x34,
11816 J32 = 0x35,
11817 SD32 = 0x36, /* MIPS64 */
11818 LD32 = 0x37, /* MIPS64 */
11820 /* 0x38 and 0x39 are reserved */
11821 RES_38 = 0x38,
11822 RES_39 = 0x39,
11823 SW16 = 0x3a,
11824 LI16 = 0x3b,
11825 JALX32 = 0x3c,
11826 JAL32 = 0x3d,
11827 SW32 = 0x3e,
11828 LW32 = 0x3f
11831 /* POOL32A encoding of minor opcode field */
11833 enum {
11834 /* These opcodes are distinguished only by bits 9..6; those bits are
11835 * what are recorded below. */
11836 SLL32 = 0x0,
11837 SRL32 = 0x1,
11838 SRA = 0x2,
11839 ROTR = 0x3,
11841 SLLV = 0x0,
11842 SRLV = 0x1,
11843 SRAV = 0x2,
11844 ROTRV = 0x3,
11845 ADD = 0x4,
11846 ADDU32 = 0x5,
11847 SUB = 0x6,
11848 SUBU32 = 0x7,
11849 MUL = 0x8,
11850 AND = 0x9,
11851 OR32 = 0xa,
11852 NOR = 0xb,
11853 XOR32 = 0xc,
11854 SLT = 0xd,
11855 SLTU = 0xe,
11857 MOVN = 0x0,
11858 MOVZ = 0x1,
11859 LWXS = 0x4,
11861 /* The following can be distinguished by their lower 6 bits. */
11862 INS = 0x0c,
11863 EXT = 0x2c,
11864 POOL32AXF = 0x3c
11867 /* POOL32AXF encoding of minor opcode field extension */
11870 * 1. MIPS Architecture for Programmers Volume II-B:
11871 * The microMIPS32 Instruction Set (Revision 3.05)
11873 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
11875 * 2. MIPS Architecture for Programmers VolumeIV-e:
11876 * The MIPS DSP Application-Specific Extension
11877 * to the microMIPS32 Architecture (Revision 2.34)
11879 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
11882 enum {
11883 /* bits 11..6 */
11884 TEQ = 0x00,
11885 TGE = 0x08,
11886 TGEU = 0x10,
11887 TLT = 0x20,
11888 TLTU = 0x28,
11889 TNE = 0x30,
11891 MFC0 = 0x03,
11892 MTC0 = 0x0b,
11894 /* begin of microMIPS32 DSP */
11896 /* bits 13..12 for 0x01 */
11897 MFHI_ACC = 0x0,
11898 MFLO_ACC = 0x1,
11899 MTHI_ACC = 0x2,
11900 MTLO_ACC = 0x3,
11902 /* bits 13..12 for 0x2a */
11903 MADD_ACC = 0x0,
11904 MADDU_ACC = 0x1,
11905 MSUB_ACC = 0x2,
11906 MSUBU_ACC = 0x3,
11908 /* bits 13..12 for 0x32 */
11909 MULT_ACC = 0x0,
11910 MULTU_ACC = 0x1,
11912 /* end of microMIPS32 DSP */
11914 /* bits 15..12 for 0x2c */
11915 SEB = 0x2,
11916 SEH = 0x3,
11917 CLO = 0x4,
11918 CLZ = 0x5,
11919 RDHWR = 0x6,
11920 WSBH = 0x7,
11921 MULT = 0x8,
11922 MULTU = 0x9,
11923 DIV = 0xa,
11924 DIVU = 0xb,
11925 MADD = 0xc,
11926 MADDU = 0xd,
11927 MSUB = 0xe,
11928 MSUBU = 0xf,
11930 /* bits 15..12 for 0x34 */
11931 MFC2 = 0x4,
11932 MTC2 = 0x5,
11933 MFHC2 = 0x8,
11934 MTHC2 = 0x9,
11935 CFC2 = 0xc,
11936 CTC2 = 0xd,
11938 /* bits 15..12 for 0x3c */
11939 JALR = 0x0,
11940 JR = 0x0, /* alias */
11941 JALR_HB = 0x1,
11942 JALRS = 0x4,
11943 JALRS_HB = 0x5,
11945 /* bits 15..12 for 0x05 */
11946 RDPGPR = 0xe,
11947 WRPGPR = 0xf,
11949 /* bits 15..12 for 0x0d */
11950 TLBP = 0x0,
11951 TLBR = 0x1,
11952 TLBWI = 0x2,
11953 TLBWR = 0x3,
11954 WAIT = 0x9,
11955 IRET = 0xd,
11956 DERET = 0xe,
11957 ERET = 0xf,
11959 /* bits 15..12 for 0x15 */
11960 DMT = 0x0,
11961 DVPE = 0x1,
11962 EMT = 0x2,
11963 EVPE = 0x3,
11965 /* bits 15..12 for 0x1d */
11966 DI = 0x4,
11967 EI = 0x5,
11969 /* bits 15..12 for 0x2d */
11970 SYNC = 0x6,
11971 SYSCALL = 0x8,
11972 SDBBP = 0xd,
11974 /* bits 15..12 for 0x35 */
11975 MFHI32 = 0x0,
11976 MFLO32 = 0x1,
11977 MTHI32 = 0x2,
11978 MTLO32 = 0x3,
11981 /* POOL32B encoding of minor opcode field (bits 15..12) */
11983 enum {
11984 LWC2 = 0x0,
11985 LWP = 0x1,
11986 LDP = 0x4,
11987 LWM32 = 0x5,
11988 CACHE = 0x6,
11989 LDM = 0x7,
11990 SWC2 = 0x8,
11991 SWP = 0x9,
11992 SDP = 0xc,
11993 SWM32 = 0xd,
11994 SDM = 0xf
11997 /* POOL32C encoding of minor opcode field (bits 15..12) */
11999 enum {
12000 LWL = 0x0,
12001 SWL = 0x8,
12002 LWR = 0x1,
12003 SWR = 0x9,
12004 PREF = 0x2,
12005 /* 0xa is reserved */
12006 LL = 0x3,
12007 SC = 0xb,
12008 LDL = 0x4,
12009 SDL = 0xc,
12010 LDR = 0x5,
12011 SDR = 0xd,
12012 /* 0x6 is reserved */
12013 LWU = 0xe,
12014 LLD = 0x7,
12015 SCD = 0xf
12018 /* POOL32F encoding of minor opcode field (bits 5..0) */
12020 enum {
12021 /* These are the bit 7..6 values */
12022 ADD_FMT = 0x0,
12023 MOVN_FMT = 0x0,
12025 SUB_FMT = 0x1,
12026 MOVZ_FMT = 0x1,
12028 MUL_FMT = 0x2,
12030 DIV_FMT = 0x3,
12032 /* These are the bit 8..6 values */
12033 RSQRT2_FMT = 0x0,
12034 MOVF_FMT = 0x0,
12036 LWXC1 = 0x1,
12037 MOVT_FMT = 0x1,
12039 PLL_PS = 0x2,
12040 SWXC1 = 0x2,
12042 PLU_PS = 0x3,
12043 LDXC1 = 0x3,
12045 PUL_PS = 0x4,
12046 SDXC1 = 0x4,
12047 RECIP2_FMT = 0x4,
12049 PUU_PS = 0x5,
12050 LUXC1 = 0x5,
12052 CVT_PS_S = 0x6,
12053 SUXC1 = 0x6,
12054 ADDR_PS = 0x6,
12055 PREFX = 0x6,
12057 MULR_PS = 0x7,
12059 MADD_S = 0x01,
12060 MADD_D = 0x09,
12061 MADD_PS = 0x11,
12062 ALNV_PS = 0x19,
12063 MSUB_S = 0x21,
12064 MSUB_D = 0x29,
12065 MSUB_PS = 0x31,
12067 NMADD_S = 0x02,
12068 NMADD_D = 0x0a,
12069 NMADD_PS = 0x12,
12070 NMSUB_S = 0x22,
12071 NMSUB_D = 0x2a,
12072 NMSUB_PS = 0x32,
12074 POOL32FXF = 0x3b,
12076 CABS_COND_FMT = 0x1c, /* MIPS3D */
12077 C_COND_FMT = 0x3c
12080 /* POOL32Fxf encoding of minor opcode extension field */
12082 enum {
12083 CVT_L = 0x04,
12084 RSQRT_FMT = 0x08,
12085 FLOOR_L = 0x0c,
12086 CVT_PW_PS = 0x1c,
12087 CVT_W = 0x24,
12088 SQRT_FMT = 0x28,
12089 FLOOR_W = 0x2c,
12090 CVT_PS_PW = 0x3c,
12091 CFC1 = 0x40,
12092 RECIP_FMT = 0x48,
12093 CEIL_L = 0x4c,
12094 CTC1 = 0x60,
12095 CEIL_W = 0x6c,
12096 MFC1 = 0x80,
12097 CVT_S_PL = 0x84,
12098 TRUNC_L = 0x8c,
12099 MTC1 = 0xa0,
12100 CVT_S_PU = 0xa4,
12101 TRUNC_W = 0xac,
12102 MFHC1 = 0xc0,
12103 ROUND_L = 0xcc,
12104 MTHC1 = 0xe0,
12105 ROUND_W = 0xec,
12107 MOV_FMT = 0x01,
12108 MOVF = 0x05,
12109 ABS_FMT = 0x0d,
12110 RSQRT1_FMT = 0x1d,
12111 MOVT = 0x25,
12112 NEG_FMT = 0x2d,
12113 CVT_D = 0x4d,
12114 RECIP1_FMT = 0x5d,
12115 CVT_S = 0x6d
12118 /* POOL32I encoding of minor opcode field (bits 25..21) */
12120 enum {
12121 BLTZ = 0x00,
12122 BLTZAL = 0x01,
12123 BGEZ = 0x02,
12124 BGEZAL = 0x03,
12125 BLEZ = 0x04,
12126 BNEZC = 0x05,
12127 BGTZ = 0x06,
12128 BEQZC = 0x07,
12129 TLTI = 0x08,
12130 TGEI = 0x09,
12131 TLTIU = 0x0a,
12132 TGEIU = 0x0b,
12133 TNEI = 0x0c,
12134 LUI = 0x0d,
12135 TEQI = 0x0e,
12136 SYNCI = 0x10,
12137 BLTZALS = 0x11,
12138 BGEZALS = 0x13,
12139 BC2F = 0x14,
12140 BC2T = 0x15,
12141 BPOSGE64 = 0x1a,
12142 BPOSGE32 = 0x1b,
12143 /* These overlap and are distinguished by bit16 of the instruction */
12144 BC1F = 0x1c,
12145 BC1T = 0x1d,
12146 BC1ANY2F = 0x1c,
12147 BC1ANY2T = 0x1d,
12148 BC1ANY4F = 0x1e,
12149 BC1ANY4T = 0x1f
12152 /* POOL16A encoding of minor opcode field */
12154 enum {
12155 ADDU16 = 0x0,
12156 SUBU16 = 0x1
12159 /* POOL16B encoding of minor opcode field */
12161 enum {
12162 SLL16 = 0x0,
12163 SRL16 = 0x1
12166 /* POOL16C encoding of minor opcode field */
12168 enum {
12169 NOT16 = 0x00,
12170 XOR16 = 0x04,
12171 AND16 = 0x08,
12172 OR16 = 0x0c,
12173 LWM16 = 0x10,
12174 SWM16 = 0x14,
12175 JR16 = 0x18,
12176 JRC16 = 0x1a,
12177 JALR16 = 0x1c,
12178 JALR16S = 0x1e,
12179 MFHI16 = 0x20,
12180 MFLO16 = 0x24,
12181 BREAK16 = 0x28,
12182 SDBBP16 = 0x2c,
12183 JRADDIUSP = 0x30
12186 /* POOL16D encoding of minor opcode field */
12188 enum {
12189 ADDIUS5 = 0x0,
12190 ADDIUSP = 0x1
12193 /* POOL16E encoding of minor opcode field */
12195 enum {
12196 ADDIUR2 = 0x0,
12197 ADDIUR1SP = 0x1
12200 static int mmreg (int r)
12202 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12204 return map[r];
12207 /* Used for 16-bit store instructions. */
12208 static int mmreg2 (int r)
12210 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12212 return map[r];
12215 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12216 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12217 #define uMIPS_RS2(op) uMIPS_RS(op)
12218 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12219 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12220 #define uMIPS_RS5(op) (op & 0x1f)
12222 /* Signed immediate */
12223 #define SIMM(op, start, width) \
12224 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12225 << (32-width)) \
12226 >> (32-width))
12227 /* Zero-extended immediate */
12228 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12230 static void gen_addiur1sp(DisasContext *ctx)
12232 int rd = mmreg(uMIPS_RD(ctx->opcode));
12234 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12237 static void gen_addiur2(DisasContext *ctx)
12239 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12240 int rd = mmreg(uMIPS_RD(ctx->opcode));
12241 int rs = mmreg(uMIPS_RS(ctx->opcode));
12243 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12246 static void gen_addiusp(DisasContext *ctx)
12248 int encoded = ZIMM(ctx->opcode, 1, 9);
12249 int decoded;
12251 if (encoded <= 1) {
12252 decoded = 256 + encoded;
12253 } else if (encoded <= 255) {
12254 decoded = encoded;
12255 } else if (encoded <= 509) {
12256 decoded = encoded - 512;
12257 } else {
12258 decoded = encoded - 768;
12261 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
12264 static void gen_addius5(DisasContext *ctx)
12266 int imm = SIMM(ctx->opcode, 1, 4);
12267 int rd = (ctx->opcode >> 5) & 0x1f;
12269 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
12272 static void gen_andi16(DisasContext *ctx)
12274 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
12275 31, 32, 63, 64, 255, 32768, 65535 };
12276 int rd = mmreg(uMIPS_RD(ctx->opcode));
12277 int rs = mmreg(uMIPS_RS(ctx->opcode));
12278 int encoded = ZIMM(ctx->opcode, 0, 4);
12280 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
12283 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
12284 int base, int16_t offset)
12286 const char *opn = "ldst_multiple";
12287 TCGv t0, t1;
12288 TCGv_i32 t2;
12290 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12291 generate_exception(ctx, EXCP_RI);
12292 return;
12295 t0 = tcg_temp_new();
12297 gen_base_offset_addr(ctx, t0, base, offset);
12299 t1 = tcg_const_tl(reglist);
12300 t2 = tcg_const_i32(ctx->mem_idx);
12302 save_cpu_state(ctx, 1);
12303 switch (opc) {
12304 case LWM32:
12305 gen_helper_lwm(cpu_env, t0, t1, t2);
12306 opn = "lwm";
12307 break;
12308 case SWM32:
12309 gen_helper_swm(cpu_env, t0, t1, t2);
12310 opn = "swm";
12311 break;
12312 #ifdef TARGET_MIPS64
12313 case LDM:
12314 gen_helper_ldm(cpu_env, t0, t1, t2);
12315 opn = "ldm";
12316 break;
12317 case SDM:
12318 gen_helper_sdm(cpu_env, t0, t1, t2);
12319 opn = "sdm";
12320 break;
12321 #endif
12323 (void)opn;
12324 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
12325 tcg_temp_free(t0);
12326 tcg_temp_free(t1);
12327 tcg_temp_free_i32(t2);
12331 static void gen_pool16c_insn(DisasContext *ctx)
12333 int rd = mmreg((ctx->opcode >> 3) & 0x7);
12334 int rs = mmreg(ctx->opcode & 0x7);
12336 switch (((ctx->opcode) >> 4) & 0x3f) {
12337 case NOT16 + 0:
12338 case NOT16 + 1:
12339 case NOT16 + 2:
12340 case NOT16 + 3:
12341 gen_logic(ctx, OPC_NOR, rd, rs, 0);
12342 break;
12343 case XOR16 + 0:
12344 case XOR16 + 1:
12345 case XOR16 + 2:
12346 case XOR16 + 3:
12347 gen_logic(ctx, OPC_XOR, rd, rd, rs);
12348 break;
12349 case AND16 + 0:
12350 case AND16 + 1:
12351 case AND16 + 2:
12352 case AND16 + 3:
12353 gen_logic(ctx, OPC_AND, rd, rd, rs);
12354 break;
12355 case OR16 + 0:
12356 case OR16 + 1:
12357 case OR16 + 2:
12358 case OR16 + 3:
12359 gen_logic(ctx, OPC_OR, rd, rd, rs);
12360 break;
12361 case LWM16 + 0:
12362 case LWM16 + 1:
12363 case LWM16 + 2:
12364 case LWM16 + 3:
12366 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12367 int offset = ZIMM(ctx->opcode, 0, 4);
12369 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
12370 29, offset << 2);
12372 break;
12373 case SWM16 + 0:
12374 case SWM16 + 1:
12375 case SWM16 + 2:
12376 case SWM16 + 3:
12378 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12379 int offset = ZIMM(ctx->opcode, 0, 4);
12381 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
12382 29, offset << 2);
12384 break;
12385 case JR16 + 0:
12386 case JR16 + 1:
12388 int reg = ctx->opcode & 0x1f;
12390 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
12392 break;
12393 case JRC16 + 0:
12394 case JRC16 + 1:
12396 int reg = ctx->opcode & 0x1f;
12397 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
12398 /* Let normal delay slot handling in our caller take us
12399 to the branch target. */
12401 break;
12402 case JALR16 + 0:
12403 case JALR16 + 1:
12404 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
12405 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12406 break;
12407 case JALR16S + 0:
12408 case JALR16S + 1:
12409 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
12410 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12411 break;
12412 case MFHI16 + 0:
12413 case MFHI16 + 1:
12414 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
12415 break;
12416 case MFLO16 + 0:
12417 case MFLO16 + 1:
12418 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
12419 break;
12420 case BREAK16:
12421 generate_exception(ctx, EXCP_BREAK);
12422 break;
12423 case SDBBP16:
12424 /* XXX: not clear which exception should be raised
12425 * when in debug mode...
12427 check_insn(ctx, ISA_MIPS32);
12428 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
12429 generate_exception(ctx, EXCP_DBp);
12430 } else {
12431 generate_exception(ctx, EXCP_DBp);
12433 break;
12434 case JRADDIUSP + 0:
12435 case JRADDIUSP + 1:
12437 int imm = ZIMM(ctx->opcode, 0, 5);
12438 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12439 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12440 /* Let normal delay slot handling in our caller take us
12441 to the branch target. */
12443 break;
12444 default:
12445 generate_exception(ctx, EXCP_RI);
12446 break;
12450 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
12452 TCGv t0 = tcg_temp_new();
12453 TCGv t1 = tcg_temp_new();
12455 gen_load_gpr(t0, base);
12457 if (index != 0) {
12458 gen_load_gpr(t1, index);
12459 tcg_gen_shli_tl(t1, t1, 2);
12460 gen_op_addr_add(ctx, t0, t1, t0);
12463 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12464 gen_store_gpr(t1, rd);
12466 tcg_temp_free(t0);
12467 tcg_temp_free(t1);
12470 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
12471 int base, int16_t offset)
12473 const char *opn = "ldst_pair";
12474 TCGv t0, t1;
12476 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
12477 generate_exception(ctx, EXCP_RI);
12478 return;
12481 t0 = tcg_temp_new();
12482 t1 = tcg_temp_new();
12484 gen_base_offset_addr(ctx, t0, base, offset);
12486 switch (opc) {
12487 case LWP:
12488 if (rd == base) {
12489 generate_exception(ctx, EXCP_RI);
12490 return;
12492 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12493 gen_store_gpr(t1, rd);
12494 tcg_gen_movi_tl(t1, 4);
12495 gen_op_addr_add(ctx, t0, t0, t1);
12496 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12497 gen_store_gpr(t1, rd+1);
12498 opn = "lwp";
12499 break;
12500 case SWP:
12501 gen_load_gpr(t1, rd);
12502 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12503 tcg_gen_movi_tl(t1, 4);
12504 gen_op_addr_add(ctx, t0, t0, t1);
12505 gen_load_gpr(t1, rd+1);
12506 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12507 opn = "swp";
12508 break;
12509 #ifdef TARGET_MIPS64
12510 case LDP:
12511 if (rd == base) {
12512 generate_exception(ctx, EXCP_RI);
12513 return;
12515 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12516 gen_store_gpr(t1, rd);
12517 tcg_gen_movi_tl(t1, 8);
12518 gen_op_addr_add(ctx, t0, t0, t1);
12519 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12520 gen_store_gpr(t1, rd+1);
12521 opn = "ldp";
12522 break;
12523 case SDP:
12524 gen_load_gpr(t1, rd);
12525 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12526 tcg_gen_movi_tl(t1, 8);
12527 gen_op_addr_add(ctx, t0, t0, t1);
12528 gen_load_gpr(t1, rd+1);
12529 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12530 opn = "sdp";
12531 break;
12532 #endif
12534 (void)opn; /* avoid a compiler warning */
12535 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
12536 tcg_temp_free(t0);
12537 tcg_temp_free(t1);
12540 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
12542 int extension = (ctx->opcode >> 6) & 0x3f;
12543 int minor = (ctx->opcode >> 12) & 0xf;
12544 uint32_t mips32_op;
12546 switch (extension) {
12547 case TEQ:
12548 mips32_op = OPC_TEQ;
12549 goto do_trap;
12550 case TGE:
12551 mips32_op = OPC_TGE;
12552 goto do_trap;
12553 case TGEU:
12554 mips32_op = OPC_TGEU;
12555 goto do_trap;
12556 case TLT:
12557 mips32_op = OPC_TLT;
12558 goto do_trap;
12559 case TLTU:
12560 mips32_op = OPC_TLTU;
12561 goto do_trap;
12562 case TNE:
12563 mips32_op = OPC_TNE;
12564 do_trap:
12565 gen_trap(ctx, mips32_op, rs, rt, -1);
12566 break;
12567 #ifndef CONFIG_USER_ONLY
12568 case MFC0:
12569 case MFC0 + 32:
12570 check_cp0_enabled(ctx);
12571 if (rt == 0) {
12572 /* Treat as NOP. */
12573 break;
12575 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
12576 break;
12577 case MTC0:
12578 case MTC0 + 32:
12579 check_cp0_enabled(ctx);
12581 TCGv t0 = tcg_temp_new();
12583 gen_load_gpr(t0, rt);
12584 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
12585 tcg_temp_free(t0);
12587 break;
12588 #endif
12589 case 0x2a:
12590 switch (minor & 3) {
12591 case MADD_ACC:
12592 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
12593 break;
12594 case MADDU_ACC:
12595 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
12596 break;
12597 case MSUB_ACC:
12598 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
12599 break;
12600 case MSUBU_ACC:
12601 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
12602 break;
12603 default:
12604 goto pool32axf_invalid;
12606 break;
12607 case 0x32:
12608 switch (minor & 3) {
12609 case MULT_ACC:
12610 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
12611 break;
12612 case MULTU_ACC:
12613 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
12614 break;
12615 default:
12616 goto pool32axf_invalid;
12618 break;
12619 case 0x2c:
12620 switch (minor) {
12621 case SEB:
12622 gen_bshfl(ctx, OPC_SEB, rs, rt);
12623 break;
12624 case SEH:
12625 gen_bshfl(ctx, OPC_SEH, rs, rt);
12626 break;
12627 case CLO:
12628 mips32_op = OPC_CLO;
12629 goto do_cl;
12630 case CLZ:
12631 mips32_op = OPC_CLZ;
12632 do_cl:
12633 check_insn(ctx, ISA_MIPS32);
12634 gen_cl(ctx, mips32_op, rt, rs);
12635 break;
12636 case RDHWR:
12637 gen_rdhwr(ctx, rt, rs);
12638 break;
12639 case WSBH:
12640 gen_bshfl(ctx, OPC_WSBH, rs, rt);
12641 break;
12642 case MULT:
12643 mips32_op = OPC_MULT;
12644 goto do_mul;
12645 case MULTU:
12646 mips32_op = OPC_MULTU;
12647 goto do_mul;
12648 case DIV:
12649 mips32_op = OPC_DIV;
12650 goto do_div;
12651 case DIVU:
12652 mips32_op = OPC_DIVU;
12653 goto do_div;
12654 do_div:
12655 check_insn(ctx, ISA_MIPS32);
12656 gen_muldiv(ctx, mips32_op, 0, rs, rt);
12657 break;
12658 case MADD:
12659 mips32_op = OPC_MADD;
12660 goto do_mul;
12661 case MADDU:
12662 mips32_op = OPC_MADDU;
12663 goto do_mul;
12664 case MSUB:
12665 mips32_op = OPC_MSUB;
12666 goto do_mul;
12667 case MSUBU:
12668 mips32_op = OPC_MSUBU;
12669 do_mul:
12670 check_insn(ctx, ISA_MIPS32);
12671 gen_muldiv(ctx, mips32_op, 0, rs, rt);
12672 break;
12673 default:
12674 goto pool32axf_invalid;
12676 break;
12677 case 0x34:
12678 switch (minor) {
12679 case MFC2:
12680 case MTC2:
12681 case MFHC2:
12682 case MTHC2:
12683 case CFC2:
12684 case CTC2:
12685 generate_exception_err(ctx, EXCP_CpU, 2);
12686 break;
12687 default:
12688 goto pool32axf_invalid;
12690 break;
12691 case 0x3c:
12692 switch (minor) {
12693 case JALR:
12694 case JALR_HB:
12695 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
12696 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12697 break;
12698 case JALRS:
12699 case JALRS_HB:
12700 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
12701 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12702 break;
12703 default:
12704 goto pool32axf_invalid;
12706 break;
12707 case 0x05:
12708 switch (minor) {
12709 case RDPGPR:
12710 check_cp0_enabled(ctx);
12711 check_insn(ctx, ISA_MIPS32R2);
12712 gen_load_srsgpr(rt, rs);
12713 break;
12714 case WRPGPR:
12715 check_cp0_enabled(ctx);
12716 check_insn(ctx, ISA_MIPS32R2);
12717 gen_store_srsgpr(rt, rs);
12718 break;
12719 default:
12720 goto pool32axf_invalid;
12722 break;
12723 #ifndef CONFIG_USER_ONLY
12724 case 0x0d:
12725 switch (minor) {
12726 case TLBP:
12727 mips32_op = OPC_TLBP;
12728 goto do_cp0;
12729 case TLBR:
12730 mips32_op = OPC_TLBR;
12731 goto do_cp0;
12732 case TLBWI:
12733 mips32_op = OPC_TLBWI;
12734 goto do_cp0;
12735 case TLBWR:
12736 mips32_op = OPC_TLBWR;
12737 goto do_cp0;
12738 case WAIT:
12739 mips32_op = OPC_WAIT;
12740 goto do_cp0;
12741 case DERET:
12742 mips32_op = OPC_DERET;
12743 goto do_cp0;
12744 case ERET:
12745 mips32_op = OPC_ERET;
12746 do_cp0:
12747 gen_cp0(env, ctx, mips32_op, rt, rs);
12748 break;
12749 default:
12750 goto pool32axf_invalid;
12752 break;
12753 case 0x1d:
12754 switch (minor) {
12755 case DI:
12756 check_cp0_enabled(ctx);
12758 TCGv t0 = tcg_temp_new();
12760 save_cpu_state(ctx, 1);
12761 gen_helper_di(t0, cpu_env);
12762 gen_store_gpr(t0, rs);
12763 /* Stop translation as we may have switched the execution mode */
12764 ctx->bstate = BS_STOP;
12765 tcg_temp_free(t0);
12767 break;
12768 case EI:
12769 check_cp0_enabled(ctx);
12771 TCGv t0 = tcg_temp_new();
12773 save_cpu_state(ctx, 1);
12774 gen_helper_ei(t0, cpu_env);
12775 gen_store_gpr(t0, rs);
12776 /* Stop translation as we may have switched the execution mode */
12777 ctx->bstate = BS_STOP;
12778 tcg_temp_free(t0);
12780 break;
12781 default:
12782 goto pool32axf_invalid;
12784 break;
12785 #endif
12786 case 0x2d:
12787 switch (minor) {
12788 case SYNC:
12789 /* NOP */
12790 break;
12791 case SYSCALL:
12792 generate_exception(ctx, EXCP_SYSCALL);
12793 ctx->bstate = BS_STOP;
12794 break;
12795 case SDBBP:
12796 check_insn(ctx, ISA_MIPS32);
12797 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
12798 generate_exception(ctx, EXCP_DBp);
12799 } else {
12800 generate_exception(ctx, EXCP_DBp);
12802 break;
12803 default:
12804 goto pool32axf_invalid;
12806 break;
12807 case 0x01:
12808 switch (minor & 3) {
12809 case MFHI_ACC:
12810 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
12811 break;
12812 case MFLO_ACC:
12813 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
12814 break;
12815 case MTHI_ACC:
12816 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
12817 break;
12818 case MTLO_ACC:
12819 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
12820 break;
12821 default:
12822 goto pool32axf_invalid;
12824 break;
12825 case 0x35:
12826 switch (minor) {
12827 case MFHI32:
12828 gen_HILO(ctx, OPC_MFHI, 0, rs);
12829 break;
12830 case MFLO32:
12831 gen_HILO(ctx, OPC_MFLO, 0, rs);
12832 break;
12833 case MTHI32:
12834 gen_HILO(ctx, OPC_MTHI, 0, rs);
12835 break;
12836 case MTLO32:
12837 gen_HILO(ctx, OPC_MTLO, 0, rs);
12838 break;
12839 default:
12840 goto pool32axf_invalid;
12842 break;
12843 default:
12844 pool32axf_invalid:
12845 MIPS_INVAL("pool32axf");
12846 generate_exception(ctx, EXCP_RI);
12847 break;
12851 /* Values for microMIPS fmt field. Variable-width, depending on which
12852 formats the instruction supports. */
12854 enum {
12855 FMT_SD_S = 0,
12856 FMT_SD_D = 1,
12858 FMT_SDPS_S = 0,
12859 FMT_SDPS_D = 1,
12860 FMT_SDPS_PS = 2,
12862 FMT_SWL_S = 0,
12863 FMT_SWL_W = 1,
12864 FMT_SWL_L = 2,
12866 FMT_DWL_D = 0,
12867 FMT_DWL_W = 1,
12868 FMT_DWL_L = 2
12871 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
12873 int extension = (ctx->opcode >> 6) & 0x3ff;
12874 uint32_t mips32_op;
12876 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
12877 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
12878 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
12880 switch (extension) {
12881 case FLOAT_1BIT_FMT(CFC1, 0):
12882 mips32_op = OPC_CFC1;
12883 goto do_cp1;
12884 case FLOAT_1BIT_FMT(CTC1, 0):
12885 mips32_op = OPC_CTC1;
12886 goto do_cp1;
12887 case FLOAT_1BIT_FMT(MFC1, 0):
12888 mips32_op = OPC_MFC1;
12889 goto do_cp1;
12890 case FLOAT_1BIT_FMT(MTC1, 0):
12891 mips32_op = OPC_MTC1;
12892 goto do_cp1;
12893 case FLOAT_1BIT_FMT(MFHC1, 0):
12894 mips32_op = OPC_MFHC1;
12895 goto do_cp1;
12896 case FLOAT_1BIT_FMT(MTHC1, 0):
12897 mips32_op = OPC_MTHC1;
12898 do_cp1:
12899 gen_cp1(ctx, mips32_op, rt, rs);
12900 break;
12902 /* Reciprocal square root */
12903 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
12904 mips32_op = OPC_RSQRT_S;
12905 goto do_unaryfp;
12906 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
12907 mips32_op = OPC_RSQRT_D;
12908 goto do_unaryfp;
12910 /* Square root */
12911 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
12912 mips32_op = OPC_SQRT_S;
12913 goto do_unaryfp;
12914 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
12915 mips32_op = OPC_SQRT_D;
12916 goto do_unaryfp;
12918 /* Reciprocal */
12919 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
12920 mips32_op = OPC_RECIP_S;
12921 goto do_unaryfp;
12922 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
12923 mips32_op = OPC_RECIP_D;
12924 goto do_unaryfp;
12926 /* Floor */
12927 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
12928 mips32_op = OPC_FLOOR_L_S;
12929 goto do_unaryfp;
12930 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
12931 mips32_op = OPC_FLOOR_L_D;
12932 goto do_unaryfp;
12933 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
12934 mips32_op = OPC_FLOOR_W_S;
12935 goto do_unaryfp;
12936 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
12937 mips32_op = OPC_FLOOR_W_D;
12938 goto do_unaryfp;
12940 /* Ceiling */
12941 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
12942 mips32_op = OPC_CEIL_L_S;
12943 goto do_unaryfp;
12944 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
12945 mips32_op = OPC_CEIL_L_D;
12946 goto do_unaryfp;
12947 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
12948 mips32_op = OPC_CEIL_W_S;
12949 goto do_unaryfp;
12950 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
12951 mips32_op = OPC_CEIL_W_D;
12952 goto do_unaryfp;
12954 /* Truncation */
12955 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
12956 mips32_op = OPC_TRUNC_L_S;
12957 goto do_unaryfp;
12958 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
12959 mips32_op = OPC_TRUNC_L_D;
12960 goto do_unaryfp;
12961 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
12962 mips32_op = OPC_TRUNC_W_S;
12963 goto do_unaryfp;
12964 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
12965 mips32_op = OPC_TRUNC_W_D;
12966 goto do_unaryfp;
12968 /* Round */
12969 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
12970 mips32_op = OPC_ROUND_L_S;
12971 goto do_unaryfp;
12972 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
12973 mips32_op = OPC_ROUND_L_D;
12974 goto do_unaryfp;
12975 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
12976 mips32_op = OPC_ROUND_W_S;
12977 goto do_unaryfp;
12978 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
12979 mips32_op = OPC_ROUND_W_D;
12980 goto do_unaryfp;
12982 /* Integer to floating-point conversion */
12983 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
12984 mips32_op = OPC_CVT_L_S;
12985 goto do_unaryfp;
12986 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
12987 mips32_op = OPC_CVT_L_D;
12988 goto do_unaryfp;
12989 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
12990 mips32_op = OPC_CVT_W_S;
12991 goto do_unaryfp;
12992 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
12993 mips32_op = OPC_CVT_W_D;
12994 goto do_unaryfp;
12996 /* Paired-foo conversions */
12997 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
12998 mips32_op = OPC_CVT_S_PL;
12999 goto do_unaryfp;
13000 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13001 mips32_op = OPC_CVT_S_PU;
13002 goto do_unaryfp;
13003 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13004 mips32_op = OPC_CVT_PW_PS;
13005 goto do_unaryfp;
13006 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13007 mips32_op = OPC_CVT_PS_PW;
13008 goto do_unaryfp;
13010 /* Floating-point moves */
13011 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13012 mips32_op = OPC_MOV_S;
13013 goto do_unaryfp;
13014 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13015 mips32_op = OPC_MOV_D;
13016 goto do_unaryfp;
13017 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13018 mips32_op = OPC_MOV_PS;
13019 goto do_unaryfp;
13021 /* Absolute value */
13022 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13023 mips32_op = OPC_ABS_S;
13024 goto do_unaryfp;
13025 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13026 mips32_op = OPC_ABS_D;
13027 goto do_unaryfp;
13028 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13029 mips32_op = OPC_ABS_PS;
13030 goto do_unaryfp;
13032 /* Negation */
13033 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13034 mips32_op = OPC_NEG_S;
13035 goto do_unaryfp;
13036 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13037 mips32_op = OPC_NEG_D;
13038 goto do_unaryfp;
13039 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13040 mips32_op = OPC_NEG_PS;
13041 goto do_unaryfp;
13043 /* Reciprocal square root step */
13044 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13045 mips32_op = OPC_RSQRT1_S;
13046 goto do_unaryfp;
13047 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13048 mips32_op = OPC_RSQRT1_D;
13049 goto do_unaryfp;
13050 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13051 mips32_op = OPC_RSQRT1_PS;
13052 goto do_unaryfp;
13054 /* Reciprocal step */
13055 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13056 mips32_op = OPC_RECIP1_S;
13057 goto do_unaryfp;
13058 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13059 mips32_op = OPC_RECIP1_S;
13060 goto do_unaryfp;
13061 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13062 mips32_op = OPC_RECIP1_PS;
13063 goto do_unaryfp;
13065 /* Conversions from double */
13066 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13067 mips32_op = OPC_CVT_D_S;
13068 goto do_unaryfp;
13069 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13070 mips32_op = OPC_CVT_D_W;
13071 goto do_unaryfp;
13072 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13073 mips32_op = OPC_CVT_D_L;
13074 goto do_unaryfp;
13076 /* Conversions from single */
13077 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13078 mips32_op = OPC_CVT_S_D;
13079 goto do_unaryfp;
13080 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13081 mips32_op = OPC_CVT_S_W;
13082 goto do_unaryfp;
13083 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13084 mips32_op = OPC_CVT_S_L;
13085 do_unaryfp:
13086 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13087 break;
13089 /* Conditional moves on floating-point codes */
13090 case COND_FLOAT_MOV(MOVT, 0):
13091 case COND_FLOAT_MOV(MOVT, 1):
13092 case COND_FLOAT_MOV(MOVT, 2):
13093 case COND_FLOAT_MOV(MOVT, 3):
13094 case COND_FLOAT_MOV(MOVT, 4):
13095 case COND_FLOAT_MOV(MOVT, 5):
13096 case COND_FLOAT_MOV(MOVT, 6):
13097 case COND_FLOAT_MOV(MOVT, 7):
13098 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13099 break;
13100 case COND_FLOAT_MOV(MOVF, 0):
13101 case COND_FLOAT_MOV(MOVF, 1):
13102 case COND_FLOAT_MOV(MOVF, 2):
13103 case COND_FLOAT_MOV(MOVF, 3):
13104 case COND_FLOAT_MOV(MOVF, 4):
13105 case COND_FLOAT_MOV(MOVF, 5):
13106 case COND_FLOAT_MOV(MOVF, 6):
13107 case COND_FLOAT_MOV(MOVF, 7):
13108 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13109 break;
13110 default:
13111 MIPS_INVAL("pool32fxf");
13112 generate_exception(ctx, EXCP_RI);
13113 break;
13117 static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
13118 uint16_t insn_hw1)
13120 int32_t offset;
13121 uint16_t insn;
13122 int rt, rs, rd, rr;
13123 int16_t imm;
13124 uint32_t op, minor, mips32_op;
13125 uint32_t cond, fmt, cc;
13127 insn = cpu_lduw_code(env, ctx->pc + 2);
13128 ctx->opcode = (ctx->opcode << 16) | insn;
13130 rt = (ctx->opcode >> 21) & 0x1f;
13131 rs = (ctx->opcode >> 16) & 0x1f;
13132 rd = (ctx->opcode >> 11) & 0x1f;
13133 rr = (ctx->opcode >> 6) & 0x1f;
13134 imm = (int16_t) ctx->opcode;
13136 op = (ctx->opcode >> 26) & 0x3f;
13137 switch (op) {
13138 case POOL32A:
13139 minor = ctx->opcode & 0x3f;
13140 switch (minor) {
13141 case 0x00:
13142 minor = (ctx->opcode >> 6) & 0xf;
13143 switch (minor) {
13144 case SLL32:
13145 mips32_op = OPC_SLL;
13146 goto do_shifti;
13147 case SRA:
13148 mips32_op = OPC_SRA;
13149 goto do_shifti;
13150 case SRL32:
13151 mips32_op = OPC_SRL;
13152 goto do_shifti;
13153 case ROTR:
13154 mips32_op = OPC_ROTR;
13155 do_shifti:
13156 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
13157 break;
13158 default:
13159 goto pool32a_invalid;
13161 break;
13162 case 0x10:
13163 minor = (ctx->opcode >> 6) & 0xf;
13164 switch (minor) {
13165 /* Arithmetic */
13166 case ADD:
13167 mips32_op = OPC_ADD;
13168 goto do_arith;
13169 case ADDU32:
13170 mips32_op = OPC_ADDU;
13171 goto do_arith;
13172 case SUB:
13173 mips32_op = OPC_SUB;
13174 goto do_arith;
13175 case SUBU32:
13176 mips32_op = OPC_SUBU;
13177 goto do_arith;
13178 case MUL:
13179 mips32_op = OPC_MUL;
13180 do_arith:
13181 gen_arith(ctx, mips32_op, rd, rs, rt);
13182 break;
13183 /* Shifts */
13184 case SLLV:
13185 mips32_op = OPC_SLLV;
13186 goto do_shift;
13187 case SRLV:
13188 mips32_op = OPC_SRLV;
13189 goto do_shift;
13190 case SRAV:
13191 mips32_op = OPC_SRAV;
13192 goto do_shift;
13193 case ROTRV:
13194 mips32_op = OPC_ROTRV;
13195 do_shift:
13196 gen_shift(ctx, mips32_op, rd, rs, rt);
13197 break;
13198 /* Logical operations */
13199 case AND:
13200 mips32_op = OPC_AND;
13201 goto do_logic;
13202 case OR32:
13203 mips32_op = OPC_OR;
13204 goto do_logic;
13205 case NOR:
13206 mips32_op = OPC_NOR;
13207 goto do_logic;
13208 case XOR32:
13209 mips32_op = OPC_XOR;
13210 do_logic:
13211 gen_logic(ctx, mips32_op, rd, rs, rt);
13212 break;
13213 /* Set less than */
13214 case SLT:
13215 mips32_op = OPC_SLT;
13216 goto do_slt;
13217 case SLTU:
13218 mips32_op = OPC_SLTU;
13219 do_slt:
13220 gen_slt(ctx, mips32_op, rd, rs, rt);
13221 break;
13222 default:
13223 goto pool32a_invalid;
13225 break;
13226 case 0x18:
13227 minor = (ctx->opcode >> 6) & 0xf;
13228 switch (minor) {
13229 /* Conditional moves */
13230 case MOVN:
13231 mips32_op = OPC_MOVN;
13232 goto do_cmov;
13233 case MOVZ:
13234 mips32_op = OPC_MOVZ;
13235 do_cmov:
13236 gen_cond_move(ctx, mips32_op, rd, rs, rt);
13237 break;
13238 case LWXS:
13239 gen_ldxs(ctx, rs, rt, rd);
13240 break;
13241 default:
13242 goto pool32a_invalid;
13244 break;
13245 case INS:
13246 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
13247 return;
13248 case EXT:
13249 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
13250 return;
13251 case POOL32AXF:
13252 gen_pool32axf(env, ctx, rt, rs);
13253 break;
13254 case 0x07:
13255 generate_exception(ctx, EXCP_BREAK);
13256 break;
13257 default:
13258 pool32a_invalid:
13259 MIPS_INVAL("pool32a");
13260 generate_exception(ctx, EXCP_RI);
13261 break;
13263 break;
13264 case POOL32B:
13265 minor = (ctx->opcode >> 12) & 0xf;
13266 switch (minor) {
13267 case CACHE:
13268 check_cp0_enabled(ctx);
13269 /* Treat as no-op. */
13270 break;
13271 case LWC2:
13272 case SWC2:
13273 /* COP2: Not implemented. */
13274 generate_exception_err(ctx, EXCP_CpU, 2);
13275 break;
13276 #ifdef TARGET_MIPS64
13277 case LDP:
13278 case SDP:
13279 check_insn(ctx, ISA_MIPS3);
13280 check_mips_64(ctx);
13281 /* Fallthrough */
13282 #endif
13283 case LWP:
13284 case SWP:
13285 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13286 break;
13287 #ifdef TARGET_MIPS64
13288 case LDM:
13289 case SDM:
13290 check_insn(ctx, ISA_MIPS3);
13291 check_mips_64(ctx);
13292 /* Fallthrough */
13293 #endif
13294 case LWM32:
13295 case SWM32:
13296 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13297 break;
13298 default:
13299 MIPS_INVAL("pool32b");
13300 generate_exception(ctx, EXCP_RI);
13301 break;
13303 break;
13304 case POOL32F:
13305 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
13306 minor = ctx->opcode & 0x3f;
13307 check_cp1_enabled(ctx);
13308 switch (minor) {
13309 case ALNV_PS:
13310 mips32_op = OPC_ALNV_PS;
13311 goto do_madd;
13312 case MADD_S:
13313 mips32_op = OPC_MADD_S;
13314 goto do_madd;
13315 case MADD_D:
13316 mips32_op = OPC_MADD_D;
13317 goto do_madd;
13318 case MADD_PS:
13319 mips32_op = OPC_MADD_PS;
13320 goto do_madd;
13321 case MSUB_S:
13322 mips32_op = OPC_MSUB_S;
13323 goto do_madd;
13324 case MSUB_D:
13325 mips32_op = OPC_MSUB_D;
13326 goto do_madd;
13327 case MSUB_PS:
13328 mips32_op = OPC_MSUB_PS;
13329 goto do_madd;
13330 case NMADD_S:
13331 mips32_op = OPC_NMADD_S;
13332 goto do_madd;
13333 case NMADD_D:
13334 mips32_op = OPC_NMADD_D;
13335 goto do_madd;
13336 case NMADD_PS:
13337 mips32_op = OPC_NMADD_PS;
13338 goto do_madd;
13339 case NMSUB_S:
13340 mips32_op = OPC_NMSUB_S;
13341 goto do_madd;
13342 case NMSUB_D:
13343 mips32_op = OPC_NMSUB_D;
13344 goto do_madd;
13345 case NMSUB_PS:
13346 mips32_op = OPC_NMSUB_PS;
13347 do_madd:
13348 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
13349 break;
13350 case CABS_COND_FMT:
13351 cond = (ctx->opcode >> 6) & 0xf;
13352 cc = (ctx->opcode >> 13) & 0x7;
13353 fmt = (ctx->opcode >> 10) & 0x3;
13354 switch (fmt) {
13355 case 0x0:
13356 gen_cmpabs_s(ctx, cond, rt, rs, cc);
13357 break;
13358 case 0x1:
13359 gen_cmpabs_d(ctx, cond, rt, rs, cc);
13360 break;
13361 case 0x2:
13362 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
13363 break;
13364 default:
13365 goto pool32f_invalid;
13367 break;
13368 case C_COND_FMT:
13369 cond = (ctx->opcode >> 6) & 0xf;
13370 cc = (ctx->opcode >> 13) & 0x7;
13371 fmt = (ctx->opcode >> 10) & 0x3;
13372 switch (fmt) {
13373 case 0x0:
13374 gen_cmp_s(ctx, cond, rt, rs, cc);
13375 break;
13376 case 0x1:
13377 gen_cmp_d(ctx, cond, rt, rs, cc);
13378 break;
13379 case 0x2:
13380 gen_cmp_ps(ctx, cond, rt, rs, cc);
13381 break;
13382 default:
13383 goto pool32f_invalid;
13385 break;
13386 case POOL32FXF:
13387 gen_pool32fxf(ctx, rt, rs);
13388 break;
13389 case 0x00:
13390 /* PLL foo */
13391 switch ((ctx->opcode >> 6) & 0x7) {
13392 case PLL_PS:
13393 mips32_op = OPC_PLL_PS;
13394 goto do_ps;
13395 case PLU_PS:
13396 mips32_op = OPC_PLU_PS;
13397 goto do_ps;
13398 case PUL_PS:
13399 mips32_op = OPC_PUL_PS;
13400 goto do_ps;
13401 case PUU_PS:
13402 mips32_op = OPC_PUU_PS;
13403 goto do_ps;
13404 case CVT_PS_S:
13405 mips32_op = OPC_CVT_PS_S;
13406 do_ps:
13407 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13408 break;
13409 default:
13410 goto pool32f_invalid;
13412 break;
13413 case 0x08:
13414 /* [LS][WDU]XC1 */
13415 switch ((ctx->opcode >> 6) & 0x7) {
13416 case LWXC1:
13417 mips32_op = OPC_LWXC1;
13418 goto do_ldst_cp1;
13419 case SWXC1:
13420 mips32_op = OPC_SWXC1;
13421 goto do_ldst_cp1;
13422 case LDXC1:
13423 mips32_op = OPC_LDXC1;
13424 goto do_ldst_cp1;
13425 case SDXC1:
13426 mips32_op = OPC_SDXC1;
13427 goto do_ldst_cp1;
13428 case LUXC1:
13429 mips32_op = OPC_LUXC1;
13430 goto do_ldst_cp1;
13431 case SUXC1:
13432 mips32_op = OPC_SUXC1;
13433 do_ldst_cp1:
13434 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
13435 break;
13436 default:
13437 goto pool32f_invalid;
13439 break;
13440 case 0x18:
13441 /* 3D insns */
13442 fmt = (ctx->opcode >> 9) & 0x3;
13443 switch ((ctx->opcode >> 6) & 0x7) {
13444 case RSQRT2_FMT:
13445 switch (fmt) {
13446 case FMT_SDPS_S:
13447 mips32_op = OPC_RSQRT2_S;
13448 goto do_3d;
13449 case FMT_SDPS_D:
13450 mips32_op = OPC_RSQRT2_D;
13451 goto do_3d;
13452 case FMT_SDPS_PS:
13453 mips32_op = OPC_RSQRT2_PS;
13454 goto do_3d;
13455 default:
13456 goto pool32f_invalid;
13458 break;
13459 case RECIP2_FMT:
13460 switch (fmt) {
13461 case FMT_SDPS_S:
13462 mips32_op = OPC_RECIP2_S;
13463 goto do_3d;
13464 case FMT_SDPS_D:
13465 mips32_op = OPC_RECIP2_D;
13466 goto do_3d;
13467 case FMT_SDPS_PS:
13468 mips32_op = OPC_RECIP2_PS;
13469 goto do_3d;
13470 default:
13471 goto pool32f_invalid;
13473 break;
13474 case ADDR_PS:
13475 mips32_op = OPC_ADDR_PS;
13476 goto do_3d;
13477 case MULR_PS:
13478 mips32_op = OPC_MULR_PS;
13479 do_3d:
13480 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13481 break;
13482 default:
13483 goto pool32f_invalid;
13485 break;
13486 case 0x20:
13487 /* MOV[FT].fmt and PREFX */
13488 cc = (ctx->opcode >> 13) & 0x7;
13489 fmt = (ctx->opcode >> 9) & 0x3;
13490 switch ((ctx->opcode >> 6) & 0x7) {
13491 case MOVF_FMT:
13492 switch (fmt) {
13493 case FMT_SDPS_S:
13494 gen_movcf_s(rs, rt, cc, 0);
13495 break;
13496 case FMT_SDPS_D:
13497 gen_movcf_d(ctx, rs, rt, cc, 0);
13498 break;
13499 case FMT_SDPS_PS:
13500 gen_movcf_ps(ctx, rs, rt, cc, 0);
13501 break;
13502 default:
13503 goto pool32f_invalid;
13505 break;
13506 case MOVT_FMT:
13507 switch (fmt) {
13508 case FMT_SDPS_S:
13509 gen_movcf_s(rs, rt, cc, 1);
13510 break;
13511 case FMT_SDPS_D:
13512 gen_movcf_d(ctx, rs, rt, cc, 1);
13513 break;
13514 case FMT_SDPS_PS:
13515 gen_movcf_ps(ctx, rs, rt, cc, 1);
13516 break;
13517 default:
13518 goto pool32f_invalid;
13520 break;
13521 case PREFX:
13522 break;
13523 default:
13524 goto pool32f_invalid;
13526 break;
13527 #define FINSN_3ARG_SDPS(prfx) \
13528 switch ((ctx->opcode >> 8) & 0x3) { \
13529 case FMT_SDPS_S: \
13530 mips32_op = OPC_##prfx##_S; \
13531 goto do_fpop; \
13532 case FMT_SDPS_D: \
13533 mips32_op = OPC_##prfx##_D; \
13534 goto do_fpop; \
13535 case FMT_SDPS_PS: \
13536 mips32_op = OPC_##prfx##_PS; \
13537 goto do_fpop; \
13538 default: \
13539 goto pool32f_invalid; \
13541 case 0x30:
13542 /* regular FP ops */
13543 switch ((ctx->opcode >> 6) & 0x3) {
13544 case ADD_FMT:
13545 FINSN_3ARG_SDPS(ADD);
13546 break;
13547 case SUB_FMT:
13548 FINSN_3ARG_SDPS(SUB);
13549 break;
13550 case MUL_FMT:
13551 FINSN_3ARG_SDPS(MUL);
13552 break;
13553 case DIV_FMT:
13554 fmt = (ctx->opcode >> 8) & 0x3;
13555 if (fmt == 1) {
13556 mips32_op = OPC_DIV_D;
13557 } else if (fmt == 0) {
13558 mips32_op = OPC_DIV_S;
13559 } else {
13560 goto pool32f_invalid;
13562 goto do_fpop;
13563 default:
13564 goto pool32f_invalid;
13566 break;
13567 case 0x38:
13568 /* cmovs */
13569 switch ((ctx->opcode >> 6) & 0x3) {
13570 case MOVN_FMT:
13571 FINSN_3ARG_SDPS(MOVN);
13572 break;
13573 case MOVZ_FMT:
13574 FINSN_3ARG_SDPS(MOVZ);
13575 break;
13576 default:
13577 goto pool32f_invalid;
13579 break;
13580 do_fpop:
13581 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13582 break;
13583 default:
13584 pool32f_invalid:
13585 MIPS_INVAL("pool32f");
13586 generate_exception(ctx, EXCP_RI);
13587 break;
13589 } else {
13590 generate_exception_err(ctx, EXCP_CpU, 1);
13592 break;
13593 case POOL32I:
13594 minor = (ctx->opcode >> 21) & 0x1f;
13595 switch (minor) {
13596 case BLTZ:
13597 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
13598 break;
13599 case BLTZAL:
13600 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
13601 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13602 break;
13603 case BLTZALS:
13604 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
13605 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13606 break;
13607 case BGEZ:
13608 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
13609 break;
13610 case BGEZAL:
13611 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
13612 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13613 break;
13614 case BGEZALS:
13615 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
13616 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13617 break;
13618 case BLEZ:
13619 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
13620 break;
13621 case BGTZ:
13622 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
13623 break;
13625 /* Traps */
13626 case TLTI:
13627 mips32_op = OPC_TLTI;
13628 goto do_trapi;
13629 case TGEI:
13630 mips32_op = OPC_TGEI;
13631 goto do_trapi;
13632 case TLTIU:
13633 mips32_op = OPC_TLTIU;
13634 goto do_trapi;
13635 case TGEIU:
13636 mips32_op = OPC_TGEIU;
13637 goto do_trapi;
13638 case TNEI:
13639 mips32_op = OPC_TNEI;
13640 goto do_trapi;
13641 case TEQI:
13642 mips32_op = OPC_TEQI;
13643 do_trapi:
13644 gen_trap(ctx, mips32_op, rs, -1, imm);
13645 break;
13647 case BNEZC:
13648 case BEQZC:
13649 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
13650 4, rs, 0, imm << 1, 0);
13651 /* Compact branches don't have a delay slot, so just let
13652 the normal delay slot handling take us to the branch
13653 target. */
13654 break;
13655 case LUI:
13656 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
13657 break;
13658 case SYNCI:
13659 /* Break the TB to be able to sync copied instructions
13660 immediately */
13661 ctx->bstate = BS_STOP;
13662 break;
13663 case BC2F:
13664 case BC2T:
13665 /* COP2: Not implemented. */
13666 generate_exception_err(ctx, EXCP_CpU, 2);
13667 break;
13668 case BC1F:
13669 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
13670 goto do_cp1branch;
13671 case BC1T:
13672 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
13673 goto do_cp1branch;
13674 case BC1ANY4F:
13675 mips32_op = OPC_BC1FANY4;
13676 goto do_cp1mips3d;
13677 case BC1ANY4T:
13678 mips32_op = OPC_BC1TANY4;
13679 do_cp1mips3d:
13680 check_cop1x(ctx);
13681 check_insn(ctx, ASE_MIPS3D);
13682 /* Fall through */
13683 do_cp1branch:
13684 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
13685 check_cp1_enabled(ctx);
13686 gen_compute_branch1(ctx, mips32_op,
13687 (ctx->opcode >> 18) & 0x7, imm << 1);
13688 } else {
13689 generate_exception_err(ctx, EXCP_CpU, 1);
13691 break;
13692 case BPOSGE64:
13693 case BPOSGE32:
13694 /* MIPS DSP: not implemented */
13695 /* Fall through */
13696 default:
13697 MIPS_INVAL("pool32i");
13698 generate_exception(ctx, EXCP_RI);
13699 break;
13701 break;
13702 case POOL32C:
13703 minor = (ctx->opcode >> 12) & 0xf;
13704 switch (minor) {
13705 case LWL:
13706 mips32_op = OPC_LWL;
13707 goto do_ld_lr;
13708 case SWL:
13709 mips32_op = OPC_SWL;
13710 goto do_st_lr;
13711 case LWR:
13712 mips32_op = OPC_LWR;
13713 goto do_ld_lr;
13714 case SWR:
13715 mips32_op = OPC_SWR;
13716 goto do_st_lr;
13717 #if defined(TARGET_MIPS64)
13718 case LDL:
13719 check_insn(ctx, ISA_MIPS3);
13720 check_mips_64(ctx);
13721 mips32_op = OPC_LDL;
13722 goto do_ld_lr;
13723 case SDL:
13724 check_insn(ctx, ISA_MIPS3);
13725 check_mips_64(ctx);
13726 mips32_op = OPC_SDL;
13727 goto do_st_lr;
13728 case LDR:
13729 check_insn(ctx, ISA_MIPS3);
13730 check_mips_64(ctx);
13731 mips32_op = OPC_LDR;
13732 goto do_ld_lr;
13733 case SDR:
13734 check_insn(ctx, ISA_MIPS3);
13735 check_mips_64(ctx);
13736 mips32_op = OPC_SDR;
13737 goto do_st_lr;
13738 case LWU:
13739 check_insn(ctx, ISA_MIPS3);
13740 check_mips_64(ctx);
13741 mips32_op = OPC_LWU;
13742 goto do_ld_lr;
13743 case LLD:
13744 check_insn(ctx, ISA_MIPS3);
13745 check_mips_64(ctx);
13746 mips32_op = OPC_LLD;
13747 goto do_ld_lr;
13748 #endif
13749 case LL:
13750 mips32_op = OPC_LL;
13751 goto do_ld_lr;
13752 do_ld_lr:
13753 gen_ld(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
13754 break;
13755 do_st_lr:
13756 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
13757 break;
13758 case SC:
13759 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
13760 break;
13761 #if defined(TARGET_MIPS64)
13762 case SCD:
13763 check_insn(ctx, ISA_MIPS3);
13764 check_mips_64(ctx);
13765 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
13766 break;
13767 #endif
13768 case PREF:
13769 /* Treat as no-op */
13770 break;
13771 default:
13772 MIPS_INVAL("pool32c");
13773 generate_exception(ctx, EXCP_RI);
13774 break;
13776 break;
13777 case ADDI32:
13778 mips32_op = OPC_ADDI;
13779 goto do_addi;
13780 case ADDIU32:
13781 mips32_op = OPC_ADDIU;
13782 do_addi:
13783 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
13784 break;
13786 /* Logical operations */
13787 case ORI32:
13788 mips32_op = OPC_ORI;
13789 goto do_logici;
13790 case XORI32:
13791 mips32_op = OPC_XORI;
13792 goto do_logici;
13793 case ANDI32:
13794 mips32_op = OPC_ANDI;
13795 do_logici:
13796 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
13797 break;
13799 /* Set less than immediate */
13800 case SLTI32:
13801 mips32_op = OPC_SLTI;
13802 goto do_slti;
13803 case SLTIU32:
13804 mips32_op = OPC_SLTIU;
13805 do_slti:
13806 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
13807 break;
13808 case JALX32:
13809 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
13810 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
13811 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13812 break;
13813 case JALS32:
13814 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
13815 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
13816 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13817 break;
13818 case BEQ32:
13819 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
13820 break;
13821 case BNE32:
13822 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
13823 break;
13824 case J32:
13825 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
13826 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
13827 break;
13828 case JAL32:
13829 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
13830 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
13831 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13832 break;
13833 /* Floating point (COP1) */
13834 case LWC132:
13835 mips32_op = OPC_LWC1;
13836 goto do_cop1;
13837 case LDC132:
13838 mips32_op = OPC_LDC1;
13839 goto do_cop1;
13840 case SWC132:
13841 mips32_op = OPC_SWC1;
13842 goto do_cop1;
13843 case SDC132:
13844 mips32_op = OPC_SDC1;
13845 do_cop1:
13846 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
13847 break;
13848 case ADDIUPC:
13850 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
13851 int offset = SIMM(ctx->opcode, 0, 23) << 2;
13853 gen_addiupc(ctx, reg, offset, 0, 0);
13855 break;
13856 /* Loads and stores */
13857 case LB32:
13858 mips32_op = OPC_LB;
13859 goto do_ld;
13860 case LBU32:
13861 mips32_op = OPC_LBU;
13862 goto do_ld;
13863 case LH32:
13864 mips32_op = OPC_LH;
13865 goto do_ld;
13866 case LHU32:
13867 mips32_op = OPC_LHU;
13868 goto do_ld;
13869 case LW32:
13870 mips32_op = OPC_LW;
13871 goto do_ld;
13872 #ifdef TARGET_MIPS64
13873 case LD32:
13874 check_insn(ctx, ISA_MIPS3);
13875 check_mips_64(ctx);
13876 mips32_op = OPC_LD;
13877 goto do_ld;
13878 case SD32:
13879 check_insn(ctx, ISA_MIPS3);
13880 check_mips_64(ctx);
13881 mips32_op = OPC_SD;
13882 goto do_st;
13883 #endif
13884 case SB32:
13885 mips32_op = OPC_SB;
13886 goto do_st;
13887 case SH32:
13888 mips32_op = OPC_SH;
13889 goto do_st;
13890 case SW32:
13891 mips32_op = OPC_SW;
13892 goto do_st;
13893 do_ld:
13894 gen_ld(ctx, mips32_op, rt, rs, imm);
13895 break;
13896 do_st:
13897 gen_st(ctx, mips32_op, rt, rs, imm);
13898 break;
13899 default:
13900 generate_exception(ctx, EXCP_RI);
13901 break;
13905 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
13907 uint32_t op;
13909 /* make sure instructions are on a halfword boundary */
13910 if (ctx->pc & 0x1) {
13911 env->CP0_BadVAddr = ctx->pc;
13912 generate_exception(ctx, EXCP_AdEL);
13913 ctx->bstate = BS_STOP;
13914 return 2;
13917 op = (ctx->opcode >> 10) & 0x3f;
13918 /* Enforce properly-sized instructions in a delay slot */
13919 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
13920 switch (op & 0x7) { /* MSB-3..MSB-5 */
13921 case 0:
13922 /* POOL32A, POOL32B, POOL32I, POOL32C */
13923 case 4:
13924 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
13925 case 5:
13926 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
13927 case 6:
13928 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
13929 case 7:
13930 /* LB32, LH32, LWC132, LDC132, LW32 */
13931 if (ctx->hflags & MIPS_HFLAG_BDS16) {
13932 generate_exception(ctx, EXCP_RI);
13933 /* Just stop translation; the user is confused. */
13934 ctx->bstate = BS_STOP;
13935 return 2;
13937 break;
13938 case 1:
13939 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
13940 case 2:
13941 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
13942 case 3:
13943 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
13944 if (ctx->hflags & MIPS_HFLAG_BDS32) {
13945 generate_exception(ctx, EXCP_RI);
13946 /* Just stop translation; the user is confused. */
13947 ctx->bstate = BS_STOP;
13948 return 2;
13950 break;
13954 switch (op) {
13955 case POOL16A:
13957 int rd = mmreg(uMIPS_RD(ctx->opcode));
13958 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
13959 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
13960 uint32_t opc = 0;
13962 switch (ctx->opcode & 0x1) {
13963 case ADDU16:
13964 opc = OPC_ADDU;
13965 break;
13966 case SUBU16:
13967 opc = OPC_SUBU;
13968 break;
13971 gen_arith(ctx, opc, rd, rs1, rs2);
13973 break;
13974 case POOL16B:
13976 int rd = mmreg(uMIPS_RD(ctx->opcode));
13977 int rs = mmreg(uMIPS_RS(ctx->opcode));
13978 int amount = (ctx->opcode >> 1) & 0x7;
13979 uint32_t opc = 0;
13980 amount = amount == 0 ? 8 : amount;
13982 switch (ctx->opcode & 0x1) {
13983 case SLL16:
13984 opc = OPC_SLL;
13985 break;
13986 case SRL16:
13987 opc = OPC_SRL;
13988 break;
13991 gen_shift_imm(ctx, opc, rd, rs, amount);
13993 break;
13994 case POOL16C:
13995 gen_pool16c_insn(ctx);
13996 break;
13997 case LWGP16:
13999 int rd = mmreg(uMIPS_RD(ctx->opcode));
14000 int rb = 28; /* GP */
14001 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
14003 gen_ld(ctx, OPC_LW, rd, rb, offset);
14005 break;
14006 case POOL16F:
14007 if (ctx->opcode & 1) {
14008 generate_exception(ctx, EXCP_RI);
14009 } else {
14010 /* MOVEP */
14011 int enc_dest = uMIPS_RD(ctx->opcode);
14012 int enc_rt = uMIPS_RS2(ctx->opcode);
14013 int enc_rs = uMIPS_RS1(ctx->opcode);
14014 int rd, rs, re, rt;
14015 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14016 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14017 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14019 rd = rd_enc[enc_dest];
14020 re = re_enc[enc_dest];
14021 rs = rs_rt_enc[enc_rs];
14022 rt = rs_rt_enc[enc_rt];
14024 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
14025 gen_arith(ctx, OPC_ADDU, re, rt, 0);
14027 break;
14028 case LBU16:
14030 int rd = mmreg(uMIPS_RD(ctx->opcode));
14031 int rb = mmreg(uMIPS_RS(ctx->opcode));
14032 int16_t offset = ZIMM(ctx->opcode, 0, 4);
14033 offset = (offset == 0xf ? -1 : offset);
14035 gen_ld(ctx, OPC_LBU, rd, rb, offset);
14037 break;
14038 case LHU16:
14040 int rd = mmreg(uMIPS_RD(ctx->opcode));
14041 int rb = mmreg(uMIPS_RS(ctx->opcode));
14042 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
14044 gen_ld(ctx, OPC_LHU, rd, rb, offset);
14046 break;
14047 case LWSP16:
14049 int rd = (ctx->opcode >> 5) & 0x1f;
14050 int rb = 29; /* SP */
14051 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
14053 gen_ld(ctx, OPC_LW, rd, rb, offset);
14055 break;
14056 case LW16:
14058 int rd = mmreg(uMIPS_RD(ctx->opcode));
14059 int rb = mmreg(uMIPS_RS(ctx->opcode));
14060 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
14062 gen_ld(ctx, OPC_LW, rd, rb, offset);
14064 break;
14065 case SB16:
14067 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14068 int rb = mmreg(uMIPS_RS(ctx->opcode));
14069 int16_t offset = ZIMM(ctx->opcode, 0, 4);
14071 gen_st(ctx, OPC_SB, rd, rb, offset);
14073 break;
14074 case SH16:
14076 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14077 int rb = mmreg(uMIPS_RS(ctx->opcode));
14078 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
14080 gen_st(ctx, OPC_SH, rd, rb, offset);
14082 break;
14083 case SWSP16:
14085 int rd = (ctx->opcode >> 5) & 0x1f;
14086 int rb = 29; /* SP */
14087 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
14089 gen_st(ctx, OPC_SW, rd, rb, offset);
14091 break;
14092 case SW16:
14094 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14095 int rb = mmreg(uMIPS_RS(ctx->opcode));
14096 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
14098 gen_st(ctx, OPC_SW, rd, rb, offset);
14100 break;
14101 case MOVE16:
14103 int rd = uMIPS_RD5(ctx->opcode);
14104 int rs = uMIPS_RS5(ctx->opcode);
14106 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
14108 break;
14109 case ANDI16:
14110 gen_andi16(ctx);
14111 break;
14112 case POOL16D:
14113 switch (ctx->opcode & 0x1) {
14114 case ADDIUS5:
14115 gen_addius5(ctx);
14116 break;
14117 case ADDIUSP:
14118 gen_addiusp(ctx);
14119 break;
14121 break;
14122 case POOL16E:
14123 switch (ctx->opcode & 0x1) {
14124 case ADDIUR2:
14125 gen_addiur2(ctx);
14126 break;
14127 case ADDIUR1SP:
14128 gen_addiur1sp(ctx);
14129 break;
14131 break;
14132 case B16:
14133 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
14134 SIMM(ctx->opcode, 0, 10) << 1, 4);
14135 break;
14136 case BNEZ16:
14137 case BEQZ16:
14138 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
14139 mmreg(uMIPS_RD(ctx->opcode)),
14140 0, SIMM(ctx->opcode, 0, 7) << 1, 4);
14141 break;
14142 case LI16:
14144 int reg = mmreg(uMIPS_RD(ctx->opcode));
14145 int imm = ZIMM(ctx->opcode, 0, 7);
14147 imm = (imm == 0x7f ? -1 : imm);
14148 tcg_gen_movi_tl(cpu_gpr[reg], imm);
14150 break;
14151 case RES_20:
14152 case RES_28:
14153 case RES_29:
14154 case RES_30:
14155 case RES_31:
14156 case RES_38:
14157 case RES_39:
14158 generate_exception(ctx, EXCP_RI);
14159 break;
14160 default:
14161 decode_micromips32_opc (env, ctx, op);
14162 return 4;
14165 return 2;
14168 /* SmartMIPS extension to MIPS32 */
14170 #if defined(TARGET_MIPS64)
14172 /* MDMX extension to MIPS64 */
14174 #endif
14176 /* MIPSDSP functions. */
14177 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
14178 int rd, int base, int offset)
14180 const char *opn = "ldx";
14181 TCGv t0;
14183 check_dsp(ctx);
14184 t0 = tcg_temp_new();
14186 if (base == 0) {
14187 gen_load_gpr(t0, offset);
14188 } else if (offset == 0) {
14189 gen_load_gpr(t0, base);
14190 } else {
14191 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
14194 switch (opc) {
14195 case OPC_LBUX:
14196 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
14197 gen_store_gpr(t0, rd);
14198 opn = "lbux";
14199 break;
14200 case OPC_LHX:
14201 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
14202 gen_store_gpr(t0, rd);
14203 opn = "lhx";
14204 break;
14205 case OPC_LWX:
14206 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
14207 gen_store_gpr(t0, rd);
14208 opn = "lwx";
14209 break;
14210 #if defined(TARGET_MIPS64)
14211 case OPC_LDX:
14212 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
14213 gen_store_gpr(t0, rd);
14214 opn = "ldx";
14215 break;
14216 #endif
14218 (void)opn; /* avoid a compiler warning */
14219 MIPS_DEBUG("%s %s, %s(%s)", opn,
14220 regnames[rd], regnames[offset], regnames[base]);
14221 tcg_temp_free(t0);
14224 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
14225 int ret, int v1, int v2)
14227 const char *opn = "mipsdsp arith";
14228 TCGv v1_t;
14229 TCGv v2_t;
14231 if (ret == 0) {
14232 /* Treat as NOP. */
14233 MIPS_DEBUG("NOP");
14234 return;
14237 v1_t = tcg_temp_new();
14238 v2_t = tcg_temp_new();
14240 gen_load_gpr(v1_t, v1);
14241 gen_load_gpr(v2_t, v2);
14243 switch (op1) {
14244 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
14245 case OPC_MULT_G_2E:
14246 check_dspr2(ctx);
14247 switch (op2) {
14248 case OPC_ADDUH_QB:
14249 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
14250 break;
14251 case OPC_ADDUH_R_QB:
14252 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
14253 break;
14254 case OPC_ADDQH_PH:
14255 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
14256 break;
14257 case OPC_ADDQH_R_PH:
14258 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
14259 break;
14260 case OPC_ADDQH_W:
14261 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
14262 break;
14263 case OPC_ADDQH_R_W:
14264 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
14265 break;
14266 case OPC_SUBUH_QB:
14267 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
14268 break;
14269 case OPC_SUBUH_R_QB:
14270 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
14271 break;
14272 case OPC_SUBQH_PH:
14273 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
14274 break;
14275 case OPC_SUBQH_R_PH:
14276 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
14277 break;
14278 case OPC_SUBQH_W:
14279 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
14280 break;
14281 case OPC_SUBQH_R_W:
14282 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
14283 break;
14285 break;
14286 case OPC_ABSQ_S_PH_DSP:
14287 switch (op2) {
14288 case OPC_ABSQ_S_QB:
14289 check_dspr2(ctx);
14290 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
14291 break;
14292 case OPC_ABSQ_S_PH:
14293 check_dsp(ctx);
14294 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
14295 break;
14296 case OPC_ABSQ_S_W:
14297 check_dsp(ctx);
14298 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
14299 break;
14300 case OPC_PRECEQ_W_PHL:
14301 check_dsp(ctx);
14302 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
14303 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
14304 break;
14305 case OPC_PRECEQ_W_PHR:
14306 check_dsp(ctx);
14307 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
14308 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
14309 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
14310 break;
14311 case OPC_PRECEQU_PH_QBL:
14312 check_dsp(ctx);
14313 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
14314 break;
14315 case OPC_PRECEQU_PH_QBR:
14316 check_dsp(ctx);
14317 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
14318 break;
14319 case OPC_PRECEQU_PH_QBLA:
14320 check_dsp(ctx);
14321 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
14322 break;
14323 case OPC_PRECEQU_PH_QBRA:
14324 check_dsp(ctx);
14325 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
14326 break;
14327 case OPC_PRECEU_PH_QBL:
14328 check_dsp(ctx);
14329 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
14330 break;
14331 case OPC_PRECEU_PH_QBR:
14332 check_dsp(ctx);
14333 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
14334 break;
14335 case OPC_PRECEU_PH_QBLA:
14336 check_dsp(ctx);
14337 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
14338 break;
14339 case OPC_PRECEU_PH_QBRA:
14340 check_dsp(ctx);
14341 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
14342 break;
14344 break;
14345 case OPC_ADDU_QB_DSP:
14346 switch (op2) {
14347 case OPC_ADDQ_PH:
14348 check_dsp(ctx);
14349 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14350 break;
14351 case OPC_ADDQ_S_PH:
14352 check_dsp(ctx);
14353 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14354 break;
14355 case OPC_ADDQ_S_W:
14356 check_dsp(ctx);
14357 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14358 break;
14359 case OPC_ADDU_QB:
14360 check_dsp(ctx);
14361 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14362 break;
14363 case OPC_ADDU_S_QB:
14364 check_dsp(ctx);
14365 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14366 break;
14367 case OPC_ADDU_PH:
14368 check_dspr2(ctx);
14369 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14370 break;
14371 case OPC_ADDU_S_PH:
14372 check_dspr2(ctx);
14373 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14374 break;
14375 case OPC_SUBQ_PH:
14376 check_dsp(ctx);
14377 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14378 break;
14379 case OPC_SUBQ_S_PH:
14380 check_dsp(ctx);
14381 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14382 break;
14383 case OPC_SUBQ_S_W:
14384 check_dsp(ctx);
14385 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14386 break;
14387 case OPC_SUBU_QB:
14388 check_dsp(ctx);
14389 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14390 break;
14391 case OPC_SUBU_S_QB:
14392 check_dsp(ctx);
14393 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14394 break;
14395 case OPC_SUBU_PH:
14396 check_dspr2(ctx);
14397 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14398 break;
14399 case OPC_SUBU_S_PH:
14400 check_dspr2(ctx);
14401 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14402 break;
14403 case OPC_ADDSC:
14404 check_dsp(ctx);
14405 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14406 break;
14407 case OPC_ADDWC:
14408 check_dsp(ctx);
14409 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14410 break;
14411 case OPC_MODSUB:
14412 check_dsp(ctx);
14413 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
14414 break;
14415 case OPC_RADDU_W_QB:
14416 check_dsp(ctx);
14417 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
14418 break;
14420 break;
14421 case OPC_CMPU_EQ_QB_DSP:
14422 switch (op2) {
14423 case OPC_PRECR_QB_PH:
14424 check_dspr2(ctx);
14425 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
14426 break;
14427 case OPC_PRECRQ_QB_PH:
14428 check_dsp(ctx);
14429 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
14430 break;
14431 case OPC_PRECR_SRA_PH_W:
14432 check_dspr2(ctx);
14434 TCGv_i32 sa_t = tcg_const_i32(v2);
14435 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
14436 cpu_gpr[ret]);
14437 tcg_temp_free_i32(sa_t);
14438 break;
14440 case OPC_PRECR_SRA_R_PH_W:
14441 check_dspr2(ctx);
14443 TCGv_i32 sa_t = tcg_const_i32(v2);
14444 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
14445 cpu_gpr[ret]);
14446 tcg_temp_free_i32(sa_t);
14447 break;
14449 case OPC_PRECRQ_PH_W:
14450 check_dsp(ctx);
14451 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
14452 break;
14453 case OPC_PRECRQ_RS_PH_W:
14454 check_dsp(ctx);
14455 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14456 break;
14457 case OPC_PRECRQU_S_QB_PH:
14458 check_dsp(ctx);
14459 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14460 break;
14462 break;
14463 #ifdef TARGET_MIPS64
14464 case OPC_ABSQ_S_QH_DSP:
14465 switch (op2) {
14466 case OPC_PRECEQ_L_PWL:
14467 check_dsp(ctx);
14468 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
14469 break;
14470 case OPC_PRECEQ_L_PWR:
14471 check_dsp(ctx);
14472 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
14473 break;
14474 case OPC_PRECEQ_PW_QHL:
14475 check_dsp(ctx);
14476 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
14477 break;
14478 case OPC_PRECEQ_PW_QHR:
14479 check_dsp(ctx);
14480 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
14481 break;
14482 case OPC_PRECEQ_PW_QHLA:
14483 check_dsp(ctx);
14484 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
14485 break;
14486 case OPC_PRECEQ_PW_QHRA:
14487 check_dsp(ctx);
14488 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
14489 break;
14490 case OPC_PRECEQU_QH_OBL:
14491 check_dsp(ctx);
14492 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
14493 break;
14494 case OPC_PRECEQU_QH_OBR:
14495 check_dsp(ctx);
14496 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
14497 break;
14498 case OPC_PRECEQU_QH_OBLA:
14499 check_dsp(ctx);
14500 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
14501 break;
14502 case OPC_PRECEQU_QH_OBRA:
14503 check_dsp(ctx);
14504 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
14505 break;
14506 case OPC_PRECEU_QH_OBL:
14507 check_dsp(ctx);
14508 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
14509 break;
14510 case OPC_PRECEU_QH_OBR:
14511 check_dsp(ctx);
14512 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
14513 break;
14514 case OPC_PRECEU_QH_OBLA:
14515 check_dsp(ctx);
14516 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
14517 break;
14518 case OPC_PRECEU_QH_OBRA:
14519 check_dsp(ctx);
14520 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
14521 break;
14522 case OPC_ABSQ_S_OB:
14523 check_dspr2(ctx);
14524 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
14525 break;
14526 case OPC_ABSQ_S_PW:
14527 check_dsp(ctx);
14528 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
14529 break;
14530 case OPC_ABSQ_S_QH:
14531 check_dsp(ctx);
14532 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
14533 break;
14535 break;
14536 case OPC_ADDU_OB_DSP:
14537 switch (op2) {
14538 case OPC_RADDU_L_OB:
14539 check_dsp(ctx);
14540 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
14541 break;
14542 case OPC_SUBQ_PW:
14543 check_dsp(ctx);
14544 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14545 break;
14546 case OPC_SUBQ_S_PW:
14547 check_dsp(ctx);
14548 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14549 break;
14550 case OPC_SUBQ_QH:
14551 check_dsp(ctx);
14552 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14553 break;
14554 case OPC_SUBQ_S_QH:
14555 check_dsp(ctx);
14556 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14557 break;
14558 case OPC_SUBU_OB:
14559 check_dsp(ctx);
14560 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14561 break;
14562 case OPC_SUBU_S_OB:
14563 check_dsp(ctx);
14564 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14565 break;
14566 case OPC_SUBU_QH:
14567 check_dspr2(ctx);
14568 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14569 break;
14570 case OPC_SUBU_S_QH:
14571 check_dspr2(ctx);
14572 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14573 break;
14574 case OPC_SUBUH_OB:
14575 check_dspr2(ctx);
14576 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
14577 break;
14578 case OPC_SUBUH_R_OB:
14579 check_dspr2(ctx);
14580 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
14581 break;
14582 case OPC_ADDQ_PW:
14583 check_dsp(ctx);
14584 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14585 break;
14586 case OPC_ADDQ_S_PW:
14587 check_dsp(ctx);
14588 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14589 break;
14590 case OPC_ADDQ_QH:
14591 check_dsp(ctx);
14592 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14593 break;
14594 case OPC_ADDQ_S_QH:
14595 check_dsp(ctx);
14596 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14597 break;
14598 case OPC_ADDU_OB:
14599 check_dsp(ctx);
14600 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14601 break;
14602 case OPC_ADDU_S_OB:
14603 check_dsp(ctx);
14604 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14605 break;
14606 case OPC_ADDU_QH:
14607 check_dspr2(ctx);
14608 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14609 break;
14610 case OPC_ADDU_S_QH:
14611 check_dspr2(ctx);
14612 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14613 break;
14614 case OPC_ADDUH_OB:
14615 check_dspr2(ctx);
14616 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
14617 break;
14618 case OPC_ADDUH_R_OB:
14619 check_dspr2(ctx);
14620 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
14621 break;
14623 break;
14624 case OPC_CMPU_EQ_OB_DSP:
14625 switch (op2) {
14626 case OPC_PRECR_OB_QH:
14627 check_dspr2(ctx);
14628 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
14629 break;
14630 case OPC_PRECR_SRA_QH_PW:
14631 check_dspr2(ctx);
14633 TCGv_i32 ret_t = tcg_const_i32(ret);
14634 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
14635 tcg_temp_free_i32(ret_t);
14636 break;
14638 case OPC_PRECR_SRA_R_QH_PW:
14639 check_dspr2(ctx);
14641 TCGv_i32 sa_v = tcg_const_i32(ret);
14642 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
14643 tcg_temp_free_i32(sa_v);
14644 break;
14646 case OPC_PRECRQ_OB_QH:
14647 check_dsp(ctx);
14648 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
14649 break;
14650 case OPC_PRECRQ_PW_L:
14651 check_dsp(ctx);
14652 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
14653 break;
14654 case OPC_PRECRQ_QH_PW:
14655 check_dsp(ctx);
14656 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
14657 break;
14658 case OPC_PRECRQ_RS_QH_PW:
14659 check_dsp(ctx);
14660 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14661 break;
14662 case OPC_PRECRQU_S_OB_QH:
14663 check_dsp(ctx);
14664 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14665 break;
14667 break;
14668 #endif
14671 tcg_temp_free(v1_t);
14672 tcg_temp_free(v2_t);
14674 (void)opn; /* avoid a compiler warning */
14675 MIPS_DEBUG("%s", opn);
14678 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
14679 int ret, int v1, int v2)
14681 uint32_t op2;
14682 const char *opn = "mipsdsp shift";
14683 TCGv t0;
14684 TCGv v1_t;
14685 TCGv v2_t;
14687 if (ret == 0) {
14688 /* Treat as NOP. */
14689 MIPS_DEBUG("NOP");
14690 return;
14693 t0 = tcg_temp_new();
14694 v1_t = tcg_temp_new();
14695 v2_t = tcg_temp_new();
14697 tcg_gen_movi_tl(t0, v1);
14698 gen_load_gpr(v1_t, v1);
14699 gen_load_gpr(v2_t, v2);
14701 switch (opc) {
14702 case OPC_SHLL_QB_DSP:
14704 op2 = MASK_SHLL_QB(ctx->opcode);
14705 switch (op2) {
14706 case OPC_SHLL_QB:
14707 check_dsp(ctx);
14708 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
14709 break;
14710 case OPC_SHLLV_QB:
14711 check_dsp(ctx);
14712 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14713 break;
14714 case OPC_SHLL_PH:
14715 check_dsp(ctx);
14716 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
14717 break;
14718 case OPC_SHLLV_PH:
14719 check_dsp(ctx);
14720 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14721 break;
14722 case OPC_SHLL_S_PH:
14723 check_dsp(ctx);
14724 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
14725 break;
14726 case OPC_SHLLV_S_PH:
14727 check_dsp(ctx);
14728 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14729 break;
14730 case OPC_SHLL_S_W:
14731 check_dsp(ctx);
14732 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
14733 break;
14734 case OPC_SHLLV_S_W:
14735 check_dsp(ctx);
14736 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14737 break;
14738 case OPC_SHRL_QB:
14739 check_dsp(ctx);
14740 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
14741 break;
14742 case OPC_SHRLV_QB:
14743 check_dsp(ctx);
14744 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
14745 break;
14746 case OPC_SHRL_PH:
14747 check_dspr2(ctx);
14748 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
14749 break;
14750 case OPC_SHRLV_PH:
14751 check_dspr2(ctx);
14752 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
14753 break;
14754 case OPC_SHRA_QB:
14755 check_dspr2(ctx);
14756 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
14757 break;
14758 case OPC_SHRA_R_QB:
14759 check_dspr2(ctx);
14760 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
14761 break;
14762 case OPC_SHRAV_QB:
14763 check_dspr2(ctx);
14764 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
14765 break;
14766 case OPC_SHRAV_R_QB:
14767 check_dspr2(ctx);
14768 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
14769 break;
14770 case OPC_SHRA_PH:
14771 check_dsp(ctx);
14772 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
14773 break;
14774 case OPC_SHRA_R_PH:
14775 check_dsp(ctx);
14776 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
14777 break;
14778 case OPC_SHRAV_PH:
14779 check_dsp(ctx);
14780 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
14781 break;
14782 case OPC_SHRAV_R_PH:
14783 check_dsp(ctx);
14784 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
14785 break;
14786 case OPC_SHRA_R_W:
14787 check_dsp(ctx);
14788 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
14789 break;
14790 case OPC_SHRAV_R_W:
14791 check_dsp(ctx);
14792 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
14793 break;
14794 default: /* Invalid */
14795 MIPS_INVAL("MASK SHLL.QB");
14796 generate_exception(ctx, EXCP_RI);
14797 break;
14799 break;
14801 #ifdef TARGET_MIPS64
14802 case OPC_SHLL_OB_DSP:
14803 op2 = MASK_SHLL_OB(ctx->opcode);
14804 switch (op2) {
14805 case OPC_SHLL_PW:
14806 check_dsp(ctx);
14807 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
14808 break;
14809 case OPC_SHLLV_PW:
14810 check_dsp(ctx);
14811 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14812 break;
14813 case OPC_SHLL_S_PW:
14814 check_dsp(ctx);
14815 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
14816 break;
14817 case OPC_SHLLV_S_PW:
14818 check_dsp(ctx);
14819 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14820 break;
14821 case OPC_SHLL_OB:
14822 check_dsp(ctx);
14823 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
14824 break;
14825 case OPC_SHLLV_OB:
14826 check_dsp(ctx);
14827 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14828 break;
14829 case OPC_SHLL_QH:
14830 check_dsp(ctx);
14831 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
14832 break;
14833 case OPC_SHLLV_QH:
14834 check_dsp(ctx);
14835 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14836 break;
14837 case OPC_SHLL_S_QH:
14838 check_dsp(ctx);
14839 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
14840 break;
14841 case OPC_SHLLV_S_QH:
14842 check_dsp(ctx);
14843 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14844 break;
14845 case OPC_SHRA_OB:
14846 check_dspr2(ctx);
14847 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
14848 break;
14849 case OPC_SHRAV_OB:
14850 check_dspr2(ctx);
14851 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
14852 break;
14853 case OPC_SHRA_R_OB:
14854 check_dspr2(ctx);
14855 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
14856 break;
14857 case OPC_SHRAV_R_OB:
14858 check_dspr2(ctx);
14859 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
14860 break;
14861 case OPC_SHRA_PW:
14862 check_dsp(ctx);
14863 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
14864 break;
14865 case OPC_SHRAV_PW:
14866 check_dsp(ctx);
14867 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
14868 break;
14869 case OPC_SHRA_R_PW:
14870 check_dsp(ctx);
14871 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
14872 break;
14873 case OPC_SHRAV_R_PW:
14874 check_dsp(ctx);
14875 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
14876 break;
14877 case OPC_SHRA_QH:
14878 check_dsp(ctx);
14879 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
14880 break;
14881 case OPC_SHRAV_QH:
14882 check_dsp(ctx);
14883 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
14884 break;
14885 case OPC_SHRA_R_QH:
14886 check_dsp(ctx);
14887 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
14888 break;
14889 case OPC_SHRAV_R_QH:
14890 check_dsp(ctx);
14891 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
14892 break;
14893 case OPC_SHRL_OB:
14894 check_dsp(ctx);
14895 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
14896 break;
14897 case OPC_SHRLV_OB:
14898 check_dsp(ctx);
14899 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
14900 break;
14901 case OPC_SHRL_QH:
14902 check_dspr2(ctx);
14903 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
14904 break;
14905 case OPC_SHRLV_QH:
14906 check_dspr2(ctx);
14907 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
14908 break;
14909 default: /* Invalid */
14910 MIPS_INVAL("MASK SHLL.OB");
14911 generate_exception(ctx, EXCP_RI);
14912 break;
14914 break;
14915 #endif
14918 tcg_temp_free(t0);
14919 tcg_temp_free(v1_t);
14920 tcg_temp_free(v2_t);
14921 (void)opn; /* avoid a compiler warning */
14922 MIPS_DEBUG("%s", opn);
14925 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
14926 int ret, int v1, int v2, int check_ret)
14928 const char *opn = "mipsdsp multiply";
14929 TCGv_i32 t0;
14930 TCGv v1_t;
14931 TCGv v2_t;
14933 if ((ret == 0) && (check_ret == 1)) {
14934 /* Treat as NOP. */
14935 MIPS_DEBUG("NOP");
14936 return;
14939 t0 = tcg_temp_new_i32();
14940 v1_t = tcg_temp_new();
14941 v2_t = tcg_temp_new();
14943 tcg_gen_movi_i32(t0, ret);
14944 gen_load_gpr(v1_t, v1);
14945 gen_load_gpr(v2_t, v2);
14947 switch (op1) {
14948 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
14949 * the same mask and op1. */
14950 case OPC_MULT_G_2E:
14951 check_dspr2(ctx);
14952 switch (op2) {
14953 case OPC_MUL_PH:
14954 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14955 break;
14956 case OPC_MUL_S_PH:
14957 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14958 break;
14959 case OPC_MULQ_S_W:
14960 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14961 break;
14962 case OPC_MULQ_RS_W:
14963 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14964 break;
14966 break;
14967 case OPC_DPA_W_PH_DSP:
14968 switch (op2) {
14969 case OPC_DPAU_H_QBL:
14970 check_dsp(ctx);
14971 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
14972 break;
14973 case OPC_DPAU_H_QBR:
14974 check_dsp(ctx);
14975 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
14976 break;
14977 case OPC_DPSU_H_QBL:
14978 check_dsp(ctx);
14979 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
14980 break;
14981 case OPC_DPSU_H_QBR:
14982 check_dsp(ctx);
14983 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
14984 break;
14985 case OPC_DPA_W_PH:
14986 check_dspr2(ctx);
14987 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
14988 break;
14989 case OPC_DPAX_W_PH:
14990 check_dspr2(ctx);
14991 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
14992 break;
14993 case OPC_DPAQ_S_W_PH:
14994 check_dsp(ctx);
14995 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
14996 break;
14997 case OPC_DPAQX_S_W_PH:
14998 check_dspr2(ctx);
14999 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
15000 break;
15001 case OPC_DPAQX_SA_W_PH:
15002 check_dspr2(ctx);
15003 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
15004 break;
15005 case OPC_DPS_W_PH:
15006 check_dspr2(ctx);
15007 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
15008 break;
15009 case OPC_DPSX_W_PH:
15010 check_dspr2(ctx);
15011 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
15012 break;
15013 case OPC_DPSQ_S_W_PH:
15014 check_dsp(ctx);
15015 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15016 break;
15017 case OPC_DPSQX_S_W_PH:
15018 check_dspr2(ctx);
15019 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
15020 break;
15021 case OPC_DPSQX_SA_W_PH:
15022 check_dspr2(ctx);
15023 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
15024 break;
15025 case OPC_MULSAQ_S_W_PH:
15026 check_dsp(ctx);
15027 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15028 break;
15029 case OPC_DPAQ_SA_L_W:
15030 check_dsp(ctx);
15031 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
15032 break;
15033 case OPC_DPSQ_SA_L_W:
15034 check_dsp(ctx);
15035 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
15036 break;
15037 case OPC_MAQ_S_W_PHL:
15038 check_dsp(ctx);
15039 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
15040 break;
15041 case OPC_MAQ_S_W_PHR:
15042 check_dsp(ctx);
15043 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
15044 break;
15045 case OPC_MAQ_SA_W_PHL:
15046 check_dsp(ctx);
15047 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
15048 break;
15049 case OPC_MAQ_SA_W_PHR:
15050 check_dsp(ctx);
15051 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
15052 break;
15053 case OPC_MULSA_W_PH:
15054 check_dspr2(ctx);
15055 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
15056 break;
15058 break;
15059 #ifdef TARGET_MIPS64
15060 case OPC_DPAQ_W_QH_DSP:
15062 int ac = ret & 0x03;
15063 tcg_gen_movi_i32(t0, ac);
15065 switch (op2) {
15066 case OPC_DMADD:
15067 check_dsp(ctx);
15068 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
15069 break;
15070 case OPC_DMADDU:
15071 check_dsp(ctx);
15072 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
15073 break;
15074 case OPC_DMSUB:
15075 check_dsp(ctx);
15076 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
15077 break;
15078 case OPC_DMSUBU:
15079 check_dsp(ctx);
15080 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
15081 break;
15082 case OPC_DPA_W_QH:
15083 check_dspr2(ctx);
15084 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
15085 break;
15086 case OPC_DPAQ_S_W_QH:
15087 check_dsp(ctx);
15088 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15089 break;
15090 case OPC_DPAQ_SA_L_PW:
15091 check_dsp(ctx);
15092 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
15093 break;
15094 case OPC_DPAU_H_OBL:
15095 check_dsp(ctx);
15096 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
15097 break;
15098 case OPC_DPAU_H_OBR:
15099 check_dsp(ctx);
15100 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
15101 break;
15102 case OPC_DPS_W_QH:
15103 check_dspr2(ctx);
15104 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
15105 break;
15106 case OPC_DPSQ_S_W_QH:
15107 check_dsp(ctx);
15108 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15109 break;
15110 case OPC_DPSQ_SA_L_PW:
15111 check_dsp(ctx);
15112 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
15113 break;
15114 case OPC_DPSU_H_OBL:
15115 check_dsp(ctx);
15116 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
15117 break;
15118 case OPC_DPSU_H_OBR:
15119 check_dsp(ctx);
15120 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
15121 break;
15122 case OPC_MAQ_S_L_PWL:
15123 check_dsp(ctx);
15124 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
15125 break;
15126 case OPC_MAQ_S_L_PWR:
15127 check_dsp(ctx);
15128 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
15129 break;
15130 case OPC_MAQ_S_W_QHLL:
15131 check_dsp(ctx);
15132 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
15133 break;
15134 case OPC_MAQ_SA_W_QHLL:
15135 check_dsp(ctx);
15136 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
15137 break;
15138 case OPC_MAQ_S_W_QHLR:
15139 check_dsp(ctx);
15140 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
15141 break;
15142 case OPC_MAQ_SA_W_QHLR:
15143 check_dsp(ctx);
15144 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
15145 break;
15146 case OPC_MAQ_S_W_QHRL:
15147 check_dsp(ctx);
15148 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
15149 break;
15150 case OPC_MAQ_SA_W_QHRL:
15151 check_dsp(ctx);
15152 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
15153 break;
15154 case OPC_MAQ_S_W_QHRR:
15155 check_dsp(ctx);
15156 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
15157 break;
15158 case OPC_MAQ_SA_W_QHRR:
15159 check_dsp(ctx);
15160 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
15161 break;
15162 case OPC_MULSAQ_S_L_PW:
15163 check_dsp(ctx);
15164 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
15165 break;
15166 case OPC_MULSAQ_S_W_QH:
15167 check_dsp(ctx);
15168 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15169 break;
15172 break;
15173 #endif
15174 case OPC_ADDU_QB_DSP:
15175 switch (op2) {
15176 case OPC_MULEU_S_PH_QBL:
15177 check_dsp(ctx);
15178 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15179 break;
15180 case OPC_MULEU_S_PH_QBR:
15181 check_dsp(ctx);
15182 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15183 break;
15184 case OPC_MULQ_RS_PH:
15185 check_dsp(ctx);
15186 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15187 break;
15188 case OPC_MULEQ_S_W_PHL:
15189 check_dsp(ctx);
15190 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15191 break;
15192 case OPC_MULEQ_S_W_PHR:
15193 check_dsp(ctx);
15194 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15195 break;
15196 case OPC_MULQ_S_PH:
15197 check_dspr2(ctx);
15198 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15199 break;
15201 break;
15202 #ifdef TARGET_MIPS64
15203 case OPC_ADDU_OB_DSP:
15204 switch (op2) {
15205 case OPC_MULEQ_S_PW_QHL:
15206 check_dsp(ctx);
15207 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15208 break;
15209 case OPC_MULEQ_S_PW_QHR:
15210 check_dsp(ctx);
15211 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15212 break;
15213 case OPC_MULEU_S_QH_OBL:
15214 check_dsp(ctx);
15215 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15216 break;
15217 case OPC_MULEU_S_QH_OBR:
15218 check_dsp(ctx);
15219 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15220 break;
15221 case OPC_MULQ_RS_QH:
15222 check_dsp(ctx);
15223 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15224 break;
15226 break;
15227 #endif
15230 tcg_temp_free_i32(t0);
15231 tcg_temp_free(v1_t);
15232 tcg_temp_free(v2_t);
15234 (void)opn; /* avoid a compiler warning */
15235 MIPS_DEBUG("%s", opn);
15239 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
15240 int ret, int val)
15242 const char *opn = "mipsdsp Bit/ Manipulation";
15243 int16_t imm;
15244 TCGv t0;
15245 TCGv val_t;
15247 if (ret == 0) {
15248 /* Treat as NOP. */
15249 MIPS_DEBUG("NOP");
15250 return;
15253 t0 = tcg_temp_new();
15254 val_t = tcg_temp_new();
15255 gen_load_gpr(val_t, val);
15257 switch (op1) {
15258 case OPC_ABSQ_S_PH_DSP:
15259 switch (op2) {
15260 case OPC_BITREV:
15261 check_dsp(ctx);
15262 gen_helper_bitrev(cpu_gpr[ret], val_t);
15263 break;
15264 case OPC_REPL_QB:
15265 check_dsp(ctx);
15267 target_long result;
15268 imm = (ctx->opcode >> 16) & 0xFF;
15269 result = (uint32_t)imm << 24 |
15270 (uint32_t)imm << 16 |
15271 (uint32_t)imm << 8 |
15272 (uint32_t)imm;
15273 result = (int32_t)result;
15274 tcg_gen_movi_tl(cpu_gpr[ret], result);
15276 break;
15277 case OPC_REPLV_QB:
15278 check_dsp(ctx);
15279 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
15280 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
15281 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15282 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
15283 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15284 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15285 break;
15286 case OPC_REPL_PH:
15287 check_dsp(ctx);
15289 imm = (ctx->opcode >> 16) & 0x03FF;
15290 imm = (int16_t)(imm << 6) >> 6;
15291 tcg_gen_movi_tl(cpu_gpr[ret], \
15292 (target_long)((int32_t)imm << 16 | \
15293 (uint16_t)imm));
15295 break;
15296 case OPC_REPLV_PH:
15297 check_dsp(ctx);
15298 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
15299 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
15300 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15301 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15302 break;
15304 break;
15305 #ifdef TARGET_MIPS64
15306 case OPC_ABSQ_S_QH_DSP:
15307 switch (op2) {
15308 case OPC_REPL_OB:
15309 check_dsp(ctx);
15311 target_long temp;
15313 imm = (ctx->opcode >> 16) & 0xFF;
15314 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
15315 temp = (temp << 16) | temp;
15316 temp = (temp << 32) | temp;
15317 tcg_gen_movi_tl(cpu_gpr[ret], temp);
15318 break;
15320 case OPC_REPL_PW:
15321 check_dsp(ctx);
15323 target_long temp;
15325 imm = (ctx->opcode >> 16) & 0x03FF;
15326 imm = (int16_t)(imm << 6) >> 6;
15327 temp = ((target_long)imm << 32) \
15328 | ((target_long)imm & 0xFFFFFFFF);
15329 tcg_gen_movi_tl(cpu_gpr[ret], temp);
15330 break;
15332 case OPC_REPL_QH:
15333 check_dsp(ctx);
15335 target_long temp;
15337 imm = (ctx->opcode >> 16) & 0x03FF;
15338 imm = (int16_t)(imm << 6) >> 6;
15340 temp = ((uint64_t)(uint16_t)imm << 48) |
15341 ((uint64_t)(uint16_t)imm << 32) |
15342 ((uint64_t)(uint16_t)imm << 16) |
15343 (uint64_t)(uint16_t)imm;
15344 tcg_gen_movi_tl(cpu_gpr[ret], temp);
15345 break;
15347 case OPC_REPLV_OB:
15348 check_dsp(ctx);
15349 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
15350 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
15351 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15352 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
15353 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15354 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
15355 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15356 break;
15357 case OPC_REPLV_PW:
15358 check_dsp(ctx);
15359 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
15360 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
15361 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15362 break;
15363 case OPC_REPLV_QH:
15364 check_dsp(ctx);
15365 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
15366 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
15367 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15368 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
15369 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15370 break;
15372 break;
15373 #endif
15375 tcg_temp_free(t0);
15376 tcg_temp_free(val_t);
15378 (void)opn; /* avoid a compiler warning */
15379 MIPS_DEBUG("%s", opn);
15382 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
15383 uint32_t op1, uint32_t op2,
15384 int ret, int v1, int v2, int check_ret)
15386 const char *opn = "mipsdsp add compare pick";
15387 TCGv t1;
15388 TCGv v1_t;
15389 TCGv v2_t;
15391 if ((ret == 0) && (check_ret == 1)) {
15392 /* Treat as NOP. */
15393 MIPS_DEBUG("NOP");
15394 return;
15397 t1 = tcg_temp_new();
15398 v1_t = tcg_temp_new();
15399 v2_t = tcg_temp_new();
15401 gen_load_gpr(v1_t, v1);
15402 gen_load_gpr(v2_t, v2);
15404 switch (op1) {
15405 case OPC_CMPU_EQ_QB_DSP:
15406 switch (op2) {
15407 case OPC_CMPU_EQ_QB:
15408 check_dsp(ctx);
15409 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
15410 break;
15411 case OPC_CMPU_LT_QB:
15412 check_dsp(ctx);
15413 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
15414 break;
15415 case OPC_CMPU_LE_QB:
15416 check_dsp(ctx);
15417 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
15418 break;
15419 case OPC_CMPGU_EQ_QB:
15420 check_dsp(ctx);
15421 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
15422 break;
15423 case OPC_CMPGU_LT_QB:
15424 check_dsp(ctx);
15425 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
15426 break;
15427 case OPC_CMPGU_LE_QB:
15428 check_dsp(ctx);
15429 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
15430 break;
15431 case OPC_CMPGDU_EQ_QB:
15432 check_dspr2(ctx);
15433 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
15434 tcg_gen_mov_tl(cpu_gpr[ret], t1);
15435 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
15436 tcg_gen_shli_tl(t1, t1, 24);
15437 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
15438 break;
15439 case OPC_CMPGDU_LT_QB:
15440 check_dspr2(ctx);
15441 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
15442 tcg_gen_mov_tl(cpu_gpr[ret], t1);
15443 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
15444 tcg_gen_shli_tl(t1, t1, 24);
15445 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
15446 break;
15447 case OPC_CMPGDU_LE_QB:
15448 check_dspr2(ctx);
15449 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
15450 tcg_gen_mov_tl(cpu_gpr[ret], t1);
15451 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
15452 tcg_gen_shli_tl(t1, t1, 24);
15453 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
15454 break;
15455 case OPC_CMP_EQ_PH:
15456 check_dsp(ctx);
15457 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
15458 break;
15459 case OPC_CMP_LT_PH:
15460 check_dsp(ctx);
15461 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
15462 break;
15463 case OPC_CMP_LE_PH:
15464 check_dsp(ctx);
15465 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
15466 break;
15467 case OPC_PICK_QB:
15468 check_dsp(ctx);
15469 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15470 break;
15471 case OPC_PICK_PH:
15472 check_dsp(ctx);
15473 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15474 break;
15475 case OPC_PACKRL_PH:
15476 check_dsp(ctx);
15477 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
15478 break;
15480 break;
15481 #ifdef TARGET_MIPS64
15482 case OPC_CMPU_EQ_OB_DSP:
15483 switch (op2) {
15484 case OPC_CMP_EQ_PW:
15485 check_dsp(ctx);
15486 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
15487 break;
15488 case OPC_CMP_LT_PW:
15489 check_dsp(ctx);
15490 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
15491 break;
15492 case OPC_CMP_LE_PW:
15493 check_dsp(ctx);
15494 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
15495 break;
15496 case OPC_CMP_EQ_QH:
15497 check_dsp(ctx);
15498 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
15499 break;
15500 case OPC_CMP_LT_QH:
15501 check_dsp(ctx);
15502 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
15503 break;
15504 case OPC_CMP_LE_QH:
15505 check_dsp(ctx);
15506 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
15507 break;
15508 case OPC_CMPGDU_EQ_OB:
15509 check_dspr2(ctx);
15510 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15511 break;
15512 case OPC_CMPGDU_LT_OB:
15513 check_dspr2(ctx);
15514 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15515 break;
15516 case OPC_CMPGDU_LE_OB:
15517 check_dspr2(ctx);
15518 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15519 break;
15520 case OPC_CMPGU_EQ_OB:
15521 check_dsp(ctx);
15522 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
15523 break;
15524 case OPC_CMPGU_LT_OB:
15525 check_dsp(ctx);
15526 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
15527 break;
15528 case OPC_CMPGU_LE_OB:
15529 check_dsp(ctx);
15530 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
15531 break;
15532 case OPC_CMPU_EQ_OB:
15533 check_dsp(ctx);
15534 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
15535 break;
15536 case OPC_CMPU_LT_OB:
15537 check_dsp(ctx);
15538 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
15539 break;
15540 case OPC_CMPU_LE_OB:
15541 check_dsp(ctx);
15542 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
15543 break;
15544 case OPC_PACKRL_PW:
15545 check_dsp(ctx);
15546 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
15547 break;
15548 case OPC_PICK_OB:
15549 check_dsp(ctx);
15550 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15551 break;
15552 case OPC_PICK_PW:
15553 check_dsp(ctx);
15554 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15555 break;
15556 case OPC_PICK_QH:
15557 check_dsp(ctx);
15558 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15559 break;
15561 break;
15562 #endif
15565 tcg_temp_free(t1);
15566 tcg_temp_free(v1_t);
15567 tcg_temp_free(v2_t);
15569 (void)opn; /* avoid a compiler warning */
15570 MIPS_DEBUG("%s", opn);
15573 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
15574 uint32_t op1, int rt, int rs, int sa)
15576 const char *opn = "mipsdsp append/dappend";
15577 TCGv t0;
15579 check_dspr2(ctx);
15581 if (rt == 0) {
15582 /* Treat as NOP. */
15583 MIPS_DEBUG("NOP");
15584 return;
15587 t0 = tcg_temp_new();
15588 gen_load_gpr(t0, rs);
15590 switch (op1) {
15591 case OPC_APPEND_DSP:
15592 switch (MASK_APPEND(ctx->opcode)) {
15593 case OPC_APPEND:
15594 if (sa != 0) {
15595 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
15597 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15598 break;
15599 case OPC_PREPEND:
15600 if (sa != 0) {
15601 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
15602 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
15603 tcg_gen_shli_tl(t0, t0, 32 - sa);
15604 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15606 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15607 break;
15608 case OPC_BALIGN:
15609 sa &= 3;
15610 if (sa != 0 && sa != 2) {
15611 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
15612 tcg_gen_ext32u_tl(t0, t0);
15613 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
15614 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15616 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15617 break;
15618 default: /* Invalid */
15619 MIPS_INVAL("MASK APPEND");
15620 generate_exception(ctx, EXCP_RI);
15621 break;
15623 break;
15624 #ifdef TARGET_MIPS64
15625 case OPC_DAPPEND_DSP:
15626 switch (MASK_DAPPEND(ctx->opcode)) {
15627 case OPC_DAPPEND:
15628 if (sa != 0) {
15629 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
15631 break;
15632 case OPC_PREPENDD:
15633 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
15634 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
15635 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
15636 break;
15637 case OPC_PREPENDW:
15638 if (sa != 0) {
15639 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
15640 tcg_gen_shli_tl(t0, t0, 64 - sa);
15641 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15643 break;
15644 case OPC_DBALIGN:
15645 sa &= 7;
15646 if (sa != 0 && sa != 2 && sa != 4) {
15647 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
15648 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
15649 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15651 break;
15652 default: /* Invalid */
15653 MIPS_INVAL("MASK DAPPEND");
15654 generate_exception(ctx, EXCP_RI);
15655 break;
15657 break;
15658 #endif
15660 tcg_temp_free(t0);
15661 (void)opn; /* avoid a compiler warning */
15662 MIPS_DEBUG("%s", opn);
15665 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
15666 int ret, int v1, int v2, int check_ret)
15669 const char *opn = "mipsdsp accumulator";
15670 TCGv t0;
15671 TCGv t1;
15672 TCGv v1_t;
15673 TCGv v2_t;
15674 int16_t imm;
15676 if ((ret == 0) && (check_ret == 1)) {
15677 /* Treat as NOP. */
15678 MIPS_DEBUG("NOP");
15679 return;
15682 t0 = tcg_temp_new();
15683 t1 = tcg_temp_new();
15684 v1_t = tcg_temp_new();
15685 v2_t = tcg_temp_new();
15687 gen_load_gpr(v1_t, v1);
15688 gen_load_gpr(v2_t, v2);
15690 switch (op1) {
15691 case OPC_EXTR_W_DSP:
15692 check_dsp(ctx);
15693 switch (op2) {
15694 case OPC_EXTR_W:
15695 tcg_gen_movi_tl(t0, v2);
15696 tcg_gen_movi_tl(t1, v1);
15697 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
15698 break;
15699 case OPC_EXTR_R_W:
15700 tcg_gen_movi_tl(t0, v2);
15701 tcg_gen_movi_tl(t1, v1);
15702 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
15703 break;
15704 case OPC_EXTR_RS_W:
15705 tcg_gen_movi_tl(t0, v2);
15706 tcg_gen_movi_tl(t1, v1);
15707 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
15708 break;
15709 case OPC_EXTR_S_H:
15710 tcg_gen_movi_tl(t0, v2);
15711 tcg_gen_movi_tl(t1, v1);
15712 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15713 break;
15714 case OPC_EXTRV_S_H:
15715 tcg_gen_movi_tl(t0, v2);
15716 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
15717 break;
15718 case OPC_EXTRV_W:
15719 tcg_gen_movi_tl(t0, v2);
15720 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15721 break;
15722 case OPC_EXTRV_R_W:
15723 tcg_gen_movi_tl(t0, v2);
15724 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15725 break;
15726 case OPC_EXTRV_RS_W:
15727 tcg_gen_movi_tl(t0, v2);
15728 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15729 break;
15730 case OPC_EXTP:
15731 tcg_gen_movi_tl(t0, v2);
15732 tcg_gen_movi_tl(t1, v1);
15733 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
15734 break;
15735 case OPC_EXTPV:
15736 tcg_gen_movi_tl(t0, v2);
15737 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
15738 break;
15739 case OPC_EXTPDP:
15740 tcg_gen_movi_tl(t0, v2);
15741 tcg_gen_movi_tl(t1, v1);
15742 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
15743 break;
15744 case OPC_EXTPDPV:
15745 tcg_gen_movi_tl(t0, v2);
15746 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
15747 break;
15748 case OPC_SHILO:
15749 imm = (ctx->opcode >> 20) & 0x3F;
15750 tcg_gen_movi_tl(t0, ret);
15751 tcg_gen_movi_tl(t1, imm);
15752 gen_helper_shilo(t0, t1, cpu_env);
15753 break;
15754 case OPC_SHILOV:
15755 tcg_gen_movi_tl(t0, ret);
15756 gen_helper_shilo(t0, v1_t, cpu_env);
15757 break;
15758 case OPC_MTHLIP:
15759 tcg_gen_movi_tl(t0, ret);
15760 gen_helper_mthlip(t0, v1_t, cpu_env);
15761 break;
15762 case OPC_WRDSP:
15763 imm = (ctx->opcode >> 11) & 0x3FF;
15764 tcg_gen_movi_tl(t0, imm);
15765 gen_helper_wrdsp(v1_t, t0, cpu_env);
15766 break;
15767 case OPC_RDDSP:
15768 imm = (ctx->opcode >> 16) & 0x03FF;
15769 tcg_gen_movi_tl(t0, imm);
15770 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
15771 break;
15773 break;
15774 #ifdef TARGET_MIPS64
15775 case OPC_DEXTR_W_DSP:
15776 check_dsp(ctx);
15777 switch (op2) {
15778 case OPC_DMTHLIP:
15779 tcg_gen_movi_tl(t0, ret);
15780 gen_helper_dmthlip(v1_t, t0, cpu_env);
15781 break;
15782 case OPC_DSHILO:
15784 int shift = (ctx->opcode >> 19) & 0x7F;
15785 int ac = (ctx->opcode >> 11) & 0x03;
15786 tcg_gen_movi_tl(t0, shift);
15787 tcg_gen_movi_tl(t1, ac);
15788 gen_helper_dshilo(t0, t1, cpu_env);
15789 break;
15791 case OPC_DSHILOV:
15793 int ac = (ctx->opcode >> 11) & 0x03;
15794 tcg_gen_movi_tl(t0, ac);
15795 gen_helper_dshilo(v1_t, t0, cpu_env);
15796 break;
15798 case OPC_DEXTP:
15799 tcg_gen_movi_tl(t0, v2);
15800 tcg_gen_movi_tl(t1, v1);
15802 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
15803 break;
15804 case OPC_DEXTPV:
15805 tcg_gen_movi_tl(t0, v2);
15806 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
15807 break;
15808 case OPC_DEXTPDP:
15809 tcg_gen_movi_tl(t0, v2);
15810 tcg_gen_movi_tl(t1, v1);
15811 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
15812 break;
15813 case OPC_DEXTPDPV:
15814 tcg_gen_movi_tl(t0, v2);
15815 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
15816 break;
15817 case OPC_DEXTR_L:
15818 tcg_gen_movi_tl(t0, v2);
15819 tcg_gen_movi_tl(t1, v1);
15820 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
15821 break;
15822 case OPC_DEXTR_R_L:
15823 tcg_gen_movi_tl(t0, v2);
15824 tcg_gen_movi_tl(t1, v1);
15825 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
15826 break;
15827 case OPC_DEXTR_RS_L:
15828 tcg_gen_movi_tl(t0, v2);
15829 tcg_gen_movi_tl(t1, v1);
15830 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
15831 break;
15832 case OPC_DEXTR_W:
15833 tcg_gen_movi_tl(t0, v2);
15834 tcg_gen_movi_tl(t1, v1);
15835 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
15836 break;
15837 case OPC_DEXTR_R_W:
15838 tcg_gen_movi_tl(t0, v2);
15839 tcg_gen_movi_tl(t1, v1);
15840 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
15841 break;
15842 case OPC_DEXTR_RS_W:
15843 tcg_gen_movi_tl(t0, v2);
15844 tcg_gen_movi_tl(t1, v1);
15845 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
15846 break;
15847 case OPC_DEXTR_S_H:
15848 tcg_gen_movi_tl(t0, v2);
15849 tcg_gen_movi_tl(t1, v1);
15850 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15851 break;
15852 case OPC_DEXTRV_S_H:
15853 tcg_gen_movi_tl(t0, v2);
15854 tcg_gen_movi_tl(t1, v1);
15855 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15856 break;
15857 case OPC_DEXTRV_L:
15858 tcg_gen_movi_tl(t0, v2);
15859 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15860 break;
15861 case OPC_DEXTRV_R_L:
15862 tcg_gen_movi_tl(t0, v2);
15863 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15864 break;
15865 case OPC_DEXTRV_RS_L:
15866 tcg_gen_movi_tl(t0, v2);
15867 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15868 break;
15869 case OPC_DEXTRV_W:
15870 tcg_gen_movi_tl(t0, v2);
15871 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15872 break;
15873 case OPC_DEXTRV_R_W:
15874 tcg_gen_movi_tl(t0, v2);
15875 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15876 break;
15877 case OPC_DEXTRV_RS_W:
15878 tcg_gen_movi_tl(t0, v2);
15879 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15880 break;
15882 break;
15883 #endif
15886 tcg_temp_free(t0);
15887 tcg_temp_free(t1);
15888 tcg_temp_free(v1_t);
15889 tcg_temp_free(v2_t);
15891 (void)opn; /* avoid a compiler warning */
15892 MIPS_DEBUG("%s", opn);
15895 /* End MIPSDSP functions. */
15897 /* Compact Branches */
15898 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
15899 int rs, int rt, int32_t offset)
15901 int bcond_compute = 0;
15902 TCGv t0 = tcg_temp_new();
15903 TCGv t1 = tcg_temp_new();
15905 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15906 #ifdef MIPS_DEBUG_DISAS
15907 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
15908 "\n", ctx->pc);
15909 #endif
15910 generate_exception(ctx, EXCP_RI);
15911 goto out;
15914 /* Load needed operands and calculate btarget */
15915 switch (opc) {
15916 /* compact branch */
15917 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
15918 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
15919 gen_load_gpr(t0, rs);
15920 gen_load_gpr(t1, rt);
15921 bcond_compute = 1;
15922 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15923 if (rs <= rt && rs == 0) {
15924 /* OPC_BEQZALC, OPC_BNEZALC */
15925 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15927 break;
15928 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
15929 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
15930 gen_load_gpr(t0, rs);
15931 gen_load_gpr(t1, rt);
15932 bcond_compute = 1;
15933 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15934 break;
15935 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
15936 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
15937 if (rs == 0 || rs == rt) {
15938 /* OPC_BLEZALC, OPC_BGEZALC */
15939 /* OPC_BGTZALC, OPC_BLTZALC */
15940 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15942 gen_load_gpr(t0, rs);
15943 gen_load_gpr(t1, rt);
15944 bcond_compute = 1;
15945 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15946 break;
15947 case OPC_BC:
15948 case OPC_BALC:
15949 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15950 break;
15951 case OPC_BEQZC:
15952 case OPC_BNEZC:
15953 if (rs != 0) {
15954 /* OPC_BEQZC, OPC_BNEZC */
15955 gen_load_gpr(t0, rs);
15956 bcond_compute = 1;
15957 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15958 } else {
15959 /* OPC_JIC, OPC_JIALC */
15960 TCGv tbase = tcg_temp_new();
15961 TCGv toffset = tcg_temp_new();
15963 gen_load_gpr(tbase, rt);
15964 tcg_gen_movi_tl(toffset, offset);
15965 gen_op_addr_add(ctx, btarget, tbase, toffset);
15966 tcg_temp_free(tbase);
15967 tcg_temp_free(toffset);
15969 break;
15970 default:
15971 MIPS_INVAL("Compact branch/jump");
15972 generate_exception(ctx, EXCP_RI);
15973 goto out;
15976 if (bcond_compute == 0) {
15977 /* Uncoditional compact branch */
15978 switch (opc) {
15979 case OPC_JIALC:
15980 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15981 /* Fallthrough */
15982 case OPC_JIC:
15983 ctx->hflags |= MIPS_HFLAG_BR;
15984 break;
15985 case OPC_BALC:
15986 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15987 /* Fallthrough */
15988 case OPC_BC:
15989 ctx->hflags |= MIPS_HFLAG_B;
15990 break;
15991 default:
15992 MIPS_INVAL("Compact branch/jump");
15993 generate_exception(ctx, EXCP_RI);
15994 goto out;
15997 /* Generating branch here as compact branches don't have delay slot */
15998 gen_branch(ctx, 4);
15999 } else {
16000 /* Conditional compact branch */
16001 int fs = gen_new_label();
16002 save_cpu_state(ctx, 0);
16004 switch (opc) {
16005 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
16006 if (rs == 0 && rt != 0) {
16007 /* OPC_BLEZALC */
16008 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
16009 } else if (rs != 0 && rt != 0 && rs == rt) {
16010 /* OPC_BGEZALC */
16011 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
16012 } else {
16013 /* OPC_BGEUC */
16014 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
16016 break;
16017 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
16018 if (rs == 0 && rt != 0) {
16019 /* OPC_BGTZALC */
16020 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
16021 } else if (rs != 0 && rt != 0 && rs == rt) {
16022 /* OPC_BLTZALC */
16023 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
16024 } else {
16025 /* OPC_BLTUC */
16026 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
16028 break;
16029 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
16030 if (rs == 0 && rt != 0) {
16031 /* OPC_BLEZC */
16032 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
16033 } else if (rs != 0 && rt != 0 && rs == rt) {
16034 /* OPC_BGEZC */
16035 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
16036 } else {
16037 /* OPC_BGEC */
16038 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
16040 break;
16041 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
16042 if (rs == 0 && rt != 0) {
16043 /* OPC_BGTZC */
16044 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
16045 } else if (rs != 0 && rt != 0 && rs == rt) {
16046 /* OPC_BLTZC */
16047 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
16048 } else {
16049 /* OPC_BLTC */
16050 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
16052 break;
16053 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
16054 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
16055 if (rs >= rt) {
16056 /* OPC_BOVC, OPC_BNVC */
16057 TCGv t2 = tcg_temp_new();
16058 TCGv t3 = tcg_temp_new();
16059 TCGv t4 = tcg_temp_new();
16060 TCGv input_overflow = tcg_temp_new();
16062 gen_load_gpr(t0, rs);
16063 gen_load_gpr(t1, rt);
16064 tcg_gen_ext32s_tl(t2, t0);
16065 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
16066 tcg_gen_ext32s_tl(t3, t1);
16067 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
16068 tcg_gen_or_tl(input_overflow, input_overflow, t4);
16070 tcg_gen_add_tl(t4, t2, t3);
16071 tcg_gen_ext32s_tl(t4, t4);
16072 tcg_gen_xor_tl(t2, t2, t3);
16073 tcg_gen_xor_tl(t3, t4, t3);
16074 tcg_gen_andc_tl(t2, t3, t2);
16075 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
16076 tcg_gen_or_tl(t4, t4, input_overflow);
16077 if (opc == OPC_BOVC) {
16078 /* OPC_BOVC */
16079 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
16080 } else {
16081 /* OPC_BNVC */
16082 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
16084 tcg_temp_free(input_overflow);
16085 tcg_temp_free(t4);
16086 tcg_temp_free(t3);
16087 tcg_temp_free(t2);
16088 } else if (rs < rt && rs == 0) {
16089 /* OPC_BEQZALC, OPC_BNEZALC */
16090 if (opc == OPC_BEQZALC) {
16091 /* OPC_BEQZALC */
16092 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
16093 } else {
16094 /* OPC_BNEZALC */
16095 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
16097 } else {
16098 /* OPC_BEQC, OPC_BNEC */
16099 if (opc == OPC_BEQC) {
16100 /* OPC_BEQC */
16101 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
16102 } else {
16103 /* OPC_BNEC */
16104 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
16107 break;
16108 case OPC_BEQZC:
16109 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
16110 break;
16111 case OPC_BNEZC:
16112 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
16113 break;
16114 default:
16115 MIPS_INVAL("Compact conditional branch/jump");
16116 generate_exception(ctx, EXCP_RI);
16117 goto out;
16120 /* Generating branch here as compact branches don't have delay slot */
16121 gen_goto_tb(ctx, 1, ctx->btarget);
16122 gen_set_label(fs);
16124 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
16125 MIPS_DEBUG("Compact conditional branch");
16128 out:
16129 tcg_temp_free(t0);
16130 tcg_temp_free(t1);
16133 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
16135 int rs, rt, rd, sa;
16136 uint32_t op1, op2;
16138 rs = (ctx->opcode >> 21) & 0x1f;
16139 rt = (ctx->opcode >> 16) & 0x1f;
16140 rd = (ctx->opcode >> 11) & 0x1f;
16141 sa = (ctx->opcode >> 6) & 0x1f;
16143 op1 = MASK_SPECIAL(ctx->opcode);
16144 switch (op1) {
16145 case OPC_LSA:
16146 if (rd != 0) {
16147 int imm2 = extract32(ctx->opcode, 6, 3);
16148 TCGv t0 = tcg_temp_new();
16149 TCGv t1 = tcg_temp_new();
16150 gen_load_gpr(t0, rs);
16151 gen_load_gpr(t1, rt);
16152 tcg_gen_shli_tl(t0, t0, imm2 + 1);
16153 tcg_gen_add_tl(t0, t0, t1);
16154 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
16155 tcg_temp_free(t1);
16156 tcg_temp_free(t0);
16158 break;
16159 case OPC_MULT ... OPC_DIVU:
16160 op2 = MASK_R6_MULDIV(ctx->opcode);
16161 switch (op2) {
16162 case R6_OPC_MUL:
16163 case R6_OPC_MUH:
16164 case R6_OPC_MULU:
16165 case R6_OPC_MUHU:
16166 case R6_OPC_DIV:
16167 case R6_OPC_MOD:
16168 case R6_OPC_DIVU:
16169 case R6_OPC_MODU:
16170 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16171 break;
16172 default:
16173 MIPS_INVAL("special_r6 muldiv");
16174 generate_exception(ctx, EXCP_RI);
16175 break;
16177 break;
16178 case OPC_SELEQZ:
16179 case OPC_SELNEZ:
16180 gen_cond_move(ctx, op1, rd, rs, rt);
16181 break;
16182 case R6_OPC_CLO:
16183 case R6_OPC_CLZ:
16184 if (rt == 0 && sa == 1) {
16185 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16186 We need additionally to check other fields */
16187 gen_cl(ctx, op1, rd, rs);
16188 } else {
16189 generate_exception(ctx, EXCP_RI);
16191 break;
16192 case R6_OPC_SDBBP:
16193 if (ctx->hflags & MIPS_HFLAG_SBRI) {
16194 generate_exception(ctx, EXCP_RI);
16195 } else {
16196 generate_exception(ctx, EXCP_DBp);
16198 break;
16199 #if defined(TARGET_MIPS64)
16200 case OPC_DLSA:
16201 check_mips_64(ctx);
16202 if (rd != 0) {
16203 int imm2 = extract32(ctx->opcode, 6, 3);
16204 TCGv t0 = tcg_temp_new();
16205 TCGv t1 = tcg_temp_new();
16206 gen_load_gpr(t0, rs);
16207 gen_load_gpr(t1, rt);
16208 tcg_gen_shli_tl(t0, t0, imm2 + 1);
16209 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
16210 tcg_temp_free(t1);
16211 tcg_temp_free(t0);
16213 break;
16214 case R6_OPC_DCLO:
16215 case R6_OPC_DCLZ:
16216 if (rt == 0 && sa == 1) {
16217 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16218 We need additionally to check other fields */
16219 check_mips_64(ctx);
16220 gen_cl(ctx, op1, rd, rs);
16221 } else {
16222 generate_exception(ctx, EXCP_RI);
16224 break;
16225 case OPC_DMULT ... OPC_DDIVU:
16226 op2 = MASK_R6_MULDIV(ctx->opcode);
16227 switch (op2) {
16228 case R6_OPC_DMUL:
16229 case R6_OPC_DMUH:
16230 case R6_OPC_DMULU:
16231 case R6_OPC_DMUHU:
16232 case R6_OPC_DDIV:
16233 case R6_OPC_DMOD:
16234 case R6_OPC_DDIVU:
16235 case R6_OPC_DMODU:
16236 check_mips_64(ctx);
16237 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16238 break;
16239 default:
16240 MIPS_INVAL("special_r6 muldiv");
16241 generate_exception(ctx, EXCP_RI);
16242 break;
16244 break;
16245 #endif
16246 default: /* Invalid */
16247 MIPS_INVAL("special_r6");
16248 generate_exception(ctx, EXCP_RI);
16249 break;
16253 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
16255 int rs, rt, rd, sa;
16256 uint32_t op1;
16258 rs = (ctx->opcode >> 21) & 0x1f;
16259 rt = (ctx->opcode >> 16) & 0x1f;
16260 rd = (ctx->opcode >> 11) & 0x1f;
16261 sa = (ctx->opcode >> 6) & 0x1f;
16263 op1 = MASK_SPECIAL(ctx->opcode);
16264 switch (op1) {
16265 case OPC_MOVN: /* Conditional move */
16266 case OPC_MOVZ:
16267 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
16268 INSN_LOONGSON2E | INSN_LOONGSON2F);
16269 gen_cond_move(ctx, op1, rd, rs, rt);
16270 break;
16271 case OPC_MFHI: /* Move from HI/LO */
16272 case OPC_MFLO:
16273 gen_HILO(ctx, op1, rs & 3, rd);
16274 break;
16275 case OPC_MTHI:
16276 case OPC_MTLO: /* Move to HI/LO */
16277 gen_HILO(ctx, op1, rd & 3, rs);
16278 break;
16279 case OPC_MOVCI:
16280 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
16281 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16282 check_cp1_enabled(ctx);
16283 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
16284 (ctx->opcode >> 16) & 1);
16285 } else {
16286 generate_exception_err(ctx, EXCP_CpU, 1);
16288 break;
16289 case OPC_MULT:
16290 case OPC_MULTU:
16291 if (sa) {
16292 check_insn(ctx, INSN_VR54XX);
16293 op1 = MASK_MUL_VR54XX(ctx->opcode);
16294 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
16295 } else {
16296 gen_muldiv(ctx, op1, rd & 3, rs, rt);
16298 break;
16299 case OPC_DIV:
16300 case OPC_DIVU:
16301 gen_muldiv(ctx, op1, 0, rs, rt);
16302 break;
16303 #if defined(TARGET_MIPS64)
16304 case OPC_DMULT ... OPC_DDIVU:
16305 check_insn(ctx, ISA_MIPS3);
16306 check_mips_64(ctx);
16307 gen_muldiv(ctx, op1, 0, rs, rt);
16308 break;
16309 #endif
16310 case OPC_JR:
16311 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
16312 break;
16313 case OPC_SPIM:
16314 #ifdef MIPS_STRICT_STANDARD
16315 MIPS_INVAL("SPIM");
16316 generate_exception(ctx, EXCP_RI);
16317 #else
16318 /* Implemented as RI exception for now. */
16319 MIPS_INVAL("spim (unofficial)");
16320 generate_exception(ctx, EXCP_RI);
16321 #endif
16322 break;
16323 default: /* Invalid */
16324 MIPS_INVAL("special_legacy");
16325 generate_exception(ctx, EXCP_RI);
16326 break;
16330 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
16332 int rs, rt, rd, sa;
16333 uint32_t op1;
16335 rs = (ctx->opcode >> 21) & 0x1f;
16336 rt = (ctx->opcode >> 16) & 0x1f;
16337 rd = (ctx->opcode >> 11) & 0x1f;
16338 sa = (ctx->opcode >> 6) & 0x1f;
16340 op1 = MASK_SPECIAL(ctx->opcode);
16341 switch (op1) {
16342 case OPC_SLL: /* Shift with immediate */
16343 if (sa == 5 && rd == 0 &&
16344 rs == 0 && rt == 0) { /* PAUSE */
16345 if ((ctx->insn_flags & ISA_MIPS32R6) &&
16346 (ctx->hflags & MIPS_HFLAG_BMASK)) {
16347 MIPS_DEBUG("CTI in delay / forbidden slot");
16348 generate_exception(ctx, EXCP_RI);
16349 break;
16352 /* Fallthrough */
16353 case OPC_SRA:
16354 gen_shift_imm(ctx, op1, rd, rt, sa);
16355 break;
16356 case OPC_SRL:
16357 switch ((ctx->opcode >> 21) & 0x1f) {
16358 case 1:
16359 /* rotr is decoded as srl on non-R2 CPUs */
16360 if (ctx->insn_flags & ISA_MIPS32R2) {
16361 op1 = OPC_ROTR;
16363 /* Fallthrough */
16364 case 0:
16365 gen_shift_imm(ctx, op1, rd, rt, sa);
16366 break;
16367 default:
16368 generate_exception(ctx, EXCP_RI);
16369 break;
16371 break;
16372 case OPC_ADD ... OPC_SUBU:
16373 gen_arith(ctx, op1, rd, rs, rt);
16374 break;
16375 case OPC_SLLV: /* Shifts */
16376 case OPC_SRAV:
16377 gen_shift(ctx, op1, rd, rs, rt);
16378 break;
16379 case OPC_SRLV:
16380 switch ((ctx->opcode >> 6) & 0x1f) {
16381 case 1:
16382 /* rotrv is decoded as srlv on non-R2 CPUs */
16383 if (ctx->insn_flags & ISA_MIPS32R2) {
16384 op1 = OPC_ROTRV;
16386 /* Fallthrough */
16387 case 0:
16388 gen_shift(ctx, op1, rd, rs, rt);
16389 break;
16390 default:
16391 generate_exception(ctx, EXCP_RI);
16392 break;
16394 break;
16395 case OPC_SLT: /* Set on less than */
16396 case OPC_SLTU:
16397 gen_slt(ctx, op1, rd, rs, rt);
16398 break;
16399 case OPC_AND: /* Logic*/
16400 case OPC_OR:
16401 case OPC_NOR:
16402 case OPC_XOR:
16403 gen_logic(ctx, op1, rd, rs, rt);
16404 break;
16405 case OPC_JALR:
16406 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
16407 break;
16408 case OPC_TGE ... OPC_TEQ: /* Traps */
16409 case OPC_TNE:
16410 check_insn(ctx, ISA_MIPS2);
16411 gen_trap(ctx, op1, rs, rt, -1);
16412 break;
16413 case OPC_LSA: /* OPC_PMON */
16414 if ((ctx->insn_flags & ISA_MIPS32R6) ||
16415 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
16416 decode_opc_special_r6(env, ctx);
16417 } else {
16418 /* Pmon entry point, also R4010 selsl */
16419 #ifdef MIPS_STRICT_STANDARD
16420 MIPS_INVAL("PMON / selsl");
16421 generate_exception(ctx, EXCP_RI);
16422 #else
16423 gen_helper_0e0i(pmon, sa);
16424 #endif
16426 break;
16427 case OPC_SYSCALL:
16428 generate_exception(ctx, EXCP_SYSCALL);
16429 ctx->bstate = BS_STOP;
16430 break;
16431 case OPC_BREAK:
16432 generate_exception(ctx, EXCP_BREAK);
16433 break;
16434 case OPC_SYNC:
16435 check_insn(ctx, ISA_MIPS2);
16436 /* Treat as NOP. */
16437 break;
16439 #if defined(TARGET_MIPS64)
16440 /* MIPS64 specific opcodes */
16441 case OPC_DSLL:
16442 case OPC_DSRA:
16443 case OPC_DSLL32:
16444 case OPC_DSRA32:
16445 check_insn(ctx, ISA_MIPS3);
16446 check_mips_64(ctx);
16447 gen_shift_imm(ctx, op1, rd, rt, sa);
16448 break;
16449 case OPC_DSRL:
16450 switch ((ctx->opcode >> 21) & 0x1f) {
16451 case 1:
16452 /* drotr is decoded as dsrl on non-R2 CPUs */
16453 if (ctx->insn_flags & ISA_MIPS32R2) {
16454 op1 = OPC_DROTR;
16456 /* Fallthrough */
16457 case 0:
16458 check_insn(ctx, ISA_MIPS3);
16459 check_mips_64(ctx);
16460 gen_shift_imm(ctx, op1, rd, rt, sa);
16461 break;
16462 default:
16463 generate_exception(ctx, EXCP_RI);
16464 break;
16466 break;
16467 case OPC_DSRL32:
16468 switch ((ctx->opcode >> 21) & 0x1f) {
16469 case 1:
16470 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
16471 if (ctx->insn_flags & ISA_MIPS32R2) {
16472 op1 = OPC_DROTR32;
16474 /* Fallthrough */
16475 case 0:
16476 check_insn(ctx, ISA_MIPS3);
16477 check_mips_64(ctx);
16478 gen_shift_imm(ctx, op1, rd, rt, sa);
16479 break;
16480 default:
16481 generate_exception(ctx, EXCP_RI);
16482 break;
16484 break;
16485 case OPC_DADD ... OPC_DSUBU:
16486 check_insn(ctx, ISA_MIPS3);
16487 check_mips_64(ctx);
16488 gen_arith(ctx, op1, rd, rs, rt);
16489 break;
16490 case OPC_DSLLV:
16491 case OPC_DSRAV:
16492 check_insn(ctx, ISA_MIPS3);
16493 check_mips_64(ctx);
16494 gen_shift(ctx, op1, rd, rs, rt);
16495 break;
16496 case OPC_DSRLV:
16497 switch ((ctx->opcode >> 6) & 0x1f) {
16498 case 1:
16499 /* drotrv is decoded as dsrlv on non-R2 CPUs */
16500 if (ctx->insn_flags & ISA_MIPS32R2) {
16501 op1 = OPC_DROTRV;
16503 /* Fallthrough */
16504 case 0:
16505 check_insn(ctx, ISA_MIPS3);
16506 check_mips_64(ctx);
16507 gen_shift(ctx, op1, rd, rs, rt);
16508 break;
16509 default:
16510 generate_exception(ctx, EXCP_RI);
16511 break;
16513 break;
16514 case OPC_DLSA:
16515 if ((ctx->insn_flags & ISA_MIPS32R6) ||
16516 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
16517 decode_opc_special_r6(env, ctx);
16519 break;
16520 #endif
16521 default:
16522 if (ctx->insn_flags & ISA_MIPS32R6) {
16523 decode_opc_special_r6(env, ctx);
16524 } else {
16525 decode_opc_special_legacy(env, ctx);
16530 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
16532 int rs, rt, rd;
16533 uint32_t op1;
16535 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16537 rs = (ctx->opcode >> 21) & 0x1f;
16538 rt = (ctx->opcode >> 16) & 0x1f;
16539 rd = (ctx->opcode >> 11) & 0x1f;
16541 op1 = MASK_SPECIAL2(ctx->opcode);
16542 switch (op1) {
16543 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
16544 case OPC_MSUB ... OPC_MSUBU:
16545 check_insn(ctx, ISA_MIPS32);
16546 gen_muldiv(ctx, op1, rd & 3, rs, rt);
16547 break;
16548 case OPC_MUL:
16549 gen_arith(ctx, op1, rd, rs, rt);
16550 break;
16551 case OPC_DIV_G_2F:
16552 case OPC_DIVU_G_2F:
16553 case OPC_MULT_G_2F:
16554 case OPC_MULTU_G_2F:
16555 case OPC_MOD_G_2F:
16556 case OPC_MODU_G_2F:
16557 check_insn(ctx, INSN_LOONGSON2F);
16558 gen_loongson_integer(ctx, op1, rd, rs, rt);
16559 break;
16560 case OPC_CLO:
16561 case OPC_CLZ:
16562 check_insn(ctx, ISA_MIPS32);
16563 gen_cl(ctx, op1, rd, rs);
16564 break;
16565 case OPC_SDBBP:
16566 /* XXX: not clear which exception should be raised
16567 * when in debug mode...
16569 check_insn(ctx, ISA_MIPS32);
16570 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
16571 generate_exception(ctx, EXCP_DBp);
16572 } else {
16573 generate_exception(ctx, EXCP_DBp);
16575 /* Treat as NOP. */
16576 break;
16577 #if defined(TARGET_MIPS64)
16578 case OPC_DCLO:
16579 case OPC_DCLZ:
16580 check_insn(ctx, ISA_MIPS64);
16581 check_mips_64(ctx);
16582 gen_cl(ctx, op1, rd, rs);
16583 break;
16584 case OPC_DMULT_G_2F:
16585 case OPC_DMULTU_G_2F:
16586 case OPC_DDIV_G_2F:
16587 case OPC_DDIVU_G_2F:
16588 case OPC_DMOD_G_2F:
16589 case OPC_DMODU_G_2F:
16590 check_insn(ctx, INSN_LOONGSON2F);
16591 gen_loongson_integer(ctx, op1, rd, rs, rt);
16592 break;
16593 #endif
16594 default: /* Invalid */
16595 MIPS_INVAL("special2_legacy");
16596 generate_exception(ctx, EXCP_RI);
16597 break;
16601 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
16603 int rs, rt, rd, sa;
16604 uint32_t op1, op2;
16605 int16_t imm;
16607 rs = (ctx->opcode >> 21) & 0x1f;
16608 rt = (ctx->opcode >> 16) & 0x1f;
16609 rd = (ctx->opcode >> 11) & 0x1f;
16610 sa = (ctx->opcode >> 6) & 0x1f;
16611 imm = (int16_t)ctx->opcode >> 7;
16613 op1 = MASK_SPECIAL3(ctx->opcode);
16614 switch (op1) {
16615 case R6_OPC_PREF:
16616 if (rt >= 24) {
16617 /* hint codes 24-31 are reserved and signal RI */
16618 generate_exception(ctx, EXCP_RI);
16620 /* Treat as NOP. */
16621 break;
16622 case R6_OPC_CACHE:
16623 /* Treat as NOP. */
16624 break;
16625 case R6_OPC_SC:
16626 gen_st_cond(ctx, op1, rt, rs, imm);
16627 break;
16628 case R6_OPC_LL:
16629 gen_ld(ctx, op1, rt, rs, imm);
16630 break;
16631 case OPC_BSHFL:
16633 if (rd == 0) {
16634 /* Treat as NOP. */
16635 break;
16637 TCGv t0 = tcg_temp_new();
16638 gen_load_gpr(t0, rt);
16640 op2 = MASK_BSHFL(ctx->opcode);
16641 switch (op2) {
16642 case OPC_ALIGN ... OPC_ALIGN_END:
16643 sa &= 3;
16644 if (sa == 0) {
16645 tcg_gen_mov_tl(cpu_gpr[rd], t0);
16646 } else {
16647 TCGv t1 = tcg_temp_new();
16648 TCGv_i64 t2 = tcg_temp_new_i64();
16649 gen_load_gpr(t1, rs);
16650 tcg_gen_concat_tl_i64(t2, t1, t0);
16651 tcg_gen_shri_i64(t2, t2, 8 * (4 - sa));
16652 #if defined(TARGET_MIPS64)
16653 tcg_gen_ext32s_i64(cpu_gpr[rd], t2);
16654 #else
16655 tcg_gen_trunc_i64_i32(cpu_gpr[rd], t2);
16656 #endif
16657 tcg_temp_free_i64(t2);
16658 tcg_temp_free(t1);
16660 break;
16661 case OPC_BITSWAP:
16662 gen_helper_bitswap(cpu_gpr[rd], t0);
16663 break;
16665 tcg_temp_free(t0);
16667 break;
16668 #if defined(TARGET_MIPS64)
16669 case R6_OPC_SCD:
16670 gen_st_cond(ctx, op1, rt, rs, imm);
16671 break;
16672 case R6_OPC_LLD:
16673 gen_ld(ctx, op1, rt, rs, imm);
16674 break;
16675 case OPC_DBSHFL:
16676 check_mips_64(ctx);
16678 if (rd == 0) {
16679 /* Treat as NOP. */
16680 break;
16682 TCGv t0 = tcg_temp_new();
16683 gen_load_gpr(t0, rt);
16685 op2 = MASK_DBSHFL(ctx->opcode);
16686 switch (op2) {
16687 case OPC_DALIGN ... OPC_DALIGN_END:
16688 sa &= 7;
16689 if (sa == 0) {
16690 tcg_gen_mov_tl(cpu_gpr[rd], t0);
16691 } else {
16692 TCGv t1 = tcg_temp_new();
16693 gen_load_gpr(t1, rs);
16694 tcg_gen_shli_tl(t0, t0, 8 * sa);
16695 tcg_gen_shri_tl(t1, t1, 8 * (8 - sa));
16696 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
16697 tcg_temp_free(t1);
16699 break;
16700 case OPC_DBITSWAP:
16701 gen_helper_dbitswap(cpu_gpr[rd], t0);
16702 break;
16704 tcg_temp_free(t0);
16706 break;
16707 #endif
16708 default: /* Invalid */
16709 MIPS_INVAL("special3_r6");
16710 generate_exception(ctx, EXCP_RI);
16711 break;
16715 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
16717 int rs, rt, rd;
16718 uint32_t op1, op2;
16720 rs = (ctx->opcode >> 21) & 0x1f;
16721 rt = (ctx->opcode >> 16) & 0x1f;
16722 rd = (ctx->opcode >> 11) & 0x1f;
16724 op1 = MASK_SPECIAL3(ctx->opcode);
16725 switch (op1) {
16726 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
16727 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
16728 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
16729 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
16730 * the same mask and op1. */
16731 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
16732 op2 = MASK_ADDUH_QB(ctx->opcode);
16733 switch (op2) {
16734 case OPC_ADDUH_QB:
16735 case OPC_ADDUH_R_QB:
16736 case OPC_ADDQH_PH:
16737 case OPC_ADDQH_R_PH:
16738 case OPC_ADDQH_W:
16739 case OPC_ADDQH_R_W:
16740 case OPC_SUBUH_QB:
16741 case OPC_SUBUH_R_QB:
16742 case OPC_SUBQH_PH:
16743 case OPC_SUBQH_R_PH:
16744 case OPC_SUBQH_W:
16745 case OPC_SUBQH_R_W:
16746 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16747 break;
16748 case OPC_MUL_PH:
16749 case OPC_MUL_S_PH:
16750 case OPC_MULQ_S_W:
16751 case OPC_MULQ_RS_W:
16752 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
16753 break;
16754 default:
16755 MIPS_INVAL("MASK ADDUH.QB");
16756 generate_exception(ctx, EXCP_RI);
16757 break;
16759 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
16760 gen_loongson_integer(ctx, op1, rd, rs, rt);
16761 } else {
16762 generate_exception(ctx, EXCP_RI);
16764 break;
16765 case OPC_LX_DSP:
16766 op2 = MASK_LX(ctx->opcode);
16767 switch (op2) {
16768 #if defined(TARGET_MIPS64)
16769 case OPC_LDX:
16770 #endif
16771 case OPC_LBUX:
16772 case OPC_LHX:
16773 case OPC_LWX:
16774 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
16775 break;
16776 default: /* Invalid */
16777 MIPS_INVAL("MASK LX");
16778 generate_exception(ctx, EXCP_RI);
16779 break;
16781 break;
16782 case OPC_ABSQ_S_PH_DSP:
16783 op2 = MASK_ABSQ_S_PH(ctx->opcode);
16784 switch (op2) {
16785 case OPC_ABSQ_S_QB:
16786 case OPC_ABSQ_S_PH:
16787 case OPC_ABSQ_S_W:
16788 case OPC_PRECEQ_W_PHL:
16789 case OPC_PRECEQ_W_PHR:
16790 case OPC_PRECEQU_PH_QBL:
16791 case OPC_PRECEQU_PH_QBR:
16792 case OPC_PRECEQU_PH_QBLA:
16793 case OPC_PRECEQU_PH_QBRA:
16794 case OPC_PRECEU_PH_QBL:
16795 case OPC_PRECEU_PH_QBR:
16796 case OPC_PRECEU_PH_QBLA:
16797 case OPC_PRECEU_PH_QBRA:
16798 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16799 break;
16800 case OPC_BITREV:
16801 case OPC_REPL_QB:
16802 case OPC_REPLV_QB:
16803 case OPC_REPL_PH:
16804 case OPC_REPLV_PH:
16805 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
16806 break;
16807 default:
16808 MIPS_INVAL("MASK ABSQ_S.PH");
16809 generate_exception(ctx, EXCP_RI);
16810 break;
16812 break;
16813 case OPC_ADDU_QB_DSP:
16814 op2 = MASK_ADDU_QB(ctx->opcode);
16815 switch (op2) {
16816 case OPC_ADDQ_PH:
16817 case OPC_ADDQ_S_PH:
16818 case OPC_ADDQ_S_W:
16819 case OPC_ADDU_QB:
16820 case OPC_ADDU_S_QB:
16821 case OPC_ADDU_PH:
16822 case OPC_ADDU_S_PH:
16823 case OPC_SUBQ_PH:
16824 case OPC_SUBQ_S_PH:
16825 case OPC_SUBQ_S_W:
16826 case OPC_SUBU_QB:
16827 case OPC_SUBU_S_QB:
16828 case OPC_SUBU_PH:
16829 case OPC_SUBU_S_PH:
16830 case OPC_ADDSC:
16831 case OPC_ADDWC:
16832 case OPC_MODSUB:
16833 case OPC_RADDU_W_QB:
16834 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16835 break;
16836 case OPC_MULEU_S_PH_QBL:
16837 case OPC_MULEU_S_PH_QBR:
16838 case OPC_MULQ_RS_PH:
16839 case OPC_MULEQ_S_W_PHL:
16840 case OPC_MULEQ_S_W_PHR:
16841 case OPC_MULQ_S_PH:
16842 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
16843 break;
16844 default: /* Invalid */
16845 MIPS_INVAL("MASK ADDU.QB");
16846 generate_exception(ctx, EXCP_RI);
16847 break;
16850 break;
16851 case OPC_CMPU_EQ_QB_DSP:
16852 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
16853 switch (op2) {
16854 case OPC_PRECR_SRA_PH_W:
16855 case OPC_PRECR_SRA_R_PH_W:
16856 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
16857 break;
16858 case OPC_PRECR_QB_PH:
16859 case OPC_PRECRQ_QB_PH:
16860 case OPC_PRECRQ_PH_W:
16861 case OPC_PRECRQ_RS_PH_W:
16862 case OPC_PRECRQU_S_QB_PH:
16863 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16864 break;
16865 case OPC_CMPU_EQ_QB:
16866 case OPC_CMPU_LT_QB:
16867 case OPC_CMPU_LE_QB:
16868 case OPC_CMP_EQ_PH:
16869 case OPC_CMP_LT_PH:
16870 case OPC_CMP_LE_PH:
16871 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
16872 break;
16873 case OPC_CMPGU_EQ_QB:
16874 case OPC_CMPGU_LT_QB:
16875 case OPC_CMPGU_LE_QB:
16876 case OPC_CMPGDU_EQ_QB:
16877 case OPC_CMPGDU_LT_QB:
16878 case OPC_CMPGDU_LE_QB:
16879 case OPC_PICK_QB:
16880 case OPC_PICK_PH:
16881 case OPC_PACKRL_PH:
16882 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
16883 break;
16884 default: /* Invalid */
16885 MIPS_INVAL("MASK CMPU.EQ.QB");
16886 generate_exception(ctx, EXCP_RI);
16887 break;
16889 break;
16890 case OPC_SHLL_QB_DSP:
16891 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
16892 break;
16893 case OPC_DPA_W_PH_DSP:
16894 op2 = MASK_DPA_W_PH(ctx->opcode);
16895 switch (op2) {
16896 case OPC_DPAU_H_QBL:
16897 case OPC_DPAU_H_QBR:
16898 case OPC_DPSU_H_QBL:
16899 case OPC_DPSU_H_QBR:
16900 case OPC_DPA_W_PH:
16901 case OPC_DPAX_W_PH:
16902 case OPC_DPAQ_S_W_PH:
16903 case OPC_DPAQX_S_W_PH:
16904 case OPC_DPAQX_SA_W_PH:
16905 case OPC_DPS_W_PH:
16906 case OPC_DPSX_W_PH:
16907 case OPC_DPSQ_S_W_PH:
16908 case OPC_DPSQX_S_W_PH:
16909 case OPC_DPSQX_SA_W_PH:
16910 case OPC_MULSAQ_S_W_PH:
16911 case OPC_DPAQ_SA_L_W:
16912 case OPC_DPSQ_SA_L_W:
16913 case OPC_MAQ_S_W_PHL:
16914 case OPC_MAQ_S_W_PHR:
16915 case OPC_MAQ_SA_W_PHL:
16916 case OPC_MAQ_SA_W_PHR:
16917 case OPC_MULSA_W_PH:
16918 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
16919 break;
16920 default: /* Invalid */
16921 MIPS_INVAL("MASK DPAW.PH");
16922 generate_exception(ctx, EXCP_RI);
16923 break;
16925 break;
16926 case OPC_INSV_DSP:
16927 op2 = MASK_INSV(ctx->opcode);
16928 switch (op2) {
16929 case OPC_INSV:
16930 check_dsp(ctx);
16932 TCGv t0, t1;
16934 if (rt == 0) {
16935 MIPS_DEBUG("NOP");
16936 break;
16939 t0 = tcg_temp_new();
16940 t1 = tcg_temp_new();
16942 gen_load_gpr(t0, rt);
16943 gen_load_gpr(t1, rs);
16945 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
16947 tcg_temp_free(t0);
16948 tcg_temp_free(t1);
16949 break;
16951 default: /* Invalid */
16952 MIPS_INVAL("MASK INSV");
16953 generate_exception(ctx, EXCP_RI);
16954 break;
16956 break;
16957 case OPC_APPEND_DSP:
16958 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
16959 break;
16960 case OPC_EXTR_W_DSP:
16961 op2 = MASK_EXTR_W(ctx->opcode);
16962 switch (op2) {
16963 case OPC_EXTR_W:
16964 case OPC_EXTR_R_W:
16965 case OPC_EXTR_RS_W:
16966 case OPC_EXTR_S_H:
16967 case OPC_EXTRV_S_H:
16968 case OPC_EXTRV_W:
16969 case OPC_EXTRV_R_W:
16970 case OPC_EXTRV_RS_W:
16971 case OPC_EXTP:
16972 case OPC_EXTPV:
16973 case OPC_EXTPDP:
16974 case OPC_EXTPDPV:
16975 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
16976 break;
16977 case OPC_RDDSP:
16978 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
16979 break;
16980 case OPC_SHILO:
16981 case OPC_SHILOV:
16982 case OPC_MTHLIP:
16983 case OPC_WRDSP:
16984 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
16985 break;
16986 default: /* Invalid */
16987 MIPS_INVAL("MASK EXTR.W");
16988 generate_exception(ctx, EXCP_RI);
16989 break;
16991 break;
16992 #if defined(TARGET_MIPS64)
16993 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
16994 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
16995 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
16996 check_insn(ctx, INSN_LOONGSON2E);
16997 gen_loongson_integer(ctx, op1, rd, rs, rt);
16998 break;
16999 case OPC_ABSQ_S_QH_DSP:
17000 op2 = MASK_ABSQ_S_QH(ctx->opcode);
17001 switch (op2) {
17002 case OPC_PRECEQ_L_PWL:
17003 case OPC_PRECEQ_L_PWR:
17004 case OPC_PRECEQ_PW_QHL:
17005 case OPC_PRECEQ_PW_QHR:
17006 case OPC_PRECEQ_PW_QHLA:
17007 case OPC_PRECEQ_PW_QHRA:
17008 case OPC_PRECEQU_QH_OBL:
17009 case OPC_PRECEQU_QH_OBR:
17010 case OPC_PRECEQU_QH_OBLA:
17011 case OPC_PRECEQU_QH_OBRA:
17012 case OPC_PRECEU_QH_OBL:
17013 case OPC_PRECEU_QH_OBR:
17014 case OPC_PRECEU_QH_OBLA:
17015 case OPC_PRECEU_QH_OBRA:
17016 case OPC_ABSQ_S_OB:
17017 case OPC_ABSQ_S_PW:
17018 case OPC_ABSQ_S_QH:
17019 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17020 break;
17021 case OPC_REPL_OB:
17022 case OPC_REPL_PW:
17023 case OPC_REPL_QH:
17024 case OPC_REPLV_OB:
17025 case OPC_REPLV_PW:
17026 case OPC_REPLV_QH:
17027 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17028 break;
17029 default: /* Invalid */
17030 MIPS_INVAL("MASK ABSQ_S.QH");
17031 generate_exception(ctx, EXCP_RI);
17032 break;
17034 break;
17035 case OPC_ADDU_OB_DSP:
17036 op2 = MASK_ADDU_OB(ctx->opcode);
17037 switch (op2) {
17038 case OPC_RADDU_L_OB:
17039 case OPC_SUBQ_PW:
17040 case OPC_SUBQ_S_PW:
17041 case OPC_SUBQ_QH:
17042 case OPC_SUBQ_S_QH:
17043 case OPC_SUBU_OB:
17044 case OPC_SUBU_S_OB:
17045 case OPC_SUBU_QH:
17046 case OPC_SUBU_S_QH:
17047 case OPC_SUBUH_OB:
17048 case OPC_SUBUH_R_OB:
17049 case OPC_ADDQ_PW:
17050 case OPC_ADDQ_S_PW:
17051 case OPC_ADDQ_QH:
17052 case OPC_ADDQ_S_QH:
17053 case OPC_ADDU_OB:
17054 case OPC_ADDU_S_OB:
17055 case OPC_ADDU_QH:
17056 case OPC_ADDU_S_QH:
17057 case OPC_ADDUH_OB:
17058 case OPC_ADDUH_R_OB:
17059 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17060 break;
17061 case OPC_MULEQ_S_PW_QHL:
17062 case OPC_MULEQ_S_PW_QHR:
17063 case OPC_MULEU_S_QH_OBL:
17064 case OPC_MULEU_S_QH_OBR:
17065 case OPC_MULQ_RS_QH:
17066 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17067 break;
17068 default: /* Invalid */
17069 MIPS_INVAL("MASK ADDU.OB");
17070 generate_exception(ctx, EXCP_RI);
17071 break;
17073 break;
17074 case OPC_CMPU_EQ_OB_DSP:
17075 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
17076 switch (op2) {
17077 case OPC_PRECR_SRA_QH_PW:
17078 case OPC_PRECR_SRA_R_QH_PW:
17079 /* Return value is rt. */
17080 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17081 break;
17082 case OPC_PRECR_OB_QH:
17083 case OPC_PRECRQ_OB_QH:
17084 case OPC_PRECRQ_PW_L:
17085 case OPC_PRECRQ_QH_PW:
17086 case OPC_PRECRQ_RS_QH_PW:
17087 case OPC_PRECRQU_S_OB_QH:
17088 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17089 break;
17090 case OPC_CMPU_EQ_OB:
17091 case OPC_CMPU_LT_OB:
17092 case OPC_CMPU_LE_OB:
17093 case OPC_CMP_EQ_QH:
17094 case OPC_CMP_LT_QH:
17095 case OPC_CMP_LE_QH:
17096 case OPC_CMP_EQ_PW:
17097 case OPC_CMP_LT_PW:
17098 case OPC_CMP_LE_PW:
17099 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17100 break;
17101 case OPC_CMPGDU_EQ_OB:
17102 case OPC_CMPGDU_LT_OB:
17103 case OPC_CMPGDU_LE_OB:
17104 case OPC_CMPGU_EQ_OB:
17105 case OPC_CMPGU_LT_OB:
17106 case OPC_CMPGU_LE_OB:
17107 case OPC_PACKRL_PW:
17108 case OPC_PICK_OB:
17109 case OPC_PICK_PW:
17110 case OPC_PICK_QH:
17111 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17112 break;
17113 default: /* Invalid */
17114 MIPS_INVAL("MASK CMPU_EQ.OB");
17115 generate_exception(ctx, EXCP_RI);
17116 break;
17118 break;
17119 case OPC_DAPPEND_DSP:
17120 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17121 break;
17122 case OPC_DEXTR_W_DSP:
17123 op2 = MASK_DEXTR_W(ctx->opcode);
17124 switch (op2) {
17125 case OPC_DEXTP:
17126 case OPC_DEXTPDP:
17127 case OPC_DEXTPDPV:
17128 case OPC_DEXTPV:
17129 case OPC_DEXTR_L:
17130 case OPC_DEXTR_R_L:
17131 case OPC_DEXTR_RS_L:
17132 case OPC_DEXTR_W:
17133 case OPC_DEXTR_R_W:
17134 case OPC_DEXTR_RS_W:
17135 case OPC_DEXTR_S_H:
17136 case OPC_DEXTRV_L:
17137 case OPC_DEXTRV_R_L:
17138 case OPC_DEXTRV_RS_L:
17139 case OPC_DEXTRV_S_H:
17140 case OPC_DEXTRV_W:
17141 case OPC_DEXTRV_R_W:
17142 case OPC_DEXTRV_RS_W:
17143 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17144 break;
17145 case OPC_DMTHLIP:
17146 case OPC_DSHILO:
17147 case OPC_DSHILOV:
17148 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17149 break;
17150 default: /* Invalid */
17151 MIPS_INVAL("MASK EXTR.W");
17152 generate_exception(ctx, EXCP_RI);
17153 break;
17155 break;
17156 case OPC_DPAQ_W_QH_DSP:
17157 op2 = MASK_DPAQ_W_QH(ctx->opcode);
17158 switch (op2) {
17159 case OPC_DPAU_H_OBL:
17160 case OPC_DPAU_H_OBR:
17161 case OPC_DPSU_H_OBL:
17162 case OPC_DPSU_H_OBR:
17163 case OPC_DPA_W_QH:
17164 case OPC_DPAQ_S_W_QH:
17165 case OPC_DPS_W_QH:
17166 case OPC_DPSQ_S_W_QH:
17167 case OPC_MULSAQ_S_W_QH:
17168 case OPC_DPAQ_SA_L_PW:
17169 case OPC_DPSQ_SA_L_PW:
17170 case OPC_MULSAQ_S_L_PW:
17171 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17172 break;
17173 case OPC_MAQ_S_W_QHLL:
17174 case OPC_MAQ_S_W_QHLR:
17175 case OPC_MAQ_S_W_QHRL:
17176 case OPC_MAQ_S_W_QHRR:
17177 case OPC_MAQ_SA_W_QHLL:
17178 case OPC_MAQ_SA_W_QHLR:
17179 case OPC_MAQ_SA_W_QHRL:
17180 case OPC_MAQ_SA_W_QHRR:
17181 case OPC_MAQ_S_L_PWL:
17182 case OPC_MAQ_S_L_PWR:
17183 case OPC_DMADD:
17184 case OPC_DMADDU:
17185 case OPC_DMSUB:
17186 case OPC_DMSUBU:
17187 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17188 break;
17189 default: /* Invalid */
17190 MIPS_INVAL("MASK DPAQ.W.QH");
17191 generate_exception(ctx, EXCP_RI);
17192 break;
17194 break;
17195 case OPC_DINSV_DSP:
17196 op2 = MASK_INSV(ctx->opcode);
17197 switch (op2) {
17198 case OPC_DINSV:
17200 TCGv t0, t1;
17202 if (rt == 0) {
17203 MIPS_DEBUG("NOP");
17204 break;
17206 check_dsp(ctx);
17208 t0 = tcg_temp_new();
17209 t1 = tcg_temp_new();
17211 gen_load_gpr(t0, rt);
17212 gen_load_gpr(t1, rs);
17214 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
17216 tcg_temp_free(t0);
17217 tcg_temp_free(t1);
17218 break;
17220 default: /* Invalid */
17221 MIPS_INVAL("MASK DINSV");
17222 generate_exception(ctx, EXCP_RI);
17223 break;
17225 break;
17226 case OPC_SHLL_OB_DSP:
17227 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17228 break;
17229 #endif
17230 default: /* Invalid */
17231 MIPS_INVAL("special3_legacy");
17232 generate_exception(ctx, EXCP_RI);
17233 break;
17237 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
17239 int rs, rt, rd, sa;
17240 uint32_t op1, op2;
17242 rs = (ctx->opcode >> 21) & 0x1f;
17243 rt = (ctx->opcode >> 16) & 0x1f;
17244 rd = (ctx->opcode >> 11) & 0x1f;
17245 sa = (ctx->opcode >> 6) & 0x1f;
17247 op1 = MASK_SPECIAL3(ctx->opcode);
17248 switch (op1) {
17249 case OPC_EXT:
17250 case OPC_INS:
17251 check_insn(ctx, ISA_MIPS32R2);
17252 gen_bitops(ctx, op1, rt, rs, sa, rd);
17253 break;
17254 case OPC_BSHFL:
17255 op2 = MASK_BSHFL(ctx->opcode);
17256 switch (op2) {
17257 case OPC_ALIGN ... OPC_ALIGN_END:
17258 case OPC_BITSWAP:
17259 check_insn(ctx, ISA_MIPS32R6);
17260 decode_opc_special3_r6(env, ctx);
17261 break;
17262 default:
17263 check_insn(ctx, ISA_MIPS32R2);
17264 gen_bshfl(ctx, op2, rt, rd);
17265 break;
17267 break;
17268 #if defined(TARGET_MIPS64)
17269 case OPC_DEXTM ... OPC_DEXT:
17270 case OPC_DINSM ... OPC_DINS:
17271 check_insn(ctx, ISA_MIPS64R2);
17272 check_mips_64(ctx);
17273 gen_bitops(ctx, op1, rt, rs, sa, rd);
17274 break;
17275 case OPC_DBSHFL:
17276 op2 = MASK_DBSHFL(ctx->opcode);
17277 switch (op2) {
17278 case OPC_DALIGN ... OPC_DALIGN_END:
17279 case OPC_DBITSWAP:
17280 check_insn(ctx, ISA_MIPS32R6);
17281 decode_opc_special3_r6(env, ctx);
17282 break;
17283 default:
17284 check_insn(ctx, ISA_MIPS64R2);
17285 check_mips_64(ctx);
17286 op2 = MASK_DBSHFL(ctx->opcode);
17287 gen_bshfl(ctx, op2, rt, rd);
17288 break;
17290 break;
17291 #endif
17292 case OPC_RDHWR:
17293 gen_rdhwr(ctx, rt, rd);
17294 break;
17295 case OPC_FORK:
17296 check_insn(ctx, ASE_MT);
17298 TCGv t0 = tcg_temp_new();
17299 TCGv t1 = tcg_temp_new();
17301 gen_load_gpr(t0, rt);
17302 gen_load_gpr(t1, rs);
17303 gen_helper_fork(t0, t1);
17304 tcg_temp_free(t0);
17305 tcg_temp_free(t1);
17307 break;
17308 case OPC_YIELD:
17309 check_insn(ctx, ASE_MT);
17311 TCGv t0 = tcg_temp_new();
17313 save_cpu_state(ctx, 1);
17314 gen_load_gpr(t0, rs);
17315 gen_helper_yield(t0, cpu_env, t0);
17316 gen_store_gpr(t0, rd);
17317 tcg_temp_free(t0);
17319 break;
17320 default:
17321 if (ctx->insn_flags & ISA_MIPS32R6) {
17322 decode_opc_special3_r6(env, ctx);
17323 } else {
17324 decode_opc_special3_legacy(env, ctx);
17329 /* MIPS SIMD Architecture (MSA) */
17330 static inline int check_msa_access(DisasContext *ctx)
17332 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
17333 !(ctx->hflags & MIPS_HFLAG_F64))) {
17334 generate_exception(ctx, EXCP_RI);
17335 return 0;
17338 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
17339 if (ctx->insn_flags & ASE_MSA) {
17340 generate_exception(ctx, EXCP_MSADIS);
17341 return 0;
17342 } else {
17343 generate_exception(ctx, EXCP_RI);
17344 return 0;
17347 return 1;
17350 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
17352 /* generates tcg ops to check if any element is 0 */
17353 /* Note this function only works with MSA_WRLEN = 128 */
17354 uint64_t eval_zero_or_big = 0;
17355 uint64_t eval_big = 0;
17356 TCGv_i64 t0 = tcg_temp_new_i64();
17357 TCGv_i64 t1 = tcg_temp_new_i64();
17358 switch (df) {
17359 case DF_BYTE:
17360 eval_zero_or_big = 0x0101010101010101ULL;
17361 eval_big = 0x8080808080808080ULL;
17362 break;
17363 case DF_HALF:
17364 eval_zero_or_big = 0x0001000100010001ULL;
17365 eval_big = 0x8000800080008000ULL;
17366 break;
17367 case DF_WORD:
17368 eval_zero_or_big = 0x0000000100000001ULL;
17369 eval_big = 0x8000000080000000ULL;
17370 break;
17371 case DF_DOUBLE:
17372 eval_zero_or_big = 0x0000000000000001ULL;
17373 eval_big = 0x8000000000000000ULL;
17374 break;
17376 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
17377 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
17378 tcg_gen_andi_i64(t0, t0, eval_big);
17379 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
17380 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
17381 tcg_gen_andi_i64(t1, t1, eval_big);
17382 tcg_gen_or_i64(t0, t0, t1);
17383 /* if all bits are zero then all elements are not zero */
17384 /* if some bit is non-zero then some element is zero */
17385 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
17386 tcg_gen_trunc_i64_tl(tresult, t0);
17387 tcg_temp_free_i64(t0);
17388 tcg_temp_free_i64(t1);
17391 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
17393 uint8_t df = (ctx->opcode >> 21) & 0x3;
17394 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
17395 int64_t s16 = (int16_t)ctx->opcode;
17397 check_msa_access(ctx);
17399 if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
17400 MIPS_DEBUG("CTI in delay / forbidden slot");
17401 generate_exception(ctx, EXCP_RI);
17402 return;
17404 switch (op1) {
17405 case OPC_BZ_V:
17406 case OPC_BNZ_V:
17408 TCGv_i64 t0 = tcg_temp_new_i64();
17409 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
17410 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
17411 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
17412 tcg_gen_trunc_i64_tl(bcond, t0);
17413 tcg_temp_free_i64(t0);
17415 break;
17416 case OPC_BZ_B:
17417 case OPC_BZ_H:
17418 case OPC_BZ_W:
17419 case OPC_BZ_D:
17420 gen_check_zero_element(bcond, df, wt);
17421 break;
17422 case OPC_BNZ_B:
17423 case OPC_BNZ_H:
17424 case OPC_BNZ_W:
17425 case OPC_BNZ_D:
17426 gen_check_zero_element(bcond, df, wt);
17427 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
17428 break;
17431 ctx->btarget = ctx->pc + (s16 << 2) + 4;
17433 ctx->hflags |= MIPS_HFLAG_BC;
17434 ctx->hflags |= MIPS_HFLAG_BDS32;
17437 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
17439 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
17440 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
17441 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17442 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17444 TCGv_i32 twd = tcg_const_i32(wd);
17445 TCGv_i32 tws = tcg_const_i32(ws);
17446 TCGv_i32 ti8 = tcg_const_i32(i8);
17448 switch (MASK_MSA_I8(ctx->opcode)) {
17449 case OPC_ANDI_B:
17450 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
17451 break;
17452 case OPC_ORI_B:
17453 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
17454 break;
17455 case OPC_NORI_B:
17456 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
17457 break;
17458 case OPC_XORI_B:
17459 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
17460 break;
17461 case OPC_BMNZI_B:
17462 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
17463 break;
17464 case OPC_BMZI_B:
17465 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
17466 break;
17467 case OPC_BSELI_B:
17468 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
17469 break;
17470 case OPC_SHF_B:
17471 case OPC_SHF_H:
17472 case OPC_SHF_W:
17474 uint8_t df = (ctx->opcode >> 24) & 0x3;
17475 if (df == DF_DOUBLE) {
17476 generate_exception(ctx, EXCP_RI);
17477 } else {
17478 TCGv_i32 tdf = tcg_const_i32(df);
17479 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
17480 tcg_temp_free_i32(tdf);
17483 break;
17484 default:
17485 MIPS_INVAL("MSA instruction");
17486 generate_exception(ctx, EXCP_RI);
17487 break;
17490 tcg_temp_free_i32(twd);
17491 tcg_temp_free_i32(tws);
17492 tcg_temp_free_i32(ti8);
17495 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
17497 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
17498 uint8_t df = (ctx->opcode >> 21) & 0x3;
17499 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
17500 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
17501 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17502 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17504 TCGv_i32 tdf = tcg_const_i32(df);
17505 TCGv_i32 twd = tcg_const_i32(wd);
17506 TCGv_i32 tws = tcg_const_i32(ws);
17507 TCGv_i32 timm = tcg_temp_new_i32();
17508 tcg_gen_movi_i32(timm, u5);
17510 switch (MASK_MSA_I5(ctx->opcode)) {
17511 case OPC_ADDVI_df:
17512 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
17513 break;
17514 case OPC_SUBVI_df:
17515 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
17516 break;
17517 case OPC_MAXI_S_df:
17518 tcg_gen_movi_i32(timm, s5);
17519 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
17520 break;
17521 case OPC_MAXI_U_df:
17522 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
17523 break;
17524 case OPC_MINI_S_df:
17525 tcg_gen_movi_i32(timm, s5);
17526 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
17527 break;
17528 case OPC_MINI_U_df:
17529 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
17530 break;
17531 case OPC_CEQI_df:
17532 tcg_gen_movi_i32(timm, s5);
17533 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
17534 break;
17535 case OPC_CLTI_S_df:
17536 tcg_gen_movi_i32(timm, s5);
17537 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
17538 break;
17539 case OPC_CLTI_U_df:
17540 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
17541 break;
17542 case OPC_CLEI_S_df:
17543 tcg_gen_movi_i32(timm, s5);
17544 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
17545 break;
17546 case OPC_CLEI_U_df:
17547 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
17548 break;
17549 case OPC_LDI_df:
17551 int32_t s10 = sextract32(ctx->opcode, 11, 10);
17552 tcg_gen_movi_i32(timm, s10);
17553 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
17555 break;
17556 default:
17557 MIPS_INVAL("MSA instruction");
17558 generate_exception(ctx, EXCP_RI);
17559 break;
17562 tcg_temp_free_i32(tdf);
17563 tcg_temp_free_i32(twd);
17564 tcg_temp_free_i32(tws);
17565 tcg_temp_free_i32(timm);
17568 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
17570 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
17571 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
17572 uint32_t df = 0, m = 0;
17573 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17574 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17576 TCGv_i32 tdf;
17577 TCGv_i32 tm;
17578 TCGv_i32 twd;
17579 TCGv_i32 tws;
17581 if ((dfm & 0x40) == 0x00) {
17582 m = dfm & 0x3f;
17583 df = DF_DOUBLE;
17584 } else if ((dfm & 0x60) == 0x40) {
17585 m = dfm & 0x1f;
17586 df = DF_WORD;
17587 } else if ((dfm & 0x70) == 0x60) {
17588 m = dfm & 0x0f;
17589 df = DF_HALF;
17590 } else if ((dfm & 0x78) == 0x70) {
17591 m = dfm & 0x7;
17592 df = DF_BYTE;
17593 } else {
17594 generate_exception(ctx, EXCP_RI);
17595 return;
17598 tdf = tcg_const_i32(df);
17599 tm = tcg_const_i32(m);
17600 twd = tcg_const_i32(wd);
17601 tws = tcg_const_i32(ws);
17603 switch (MASK_MSA_BIT(ctx->opcode)) {
17604 case OPC_SLLI_df:
17605 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
17606 break;
17607 case OPC_SRAI_df:
17608 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
17609 break;
17610 case OPC_SRLI_df:
17611 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
17612 break;
17613 case OPC_BCLRI_df:
17614 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
17615 break;
17616 case OPC_BSETI_df:
17617 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
17618 break;
17619 case OPC_BNEGI_df:
17620 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
17621 break;
17622 case OPC_BINSLI_df:
17623 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
17624 break;
17625 case OPC_BINSRI_df:
17626 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
17627 break;
17628 case OPC_SAT_S_df:
17629 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
17630 break;
17631 case OPC_SAT_U_df:
17632 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
17633 break;
17634 case OPC_SRARI_df:
17635 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
17636 break;
17637 case OPC_SRLRI_df:
17638 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
17639 break;
17640 default:
17641 MIPS_INVAL("MSA instruction");
17642 generate_exception(ctx, EXCP_RI);
17643 break;
17646 tcg_temp_free_i32(tdf);
17647 tcg_temp_free_i32(tm);
17648 tcg_temp_free_i32(twd);
17649 tcg_temp_free_i32(tws);
17652 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
17654 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
17655 uint8_t df = (ctx->opcode >> 21) & 0x3;
17656 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
17657 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17658 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17660 TCGv_i32 tdf = tcg_const_i32(df);
17661 TCGv_i32 twd = tcg_const_i32(wd);
17662 TCGv_i32 tws = tcg_const_i32(ws);
17663 TCGv_i32 twt = tcg_const_i32(wt);
17665 switch (MASK_MSA_3R(ctx->opcode)) {
17666 case OPC_SLL_df:
17667 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
17668 break;
17669 case OPC_ADDV_df:
17670 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
17671 break;
17672 case OPC_CEQ_df:
17673 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
17674 break;
17675 case OPC_ADD_A_df:
17676 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
17677 break;
17678 case OPC_SUBS_S_df:
17679 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
17680 break;
17681 case OPC_MULV_df:
17682 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
17683 break;
17684 case OPC_SLD_df:
17685 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
17686 break;
17687 case OPC_VSHF_df:
17688 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
17689 break;
17690 case OPC_SRA_df:
17691 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
17692 break;
17693 case OPC_SUBV_df:
17694 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
17695 break;
17696 case OPC_ADDS_A_df:
17697 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
17698 break;
17699 case OPC_SUBS_U_df:
17700 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
17701 break;
17702 case OPC_MADDV_df:
17703 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
17704 break;
17705 case OPC_SPLAT_df:
17706 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
17707 break;
17708 case OPC_SRAR_df:
17709 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
17710 break;
17711 case OPC_SRL_df:
17712 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
17713 break;
17714 case OPC_MAX_S_df:
17715 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
17716 break;
17717 case OPC_CLT_S_df:
17718 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
17719 break;
17720 case OPC_ADDS_S_df:
17721 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
17722 break;
17723 case OPC_SUBSUS_U_df:
17724 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
17725 break;
17726 case OPC_MSUBV_df:
17727 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
17728 break;
17729 case OPC_PCKEV_df:
17730 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
17731 break;
17732 case OPC_SRLR_df:
17733 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
17734 break;
17735 case OPC_BCLR_df:
17736 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
17737 break;
17738 case OPC_MAX_U_df:
17739 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
17740 break;
17741 case OPC_CLT_U_df:
17742 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
17743 break;
17744 case OPC_ADDS_U_df:
17745 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
17746 break;
17747 case OPC_SUBSUU_S_df:
17748 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
17749 break;
17750 case OPC_PCKOD_df:
17751 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
17752 break;
17753 case OPC_BSET_df:
17754 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
17755 break;
17756 case OPC_MIN_S_df:
17757 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
17758 break;
17759 case OPC_CLE_S_df:
17760 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
17761 break;
17762 case OPC_AVE_S_df:
17763 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
17764 break;
17765 case OPC_ASUB_S_df:
17766 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
17767 break;
17768 case OPC_DIV_S_df:
17769 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
17770 break;
17771 case OPC_ILVL_df:
17772 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
17773 break;
17774 case OPC_BNEG_df:
17775 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
17776 break;
17777 case OPC_MIN_U_df:
17778 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
17779 break;
17780 case OPC_CLE_U_df:
17781 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
17782 break;
17783 case OPC_AVE_U_df:
17784 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
17785 break;
17786 case OPC_ASUB_U_df:
17787 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
17788 break;
17789 case OPC_DIV_U_df:
17790 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
17791 break;
17792 case OPC_ILVR_df:
17793 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
17794 break;
17795 case OPC_BINSL_df:
17796 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
17797 break;
17798 case OPC_MAX_A_df:
17799 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
17800 break;
17801 case OPC_AVER_S_df:
17802 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
17803 break;
17804 case OPC_MOD_S_df:
17805 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
17806 break;
17807 case OPC_ILVEV_df:
17808 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
17809 break;
17810 case OPC_BINSR_df:
17811 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
17812 break;
17813 case OPC_MIN_A_df:
17814 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
17815 break;
17816 case OPC_AVER_U_df:
17817 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
17818 break;
17819 case OPC_MOD_U_df:
17820 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
17821 break;
17822 case OPC_ILVOD_df:
17823 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
17824 break;
17826 case OPC_DOTP_S_df:
17827 case OPC_DOTP_U_df:
17828 case OPC_DPADD_S_df:
17829 case OPC_DPADD_U_df:
17830 case OPC_DPSUB_S_df:
17831 case OPC_HADD_S_df:
17832 case OPC_DPSUB_U_df:
17833 case OPC_HADD_U_df:
17834 case OPC_HSUB_S_df:
17835 case OPC_HSUB_U_df:
17836 if (df == DF_BYTE) {
17837 generate_exception(ctx, EXCP_RI);
17839 switch (MASK_MSA_3R(ctx->opcode)) {
17840 case OPC_DOTP_S_df:
17841 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
17842 break;
17843 case OPC_DOTP_U_df:
17844 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
17845 break;
17846 case OPC_DPADD_S_df:
17847 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
17848 break;
17849 case OPC_DPADD_U_df:
17850 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
17851 break;
17852 case OPC_DPSUB_S_df:
17853 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
17854 break;
17855 case OPC_HADD_S_df:
17856 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
17857 break;
17858 case OPC_DPSUB_U_df:
17859 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
17860 break;
17861 case OPC_HADD_U_df:
17862 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
17863 break;
17864 case OPC_HSUB_S_df:
17865 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
17866 break;
17867 case OPC_HSUB_U_df:
17868 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
17869 break;
17871 break;
17872 default:
17873 MIPS_INVAL("MSA instruction");
17874 generate_exception(ctx, EXCP_RI);
17875 break;
17877 tcg_temp_free_i32(twd);
17878 tcg_temp_free_i32(tws);
17879 tcg_temp_free_i32(twt);
17880 tcg_temp_free_i32(tdf);
17883 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
17885 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
17886 uint8_t source = (ctx->opcode >> 11) & 0x1f;
17887 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
17888 TCGv telm = tcg_temp_new();
17889 TCGv_i32 tsr = tcg_const_i32(source);
17890 TCGv_i32 tdt = tcg_const_i32(dest);
17892 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
17893 case OPC_CTCMSA:
17894 gen_load_gpr(telm, source);
17895 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
17896 break;
17897 case OPC_CFCMSA:
17898 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
17899 gen_store_gpr(telm, dest);
17900 break;
17901 case OPC_MOVE_V:
17902 gen_helper_msa_move_v(cpu_env, tdt, tsr);
17903 break;
17904 default:
17905 MIPS_INVAL("MSA instruction");
17906 generate_exception(ctx, EXCP_RI);
17907 break;
17910 tcg_temp_free(telm);
17911 tcg_temp_free_i32(tdt);
17912 tcg_temp_free_i32(tsr);
17915 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
17916 uint32_t n)
17918 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
17919 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17920 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17922 TCGv_i32 tws = tcg_const_i32(ws);
17923 TCGv_i32 twd = tcg_const_i32(wd);
17924 TCGv_i32 tn = tcg_const_i32(n);
17925 TCGv_i32 tdf = tcg_const_i32(df);
17927 switch (MASK_MSA_ELM(ctx->opcode)) {
17928 case OPC_SLDI_df:
17929 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
17930 break;
17931 case OPC_SPLATI_df:
17932 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
17933 break;
17934 case OPC_INSVE_df:
17935 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
17936 break;
17937 case OPC_COPY_S_df:
17938 case OPC_COPY_U_df:
17939 case OPC_INSERT_df:
17940 #if !defined(TARGET_MIPS64)
17941 /* Double format valid only for MIPS64 */
17942 if (df == DF_DOUBLE) {
17943 generate_exception(ctx, EXCP_RI);
17944 break;
17946 #endif
17947 switch (MASK_MSA_ELM(ctx->opcode)) {
17948 case OPC_COPY_S_df:
17949 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
17950 break;
17951 case OPC_COPY_U_df:
17952 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
17953 break;
17954 case OPC_INSERT_df:
17955 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
17956 break;
17958 break;
17959 default:
17960 MIPS_INVAL("MSA instruction");
17961 generate_exception(ctx, EXCP_RI);
17963 tcg_temp_free_i32(twd);
17964 tcg_temp_free_i32(tws);
17965 tcg_temp_free_i32(tn);
17966 tcg_temp_free_i32(tdf);
17969 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
17971 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
17972 uint32_t df = 0, n = 0;
17974 if ((dfn & 0x30) == 0x00) {
17975 n = dfn & 0x0f;
17976 df = DF_BYTE;
17977 } else if ((dfn & 0x38) == 0x20) {
17978 n = dfn & 0x07;
17979 df = DF_HALF;
17980 } else if ((dfn & 0x3c) == 0x30) {
17981 n = dfn & 0x03;
17982 df = DF_WORD;
17983 } else if ((dfn & 0x3e) == 0x38) {
17984 n = dfn & 0x01;
17985 df = DF_DOUBLE;
17986 } else if (dfn == 0x3E) {
17987 /* CTCMSA, CFCMSA, MOVE.V */
17988 gen_msa_elm_3e(env, ctx);
17989 return;
17990 } else {
17991 generate_exception(ctx, EXCP_RI);
17992 return;
17995 gen_msa_elm_df(env, ctx, df, n);
17998 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
18000 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18001 uint8_t df = (ctx->opcode >> 21) & 0x1;
18002 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18003 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18004 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18006 TCGv_i32 twd = tcg_const_i32(wd);
18007 TCGv_i32 tws = tcg_const_i32(ws);
18008 TCGv_i32 twt = tcg_const_i32(wt);
18009 TCGv_i32 tdf = tcg_temp_new_i32();
18011 /* adjust df value for floating-point instruction */
18012 tcg_gen_movi_i32(tdf, df + 2);
18014 switch (MASK_MSA_3RF(ctx->opcode)) {
18015 case OPC_FCAF_df:
18016 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
18017 break;
18018 case OPC_FADD_df:
18019 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
18020 break;
18021 case OPC_FCUN_df:
18022 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
18023 break;
18024 case OPC_FSUB_df:
18025 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
18026 break;
18027 case OPC_FCOR_df:
18028 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
18029 break;
18030 case OPC_FCEQ_df:
18031 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
18032 break;
18033 case OPC_FMUL_df:
18034 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
18035 break;
18036 case OPC_FCUNE_df:
18037 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
18038 break;
18039 case OPC_FCUEQ_df:
18040 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
18041 break;
18042 case OPC_FDIV_df:
18043 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
18044 break;
18045 case OPC_FCNE_df:
18046 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
18047 break;
18048 case OPC_FCLT_df:
18049 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
18050 break;
18051 case OPC_FMADD_df:
18052 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
18053 break;
18054 case OPC_MUL_Q_df:
18055 tcg_gen_movi_i32(tdf, df + 1);
18056 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
18057 break;
18058 case OPC_FCULT_df:
18059 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
18060 break;
18061 case OPC_FMSUB_df:
18062 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
18063 break;
18064 case OPC_MADD_Q_df:
18065 tcg_gen_movi_i32(tdf, df + 1);
18066 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
18067 break;
18068 case OPC_FCLE_df:
18069 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
18070 break;
18071 case OPC_MSUB_Q_df:
18072 tcg_gen_movi_i32(tdf, df + 1);
18073 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
18074 break;
18075 case OPC_FCULE_df:
18076 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
18077 break;
18078 case OPC_FEXP2_df:
18079 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
18080 break;
18081 case OPC_FSAF_df:
18082 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
18083 break;
18084 case OPC_FEXDO_df:
18085 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
18086 break;
18087 case OPC_FSUN_df:
18088 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
18089 break;
18090 case OPC_FSOR_df:
18091 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
18092 break;
18093 case OPC_FSEQ_df:
18094 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
18095 break;
18096 case OPC_FTQ_df:
18097 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
18098 break;
18099 case OPC_FSUNE_df:
18100 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
18101 break;
18102 case OPC_FSUEQ_df:
18103 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
18104 break;
18105 case OPC_FSNE_df:
18106 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
18107 break;
18108 case OPC_FSLT_df:
18109 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
18110 break;
18111 case OPC_FMIN_df:
18112 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
18113 break;
18114 case OPC_MULR_Q_df:
18115 tcg_gen_movi_i32(tdf, df + 1);
18116 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
18117 break;
18118 case OPC_FSULT_df:
18119 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
18120 break;
18121 case OPC_FMIN_A_df:
18122 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
18123 break;
18124 case OPC_MADDR_Q_df:
18125 tcg_gen_movi_i32(tdf, df + 1);
18126 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
18127 break;
18128 case OPC_FSLE_df:
18129 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
18130 break;
18131 case OPC_FMAX_df:
18132 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
18133 break;
18134 case OPC_MSUBR_Q_df:
18135 tcg_gen_movi_i32(tdf, df + 1);
18136 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
18137 break;
18138 case OPC_FSULE_df:
18139 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
18140 break;
18141 case OPC_FMAX_A_df:
18142 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
18143 break;
18144 default:
18145 MIPS_INVAL("MSA instruction");
18146 generate_exception(ctx, EXCP_RI);
18147 break;
18150 tcg_temp_free_i32(twd);
18151 tcg_temp_free_i32(tws);
18152 tcg_temp_free_i32(twt);
18153 tcg_temp_free_i32(tdf);
18156 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
18158 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18159 (op & (0x7 << 18)))
18160 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18161 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18162 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18163 uint8_t df = (ctx->opcode >> 16) & 0x3;
18164 TCGv_i32 twd = tcg_const_i32(wd);
18165 TCGv_i32 tws = tcg_const_i32(ws);
18166 TCGv_i32 twt = tcg_const_i32(wt);
18167 TCGv_i32 tdf = tcg_const_i32(df);
18169 switch (MASK_MSA_2R(ctx->opcode)) {
18170 case OPC_FILL_df:
18171 #if !defined(TARGET_MIPS64)
18172 /* Double format valid only for MIPS64 */
18173 if (df == DF_DOUBLE) {
18174 generate_exception(ctx, EXCP_RI);
18175 break;
18177 #endif
18178 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
18179 break;
18180 case OPC_PCNT_df:
18181 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
18182 break;
18183 case OPC_NLOC_df:
18184 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
18185 break;
18186 case OPC_NLZC_df:
18187 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
18188 break;
18189 default:
18190 MIPS_INVAL("MSA instruction");
18191 generate_exception(ctx, EXCP_RI);
18192 break;
18195 tcg_temp_free_i32(twd);
18196 tcg_temp_free_i32(tws);
18197 tcg_temp_free_i32(twt);
18198 tcg_temp_free_i32(tdf);
18201 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
18203 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18204 (op & (0xf << 17)))
18205 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18206 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18207 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18208 uint8_t df = (ctx->opcode >> 16) & 0x1;
18209 TCGv_i32 twd = tcg_const_i32(wd);
18210 TCGv_i32 tws = tcg_const_i32(ws);
18211 TCGv_i32 twt = tcg_const_i32(wt);
18212 /* adjust df value for floating-point instruction */
18213 TCGv_i32 tdf = tcg_const_i32(df + 2);
18215 switch (MASK_MSA_2RF(ctx->opcode)) {
18216 case OPC_FCLASS_df:
18217 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
18218 break;
18219 case OPC_FTRUNC_S_df:
18220 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
18221 break;
18222 case OPC_FTRUNC_U_df:
18223 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
18224 break;
18225 case OPC_FSQRT_df:
18226 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
18227 break;
18228 case OPC_FRSQRT_df:
18229 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
18230 break;
18231 case OPC_FRCP_df:
18232 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
18233 break;
18234 case OPC_FRINT_df:
18235 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
18236 break;
18237 case OPC_FLOG2_df:
18238 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
18239 break;
18240 case OPC_FEXUPL_df:
18241 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
18242 break;
18243 case OPC_FEXUPR_df:
18244 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
18245 break;
18246 case OPC_FFQL_df:
18247 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
18248 break;
18249 case OPC_FFQR_df:
18250 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
18251 break;
18252 case OPC_FTINT_S_df:
18253 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
18254 break;
18255 case OPC_FTINT_U_df:
18256 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
18257 break;
18258 case OPC_FFINT_S_df:
18259 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
18260 break;
18261 case OPC_FFINT_U_df:
18262 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
18263 break;
18266 tcg_temp_free_i32(twd);
18267 tcg_temp_free_i32(tws);
18268 tcg_temp_free_i32(twt);
18269 tcg_temp_free_i32(tdf);
18272 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
18274 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
18275 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18276 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18277 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18278 TCGv_i32 twd = tcg_const_i32(wd);
18279 TCGv_i32 tws = tcg_const_i32(ws);
18280 TCGv_i32 twt = tcg_const_i32(wt);
18282 switch (MASK_MSA_VEC(ctx->opcode)) {
18283 case OPC_AND_V:
18284 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
18285 break;
18286 case OPC_OR_V:
18287 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
18288 break;
18289 case OPC_NOR_V:
18290 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
18291 break;
18292 case OPC_XOR_V:
18293 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
18294 break;
18295 case OPC_BMNZ_V:
18296 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
18297 break;
18298 case OPC_BMZ_V:
18299 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
18300 break;
18301 case OPC_BSEL_V:
18302 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
18303 break;
18304 default:
18305 MIPS_INVAL("MSA instruction");
18306 generate_exception(ctx, EXCP_RI);
18307 break;
18310 tcg_temp_free_i32(twd);
18311 tcg_temp_free_i32(tws);
18312 tcg_temp_free_i32(twt);
18315 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
18317 switch (MASK_MSA_VEC(ctx->opcode)) {
18318 case OPC_AND_V:
18319 case OPC_OR_V:
18320 case OPC_NOR_V:
18321 case OPC_XOR_V:
18322 case OPC_BMNZ_V:
18323 case OPC_BMZ_V:
18324 case OPC_BSEL_V:
18325 gen_msa_vec_v(env, ctx);
18326 break;
18327 case OPC_MSA_2R:
18328 gen_msa_2r(env, ctx);
18329 break;
18330 case OPC_MSA_2RF:
18331 gen_msa_2rf(env, ctx);
18332 break;
18333 default:
18334 MIPS_INVAL("MSA instruction");
18335 generate_exception(ctx, EXCP_RI);
18336 break;
18340 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
18342 uint32_t opcode = ctx->opcode;
18343 check_insn(ctx, ASE_MSA);
18344 check_msa_access(ctx);
18346 switch (MASK_MSA_MINOR(opcode)) {
18347 case OPC_MSA_I8_00:
18348 case OPC_MSA_I8_01:
18349 case OPC_MSA_I8_02:
18350 gen_msa_i8(env, ctx);
18351 break;
18352 case OPC_MSA_I5_06:
18353 case OPC_MSA_I5_07:
18354 gen_msa_i5(env, ctx);
18355 break;
18356 case OPC_MSA_BIT_09:
18357 case OPC_MSA_BIT_0A:
18358 gen_msa_bit(env, ctx);
18359 break;
18360 case OPC_MSA_3R_0D:
18361 case OPC_MSA_3R_0E:
18362 case OPC_MSA_3R_0F:
18363 case OPC_MSA_3R_10:
18364 case OPC_MSA_3R_11:
18365 case OPC_MSA_3R_12:
18366 case OPC_MSA_3R_13:
18367 case OPC_MSA_3R_14:
18368 case OPC_MSA_3R_15:
18369 gen_msa_3r(env, ctx);
18370 break;
18371 case OPC_MSA_ELM:
18372 gen_msa_elm(env, ctx);
18373 break;
18374 case OPC_MSA_3RF_1A:
18375 case OPC_MSA_3RF_1B:
18376 case OPC_MSA_3RF_1C:
18377 gen_msa_3rf(env, ctx);
18378 break;
18379 case OPC_MSA_VEC:
18380 gen_msa_vec(env, ctx);
18381 break;
18382 case OPC_LD_B:
18383 case OPC_LD_H:
18384 case OPC_LD_W:
18385 case OPC_LD_D:
18386 case OPC_ST_B:
18387 case OPC_ST_H:
18388 case OPC_ST_W:
18389 case OPC_ST_D:
18391 int32_t s10 = sextract32(ctx->opcode, 16, 10);
18392 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
18393 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18394 uint8_t df = (ctx->opcode >> 0) & 0x3;
18396 TCGv_i32 tdf = tcg_const_i32(df);
18397 TCGv_i32 twd = tcg_const_i32(wd);
18398 TCGv_i32 trs = tcg_const_i32(rs);
18399 TCGv_i32 ts10 = tcg_const_i32(s10);
18401 switch (MASK_MSA_MINOR(opcode)) {
18402 case OPC_LD_B:
18403 case OPC_LD_H:
18404 case OPC_LD_W:
18405 case OPC_LD_D:
18406 gen_helper_msa_ld_df(cpu_env, tdf, twd, trs, ts10);
18407 break;
18408 case OPC_ST_B:
18409 case OPC_ST_H:
18410 case OPC_ST_W:
18411 case OPC_ST_D:
18412 gen_helper_msa_st_df(cpu_env, tdf, twd, trs, ts10);
18413 break;
18416 tcg_temp_free_i32(twd);
18417 tcg_temp_free_i32(tdf);
18418 tcg_temp_free_i32(trs);
18419 tcg_temp_free_i32(ts10);
18421 break;
18422 default:
18423 MIPS_INVAL("MSA instruction");
18424 generate_exception(ctx, EXCP_RI);
18425 break;
18430 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
18432 int32_t offset;
18433 int rs, rt, rd, sa;
18434 uint32_t op, op1;
18435 int16_t imm;
18437 /* make sure instructions are on a word boundary */
18438 if (ctx->pc & 0x3) {
18439 env->CP0_BadVAddr = ctx->pc;
18440 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
18441 return;
18444 /* Handle blikely not taken case */
18445 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
18446 int l1 = gen_new_label();
18448 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
18449 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
18450 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
18451 gen_goto_tb(ctx, 1, ctx->pc + 4);
18452 gen_set_label(l1);
18455 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
18456 tcg_gen_debug_insn_start(ctx->pc);
18459 op = MASK_OP_MAJOR(ctx->opcode);
18460 rs = (ctx->opcode >> 21) & 0x1f;
18461 rt = (ctx->opcode >> 16) & 0x1f;
18462 rd = (ctx->opcode >> 11) & 0x1f;
18463 sa = (ctx->opcode >> 6) & 0x1f;
18464 imm = (int16_t)ctx->opcode;
18465 switch (op) {
18466 case OPC_SPECIAL:
18467 decode_opc_special(env, ctx);
18468 break;
18469 case OPC_SPECIAL2:
18470 decode_opc_special2_legacy(env, ctx);
18471 break;
18472 case OPC_SPECIAL3:
18473 decode_opc_special3(env, ctx);
18474 break;
18475 case OPC_REGIMM:
18476 op1 = MASK_REGIMM(ctx->opcode);
18477 switch (op1) {
18478 case OPC_BLTZL: /* REGIMM branches */
18479 case OPC_BGEZL:
18480 case OPC_BLTZALL:
18481 case OPC_BGEZALL:
18482 check_insn(ctx, ISA_MIPS2);
18483 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18484 /* Fallthrough */
18485 case OPC_BLTZ:
18486 case OPC_BGEZ:
18487 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
18488 break;
18489 case OPC_BLTZAL:
18490 case OPC_BGEZAL:
18491 if (ctx->insn_flags & ISA_MIPS32R6) {
18492 if (rs == 0) {
18493 /* OPC_NAL, OPC_BAL */
18494 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
18495 } else {
18496 generate_exception(ctx, EXCP_RI);
18498 } else {
18499 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
18501 break;
18502 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
18503 case OPC_TNEI:
18504 check_insn(ctx, ISA_MIPS2);
18505 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18506 gen_trap(ctx, op1, rs, -1, imm);
18507 break;
18508 case OPC_SYNCI:
18509 check_insn(ctx, ISA_MIPS32R2);
18510 /* Break the TB to be able to sync copied instructions
18511 immediately */
18512 ctx->bstate = BS_STOP;
18513 break;
18514 case OPC_BPOSGE32: /* MIPS DSP branch */
18515 #if defined(TARGET_MIPS64)
18516 case OPC_BPOSGE64:
18517 #endif
18518 check_dsp(ctx);
18519 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
18520 break;
18521 #if defined(TARGET_MIPS64)
18522 case OPC_DAHI:
18523 check_insn(ctx, ISA_MIPS32R6);
18524 check_mips_64(ctx);
18525 if (rs != 0) {
18526 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
18528 MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm);
18529 break;
18530 case OPC_DATI:
18531 check_insn(ctx, ISA_MIPS32R6);
18532 check_mips_64(ctx);
18533 if (rs != 0) {
18534 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
18536 MIPS_DEBUG("dati %s, %04x", regnames[rs], imm);
18537 break;
18538 #endif
18539 default: /* Invalid */
18540 MIPS_INVAL("regimm");
18541 generate_exception(ctx, EXCP_RI);
18542 break;
18544 break;
18545 case OPC_CP0:
18546 check_cp0_enabled(ctx);
18547 op1 = MASK_CP0(ctx->opcode);
18548 switch (op1) {
18549 case OPC_MFC0:
18550 case OPC_MTC0:
18551 case OPC_MFTR:
18552 case OPC_MTTR:
18553 #if defined(TARGET_MIPS64)
18554 case OPC_DMFC0:
18555 case OPC_DMTC0:
18556 #endif
18557 #ifndef CONFIG_USER_ONLY
18558 gen_cp0(env, ctx, op1, rt, rd);
18559 #endif /* !CONFIG_USER_ONLY */
18560 break;
18561 case OPC_C0_FIRST ... OPC_C0_LAST:
18562 #ifndef CONFIG_USER_ONLY
18563 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
18564 #endif /* !CONFIG_USER_ONLY */
18565 break;
18566 case OPC_MFMC0:
18567 #ifndef CONFIG_USER_ONLY
18569 uint32_t op2;
18570 TCGv t0 = tcg_temp_new();
18572 op2 = MASK_MFMC0(ctx->opcode);
18573 switch (op2) {
18574 case OPC_DMT:
18575 check_insn(ctx, ASE_MT);
18576 gen_helper_dmt(t0);
18577 gen_store_gpr(t0, rt);
18578 break;
18579 case OPC_EMT:
18580 check_insn(ctx, ASE_MT);
18581 gen_helper_emt(t0);
18582 gen_store_gpr(t0, rt);
18583 break;
18584 case OPC_DVPE:
18585 check_insn(ctx, ASE_MT);
18586 gen_helper_dvpe(t0, cpu_env);
18587 gen_store_gpr(t0, rt);
18588 break;
18589 case OPC_EVPE:
18590 check_insn(ctx, ASE_MT);
18591 gen_helper_evpe(t0, cpu_env);
18592 gen_store_gpr(t0, rt);
18593 break;
18594 case OPC_DI:
18595 check_insn(ctx, ISA_MIPS32R2);
18596 save_cpu_state(ctx, 1);
18597 gen_helper_di(t0, cpu_env);
18598 gen_store_gpr(t0, rt);
18599 /* Stop translation as we may have switched
18600 the execution mode. */
18601 ctx->bstate = BS_STOP;
18602 break;
18603 case OPC_EI:
18604 check_insn(ctx, ISA_MIPS32R2);
18605 save_cpu_state(ctx, 1);
18606 gen_helper_ei(t0, cpu_env);
18607 gen_store_gpr(t0, rt);
18608 /* Stop translation as we may have switched
18609 the execution mode. */
18610 ctx->bstate = BS_STOP;
18611 break;
18612 default: /* Invalid */
18613 MIPS_INVAL("mfmc0");
18614 generate_exception(ctx, EXCP_RI);
18615 break;
18617 tcg_temp_free(t0);
18619 #endif /* !CONFIG_USER_ONLY */
18620 break;
18621 case OPC_RDPGPR:
18622 check_insn(ctx, ISA_MIPS32R2);
18623 gen_load_srsgpr(rt, rd);
18624 break;
18625 case OPC_WRPGPR:
18626 check_insn(ctx, ISA_MIPS32R2);
18627 gen_store_srsgpr(rt, rd);
18628 break;
18629 default:
18630 MIPS_INVAL("cp0");
18631 generate_exception(ctx, EXCP_RI);
18632 break;
18634 break;
18635 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
18636 if (ctx->insn_flags & ISA_MIPS32R6) {
18637 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
18638 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18639 } else {
18640 /* OPC_ADDI */
18641 /* Arithmetic with immediate opcode */
18642 gen_arith_imm(ctx, op, rt, rs, imm);
18644 break;
18645 case OPC_ADDIU:
18646 gen_arith_imm(ctx, op, rt, rs, imm);
18647 break;
18648 case OPC_SLTI: /* Set on less than with immediate opcode */
18649 case OPC_SLTIU:
18650 gen_slt_imm(ctx, op, rt, rs, imm);
18651 break;
18652 case OPC_ANDI: /* Arithmetic with immediate opcode */
18653 case OPC_LUI: /* OPC_AUI */
18654 case OPC_ORI:
18655 case OPC_XORI:
18656 gen_logic_imm(ctx, op, rt, rs, imm);
18657 break;
18658 case OPC_J ... OPC_JAL: /* Jump */
18659 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
18660 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
18661 break;
18662 /* Branch */
18663 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
18664 if (ctx->insn_flags & ISA_MIPS32R6) {
18665 if (rt == 0) {
18666 generate_exception(ctx, EXCP_RI);
18667 break;
18669 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
18670 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18671 } else {
18672 /* OPC_BLEZL */
18673 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18675 break;
18676 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
18677 if (ctx->insn_flags & ISA_MIPS32R6) {
18678 if (rt == 0) {
18679 generate_exception(ctx, EXCP_RI);
18680 break;
18682 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
18683 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18684 } else {
18685 /* OPC_BGTZL */
18686 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18688 break;
18689 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
18690 if (rt == 0) {
18691 /* OPC_BLEZ */
18692 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18693 } else {
18694 check_insn(ctx, ISA_MIPS32R6);
18695 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
18696 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18698 break;
18699 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
18700 if (rt == 0) {
18701 /* OPC_BGTZ */
18702 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18703 } else {
18704 check_insn(ctx, ISA_MIPS32R6);
18705 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
18706 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18708 break;
18709 case OPC_BEQL:
18710 case OPC_BNEL:
18711 check_insn(ctx, ISA_MIPS2);
18712 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18713 /* Fallthrough */
18714 case OPC_BEQ:
18715 case OPC_BNE:
18716 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18717 break;
18718 case OPC_LL: /* Load and stores */
18719 check_insn(ctx, ISA_MIPS2);
18720 /* Fallthrough */
18721 case OPC_LWL:
18722 case OPC_LWR:
18723 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18724 /* Fallthrough */
18725 case OPC_LB ... OPC_LH:
18726 case OPC_LW ... OPC_LHU:
18727 gen_ld(ctx, op, rt, rs, imm);
18728 break;
18729 case OPC_SWL:
18730 case OPC_SWR:
18731 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18732 /* fall through */
18733 case OPC_SB ... OPC_SH:
18734 case OPC_SW:
18735 gen_st(ctx, op, rt, rs, imm);
18736 break;
18737 case OPC_SC:
18738 check_insn(ctx, ISA_MIPS2);
18739 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18740 gen_st_cond(ctx, op, rt, rs, imm);
18741 break;
18742 case OPC_CACHE:
18743 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18744 check_cp0_enabled(ctx);
18745 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
18746 /* Treat as NOP. */
18747 break;
18748 case OPC_PREF:
18749 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18750 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
18751 /* Treat as NOP. */
18752 break;
18754 /* Floating point (COP1). */
18755 case OPC_LWC1:
18756 case OPC_LDC1:
18757 case OPC_SWC1:
18758 case OPC_SDC1:
18759 gen_cop1_ldst(ctx, op, rt, rs, imm);
18760 break;
18762 case OPC_CP1:
18763 op1 = MASK_CP1(ctx->opcode);
18765 switch (op1) {
18766 case OPC_MFHC1:
18767 case OPC_MTHC1:
18768 check_cp1_enabled(ctx);
18769 check_insn(ctx, ISA_MIPS32R2);
18770 case OPC_MFC1:
18771 case OPC_CFC1:
18772 case OPC_MTC1:
18773 case OPC_CTC1:
18774 check_cp1_enabled(ctx);
18775 gen_cp1(ctx, op1, rt, rd);
18776 break;
18777 #if defined(TARGET_MIPS64)
18778 case OPC_DMFC1:
18779 case OPC_DMTC1:
18780 check_cp1_enabled(ctx);
18781 check_insn(ctx, ISA_MIPS3);
18782 check_mips_64(ctx);
18783 gen_cp1(ctx, op1, rt, rd);
18784 break;
18785 #endif
18786 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
18787 check_cp1_enabled(ctx);
18788 if (ctx->insn_flags & ISA_MIPS32R6) {
18789 /* OPC_BC1EQZ */
18790 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
18791 rt, imm << 2);
18792 } else {
18793 /* OPC_BC1ANY2 */
18794 check_cop1x(ctx);
18795 check_insn(ctx, ASE_MIPS3D);
18796 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
18797 (rt >> 2) & 0x7, imm << 2);
18799 break;
18800 case OPC_BC1NEZ:
18801 check_cp1_enabled(ctx);
18802 check_insn(ctx, ISA_MIPS32R6);
18803 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
18804 rt, imm << 2);
18805 break;
18806 case OPC_BC1ANY4:
18807 check_cp1_enabled(ctx);
18808 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18809 check_cop1x(ctx);
18810 check_insn(ctx, ASE_MIPS3D);
18811 /* fall through */
18812 case OPC_BC1:
18813 check_cp1_enabled(ctx);
18814 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18815 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
18816 (rt >> 2) & 0x7, imm << 2);
18817 break;
18818 case OPC_PS_FMT:
18819 check_cp1_enabled(ctx);
18820 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18821 /* fall through */
18822 case OPC_S_FMT:
18823 case OPC_D_FMT:
18824 check_cp1_enabled(ctx);
18825 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
18826 (imm >> 8) & 0x7);
18827 break;
18828 case OPC_W_FMT:
18829 case OPC_L_FMT:
18831 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
18832 check_cp1_enabled(ctx);
18833 if (ctx->insn_flags & ISA_MIPS32R6) {
18834 switch (r6_op) {
18835 case R6_OPC_CMP_AF_S:
18836 case R6_OPC_CMP_UN_S:
18837 case R6_OPC_CMP_EQ_S:
18838 case R6_OPC_CMP_UEQ_S:
18839 case R6_OPC_CMP_LT_S:
18840 case R6_OPC_CMP_ULT_S:
18841 case R6_OPC_CMP_LE_S:
18842 case R6_OPC_CMP_ULE_S:
18843 case R6_OPC_CMP_SAF_S:
18844 case R6_OPC_CMP_SUN_S:
18845 case R6_OPC_CMP_SEQ_S:
18846 case R6_OPC_CMP_SEUQ_S:
18847 case R6_OPC_CMP_SLT_S:
18848 case R6_OPC_CMP_SULT_S:
18849 case R6_OPC_CMP_SLE_S:
18850 case R6_OPC_CMP_SULE_S:
18851 case R6_OPC_CMP_OR_S:
18852 case R6_OPC_CMP_UNE_S:
18853 case R6_OPC_CMP_NE_S:
18854 case R6_OPC_CMP_SOR_S:
18855 case R6_OPC_CMP_SUNE_S:
18856 case R6_OPC_CMP_SNE_S:
18857 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
18858 break;
18859 case R6_OPC_CMP_AF_D:
18860 case R6_OPC_CMP_UN_D:
18861 case R6_OPC_CMP_EQ_D:
18862 case R6_OPC_CMP_UEQ_D:
18863 case R6_OPC_CMP_LT_D:
18864 case R6_OPC_CMP_ULT_D:
18865 case R6_OPC_CMP_LE_D:
18866 case R6_OPC_CMP_ULE_D:
18867 case R6_OPC_CMP_SAF_D:
18868 case R6_OPC_CMP_SUN_D:
18869 case R6_OPC_CMP_SEQ_D:
18870 case R6_OPC_CMP_SEUQ_D:
18871 case R6_OPC_CMP_SLT_D:
18872 case R6_OPC_CMP_SULT_D:
18873 case R6_OPC_CMP_SLE_D:
18874 case R6_OPC_CMP_SULE_D:
18875 case R6_OPC_CMP_OR_D:
18876 case R6_OPC_CMP_UNE_D:
18877 case R6_OPC_CMP_NE_D:
18878 case R6_OPC_CMP_SOR_D:
18879 case R6_OPC_CMP_SUNE_D:
18880 case R6_OPC_CMP_SNE_D:
18881 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
18882 break;
18883 default:
18884 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
18885 rt, rd, sa, (imm >> 8) & 0x7);
18887 break;
18889 } else {
18890 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
18891 (imm >> 8) & 0x7);
18893 break;
18895 case OPC_BZ_V:
18896 case OPC_BNZ_V:
18897 case OPC_BZ_B:
18898 case OPC_BZ_H:
18899 case OPC_BZ_W:
18900 case OPC_BZ_D:
18901 case OPC_BNZ_B:
18902 case OPC_BNZ_H:
18903 case OPC_BNZ_W:
18904 case OPC_BNZ_D:
18905 check_insn(ctx, ASE_MSA);
18906 gen_msa_branch(env, ctx, op1);
18907 break;
18908 default:
18909 MIPS_INVAL("cp1");
18910 generate_exception(ctx, EXCP_RI);
18911 break;
18913 break;
18915 /* Compact branches [R6] and COP2 [non-R6] */
18916 case OPC_BC: /* OPC_LWC2 */
18917 case OPC_BALC: /* OPC_SWC2 */
18918 if (ctx->insn_flags & ISA_MIPS32R6) {
18919 /* OPC_BC, OPC_BALC */
18920 gen_compute_compact_branch(ctx, op, 0, 0,
18921 sextract32(ctx->opcode << 2, 0, 28));
18922 } else {
18923 /* OPC_LWC2, OPC_SWC2 */
18924 /* COP2: Not implemented. */
18925 generate_exception_err(ctx, EXCP_CpU, 2);
18927 break;
18928 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
18929 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
18930 if (ctx->insn_flags & ISA_MIPS32R6) {
18931 if (rs != 0) {
18932 /* OPC_BEQZC, OPC_BNEZC */
18933 gen_compute_compact_branch(ctx, op, rs, 0,
18934 sextract32(ctx->opcode << 2, 0, 23));
18935 } else {
18936 /* OPC_JIC, OPC_JIALC */
18937 gen_compute_compact_branch(ctx, op, 0, rt, imm);
18939 } else {
18940 /* OPC_LWC2, OPC_SWC2 */
18941 /* COP2: Not implemented. */
18942 generate_exception_err(ctx, EXCP_CpU, 2);
18944 break;
18945 case OPC_CP2:
18946 check_insn(ctx, INSN_LOONGSON2F);
18947 /* Note that these instructions use different fields. */
18948 gen_loongson_multimedia(ctx, sa, rd, rt);
18949 break;
18951 case OPC_CP3:
18952 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18953 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
18954 check_cp1_enabled(ctx);
18955 op1 = MASK_CP3(ctx->opcode);
18956 switch (op1) {
18957 case OPC_LUXC1:
18958 case OPC_SUXC1:
18959 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
18960 /* Fallthrough */
18961 case OPC_LWXC1:
18962 case OPC_LDXC1:
18963 case OPC_SWXC1:
18964 case OPC_SDXC1:
18965 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
18966 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
18967 break;
18968 case OPC_PREFX:
18969 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
18970 /* Treat as NOP. */
18971 break;
18972 case OPC_ALNV_PS:
18973 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
18974 /* Fallthrough */
18975 case OPC_MADD_S:
18976 case OPC_MADD_D:
18977 case OPC_MADD_PS:
18978 case OPC_MSUB_S:
18979 case OPC_MSUB_D:
18980 case OPC_MSUB_PS:
18981 case OPC_NMADD_S:
18982 case OPC_NMADD_D:
18983 case OPC_NMADD_PS:
18984 case OPC_NMSUB_S:
18985 case OPC_NMSUB_D:
18986 case OPC_NMSUB_PS:
18987 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
18988 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
18989 break;
18990 default:
18991 MIPS_INVAL("cp3");
18992 generate_exception (ctx, EXCP_RI);
18993 break;
18995 } else {
18996 generate_exception_err(ctx, EXCP_CpU, 1);
18998 break;
19000 #if defined(TARGET_MIPS64)
19001 /* MIPS64 opcodes */
19002 case OPC_LDL ... OPC_LDR:
19003 case OPC_LLD:
19004 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19005 /* fall through */
19006 case OPC_LWU:
19007 case OPC_LD:
19008 check_insn(ctx, ISA_MIPS3);
19009 check_mips_64(ctx);
19010 gen_ld(ctx, op, rt, rs, imm);
19011 break;
19012 case OPC_SDL ... OPC_SDR:
19013 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19014 /* fall through */
19015 case OPC_SD:
19016 check_insn(ctx, ISA_MIPS3);
19017 check_mips_64(ctx);
19018 gen_st(ctx, op, rt, rs, imm);
19019 break;
19020 case OPC_SCD:
19021 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19022 check_insn(ctx, ISA_MIPS3);
19023 check_mips_64(ctx);
19024 gen_st_cond(ctx, op, rt, rs, imm);
19025 break;
19026 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
19027 if (ctx->insn_flags & ISA_MIPS32R6) {
19028 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
19029 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19030 } else {
19031 /* OPC_DADDI */
19032 check_insn(ctx, ISA_MIPS3);
19033 check_mips_64(ctx);
19034 gen_arith_imm(ctx, op, rt, rs, imm);
19036 break;
19037 case OPC_DADDIU:
19038 check_insn(ctx, ISA_MIPS3);
19039 check_mips_64(ctx);
19040 gen_arith_imm(ctx, op, rt, rs, imm);
19041 break;
19042 #else
19043 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
19044 if (ctx->insn_flags & ISA_MIPS32R6) {
19045 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19046 } else {
19047 MIPS_INVAL("major opcode");
19048 generate_exception(ctx, EXCP_RI);
19050 break;
19051 #endif
19052 case OPC_DAUI: /* OPC_JALX */
19053 if (ctx->insn_flags & ISA_MIPS32R6) {
19054 #if defined(TARGET_MIPS64)
19055 /* OPC_DAUI */
19056 check_mips_64(ctx);
19057 if (rt != 0) {
19058 TCGv t0 = tcg_temp_new();
19059 gen_load_gpr(t0, rs);
19060 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
19061 tcg_temp_free(t0);
19063 MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm);
19064 #else
19065 generate_exception(ctx, EXCP_RI);
19066 MIPS_INVAL("major opcode");
19067 #endif
19068 } else {
19069 /* OPC_JALX */
19070 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
19071 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19072 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19074 break;
19075 case OPC_MSA: /* OPC_MDMX */
19076 /* MDMX: Not implemented. */
19077 gen_msa(env, ctx);
19078 break;
19079 case OPC_PCREL:
19080 check_insn(ctx, ISA_MIPS32R6);
19081 gen_pcrel(ctx, rs, imm);
19082 break;
19083 default: /* Invalid */
19084 MIPS_INVAL("major opcode");
19085 generate_exception(ctx, EXCP_RI);
19086 break;
19090 static inline void
19091 gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
19092 bool search_pc)
19094 CPUState *cs = CPU(cpu);
19095 CPUMIPSState *env = &cpu->env;
19096 DisasContext ctx;
19097 target_ulong pc_start;
19098 target_ulong next_page_start;
19099 CPUBreakpoint *bp;
19100 int j, lj = -1;
19101 int num_insns;
19102 int max_insns;
19103 int insn_bytes;
19104 int is_slot;
19106 if (search_pc)
19107 qemu_log("search pc %d\n", search_pc);
19109 pc_start = tb->pc;
19110 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
19111 ctx.pc = pc_start;
19112 ctx.saved_pc = -1;
19113 ctx.singlestep_enabled = cs->singlestep_enabled;
19114 ctx.insn_flags = env->insn_flags;
19115 ctx.CP0_Config1 = env->CP0_Config1;
19116 ctx.tb = tb;
19117 ctx.bstate = BS_NONE;
19118 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
19119 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
19120 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
19121 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
19122 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
19123 /* Restore delay slot state from the tb context. */
19124 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
19125 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
19126 restore_cpu_state(env, &ctx);
19127 #ifdef CONFIG_USER_ONLY
19128 ctx.mem_idx = MIPS_HFLAG_UM;
19129 #else
19130 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
19131 #endif
19132 num_insns = 0;
19133 max_insns = tb->cflags & CF_COUNT_MASK;
19134 if (max_insns == 0)
19135 max_insns = CF_COUNT_MASK;
19136 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
19137 gen_tb_start(tb);
19138 while (ctx.bstate == BS_NONE) {
19139 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
19140 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
19141 if (bp->pc == ctx.pc) {
19142 save_cpu_state(&ctx, 1);
19143 ctx.bstate = BS_BRANCH;
19144 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
19145 /* Include the breakpoint location or the tb won't
19146 * be flushed when it must be. */
19147 ctx.pc += 4;
19148 goto done_generating;
19153 if (search_pc) {
19154 j = tcg_op_buf_count();
19155 if (lj < j) {
19156 lj++;
19157 while (lj < j)
19158 tcg_ctx.gen_opc_instr_start[lj++] = 0;
19160 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
19161 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
19162 gen_opc_btarget[lj] = ctx.btarget;
19163 tcg_ctx.gen_opc_instr_start[lj] = 1;
19164 tcg_ctx.gen_opc_icount[lj] = num_insns;
19166 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
19167 gen_io_start();
19169 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
19170 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
19171 ctx.opcode = cpu_ldl_code(env, ctx.pc);
19172 insn_bytes = 4;
19173 decode_opc(env, &ctx);
19174 } else if (ctx.insn_flags & ASE_MICROMIPS) {
19175 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19176 insn_bytes = decode_micromips_opc(env, &ctx);
19177 } else if (ctx.insn_flags & ASE_MIPS16) {
19178 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19179 insn_bytes = decode_mips16_opc(env, &ctx);
19180 } else {
19181 generate_exception(&ctx, EXCP_RI);
19182 ctx.bstate = BS_STOP;
19183 break;
19186 if (ctx.hflags & MIPS_HFLAG_BMASK) {
19187 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
19188 MIPS_HFLAG_FBNSLOT))) {
19189 /* force to generate branch as there is neither delay nor
19190 forbidden slot */
19191 is_slot = 1;
19194 if (is_slot) {
19195 gen_branch(&ctx, insn_bytes);
19197 ctx.pc += insn_bytes;
19199 num_insns++;
19201 /* Execute a branch and its delay slot as a single instruction.
19202 This is what GDB expects and is consistent with what the
19203 hardware does (e.g. if a delay slot instruction faults, the
19204 reported PC is the PC of the branch). */
19205 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
19206 break;
19209 if (ctx.pc >= next_page_start) {
19210 break;
19213 if (tcg_op_buf_full()) {
19214 break;
19217 if (num_insns >= max_insns)
19218 break;
19220 if (singlestep)
19221 break;
19223 if (tb->cflags & CF_LAST_IO) {
19224 gen_io_end();
19226 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
19227 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
19228 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
19229 } else {
19230 switch (ctx.bstate) {
19231 case BS_STOP:
19232 gen_goto_tb(&ctx, 0, ctx.pc);
19233 break;
19234 case BS_NONE:
19235 save_cpu_state(&ctx, 0);
19236 gen_goto_tb(&ctx, 0, ctx.pc);
19237 break;
19238 case BS_EXCP:
19239 tcg_gen_exit_tb(0);
19240 break;
19241 case BS_BRANCH:
19242 default:
19243 break;
19246 done_generating:
19247 gen_tb_end(tb, num_insns);
19249 if (search_pc) {
19250 j = tcg_op_buf_count();
19251 lj++;
19252 while (lj <= j)
19253 tcg_ctx.gen_opc_instr_start[lj++] = 0;
19254 } else {
19255 tb->size = ctx.pc - pc_start;
19256 tb->icount = num_insns;
19258 #ifdef DEBUG_DISAS
19259 LOG_DISAS("\n");
19260 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
19261 qemu_log("IN: %s\n", lookup_symbol(pc_start));
19262 log_target_disas(env, pc_start, ctx.pc - pc_start, 0);
19263 qemu_log("\n");
19265 #endif
19268 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
19270 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
19273 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
19275 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
19278 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
19279 int flags)
19281 int i;
19282 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
19284 #define printfpr(fp) \
19285 do { \
19286 if (is_fpu64) \
19287 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19288 " fd:%13g fs:%13g psu: %13g\n", \
19289 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
19290 (double)(fp)->fd, \
19291 (double)(fp)->fs[FP_ENDIAN_IDX], \
19292 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
19293 else { \
19294 fpr_t tmp; \
19295 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
19296 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
19297 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19298 " fd:%13g fs:%13g psu:%13g\n", \
19299 tmp.w[FP_ENDIAN_IDX], tmp.d, \
19300 (double)tmp.fd, \
19301 (double)tmp.fs[FP_ENDIAN_IDX], \
19302 (double)tmp.fs[!FP_ENDIAN_IDX]); \
19304 } while(0)
19307 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
19308 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
19309 get_float_exception_flags(&env->active_fpu.fp_status));
19310 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
19311 fpu_fprintf(f, "%3s: ", fregnames[i]);
19312 printfpr(&env->active_fpu.fpr[i]);
19315 #undef printfpr
19318 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
19319 /* Debug help: The architecture requires 32bit code to maintain proper
19320 sign-extended values on 64bit machines. */
19322 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
19324 static void
19325 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
19326 fprintf_function cpu_fprintf,
19327 int flags)
19329 int i;
19331 if (!SIGN_EXT_P(env->active_tc.PC))
19332 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
19333 if (!SIGN_EXT_P(env->active_tc.HI[0]))
19334 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
19335 if (!SIGN_EXT_P(env->active_tc.LO[0]))
19336 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
19337 if (!SIGN_EXT_P(env->btarget))
19338 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
19340 for (i = 0; i < 32; i++) {
19341 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
19342 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
19345 if (!SIGN_EXT_P(env->CP0_EPC))
19346 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
19347 if (!SIGN_EXT_P(env->lladdr))
19348 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
19350 #endif
19352 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
19353 int flags)
19355 MIPSCPU *cpu = MIPS_CPU(cs);
19356 CPUMIPSState *env = &cpu->env;
19357 int i;
19359 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
19360 " LO=0x" TARGET_FMT_lx " ds %04x "
19361 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
19362 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
19363 env->hflags, env->btarget, env->bcond);
19364 for (i = 0; i < 32; i++) {
19365 if ((i & 3) == 0)
19366 cpu_fprintf(f, "GPR%02d:", i);
19367 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
19368 if ((i & 3) == 3)
19369 cpu_fprintf(f, "\n");
19372 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
19373 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
19374 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
19375 env->CP0_Config0, env->CP0_Config1, env->lladdr);
19376 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
19377 env->CP0_Config2, env->CP0_Config3);
19378 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
19379 env->CP0_Config4, env->CP0_Config5);
19380 if (env->hflags & MIPS_HFLAG_FPU)
19381 fpu_dump_state(env, f, cpu_fprintf, flags);
19382 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
19383 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
19384 #endif
19387 void mips_tcg_init(void)
19389 int i;
19390 static int inited;
19392 /* Initialize various static tables. */
19393 if (inited)
19394 return;
19396 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
19397 TCGV_UNUSED(cpu_gpr[0]);
19398 for (i = 1; i < 32; i++)
19399 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
19400 offsetof(CPUMIPSState, active_tc.gpr[i]),
19401 regnames[i]);
19403 for (i = 0; i < 32; i++) {
19404 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
19405 msa_wr_d[i * 2] =
19406 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]);
19407 /* The scalar floating-point unit (FPU) registers are mapped on
19408 * the MSA vector registers. */
19409 fpu_f64[i] = msa_wr_d[i * 2];
19410 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
19411 msa_wr_d[i * 2 + 1] =
19412 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + 1]);
19415 cpu_PC = tcg_global_mem_new(TCG_AREG0,
19416 offsetof(CPUMIPSState, active_tc.PC), "PC");
19417 for (i = 0; i < MIPS_DSP_ACC; i++) {
19418 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
19419 offsetof(CPUMIPSState, active_tc.HI[i]),
19420 regnames_HI[i]);
19421 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
19422 offsetof(CPUMIPSState, active_tc.LO[i]),
19423 regnames_LO[i]);
19425 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
19426 offsetof(CPUMIPSState, active_tc.DSPControl),
19427 "DSPControl");
19428 bcond = tcg_global_mem_new(TCG_AREG0,
19429 offsetof(CPUMIPSState, bcond), "bcond");
19430 btarget = tcg_global_mem_new(TCG_AREG0,
19431 offsetof(CPUMIPSState, btarget), "btarget");
19432 hflags = tcg_global_mem_new_i32(TCG_AREG0,
19433 offsetof(CPUMIPSState, hflags), "hflags");
19435 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
19436 offsetof(CPUMIPSState, active_fpu.fcr0),
19437 "fcr0");
19438 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
19439 offsetof(CPUMIPSState, active_fpu.fcr31),
19440 "fcr31");
19442 inited = 1;
19445 #include "translate_init.c"
19447 MIPSCPU *cpu_mips_init(const char *cpu_model)
19449 MIPSCPU *cpu;
19450 CPUMIPSState *env;
19451 const mips_def_t *def;
19453 def = cpu_mips_find_by_name(cpu_model);
19454 if (!def)
19455 return NULL;
19456 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
19457 env = &cpu->env;
19458 env->cpu_model = def;
19460 #ifndef CONFIG_USER_ONLY
19461 mmu_init(env, def);
19462 #endif
19463 fpu_init(env, def);
19464 mvp_init(env, def);
19466 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
19468 return cpu;
19471 void cpu_state_reset(CPUMIPSState *env)
19473 MIPSCPU *cpu = mips_env_get_cpu(env);
19474 CPUState *cs = CPU(cpu);
19476 /* Reset registers to their default values */
19477 env->CP0_PRid = env->cpu_model->CP0_PRid;
19478 env->CP0_Config0 = env->cpu_model->CP0_Config0;
19479 #ifdef TARGET_WORDS_BIGENDIAN
19480 env->CP0_Config0 |= (1 << CP0C0_BE);
19481 #endif
19482 env->CP0_Config1 = env->cpu_model->CP0_Config1;
19483 env->CP0_Config2 = env->cpu_model->CP0_Config2;
19484 env->CP0_Config3 = env->cpu_model->CP0_Config3;
19485 env->CP0_Config4 = env->cpu_model->CP0_Config4;
19486 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
19487 env->CP0_Config5 = env->cpu_model->CP0_Config5;
19488 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
19489 env->CP0_Config6 = env->cpu_model->CP0_Config6;
19490 env->CP0_Config7 = env->cpu_model->CP0_Config7;
19491 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
19492 << env->cpu_model->CP0_LLAddr_shift;
19493 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
19494 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
19495 env->CCRes = env->cpu_model->CCRes;
19496 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
19497 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
19498 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
19499 env->current_tc = 0;
19500 env->SEGBITS = env->cpu_model->SEGBITS;
19501 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
19502 #if defined(TARGET_MIPS64)
19503 if (env->cpu_model->insn_flags & ISA_MIPS3) {
19504 env->SEGMask |= 3ULL << 62;
19506 #endif
19507 env->PABITS = env->cpu_model->PABITS;
19508 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
19509 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
19510 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
19511 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
19512 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
19513 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
19514 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
19515 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
19516 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
19517 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
19518 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
19519 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
19520 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
19521 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
19522 env->msair = env->cpu_model->MSAIR;
19523 env->insn_flags = env->cpu_model->insn_flags;
19525 #if defined(CONFIG_USER_ONLY)
19526 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
19527 # ifdef TARGET_MIPS64
19528 /* Enable 64-bit register mode. */
19529 env->CP0_Status |= (1 << CP0St_PX);
19530 # endif
19531 # ifdef TARGET_ABI_MIPSN64
19532 /* Enable 64-bit address mode. */
19533 env->CP0_Status |= (1 << CP0St_UX);
19534 # endif
19535 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
19536 hardware registers. */
19537 env->CP0_HWREna |= 0x0000000F;
19538 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
19539 env->CP0_Status |= (1 << CP0St_CU1);
19541 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
19542 env->CP0_Status |= (1 << CP0St_MX);
19544 # if defined(TARGET_MIPS64)
19545 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
19546 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
19547 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
19548 env->CP0_Status |= (1 << CP0St_FR);
19550 # endif
19551 #else
19552 if (env->hflags & MIPS_HFLAG_BMASK) {
19553 /* If the exception was raised from a delay slot,
19554 come back to the jump. */
19555 env->CP0_ErrorEPC = (env->active_tc.PC
19556 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
19557 } else {
19558 env->CP0_ErrorEPC = env->active_tc.PC;
19560 env->active_tc.PC = (int32_t)0xBFC00000;
19561 env->CP0_Random = env->tlb->nb_tlb - 1;
19562 env->tlb->tlb_in_use = env->tlb->nb_tlb;
19563 env->CP0_Wired = 0;
19564 env->CP0_EBase = (cs->cpu_index & 0x3FF);
19565 if (kvm_enabled()) {
19566 env->CP0_EBase |= 0x40000000;
19567 } else {
19568 env->CP0_EBase |= 0x80000000;
19570 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
19571 /* vectored interrupts not implemented, timer on int 7,
19572 no performance counters. */
19573 env->CP0_IntCtl = 0xe0000000;
19575 int i;
19577 for (i = 0; i < 7; i++) {
19578 env->CP0_WatchLo[i] = 0;
19579 env->CP0_WatchHi[i] = 0x80000000;
19581 env->CP0_WatchLo[7] = 0;
19582 env->CP0_WatchHi[7] = 0;
19584 /* Count register increments in debug mode, EJTAG version 1 */
19585 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
19587 cpu_mips_store_count(env, 1);
19589 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
19590 int i;
19592 /* Only TC0 on VPE 0 starts as active. */
19593 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
19594 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
19595 env->tcs[i].CP0_TCHalt = 1;
19597 env->active_tc.CP0_TCHalt = 1;
19598 cs->halted = 1;
19600 if (cs->cpu_index == 0) {
19601 /* VPE0 starts up enabled. */
19602 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
19603 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
19605 /* TC0 starts up unhalted. */
19606 cs->halted = 0;
19607 env->active_tc.CP0_TCHalt = 0;
19608 env->tcs[0].CP0_TCHalt = 0;
19609 /* With thread 0 active. */
19610 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
19611 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
19614 #endif
19615 if ((env->insn_flags & ISA_MIPS32R6) &&
19616 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
19617 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
19618 env->CP0_Status |= (1 << CP0St_FR);
19621 /* MSA */
19622 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
19623 msa_reset(env);
19626 compute_hflags(env);
19627 restore_rounding_mode(env);
19628 restore_flush_mode(env);
19629 cs->exception_index = EXCP_NONE;
19632 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
19634 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
19635 env->hflags &= ~MIPS_HFLAG_BMASK;
19636 env->hflags |= gen_opc_hflags[pc_pos];
19637 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
19638 case MIPS_HFLAG_BR:
19639 break;
19640 case MIPS_HFLAG_BC:
19641 case MIPS_HFLAG_BL:
19642 case MIPS_HFLAG_B:
19643 env->btarget = gen_opc_btarget[pc_pos];
19644 break;