msi_init: change return value to 0 on success
[qemu/ar7.git] / target-mips / translate.c
blobf420680d1fc3f7c71a582f2c13a7585f34cfdb1a
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "disas/disas.h"
27 #include "exec/exec-all.h"
28 #include "tcg-op.h"
29 #include "exec/cpu_ldst.h"
31 #include "exec/helper-proto.h"
32 #include "exec/helper-gen.h"
33 #include "sysemu/kvm.h"
34 #include "exec/semihost.h"
36 #include "trace-tcg.h"
37 #include "exec/log.h"
39 #define MIPS_DEBUG_DISAS 0
41 /* MIPS major opcodes */
42 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
44 enum {
45 /* indirect opcode tables */
46 OPC_SPECIAL = (0x00 << 26),
47 OPC_REGIMM = (0x01 << 26),
48 OPC_CP0 = (0x10 << 26),
49 OPC_CP1 = (0x11 << 26),
50 OPC_CP2 = (0x12 << 26),
51 OPC_CP3 = (0x13 << 26),
52 OPC_SPECIAL2 = (0x1C << 26),
53 OPC_SPECIAL3 = (0x1F << 26),
54 /* arithmetic with immediate */
55 OPC_ADDI = (0x08 << 26),
56 OPC_ADDIU = (0x09 << 26),
57 OPC_SLTI = (0x0A << 26),
58 OPC_SLTIU = (0x0B << 26),
59 /* logic with immediate */
60 OPC_ANDI = (0x0C << 26),
61 OPC_ORI = (0x0D << 26),
62 OPC_XORI = (0x0E << 26),
63 OPC_LUI = (0x0F << 26),
64 /* arithmetic with immediate */
65 OPC_DADDI = (0x18 << 26),
66 OPC_DADDIU = (0x19 << 26),
67 /* Jump and branches */
68 OPC_J = (0x02 << 26),
69 OPC_JAL = (0x03 << 26),
70 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
71 OPC_BEQL = (0x14 << 26),
72 OPC_BNE = (0x05 << 26),
73 OPC_BNEL = (0x15 << 26),
74 OPC_BLEZ = (0x06 << 26),
75 OPC_BLEZL = (0x16 << 26),
76 OPC_BGTZ = (0x07 << 26),
77 OPC_BGTZL = (0x17 << 26),
78 OPC_JALX = (0x1D << 26),
79 OPC_DAUI = (0x1D << 26),
80 /* Load and stores */
81 OPC_LDL = (0x1A << 26),
82 OPC_LDR = (0x1B << 26),
83 OPC_LB = (0x20 << 26),
84 OPC_LH = (0x21 << 26),
85 OPC_LWL = (0x22 << 26),
86 OPC_LW = (0x23 << 26),
87 OPC_LWPC = OPC_LW | 0x5,
88 OPC_LBU = (0x24 << 26),
89 OPC_LHU = (0x25 << 26),
90 OPC_LWR = (0x26 << 26),
91 OPC_LWU = (0x27 << 26),
92 OPC_SB = (0x28 << 26),
93 OPC_SH = (0x29 << 26),
94 OPC_SWL = (0x2A << 26),
95 OPC_SW = (0x2B << 26),
96 OPC_SDL = (0x2C << 26),
97 OPC_SDR = (0x2D << 26),
98 OPC_SWR = (0x2E << 26),
99 OPC_LL = (0x30 << 26),
100 OPC_LLD = (0x34 << 26),
101 OPC_LD = (0x37 << 26),
102 OPC_LDPC = OPC_LD | 0x5,
103 OPC_SC = (0x38 << 26),
104 OPC_SCD = (0x3C << 26),
105 OPC_SD = (0x3F << 26),
106 /* Floating point load/store */
107 OPC_LWC1 = (0x31 << 26),
108 OPC_LWC2 = (0x32 << 26),
109 OPC_LDC1 = (0x35 << 26),
110 OPC_LDC2 = (0x36 << 26),
111 OPC_SWC1 = (0x39 << 26),
112 OPC_SWC2 = (0x3A << 26),
113 OPC_SDC1 = (0x3D << 26),
114 OPC_SDC2 = (0x3E << 26),
115 /* Compact Branches */
116 OPC_BLEZALC = (0x06 << 26),
117 OPC_BGEZALC = (0x06 << 26),
118 OPC_BGEUC = (0x06 << 26),
119 OPC_BGTZALC = (0x07 << 26),
120 OPC_BLTZALC = (0x07 << 26),
121 OPC_BLTUC = (0x07 << 26),
122 OPC_BOVC = (0x08 << 26),
123 OPC_BEQZALC = (0x08 << 26),
124 OPC_BEQC = (0x08 << 26),
125 OPC_BLEZC = (0x16 << 26),
126 OPC_BGEZC = (0x16 << 26),
127 OPC_BGEC = (0x16 << 26),
128 OPC_BGTZC = (0x17 << 26),
129 OPC_BLTZC = (0x17 << 26),
130 OPC_BLTC = (0x17 << 26),
131 OPC_BNVC = (0x18 << 26),
132 OPC_BNEZALC = (0x18 << 26),
133 OPC_BNEC = (0x18 << 26),
134 OPC_BC = (0x32 << 26),
135 OPC_BEQZC = (0x36 << 26),
136 OPC_JIC = (0x36 << 26),
137 OPC_BALC = (0x3A << 26),
138 OPC_BNEZC = (0x3E << 26),
139 OPC_JIALC = (0x3E << 26),
140 /* MDMX ASE specific */
141 OPC_MDMX = (0x1E << 26),
142 /* MSA ASE, same as MDMX */
143 OPC_MSA = OPC_MDMX,
144 /* Cache and prefetch */
145 OPC_CACHE = (0x2F << 26),
146 OPC_PREF = (0x33 << 26),
147 /* PC-relative address computation / loads */
148 OPC_PCREL = (0x3B << 26),
151 /* PC-relative address computation / loads */
152 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
153 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
154 enum {
155 /* Instructions determined by bits 19 and 20 */
156 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
157 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
158 OPC_LWUPC = OPC_PCREL | (2 << 19),
160 /* Instructions determined by bits 16 ... 20 */
161 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
162 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
164 /* Other */
165 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
168 /* MIPS special opcodes */
169 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
171 enum {
172 /* Shifts */
173 OPC_SLL = 0x00 | OPC_SPECIAL,
174 /* NOP is SLL r0, r0, 0 */
175 /* SSNOP is SLL r0, r0, 1 */
176 /* EHB is SLL r0, r0, 3 */
177 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
178 OPC_ROTR = OPC_SRL | (1 << 21),
179 OPC_SRA = 0x03 | OPC_SPECIAL,
180 OPC_SLLV = 0x04 | OPC_SPECIAL,
181 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
182 OPC_ROTRV = OPC_SRLV | (1 << 6),
183 OPC_SRAV = 0x07 | OPC_SPECIAL,
184 OPC_DSLLV = 0x14 | OPC_SPECIAL,
185 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
186 OPC_DROTRV = OPC_DSRLV | (1 << 6),
187 OPC_DSRAV = 0x17 | OPC_SPECIAL,
188 OPC_DSLL = 0x38 | OPC_SPECIAL,
189 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
190 OPC_DROTR = OPC_DSRL | (1 << 21),
191 OPC_DSRA = 0x3B | OPC_SPECIAL,
192 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
193 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
194 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
195 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
196 /* Multiplication / division */
197 OPC_MULT = 0x18 | OPC_SPECIAL,
198 OPC_MULTU = 0x19 | OPC_SPECIAL,
199 OPC_DIV = 0x1A | OPC_SPECIAL,
200 OPC_DIVU = 0x1B | OPC_SPECIAL,
201 OPC_DMULT = 0x1C | OPC_SPECIAL,
202 OPC_DMULTU = 0x1D | OPC_SPECIAL,
203 OPC_DDIV = 0x1E | OPC_SPECIAL,
204 OPC_DDIVU = 0x1F | OPC_SPECIAL,
206 /* 2 registers arithmetic / logic */
207 OPC_ADD = 0x20 | OPC_SPECIAL,
208 OPC_ADDU = 0x21 | OPC_SPECIAL,
209 OPC_SUB = 0x22 | OPC_SPECIAL,
210 OPC_SUBU = 0x23 | OPC_SPECIAL,
211 OPC_AND = 0x24 | OPC_SPECIAL,
212 OPC_OR = 0x25 | OPC_SPECIAL,
213 OPC_XOR = 0x26 | OPC_SPECIAL,
214 OPC_NOR = 0x27 | OPC_SPECIAL,
215 OPC_SLT = 0x2A | OPC_SPECIAL,
216 OPC_SLTU = 0x2B | OPC_SPECIAL,
217 OPC_DADD = 0x2C | OPC_SPECIAL,
218 OPC_DADDU = 0x2D | OPC_SPECIAL,
219 OPC_DSUB = 0x2E | OPC_SPECIAL,
220 OPC_DSUBU = 0x2F | OPC_SPECIAL,
221 /* Jumps */
222 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
223 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
224 /* Traps */
225 OPC_TGE = 0x30 | OPC_SPECIAL,
226 OPC_TGEU = 0x31 | OPC_SPECIAL,
227 OPC_TLT = 0x32 | OPC_SPECIAL,
228 OPC_TLTU = 0x33 | OPC_SPECIAL,
229 OPC_TEQ = 0x34 | OPC_SPECIAL,
230 OPC_TNE = 0x36 | OPC_SPECIAL,
231 /* HI / LO registers load & stores */
232 OPC_MFHI = 0x10 | OPC_SPECIAL,
233 OPC_MTHI = 0x11 | OPC_SPECIAL,
234 OPC_MFLO = 0x12 | OPC_SPECIAL,
235 OPC_MTLO = 0x13 | OPC_SPECIAL,
236 /* Conditional moves */
237 OPC_MOVZ = 0x0A | OPC_SPECIAL,
238 OPC_MOVN = 0x0B | OPC_SPECIAL,
240 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
241 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
243 OPC_MOVCI = 0x01 | OPC_SPECIAL,
245 /* Special */
246 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
247 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
248 OPC_BREAK = 0x0D | OPC_SPECIAL,
249 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
250 OPC_SYNC = 0x0F | OPC_SPECIAL,
252 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
253 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
254 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
255 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
258 /* R6 Multiply and Divide instructions have the same Opcode
259 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
260 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
262 enum {
263 R6_OPC_MUL = OPC_MULT | (2 << 6),
264 R6_OPC_MUH = OPC_MULT | (3 << 6),
265 R6_OPC_MULU = OPC_MULTU | (2 << 6),
266 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
267 R6_OPC_DIV = OPC_DIV | (2 << 6),
268 R6_OPC_MOD = OPC_DIV | (3 << 6),
269 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
270 R6_OPC_MODU = OPC_DIVU | (3 << 6),
272 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
273 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
274 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
275 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
276 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
277 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
278 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
279 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
281 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
282 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
283 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
284 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
285 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
287 OPC_LSA = 0x05 | OPC_SPECIAL,
288 OPC_DLSA = 0x15 | OPC_SPECIAL,
291 /* Multiplication variants of the vr54xx. */
292 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
294 enum {
295 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
296 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
297 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
298 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
299 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
300 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
301 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
302 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
303 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
304 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
305 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
306 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
307 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
308 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
311 /* REGIMM (rt field) opcodes */
312 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
314 enum {
315 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
316 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
317 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
318 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
319 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
320 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
321 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
322 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
323 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
324 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
325 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
326 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
327 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
328 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
329 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
330 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
332 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
333 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
336 /* Special2 opcodes */
337 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
339 enum {
340 /* Multiply & xxx operations */
341 OPC_MADD = 0x00 | OPC_SPECIAL2,
342 OPC_MADDU = 0x01 | OPC_SPECIAL2,
343 OPC_MUL = 0x02 | OPC_SPECIAL2,
344 OPC_MSUB = 0x04 | OPC_SPECIAL2,
345 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
346 /* Loongson 2F */
347 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
348 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
349 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
350 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
351 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
352 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
353 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
354 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
355 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
356 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
357 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
358 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
359 /* Misc */
360 OPC_CLZ = 0x20 | OPC_SPECIAL2,
361 OPC_CLO = 0x21 | OPC_SPECIAL2,
362 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
363 OPC_DCLO = 0x25 | OPC_SPECIAL2,
364 /* Special */
365 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
368 /* Special3 opcodes */
369 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
371 enum {
372 OPC_EXT = 0x00 | OPC_SPECIAL3,
373 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
374 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
375 OPC_DEXT = 0x03 | OPC_SPECIAL3,
376 OPC_INS = 0x04 | OPC_SPECIAL3,
377 OPC_DINSM = 0x05 | OPC_SPECIAL3,
378 OPC_DINSU = 0x06 | OPC_SPECIAL3,
379 OPC_DINS = 0x07 | OPC_SPECIAL3,
380 OPC_FORK = 0x08 | OPC_SPECIAL3,
381 OPC_YIELD = 0x09 | OPC_SPECIAL3,
382 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
383 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
384 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
386 /* Loongson 2E */
387 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
388 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
389 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
390 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
391 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
392 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
393 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
394 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
395 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
396 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
397 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
398 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
400 /* MIPS DSP Load */
401 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
402 /* MIPS DSP Arithmetic */
403 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
404 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
405 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
406 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
407 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
408 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
409 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
410 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
411 /* MIPS DSP GPR-Based Shift Sub-class */
412 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
413 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
414 /* MIPS DSP Multiply Sub-class insns */
415 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
416 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
417 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
418 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
419 /* DSP Bit/Manipulation Sub-class */
420 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
421 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
422 /* MIPS DSP Append Sub-class */
423 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
424 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
425 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
426 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
427 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
429 /* R6 */
430 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
431 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
432 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
433 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
434 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
435 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
438 /* BSHFL opcodes */
439 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
441 enum {
442 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
443 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
444 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
445 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
446 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
447 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
450 /* DBSHFL opcodes */
451 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
453 enum {
454 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
455 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
456 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
457 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
458 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
461 /* MIPS DSP REGIMM opcodes */
462 enum {
463 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
464 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
467 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
468 /* MIPS DSP Load */
469 enum {
470 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
471 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
472 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
473 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
476 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
477 enum {
478 /* MIPS DSP Arithmetic Sub-class */
479 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
480 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
481 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
482 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
483 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
484 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
485 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
486 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
487 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
488 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
489 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
490 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
491 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
492 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
493 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
494 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
495 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
496 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
497 /* MIPS DSP Multiply Sub-class insns */
498 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
499 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
500 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
501 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
502 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
503 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
506 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
507 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
508 enum {
509 /* MIPS DSP Arithmetic Sub-class */
510 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
511 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
512 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
513 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
514 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
515 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
516 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
517 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
518 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
519 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
520 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
521 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
522 /* MIPS DSP Multiply Sub-class insns */
523 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
524 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
525 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
526 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
529 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
530 enum {
531 /* MIPS DSP Arithmetic Sub-class */
532 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
533 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
534 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
535 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
536 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
537 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
538 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
539 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
540 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
541 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
542 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
543 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
544 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
545 /* DSP Bit/Manipulation Sub-class */
546 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
547 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
548 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
549 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
550 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
553 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
554 enum {
555 /* MIPS DSP Arithmetic Sub-class */
556 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
557 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
558 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
559 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
560 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
561 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
562 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
563 /* DSP Compare-Pick Sub-class */
564 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
565 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
566 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
567 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
568 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
569 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
570 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
571 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
572 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
573 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
574 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
575 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
576 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
577 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
578 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
581 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
582 enum {
583 /* MIPS DSP GPR-Based Shift Sub-class */
584 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
585 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
586 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
587 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
588 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
589 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
590 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
591 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
592 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
593 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
594 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
595 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
596 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
597 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
598 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
599 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
600 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
601 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
602 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
603 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
604 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
605 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
608 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
609 enum {
610 /* MIPS DSP Multiply Sub-class insns */
611 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
612 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
613 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
614 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
615 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
616 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
617 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
618 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
619 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
620 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
621 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
622 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
623 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
624 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
625 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
626 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
627 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
628 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
629 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
630 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
631 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
632 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
635 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
636 enum {
637 /* DSP Bit/Manipulation Sub-class */
638 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
641 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
642 enum {
643 /* MIPS DSP Append Sub-class */
644 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
645 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
646 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
649 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
650 enum {
651 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
652 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
653 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
654 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
655 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
656 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
657 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
658 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
659 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
660 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
661 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
662 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
663 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
664 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
665 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
666 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
667 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
668 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
671 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
672 enum {
673 /* MIPS DSP Arithmetic Sub-class */
674 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
675 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
676 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
677 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
678 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
679 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
680 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
681 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
682 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
683 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
684 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
685 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
686 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
687 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
688 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
689 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
690 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
691 /* DSP Bit/Manipulation Sub-class */
692 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
693 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
694 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
695 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
697 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
700 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
701 enum {
702 /* MIPS DSP Multiply Sub-class insns */
703 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
704 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
705 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
706 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
707 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
708 /* MIPS DSP Arithmetic Sub-class */
709 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
710 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
711 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
712 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
713 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
714 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
715 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
716 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
717 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
718 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
719 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
720 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
721 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
722 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
723 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
724 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
725 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
726 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
727 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
728 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
729 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
732 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
733 enum {
734 /* DSP Compare-Pick Sub-class */
735 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
736 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
737 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
738 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
739 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
740 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
741 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
742 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
743 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
744 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
745 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
746 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
747 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
748 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
749 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
750 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
751 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
752 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
753 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
754 /* MIPS DSP Arithmetic Sub-class */
755 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
756 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
765 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
766 enum {
767 /* DSP Append Sub-class */
768 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
769 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
770 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
771 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
774 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
775 enum {
776 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
777 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
778 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
779 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
780 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
781 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
782 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
783 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
784 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
785 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
786 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
787 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
788 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
789 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
790 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
791 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
792 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
793 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
794 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
795 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
796 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
797 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
800 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
801 enum {
802 /* DSP Bit/Manipulation Sub-class */
803 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
806 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
807 enum {
808 /* MIPS DSP Multiply Sub-class insns */
809 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
810 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
811 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
812 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
813 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
814 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
815 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
816 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
817 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
818 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
819 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
820 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
821 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
822 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
823 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
824 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
825 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
826 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
827 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
828 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
829 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
830 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
837 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
838 enum {
839 /* MIPS DSP GPR-Based Shift Sub-class */
840 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
841 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
842 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
843 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
844 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
845 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
846 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
847 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
848 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
849 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
850 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
851 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
852 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
853 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
854 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
855 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
856 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
857 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
858 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
859 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
860 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
861 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
868 /* Coprocessor 0 (rs field) */
869 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
871 enum {
872 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
873 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
874 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
875 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
876 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
877 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
878 OPC_MFTR = (0x08 << 21) | OPC_CP0,
879 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
880 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
881 OPC_MTTR = (0x0C << 21) | OPC_CP0,
882 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
883 OPC_C0 = (0x10 << 21) | OPC_CP0,
884 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
885 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
888 /* MFMC0 opcodes */
889 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
891 enum {
892 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
893 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
894 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
895 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
896 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
897 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
898 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
899 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
902 /* Coprocessor 0 (with rs == C0) */
903 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
905 enum {
906 OPC_TLBR = 0x01 | OPC_C0,
907 OPC_TLBWI = 0x02 | OPC_C0,
908 OPC_TLBINV = 0x03 | OPC_C0,
909 OPC_TLBINVF = 0x04 | OPC_C0,
910 OPC_TLBWR = 0x06 | OPC_C0,
911 OPC_TLBP = 0x08 | OPC_C0,
912 OPC_RFE = 0x10 | OPC_C0,
913 OPC_ERET = 0x18 | OPC_C0,
914 OPC_DERET = 0x1F | OPC_C0,
915 OPC_WAIT = 0x20 | OPC_C0,
918 /* Coprocessor 1 (rs field) */
919 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
921 /* Values for the fmt field in FP instructions */
922 enum {
923 /* 0 - 15 are reserved */
924 FMT_S = 16, /* single fp */
925 FMT_D = 17, /* double fp */
926 FMT_E = 18, /* extended fp */
927 FMT_Q = 19, /* quad fp */
928 FMT_W = 20, /* 32-bit fixed */
929 FMT_L = 21, /* 64-bit fixed */
930 FMT_PS = 22, /* paired single fp */
931 /* 23 - 31 are reserved */
934 enum {
935 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
936 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
937 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
938 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
939 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
940 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
941 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
942 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
943 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
944 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
945 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
946 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
947 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
948 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
949 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
950 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
951 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
952 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
953 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
954 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
955 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
956 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
957 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
958 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
959 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
960 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
961 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
962 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
963 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
964 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
967 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
968 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
970 enum {
971 OPC_BC1F = (0x00 << 16) | OPC_BC1,
972 OPC_BC1T = (0x01 << 16) | OPC_BC1,
973 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
974 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
977 enum {
978 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
979 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
982 enum {
983 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
984 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
987 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
989 enum {
990 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
991 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
992 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
993 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
994 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
995 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
996 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
997 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
998 OPC_BC2 = (0x08 << 21) | OPC_CP2,
999 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1000 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1003 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1005 enum {
1006 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1007 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1008 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1009 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1010 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1011 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1012 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1013 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1015 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1016 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1018 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1019 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1020 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1021 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1022 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1024 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1025 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1026 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1027 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1028 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1029 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1030 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1031 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1033 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1034 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1035 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1036 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1037 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1038 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1039 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1040 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1042 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1043 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1044 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1045 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1046 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1047 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1049 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1050 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1051 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1052 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1053 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1054 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1056 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1057 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1058 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1059 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1060 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1061 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1063 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1064 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1065 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1066 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1067 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1068 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1070 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1071 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1072 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1073 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1074 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1075 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1077 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1078 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1079 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1080 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1081 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1082 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1084 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1085 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1086 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1087 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1088 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1089 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1091 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1092 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1093 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1094 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1095 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1096 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1100 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1102 enum {
1103 OPC_LWXC1 = 0x00 | OPC_CP3,
1104 OPC_LDXC1 = 0x01 | OPC_CP3,
1105 OPC_LUXC1 = 0x05 | OPC_CP3,
1106 OPC_SWXC1 = 0x08 | OPC_CP3,
1107 OPC_SDXC1 = 0x09 | OPC_CP3,
1108 OPC_SUXC1 = 0x0D | OPC_CP3,
1109 OPC_PREFX = 0x0F | OPC_CP3,
1110 OPC_ALNV_PS = 0x1E | OPC_CP3,
1111 OPC_MADD_S = 0x20 | OPC_CP3,
1112 OPC_MADD_D = 0x21 | OPC_CP3,
1113 OPC_MADD_PS = 0x26 | OPC_CP3,
1114 OPC_MSUB_S = 0x28 | OPC_CP3,
1115 OPC_MSUB_D = 0x29 | OPC_CP3,
1116 OPC_MSUB_PS = 0x2E | OPC_CP3,
1117 OPC_NMADD_S = 0x30 | OPC_CP3,
1118 OPC_NMADD_D = 0x31 | OPC_CP3,
1119 OPC_NMADD_PS= 0x36 | OPC_CP3,
1120 OPC_NMSUB_S = 0x38 | OPC_CP3,
1121 OPC_NMSUB_D = 0x39 | OPC_CP3,
1122 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1125 /* MSA Opcodes */
1126 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1127 enum {
1128 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1129 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1130 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1131 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1132 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1133 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1134 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1135 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1136 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1137 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1138 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1139 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1140 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1141 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1142 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1143 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1144 OPC_MSA_ELM = 0x19 | OPC_MSA,
1145 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1146 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1147 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1148 OPC_MSA_VEC = 0x1E | OPC_MSA,
1150 /* MI10 instruction */
1151 OPC_LD_B = (0x20) | OPC_MSA,
1152 OPC_LD_H = (0x21) | OPC_MSA,
1153 OPC_LD_W = (0x22) | OPC_MSA,
1154 OPC_LD_D = (0x23) | OPC_MSA,
1155 OPC_ST_B = (0x24) | OPC_MSA,
1156 OPC_ST_H = (0x25) | OPC_MSA,
1157 OPC_ST_W = (0x26) | OPC_MSA,
1158 OPC_ST_D = (0x27) | OPC_MSA,
1161 enum {
1162 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1163 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1164 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1165 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1166 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1167 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1168 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1169 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1170 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1171 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1172 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1173 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1174 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1176 /* I8 instruction */
1177 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1178 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1179 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1180 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1181 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1182 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1183 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1184 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1185 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1186 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1188 /* VEC/2R/2RF instruction */
1189 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1190 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1191 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1192 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1193 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1194 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1195 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1197 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1198 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1200 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1201 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1202 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1203 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1204 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1206 /* 2RF instruction df(bit 16) = _w, _d */
1207 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1208 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1209 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1210 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1211 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1212 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1213 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1214 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1215 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1216 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1217 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1218 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1219 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1220 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1221 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1222 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1224 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1225 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1226 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1227 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1228 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1229 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1230 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1231 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1232 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1233 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1234 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1235 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1236 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1237 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1238 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1239 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1240 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1241 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1242 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1243 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1244 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1245 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1246 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1247 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1248 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1249 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1250 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1251 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1252 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1253 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1254 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1255 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1256 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1257 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1258 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1259 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1260 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1261 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1262 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1263 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1264 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1265 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1266 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1267 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1268 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1269 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1270 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1271 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1272 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1273 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1274 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1275 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1276 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1277 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1278 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1279 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1280 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1281 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1282 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1283 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1284 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1285 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1286 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1287 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1289 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1290 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1291 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1292 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1293 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1294 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1295 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1296 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1297 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1298 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1300 /* 3RF instruction _df(bit 21) = _w, _d */
1301 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1302 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1303 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1304 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1305 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1306 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1307 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1308 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1309 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1310 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1311 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1312 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1313 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1314 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1315 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1316 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1317 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1318 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1319 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1320 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1321 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1322 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1323 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1324 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1325 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1326 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1327 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1328 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1329 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1330 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1331 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1332 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1333 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1334 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1335 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1336 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1337 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1338 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1339 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1340 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1341 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1343 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1344 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1345 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1346 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1347 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1348 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1349 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1350 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1351 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1352 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1353 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1354 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1355 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1358 /* global register indices */
1359 static TCGv_env cpu_env;
1360 static TCGv cpu_gpr[32], cpu_PC;
1361 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1362 static TCGv cpu_dspctrl, btarget, bcond;
1363 static TCGv_i32 hflags;
1364 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1365 static TCGv_i64 fpu_f64[32];
1366 static TCGv_i64 msa_wr_d[64];
1368 #include "exec/gen-icount.h"
1370 #define gen_helper_0e0i(name, arg) do { \
1371 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1372 gen_helper_##name(cpu_env, helper_tmp); \
1373 tcg_temp_free_i32(helper_tmp); \
1374 } while(0)
1376 #define gen_helper_0e1i(name, arg1, arg2) do { \
1377 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1378 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1379 tcg_temp_free_i32(helper_tmp); \
1380 } while(0)
1382 #define gen_helper_1e0i(name, ret, arg1) do { \
1383 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1384 gen_helper_##name(ret, cpu_env, helper_tmp); \
1385 tcg_temp_free_i32(helper_tmp); \
1386 } while(0)
1388 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1389 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1390 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1391 tcg_temp_free_i32(helper_tmp); \
1392 } while(0)
1394 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1395 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1396 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1397 tcg_temp_free_i32(helper_tmp); \
1398 } while(0)
1400 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1401 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1402 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1403 tcg_temp_free_i32(helper_tmp); \
1404 } while(0)
1406 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1407 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1408 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1409 tcg_temp_free_i32(helper_tmp); \
1410 } while(0)
1412 typedef struct DisasContext {
1413 struct TranslationBlock *tb;
1414 target_ulong pc, saved_pc;
1415 uint32_t opcode;
1416 int singlestep_enabled;
1417 int insn_flags;
1418 int32_t CP0_Config1;
1419 /* Routine used to access memory */
1420 int mem_idx;
1421 TCGMemOp default_tcg_memop_mask;
1422 uint32_t hflags, saved_hflags;
1423 int bstate;
1424 target_ulong btarget;
1425 bool ulri;
1426 int kscrexist;
1427 bool rxi;
1428 int ie;
1429 bool bi;
1430 bool bp;
1431 uint64_t PAMask;
1432 bool mvh;
1433 int CP0_LLAddr_shift;
1434 bool ps;
1435 bool vp;
1436 bool cmgcr;
1437 bool mrp;
1438 } DisasContext;
1440 enum {
1441 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1442 * exception condition */
1443 BS_STOP = 1, /* We want to stop translation for any reason */
1444 BS_BRANCH = 2, /* We reached a branch condition */
1445 BS_EXCP = 3, /* We reached an exception condition */
1448 static const char * const regnames[] = {
1449 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1450 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1451 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1452 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1455 static const char * const regnames_HI[] = {
1456 "HI0", "HI1", "HI2", "HI3",
1459 static const char * const regnames_LO[] = {
1460 "LO0", "LO1", "LO2", "LO3",
1463 static const char * const fregnames[] = {
1464 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1465 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1466 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1467 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1470 static const char * const msaregnames[] = {
1471 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1472 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1473 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1474 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1475 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1476 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1477 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1478 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1479 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1480 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1481 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1482 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1483 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1484 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1485 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1486 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1489 #define LOG_DISAS(...) \
1490 do { \
1491 if (MIPS_DEBUG_DISAS) { \
1492 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1494 } while (0)
1496 #define MIPS_INVAL(op) \
1497 do { \
1498 if (MIPS_DEBUG_DISAS) { \
1499 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1500 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
1501 ctx->pc, ctx->opcode, op, ctx->opcode >> 26, \
1502 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
1504 } while (0)
1506 /* General purpose registers moves. */
1507 static inline void gen_load_gpr (TCGv t, int reg)
1509 if (reg == 0)
1510 tcg_gen_movi_tl(t, 0);
1511 else
1512 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1515 static inline void gen_store_gpr (TCGv t, int reg)
1517 if (reg != 0)
1518 tcg_gen_mov_tl(cpu_gpr[reg], t);
1521 /* Moves to/from shadow registers. */
1522 static inline void gen_load_srsgpr (int from, int to)
1524 TCGv t0 = tcg_temp_new();
1526 if (from == 0)
1527 tcg_gen_movi_tl(t0, 0);
1528 else {
1529 TCGv_i32 t2 = tcg_temp_new_i32();
1530 TCGv_ptr addr = tcg_temp_new_ptr();
1532 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1533 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1534 tcg_gen_andi_i32(t2, t2, 0xf);
1535 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1536 tcg_gen_ext_i32_ptr(addr, t2);
1537 tcg_gen_add_ptr(addr, cpu_env, addr);
1539 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1540 tcg_temp_free_ptr(addr);
1541 tcg_temp_free_i32(t2);
1543 gen_store_gpr(t0, to);
1544 tcg_temp_free(t0);
1547 static inline void gen_store_srsgpr (int from, int to)
1549 if (to != 0) {
1550 TCGv t0 = tcg_temp_new();
1551 TCGv_i32 t2 = tcg_temp_new_i32();
1552 TCGv_ptr addr = tcg_temp_new_ptr();
1554 gen_load_gpr(t0, from);
1555 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1556 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1557 tcg_gen_andi_i32(t2, t2, 0xf);
1558 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1559 tcg_gen_ext_i32_ptr(addr, t2);
1560 tcg_gen_add_ptr(addr, cpu_env, addr);
1562 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1563 tcg_temp_free_ptr(addr);
1564 tcg_temp_free_i32(t2);
1565 tcg_temp_free(t0);
1569 /* Tests */
1570 static inline void gen_save_pc(target_ulong pc)
1572 tcg_gen_movi_tl(cpu_PC, pc);
1575 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1577 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1578 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1579 gen_save_pc(ctx->pc);
1580 ctx->saved_pc = ctx->pc;
1582 if (ctx->hflags != ctx->saved_hflags) {
1583 tcg_gen_movi_i32(hflags, ctx->hflags);
1584 ctx->saved_hflags = ctx->hflags;
1585 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1586 case MIPS_HFLAG_BR:
1587 break;
1588 case MIPS_HFLAG_BC:
1589 case MIPS_HFLAG_BL:
1590 case MIPS_HFLAG_B:
1591 tcg_gen_movi_tl(btarget, ctx->btarget);
1592 break;
1597 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1599 ctx->saved_hflags = ctx->hflags;
1600 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1601 case MIPS_HFLAG_BR:
1602 break;
1603 case MIPS_HFLAG_BC:
1604 case MIPS_HFLAG_BL:
1605 case MIPS_HFLAG_B:
1606 ctx->btarget = env->btarget;
1607 break;
1611 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1613 TCGv_i32 texcp = tcg_const_i32(excp);
1614 TCGv_i32 terr = tcg_const_i32(err);
1615 save_cpu_state(ctx, 1);
1616 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1617 tcg_temp_free_i32(terr);
1618 tcg_temp_free_i32(texcp);
1619 ctx->bstate = BS_EXCP;
1622 static inline void generate_exception(DisasContext *ctx, int excp)
1624 gen_helper_0e0i(raise_exception, excp);
1627 static inline void generate_exception_end(DisasContext *ctx, int excp)
1629 generate_exception_err(ctx, excp, 0);
1632 /* Floating point register moves. */
1633 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1635 if (ctx->hflags & MIPS_HFLAG_FRE) {
1636 generate_exception(ctx, EXCP_RI);
1638 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1641 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1643 TCGv_i64 t64;
1644 if (ctx->hflags & MIPS_HFLAG_FRE) {
1645 generate_exception(ctx, EXCP_RI);
1647 t64 = tcg_temp_new_i64();
1648 tcg_gen_extu_i32_i64(t64, t);
1649 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1650 tcg_temp_free_i64(t64);
1653 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1655 if (ctx->hflags & MIPS_HFLAG_F64) {
1656 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1657 } else {
1658 gen_load_fpr32(ctx, t, reg | 1);
1662 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1664 if (ctx->hflags & MIPS_HFLAG_F64) {
1665 TCGv_i64 t64 = tcg_temp_new_i64();
1666 tcg_gen_extu_i32_i64(t64, t);
1667 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1668 tcg_temp_free_i64(t64);
1669 } else {
1670 gen_store_fpr32(ctx, t, reg | 1);
1674 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1676 if (ctx->hflags & MIPS_HFLAG_F64) {
1677 tcg_gen_mov_i64(t, fpu_f64[reg]);
1678 } else {
1679 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1683 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1685 if (ctx->hflags & MIPS_HFLAG_F64) {
1686 tcg_gen_mov_i64(fpu_f64[reg], t);
1687 } else {
1688 TCGv_i64 t0;
1689 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1690 t0 = tcg_temp_new_i64();
1691 tcg_gen_shri_i64(t0, t, 32);
1692 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1693 tcg_temp_free_i64(t0);
1697 static inline int get_fp_bit (int cc)
1699 if (cc)
1700 return 24 + cc;
1701 else
1702 return 23;
1705 /* Addresses computation */
1706 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1708 tcg_gen_add_tl(ret, arg0, arg1);
1710 #if defined(TARGET_MIPS64)
1711 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1712 tcg_gen_ext32s_i64(ret, ret);
1714 #endif
1717 /* Addresses computation (translation time) */
1718 static target_long addr_add(DisasContext *ctx, target_long base,
1719 target_long offset)
1721 target_long sum = base + offset;
1723 #if defined(TARGET_MIPS64)
1724 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1725 sum = (int32_t)sum;
1727 #endif
1728 return sum;
1731 /* Sign-extract the low 32-bits to a target_long. */
1732 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
1734 #if defined(TARGET_MIPS64)
1735 tcg_gen_ext32s_i64(ret, arg);
1736 #else
1737 tcg_gen_extrl_i64_i32(ret, arg);
1738 #endif
1741 /* Sign-extract the high 32-bits to a target_long. */
1742 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
1744 #if defined(TARGET_MIPS64)
1745 tcg_gen_sari_i64(ret, arg, 32);
1746 #else
1747 tcg_gen_extrh_i64_i32(ret, arg);
1748 #endif
1751 static inline void check_cp0_enabled(DisasContext *ctx)
1753 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1754 generate_exception_err(ctx, EXCP_CpU, 0);
1757 static inline void check_cp1_enabled(DisasContext *ctx)
1759 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1760 generate_exception_err(ctx, EXCP_CpU, 1);
1763 /* Verify that the processor is running with COP1X instructions enabled.
1764 This is associated with the nabla symbol in the MIPS32 and MIPS64
1765 opcode tables. */
1767 static inline void check_cop1x(DisasContext *ctx)
1769 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1770 generate_exception_end(ctx, EXCP_RI);
1773 /* Verify that the processor is running with 64-bit floating-point
1774 operations enabled. */
1776 static inline void check_cp1_64bitmode(DisasContext *ctx)
1778 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1779 generate_exception_end(ctx, EXCP_RI);
1783 * Verify if floating point register is valid; an operation is not defined
1784 * if bit 0 of any register specification is set and the FR bit in the
1785 * Status register equals zero, since the register numbers specify an
1786 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1787 * in the Status register equals one, both even and odd register numbers
1788 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1790 * Multiple 64 bit wide registers can be checked by calling
1791 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1793 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1795 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1796 generate_exception_end(ctx, EXCP_RI);
1799 /* Verify that the processor is running with DSP instructions enabled.
1800 This is enabled by CP0 Status register MX(24) bit.
1803 static inline void check_dsp(DisasContext *ctx)
1805 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1806 if (ctx->insn_flags & ASE_DSP) {
1807 generate_exception_end(ctx, EXCP_DSPDIS);
1808 } else {
1809 generate_exception_end(ctx, EXCP_RI);
1814 static inline void check_dspr2(DisasContext *ctx)
1816 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1817 if (ctx->insn_flags & ASE_DSP) {
1818 generate_exception_end(ctx, EXCP_DSPDIS);
1819 } else {
1820 generate_exception_end(ctx, EXCP_RI);
1825 /* This code generates a "reserved instruction" exception if the
1826 CPU does not support the instruction set corresponding to flags. */
1827 static inline void check_insn(DisasContext *ctx, int flags)
1829 if (unlikely(!(ctx->insn_flags & flags))) {
1830 generate_exception_end(ctx, EXCP_RI);
1834 /* This code generates a "reserved instruction" exception if the
1835 CPU has corresponding flag set which indicates that the instruction
1836 has been removed. */
1837 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1839 if (unlikely(ctx->insn_flags & flags)) {
1840 generate_exception_end(ctx, EXCP_RI);
1844 /* This code generates a "reserved instruction" exception if the
1845 CPU does not support 64-bit paired-single (PS) floating point data type */
1846 static inline void check_ps(DisasContext *ctx)
1848 if (unlikely(!ctx->ps)) {
1849 generate_exception(ctx, EXCP_RI);
1851 check_cp1_64bitmode(ctx);
1854 #ifdef TARGET_MIPS64
1855 /* This code generates a "reserved instruction" exception if 64-bit
1856 instructions are not enabled. */
1857 static inline void check_mips_64(DisasContext *ctx)
1859 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1860 generate_exception_end(ctx, EXCP_RI);
1862 #endif
1864 #ifndef CONFIG_USER_ONLY
1865 static inline void check_mvh(DisasContext *ctx)
1867 if (unlikely(!ctx->mvh)) {
1868 generate_exception(ctx, EXCP_RI);
1871 #endif
1873 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1874 calling interface for 32 and 64-bit FPRs. No sense in changing
1875 all callers for gen_load_fpr32 when we need the CTX parameter for
1876 this one use. */
1877 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1878 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1879 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1880 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1881 int ft, int fs, int cc) \
1883 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1884 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1885 switch (ifmt) { \
1886 case FMT_PS: \
1887 check_ps(ctx); \
1888 break; \
1889 case FMT_D: \
1890 if (abs) { \
1891 check_cop1x(ctx); \
1893 check_cp1_registers(ctx, fs | ft); \
1894 break; \
1895 case FMT_S: \
1896 if (abs) { \
1897 check_cop1x(ctx); \
1899 break; \
1901 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1902 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1903 switch (n) { \
1904 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1905 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1906 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1907 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1908 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1909 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1910 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1911 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1912 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1913 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1914 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1915 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1916 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1917 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1918 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1919 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1920 default: abort(); \
1922 tcg_temp_free_i##bits (fp0); \
1923 tcg_temp_free_i##bits (fp1); \
1926 FOP_CONDS(, 0, d, FMT_D, 64)
1927 FOP_CONDS(abs, 1, d, FMT_D, 64)
1928 FOP_CONDS(, 0, s, FMT_S, 32)
1929 FOP_CONDS(abs, 1, s, FMT_S, 32)
1930 FOP_CONDS(, 0, ps, FMT_PS, 64)
1931 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1932 #undef FOP_CONDS
1934 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1935 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1936 int ft, int fs, int fd) \
1938 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1939 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1940 if (ifmt == FMT_D) { \
1941 check_cp1_registers(ctx, fs | ft | fd); \
1943 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1944 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1945 switch (n) { \
1946 case 0: \
1947 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1948 break; \
1949 case 1: \
1950 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1951 break; \
1952 case 2: \
1953 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1954 break; \
1955 case 3: \
1956 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1957 break; \
1958 case 4: \
1959 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1960 break; \
1961 case 5: \
1962 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1963 break; \
1964 case 6: \
1965 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1966 break; \
1967 case 7: \
1968 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1969 break; \
1970 case 8: \
1971 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1972 break; \
1973 case 9: \
1974 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1975 break; \
1976 case 10: \
1977 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1978 break; \
1979 case 11: \
1980 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1981 break; \
1982 case 12: \
1983 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1984 break; \
1985 case 13: \
1986 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1987 break; \
1988 case 14: \
1989 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1990 break; \
1991 case 15: \
1992 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1993 break; \
1994 case 17: \
1995 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1996 break; \
1997 case 18: \
1998 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1999 break; \
2000 case 19: \
2001 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2002 break; \
2003 case 25: \
2004 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2005 break; \
2006 case 26: \
2007 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2008 break; \
2009 case 27: \
2010 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2011 break; \
2012 default: \
2013 abort(); \
2015 STORE; \
2016 tcg_temp_free_i ## bits (fp0); \
2017 tcg_temp_free_i ## bits (fp1); \
2020 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2021 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2022 #undef FOP_CONDNS
2023 #undef gen_ldcmp_fpr32
2024 #undef gen_ldcmp_fpr64
2026 /* load/store instructions. */
2027 #ifdef CONFIG_USER_ONLY
2028 #define OP_LD_ATOMIC(insn,fname) \
2029 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2031 TCGv t0 = tcg_temp_new(); \
2032 tcg_gen_mov_tl(t0, arg1); \
2033 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2034 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2035 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2036 tcg_temp_free(t0); \
2038 #else
2039 #define OP_LD_ATOMIC(insn,fname) \
2040 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2042 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
2044 #endif
2045 OP_LD_ATOMIC(ll,ld32s);
2046 #if defined(TARGET_MIPS64)
2047 OP_LD_ATOMIC(lld,ld64);
2048 #endif
2049 #undef OP_LD_ATOMIC
2051 #ifdef CONFIG_USER_ONLY
2052 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2053 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2055 TCGv t0 = tcg_temp_new(); \
2056 TCGLabel *l1 = gen_new_label(); \
2057 TCGLabel *l2 = gen_new_label(); \
2059 tcg_gen_andi_tl(t0, arg2, almask); \
2060 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2061 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2062 generate_exception(ctx, EXCP_AdES); \
2063 gen_set_label(l1); \
2064 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2065 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2066 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2067 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2068 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2069 generate_exception_end(ctx, EXCP_SC); \
2070 gen_set_label(l2); \
2071 tcg_gen_movi_tl(t0, 0); \
2072 gen_store_gpr(t0, rt); \
2073 tcg_temp_free(t0); \
2075 #else
2076 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2077 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2079 TCGv t0 = tcg_temp_new(); \
2080 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
2081 gen_store_gpr(t0, rt); \
2082 tcg_temp_free(t0); \
2084 #endif
2085 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2086 #if defined(TARGET_MIPS64)
2087 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2088 #endif
2089 #undef OP_ST_ATOMIC
2091 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2092 int base, int16_t offset)
2094 if (base == 0) {
2095 tcg_gen_movi_tl(addr, offset);
2096 } else if (offset == 0) {
2097 gen_load_gpr(addr, base);
2098 } else {
2099 tcg_gen_movi_tl(addr, offset);
2100 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2104 static target_ulong pc_relative_pc (DisasContext *ctx)
2106 target_ulong pc = ctx->pc;
2108 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2109 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2111 pc -= branch_bytes;
2114 pc &= ~(target_ulong)3;
2115 return pc;
2118 /* Load */
2119 static void gen_ld(DisasContext *ctx, uint32_t opc,
2120 int rt, int base, int16_t offset)
2122 TCGv t0, t1, t2;
2124 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2125 /* Loongson CPU uses a load to zero register for prefetch.
2126 We emulate it as a NOP. On other CPU we must perform the
2127 actual memory access. */
2128 return;
2131 t0 = tcg_temp_new();
2132 gen_base_offset_addr(ctx, t0, base, offset);
2134 switch (opc) {
2135 #if defined(TARGET_MIPS64)
2136 case OPC_LWU:
2137 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL |
2138 ctx->default_tcg_memop_mask);
2139 gen_store_gpr(t0, rt);
2140 break;
2141 case OPC_LD:
2142 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
2143 ctx->default_tcg_memop_mask);
2144 gen_store_gpr(t0, rt);
2145 break;
2146 case OPC_LLD:
2147 case R6_OPC_LLD:
2148 op_ld_lld(t0, t0, ctx);
2149 gen_store_gpr(t0, rt);
2150 break;
2151 case OPC_LDL:
2152 t1 = tcg_temp_new();
2153 /* Do a byte access to possibly trigger a page
2154 fault with the unaligned address. */
2155 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2156 tcg_gen_andi_tl(t1, t0, 7);
2157 #ifndef TARGET_WORDS_BIGENDIAN
2158 tcg_gen_xori_tl(t1, t1, 7);
2159 #endif
2160 tcg_gen_shli_tl(t1, t1, 3);
2161 tcg_gen_andi_tl(t0, t0, ~7);
2162 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2163 tcg_gen_shl_tl(t0, t0, t1);
2164 t2 = tcg_const_tl(-1);
2165 tcg_gen_shl_tl(t2, t2, t1);
2166 gen_load_gpr(t1, rt);
2167 tcg_gen_andc_tl(t1, t1, t2);
2168 tcg_temp_free(t2);
2169 tcg_gen_or_tl(t0, t0, t1);
2170 tcg_temp_free(t1);
2171 gen_store_gpr(t0, rt);
2172 break;
2173 case OPC_LDR:
2174 t1 = tcg_temp_new();
2175 /* Do a byte access to possibly trigger a page
2176 fault with the unaligned address. */
2177 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2178 tcg_gen_andi_tl(t1, t0, 7);
2179 #ifdef TARGET_WORDS_BIGENDIAN
2180 tcg_gen_xori_tl(t1, t1, 7);
2181 #endif
2182 tcg_gen_shli_tl(t1, t1, 3);
2183 tcg_gen_andi_tl(t0, t0, ~7);
2184 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2185 tcg_gen_shr_tl(t0, t0, t1);
2186 tcg_gen_xori_tl(t1, t1, 63);
2187 t2 = tcg_const_tl(0xfffffffffffffffeull);
2188 tcg_gen_shl_tl(t2, t2, t1);
2189 gen_load_gpr(t1, rt);
2190 tcg_gen_and_tl(t1, t1, t2);
2191 tcg_temp_free(t2);
2192 tcg_gen_or_tl(t0, t0, t1);
2193 tcg_temp_free(t1);
2194 gen_store_gpr(t0, rt);
2195 break;
2196 case OPC_LDPC:
2197 t1 = tcg_const_tl(pc_relative_pc(ctx));
2198 gen_op_addr_add(ctx, t0, t0, t1);
2199 tcg_temp_free(t1);
2200 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2201 gen_store_gpr(t0, rt);
2202 break;
2203 #endif
2204 case OPC_LWPC:
2205 t1 = tcg_const_tl(pc_relative_pc(ctx));
2206 gen_op_addr_add(ctx, t0, t0, t1);
2207 tcg_temp_free(t1);
2208 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2209 gen_store_gpr(t0, rt);
2210 break;
2211 case OPC_LW:
2212 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
2213 ctx->default_tcg_memop_mask);
2214 gen_store_gpr(t0, rt);
2215 break;
2216 case OPC_LH:
2217 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
2218 ctx->default_tcg_memop_mask);
2219 gen_store_gpr(t0, rt);
2220 break;
2221 case OPC_LHU:
2222 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW |
2223 ctx->default_tcg_memop_mask);
2224 gen_store_gpr(t0, rt);
2225 break;
2226 case OPC_LB:
2227 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
2228 gen_store_gpr(t0, rt);
2229 break;
2230 case OPC_LBU:
2231 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
2232 gen_store_gpr(t0, rt);
2233 break;
2234 case OPC_LWL:
2235 t1 = tcg_temp_new();
2236 /* Do a byte access to possibly trigger a page
2237 fault with the unaligned address. */
2238 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2239 tcg_gen_andi_tl(t1, t0, 3);
2240 #ifndef TARGET_WORDS_BIGENDIAN
2241 tcg_gen_xori_tl(t1, t1, 3);
2242 #endif
2243 tcg_gen_shli_tl(t1, t1, 3);
2244 tcg_gen_andi_tl(t0, t0, ~3);
2245 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2246 tcg_gen_shl_tl(t0, t0, t1);
2247 t2 = tcg_const_tl(-1);
2248 tcg_gen_shl_tl(t2, t2, t1);
2249 gen_load_gpr(t1, rt);
2250 tcg_gen_andc_tl(t1, t1, t2);
2251 tcg_temp_free(t2);
2252 tcg_gen_or_tl(t0, t0, t1);
2253 tcg_temp_free(t1);
2254 tcg_gen_ext32s_tl(t0, t0);
2255 gen_store_gpr(t0, rt);
2256 break;
2257 case OPC_LWR:
2258 t1 = tcg_temp_new();
2259 /* Do a byte access to possibly trigger a page
2260 fault with the unaligned address. */
2261 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2262 tcg_gen_andi_tl(t1, t0, 3);
2263 #ifdef TARGET_WORDS_BIGENDIAN
2264 tcg_gen_xori_tl(t1, t1, 3);
2265 #endif
2266 tcg_gen_shli_tl(t1, t1, 3);
2267 tcg_gen_andi_tl(t0, t0, ~3);
2268 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2269 tcg_gen_shr_tl(t0, t0, t1);
2270 tcg_gen_xori_tl(t1, t1, 31);
2271 t2 = tcg_const_tl(0xfffffffeull);
2272 tcg_gen_shl_tl(t2, t2, t1);
2273 gen_load_gpr(t1, rt);
2274 tcg_gen_and_tl(t1, t1, t2);
2275 tcg_temp_free(t2);
2276 tcg_gen_or_tl(t0, t0, t1);
2277 tcg_temp_free(t1);
2278 tcg_gen_ext32s_tl(t0, t0);
2279 gen_store_gpr(t0, rt);
2280 break;
2281 case OPC_LL:
2282 case R6_OPC_LL:
2283 op_ld_ll(t0, t0, ctx);
2284 gen_store_gpr(t0, rt);
2285 break;
2287 tcg_temp_free(t0);
2290 /* Store */
2291 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2292 int base, int16_t offset)
2294 TCGv t0 = tcg_temp_new();
2295 TCGv t1 = tcg_temp_new();
2297 gen_base_offset_addr(ctx, t0, base, offset);
2298 gen_load_gpr(t1, rt);
2299 switch (opc) {
2300 #if defined(TARGET_MIPS64)
2301 case OPC_SD:
2302 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
2303 ctx->default_tcg_memop_mask);
2304 break;
2305 case OPC_SDL:
2306 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
2307 break;
2308 case OPC_SDR:
2309 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2310 break;
2311 #endif
2312 case OPC_SW:
2313 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
2314 ctx->default_tcg_memop_mask);
2315 break;
2316 case OPC_SH:
2317 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
2318 ctx->default_tcg_memop_mask);
2319 break;
2320 case OPC_SB:
2321 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2322 break;
2323 case OPC_SWL:
2324 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2325 break;
2326 case OPC_SWR:
2327 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2328 break;
2330 tcg_temp_free(t0);
2331 tcg_temp_free(t1);
2335 /* Store conditional */
2336 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2337 int base, int16_t offset)
2339 TCGv t0, t1;
2341 #ifdef CONFIG_USER_ONLY
2342 t0 = tcg_temp_local_new();
2343 t1 = tcg_temp_local_new();
2344 #else
2345 t0 = tcg_temp_new();
2346 t1 = tcg_temp_new();
2347 #endif
2348 gen_base_offset_addr(ctx, t0, base, offset);
2349 gen_load_gpr(t1, rt);
2350 switch (opc) {
2351 #if defined(TARGET_MIPS64)
2352 case OPC_SCD:
2353 case R6_OPC_SCD:
2354 op_st_scd(t1, t0, rt, ctx);
2355 break;
2356 #endif
2357 case OPC_SC:
2358 case R6_OPC_SC:
2359 op_st_sc(t1, t0, rt, ctx);
2360 break;
2362 tcg_temp_free(t1);
2363 tcg_temp_free(t0);
2366 /* Load and store */
2367 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2368 int base, int16_t offset)
2370 TCGv t0 = tcg_temp_new();
2372 gen_base_offset_addr(ctx, t0, base, offset);
2373 /* Don't do NOP if destination is zero: we must perform the actual
2374 memory access. */
2375 switch (opc) {
2376 case OPC_LWC1:
2378 TCGv_i32 fp0 = tcg_temp_new_i32();
2379 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2380 ctx->default_tcg_memop_mask);
2381 gen_store_fpr32(ctx, fp0, ft);
2382 tcg_temp_free_i32(fp0);
2384 break;
2385 case OPC_SWC1:
2387 TCGv_i32 fp0 = tcg_temp_new_i32();
2388 gen_load_fpr32(ctx, fp0, ft);
2389 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2390 ctx->default_tcg_memop_mask);
2391 tcg_temp_free_i32(fp0);
2393 break;
2394 case OPC_LDC1:
2396 TCGv_i64 fp0 = tcg_temp_new_i64();
2397 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2398 ctx->default_tcg_memop_mask);
2399 gen_store_fpr64(ctx, fp0, ft);
2400 tcg_temp_free_i64(fp0);
2402 break;
2403 case OPC_SDC1:
2405 TCGv_i64 fp0 = tcg_temp_new_i64();
2406 gen_load_fpr64(ctx, fp0, ft);
2407 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2408 ctx->default_tcg_memop_mask);
2409 tcg_temp_free_i64(fp0);
2411 break;
2412 default:
2413 MIPS_INVAL("flt_ldst");
2414 generate_exception_end(ctx, EXCP_RI);
2415 goto out;
2417 out:
2418 tcg_temp_free(t0);
2421 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2422 int rs, int16_t imm)
2424 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2425 check_cp1_enabled(ctx);
2426 switch (op) {
2427 case OPC_LDC1:
2428 case OPC_SDC1:
2429 check_insn(ctx, ISA_MIPS2);
2430 /* Fallthrough */
2431 default:
2432 gen_flt_ldst(ctx, op, rt, rs, imm);
2434 } else {
2435 generate_exception_err(ctx, EXCP_CpU, 1);
2439 /* Arithmetic with immediate operand */
2440 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2441 int rt, int rs, int16_t imm)
2443 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2445 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2446 /* If no destination, treat it as a NOP.
2447 For addi, we must generate the overflow exception when needed. */
2448 return;
2450 switch (opc) {
2451 case OPC_ADDI:
2453 TCGv t0 = tcg_temp_local_new();
2454 TCGv t1 = tcg_temp_new();
2455 TCGv t2 = tcg_temp_new();
2456 TCGLabel *l1 = gen_new_label();
2458 gen_load_gpr(t1, rs);
2459 tcg_gen_addi_tl(t0, t1, uimm);
2460 tcg_gen_ext32s_tl(t0, t0);
2462 tcg_gen_xori_tl(t1, t1, ~uimm);
2463 tcg_gen_xori_tl(t2, t0, uimm);
2464 tcg_gen_and_tl(t1, t1, t2);
2465 tcg_temp_free(t2);
2466 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2467 tcg_temp_free(t1);
2468 /* operands of same sign, result different sign */
2469 generate_exception(ctx, EXCP_OVERFLOW);
2470 gen_set_label(l1);
2471 tcg_gen_ext32s_tl(t0, t0);
2472 gen_store_gpr(t0, rt);
2473 tcg_temp_free(t0);
2475 break;
2476 case OPC_ADDIU:
2477 if (rs != 0) {
2478 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2479 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2480 } else {
2481 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2483 break;
2484 #if defined(TARGET_MIPS64)
2485 case OPC_DADDI:
2487 TCGv t0 = tcg_temp_local_new();
2488 TCGv t1 = tcg_temp_new();
2489 TCGv t2 = tcg_temp_new();
2490 TCGLabel *l1 = gen_new_label();
2492 gen_load_gpr(t1, rs);
2493 tcg_gen_addi_tl(t0, t1, uimm);
2495 tcg_gen_xori_tl(t1, t1, ~uimm);
2496 tcg_gen_xori_tl(t2, t0, uimm);
2497 tcg_gen_and_tl(t1, t1, t2);
2498 tcg_temp_free(t2);
2499 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2500 tcg_temp_free(t1);
2501 /* operands of same sign, result different sign */
2502 generate_exception(ctx, EXCP_OVERFLOW);
2503 gen_set_label(l1);
2504 gen_store_gpr(t0, rt);
2505 tcg_temp_free(t0);
2507 break;
2508 case OPC_DADDIU:
2509 if (rs != 0) {
2510 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2511 } else {
2512 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2514 break;
2515 #endif
2519 /* Logic with immediate operand */
2520 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2521 int rt, int rs, int16_t imm)
2523 target_ulong uimm;
2525 if (rt == 0) {
2526 /* If no destination, treat it as a NOP. */
2527 return;
2529 uimm = (uint16_t)imm;
2530 switch (opc) {
2531 case OPC_ANDI:
2532 if (likely(rs != 0))
2533 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2534 else
2535 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2536 break;
2537 case OPC_ORI:
2538 if (rs != 0)
2539 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2540 else
2541 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2542 break;
2543 case OPC_XORI:
2544 if (likely(rs != 0))
2545 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2546 else
2547 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2548 break;
2549 case OPC_LUI:
2550 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2551 /* OPC_AUI */
2552 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2553 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2554 } else {
2555 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2557 break;
2559 default:
2560 break;
2564 /* Set on less than with immediate operand */
2565 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2566 int rt, int rs, int16_t imm)
2568 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2569 TCGv t0;
2571 if (rt == 0) {
2572 /* If no destination, treat it as a NOP. */
2573 return;
2575 t0 = tcg_temp_new();
2576 gen_load_gpr(t0, rs);
2577 switch (opc) {
2578 case OPC_SLTI:
2579 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2580 break;
2581 case OPC_SLTIU:
2582 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2583 break;
2585 tcg_temp_free(t0);
2588 /* Shifts with immediate operand */
2589 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2590 int rt, int rs, int16_t imm)
2592 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2593 TCGv t0;
2595 if (rt == 0) {
2596 /* If no destination, treat it as a NOP. */
2597 return;
2600 t0 = tcg_temp_new();
2601 gen_load_gpr(t0, rs);
2602 switch (opc) {
2603 case OPC_SLL:
2604 tcg_gen_shli_tl(t0, t0, uimm);
2605 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2606 break;
2607 case OPC_SRA:
2608 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2609 break;
2610 case OPC_SRL:
2611 if (uimm != 0) {
2612 tcg_gen_ext32u_tl(t0, t0);
2613 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2614 } else {
2615 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2617 break;
2618 case OPC_ROTR:
2619 if (uimm != 0) {
2620 TCGv_i32 t1 = tcg_temp_new_i32();
2622 tcg_gen_trunc_tl_i32(t1, t0);
2623 tcg_gen_rotri_i32(t1, t1, uimm);
2624 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2625 tcg_temp_free_i32(t1);
2626 } else {
2627 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2629 break;
2630 #if defined(TARGET_MIPS64)
2631 case OPC_DSLL:
2632 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2633 break;
2634 case OPC_DSRA:
2635 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2636 break;
2637 case OPC_DSRL:
2638 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2639 break;
2640 case OPC_DROTR:
2641 if (uimm != 0) {
2642 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2643 } else {
2644 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2646 break;
2647 case OPC_DSLL32:
2648 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2649 break;
2650 case OPC_DSRA32:
2651 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2652 break;
2653 case OPC_DSRL32:
2654 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2655 break;
2656 case OPC_DROTR32:
2657 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2658 break;
2659 #endif
2661 tcg_temp_free(t0);
2664 /* Arithmetic */
2665 static void gen_arith(DisasContext *ctx, uint32_t opc,
2666 int rd, int rs, int rt)
2668 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2669 && opc != OPC_DADD && opc != OPC_DSUB) {
2670 /* If no destination, treat it as a NOP.
2671 For add & sub, we must generate the overflow exception when needed. */
2672 return;
2675 switch (opc) {
2676 case OPC_ADD:
2678 TCGv t0 = tcg_temp_local_new();
2679 TCGv t1 = tcg_temp_new();
2680 TCGv t2 = tcg_temp_new();
2681 TCGLabel *l1 = gen_new_label();
2683 gen_load_gpr(t1, rs);
2684 gen_load_gpr(t2, rt);
2685 tcg_gen_add_tl(t0, t1, t2);
2686 tcg_gen_ext32s_tl(t0, t0);
2687 tcg_gen_xor_tl(t1, t1, t2);
2688 tcg_gen_xor_tl(t2, t0, t2);
2689 tcg_gen_andc_tl(t1, t2, t1);
2690 tcg_temp_free(t2);
2691 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2692 tcg_temp_free(t1);
2693 /* operands of same sign, result different sign */
2694 generate_exception(ctx, EXCP_OVERFLOW);
2695 gen_set_label(l1);
2696 gen_store_gpr(t0, rd);
2697 tcg_temp_free(t0);
2699 break;
2700 case OPC_ADDU:
2701 if (rs != 0 && rt != 0) {
2702 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2703 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2704 } else if (rs == 0 && rt != 0) {
2705 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2706 } else if (rs != 0 && rt == 0) {
2707 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2708 } else {
2709 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2711 break;
2712 case OPC_SUB:
2714 TCGv t0 = tcg_temp_local_new();
2715 TCGv t1 = tcg_temp_new();
2716 TCGv t2 = tcg_temp_new();
2717 TCGLabel *l1 = gen_new_label();
2719 gen_load_gpr(t1, rs);
2720 gen_load_gpr(t2, rt);
2721 tcg_gen_sub_tl(t0, t1, t2);
2722 tcg_gen_ext32s_tl(t0, t0);
2723 tcg_gen_xor_tl(t2, t1, t2);
2724 tcg_gen_xor_tl(t1, t0, t1);
2725 tcg_gen_and_tl(t1, t1, t2);
2726 tcg_temp_free(t2);
2727 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2728 tcg_temp_free(t1);
2729 /* operands of different sign, first operand and result different sign */
2730 generate_exception(ctx, EXCP_OVERFLOW);
2731 gen_set_label(l1);
2732 gen_store_gpr(t0, rd);
2733 tcg_temp_free(t0);
2735 break;
2736 case OPC_SUBU:
2737 if (rs != 0 && rt != 0) {
2738 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2739 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2740 } else if (rs == 0 && rt != 0) {
2741 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2742 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2743 } else if (rs != 0 && rt == 0) {
2744 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2745 } else {
2746 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2748 break;
2749 #if defined(TARGET_MIPS64)
2750 case OPC_DADD:
2752 TCGv t0 = tcg_temp_local_new();
2753 TCGv t1 = tcg_temp_new();
2754 TCGv t2 = tcg_temp_new();
2755 TCGLabel *l1 = gen_new_label();
2757 gen_load_gpr(t1, rs);
2758 gen_load_gpr(t2, rt);
2759 tcg_gen_add_tl(t0, t1, t2);
2760 tcg_gen_xor_tl(t1, t1, t2);
2761 tcg_gen_xor_tl(t2, t0, t2);
2762 tcg_gen_andc_tl(t1, t2, t1);
2763 tcg_temp_free(t2);
2764 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2765 tcg_temp_free(t1);
2766 /* operands of same sign, result different sign */
2767 generate_exception(ctx, EXCP_OVERFLOW);
2768 gen_set_label(l1);
2769 gen_store_gpr(t0, rd);
2770 tcg_temp_free(t0);
2772 break;
2773 case OPC_DADDU:
2774 if (rs != 0 && rt != 0) {
2775 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2776 } else if (rs == 0 && rt != 0) {
2777 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2778 } else if (rs != 0 && rt == 0) {
2779 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2780 } else {
2781 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2783 break;
2784 case OPC_DSUB:
2786 TCGv t0 = tcg_temp_local_new();
2787 TCGv t1 = tcg_temp_new();
2788 TCGv t2 = tcg_temp_new();
2789 TCGLabel *l1 = gen_new_label();
2791 gen_load_gpr(t1, rs);
2792 gen_load_gpr(t2, rt);
2793 tcg_gen_sub_tl(t0, t1, t2);
2794 tcg_gen_xor_tl(t2, t1, t2);
2795 tcg_gen_xor_tl(t1, t0, t1);
2796 tcg_gen_and_tl(t1, t1, t2);
2797 tcg_temp_free(t2);
2798 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2799 tcg_temp_free(t1);
2800 /* operands of different sign, first operand and result different sign */
2801 generate_exception(ctx, EXCP_OVERFLOW);
2802 gen_set_label(l1);
2803 gen_store_gpr(t0, rd);
2804 tcg_temp_free(t0);
2806 break;
2807 case OPC_DSUBU:
2808 if (rs != 0 && rt != 0) {
2809 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2810 } else if (rs == 0 && rt != 0) {
2811 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2812 } else if (rs != 0 && rt == 0) {
2813 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2814 } else {
2815 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2817 break;
2818 #endif
2819 case OPC_MUL:
2820 if (likely(rs != 0 && rt != 0)) {
2821 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2822 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2823 } else {
2824 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2826 break;
2830 /* Conditional move */
2831 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2832 int rd, int rs, int rt)
2834 TCGv t0, t1, t2;
2836 if (rd == 0) {
2837 /* If no destination, treat it as a NOP. */
2838 return;
2841 t0 = tcg_temp_new();
2842 gen_load_gpr(t0, rt);
2843 t1 = tcg_const_tl(0);
2844 t2 = tcg_temp_new();
2845 gen_load_gpr(t2, rs);
2846 switch (opc) {
2847 case OPC_MOVN:
2848 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2849 break;
2850 case OPC_MOVZ:
2851 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2852 break;
2853 case OPC_SELNEZ:
2854 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2855 break;
2856 case OPC_SELEQZ:
2857 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2858 break;
2860 tcg_temp_free(t2);
2861 tcg_temp_free(t1);
2862 tcg_temp_free(t0);
2865 /* Logic */
2866 static void gen_logic(DisasContext *ctx, uint32_t opc,
2867 int rd, int rs, int rt)
2869 if (rd == 0) {
2870 /* If no destination, treat it as a NOP. */
2871 return;
2874 switch (opc) {
2875 case OPC_AND:
2876 if (likely(rs != 0 && rt != 0)) {
2877 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2878 } else {
2879 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2881 break;
2882 case OPC_NOR:
2883 if (rs != 0 && rt != 0) {
2884 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2885 } else if (rs == 0 && rt != 0) {
2886 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2887 } else if (rs != 0 && rt == 0) {
2888 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2889 } else {
2890 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2892 break;
2893 case OPC_OR:
2894 if (likely(rs != 0 && rt != 0)) {
2895 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2896 } else if (rs == 0 && rt != 0) {
2897 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2898 } else if (rs != 0 && rt == 0) {
2899 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2900 } else {
2901 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2903 break;
2904 case OPC_XOR:
2905 if (likely(rs != 0 && rt != 0)) {
2906 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2907 } else if (rs == 0 && rt != 0) {
2908 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2909 } else if (rs != 0 && rt == 0) {
2910 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2911 } else {
2912 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2914 break;
2918 /* Set on lower than */
2919 static void gen_slt(DisasContext *ctx, uint32_t opc,
2920 int rd, int rs, int rt)
2922 TCGv t0, t1;
2924 if (rd == 0) {
2925 /* If no destination, treat it as a NOP. */
2926 return;
2929 t0 = tcg_temp_new();
2930 t1 = tcg_temp_new();
2931 gen_load_gpr(t0, rs);
2932 gen_load_gpr(t1, rt);
2933 switch (opc) {
2934 case OPC_SLT:
2935 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2936 break;
2937 case OPC_SLTU:
2938 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2939 break;
2941 tcg_temp_free(t0);
2942 tcg_temp_free(t1);
2945 /* Shifts */
2946 static void gen_shift(DisasContext *ctx, uint32_t opc,
2947 int rd, int rs, int rt)
2949 TCGv t0, t1;
2951 if (rd == 0) {
2952 /* If no destination, treat it as a NOP.
2953 For add & sub, we must generate the overflow exception when needed. */
2954 return;
2957 t0 = tcg_temp_new();
2958 t1 = tcg_temp_new();
2959 gen_load_gpr(t0, rs);
2960 gen_load_gpr(t1, rt);
2961 switch (opc) {
2962 case OPC_SLLV:
2963 tcg_gen_andi_tl(t0, t0, 0x1f);
2964 tcg_gen_shl_tl(t0, t1, t0);
2965 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2966 break;
2967 case OPC_SRAV:
2968 tcg_gen_andi_tl(t0, t0, 0x1f);
2969 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2970 break;
2971 case OPC_SRLV:
2972 tcg_gen_ext32u_tl(t1, t1);
2973 tcg_gen_andi_tl(t0, t0, 0x1f);
2974 tcg_gen_shr_tl(t0, t1, t0);
2975 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2976 break;
2977 case OPC_ROTRV:
2979 TCGv_i32 t2 = tcg_temp_new_i32();
2980 TCGv_i32 t3 = tcg_temp_new_i32();
2982 tcg_gen_trunc_tl_i32(t2, t0);
2983 tcg_gen_trunc_tl_i32(t3, t1);
2984 tcg_gen_andi_i32(t2, t2, 0x1f);
2985 tcg_gen_rotr_i32(t2, t3, t2);
2986 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2987 tcg_temp_free_i32(t2);
2988 tcg_temp_free_i32(t3);
2990 break;
2991 #if defined(TARGET_MIPS64)
2992 case OPC_DSLLV:
2993 tcg_gen_andi_tl(t0, t0, 0x3f);
2994 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2995 break;
2996 case OPC_DSRAV:
2997 tcg_gen_andi_tl(t0, t0, 0x3f);
2998 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2999 break;
3000 case OPC_DSRLV:
3001 tcg_gen_andi_tl(t0, t0, 0x3f);
3002 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3003 break;
3004 case OPC_DROTRV:
3005 tcg_gen_andi_tl(t0, t0, 0x3f);
3006 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3007 break;
3008 #endif
3010 tcg_temp_free(t0);
3011 tcg_temp_free(t1);
3014 /* Arithmetic on HI/LO registers */
3015 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3017 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3018 /* Treat as NOP. */
3019 return;
3022 if (acc != 0) {
3023 check_dsp(ctx);
3026 switch (opc) {
3027 case OPC_MFHI:
3028 #if defined(TARGET_MIPS64)
3029 if (acc != 0) {
3030 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3031 } else
3032 #endif
3034 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3036 break;
3037 case OPC_MFLO:
3038 #if defined(TARGET_MIPS64)
3039 if (acc != 0) {
3040 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3041 } else
3042 #endif
3044 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3046 break;
3047 case OPC_MTHI:
3048 if (reg != 0) {
3049 #if defined(TARGET_MIPS64)
3050 if (acc != 0) {
3051 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3052 } else
3053 #endif
3055 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3057 } else {
3058 tcg_gen_movi_tl(cpu_HI[acc], 0);
3060 break;
3061 case OPC_MTLO:
3062 if (reg != 0) {
3063 #if defined(TARGET_MIPS64)
3064 if (acc != 0) {
3065 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3066 } else
3067 #endif
3069 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3071 } else {
3072 tcg_gen_movi_tl(cpu_LO[acc], 0);
3074 break;
3078 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3079 TCGMemOp memop)
3081 TCGv t0 = tcg_const_tl(addr);
3082 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3083 gen_store_gpr(t0, reg);
3084 tcg_temp_free(t0);
3087 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3088 int rs)
3090 target_long offset;
3091 target_long addr;
3093 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3094 case OPC_ADDIUPC:
3095 if (rs != 0) {
3096 offset = sextract32(ctx->opcode << 2, 0, 21);
3097 addr = addr_add(ctx, pc, offset);
3098 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3100 break;
3101 case R6_OPC_LWPC:
3102 offset = sextract32(ctx->opcode << 2, 0, 21);
3103 addr = addr_add(ctx, pc, offset);
3104 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3105 break;
3106 #if defined(TARGET_MIPS64)
3107 case OPC_LWUPC:
3108 check_mips_64(ctx);
3109 offset = sextract32(ctx->opcode << 2, 0, 21);
3110 addr = addr_add(ctx, pc, offset);
3111 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3112 break;
3113 #endif
3114 default:
3115 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3116 case OPC_AUIPC:
3117 if (rs != 0) {
3118 offset = sextract32(ctx->opcode, 0, 16) << 16;
3119 addr = addr_add(ctx, pc, offset);
3120 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3122 break;
3123 case OPC_ALUIPC:
3124 if (rs != 0) {
3125 offset = sextract32(ctx->opcode, 0, 16) << 16;
3126 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3127 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3129 break;
3130 #if defined(TARGET_MIPS64)
3131 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3132 case R6_OPC_LDPC + (1 << 16):
3133 case R6_OPC_LDPC + (2 << 16):
3134 case R6_OPC_LDPC + (3 << 16):
3135 check_mips_64(ctx);
3136 offset = sextract32(ctx->opcode << 3, 0, 21);
3137 addr = addr_add(ctx, (pc & ~0x7), offset);
3138 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3139 break;
3140 #endif
3141 default:
3142 MIPS_INVAL("OPC_PCREL");
3143 generate_exception_end(ctx, EXCP_RI);
3144 break;
3146 break;
3150 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3152 TCGv t0, t1;
3154 if (rd == 0) {
3155 /* Treat as NOP. */
3156 return;
3159 t0 = tcg_temp_new();
3160 t1 = tcg_temp_new();
3162 gen_load_gpr(t0, rs);
3163 gen_load_gpr(t1, rt);
3165 switch (opc) {
3166 case R6_OPC_DIV:
3168 TCGv t2 = tcg_temp_new();
3169 TCGv t3 = tcg_temp_new();
3170 tcg_gen_ext32s_tl(t0, t0);
3171 tcg_gen_ext32s_tl(t1, t1);
3172 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3173 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3174 tcg_gen_and_tl(t2, t2, t3);
3175 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3176 tcg_gen_or_tl(t2, t2, t3);
3177 tcg_gen_movi_tl(t3, 0);
3178 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3179 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3180 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3181 tcg_temp_free(t3);
3182 tcg_temp_free(t2);
3184 break;
3185 case R6_OPC_MOD:
3187 TCGv t2 = tcg_temp_new();
3188 TCGv t3 = tcg_temp_new();
3189 tcg_gen_ext32s_tl(t0, t0);
3190 tcg_gen_ext32s_tl(t1, t1);
3191 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3192 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3193 tcg_gen_and_tl(t2, t2, t3);
3194 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3195 tcg_gen_or_tl(t2, t2, t3);
3196 tcg_gen_movi_tl(t3, 0);
3197 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3198 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3199 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3200 tcg_temp_free(t3);
3201 tcg_temp_free(t2);
3203 break;
3204 case R6_OPC_DIVU:
3206 TCGv t2 = tcg_const_tl(0);
3207 TCGv t3 = tcg_const_tl(1);
3208 tcg_gen_ext32u_tl(t0, t0);
3209 tcg_gen_ext32u_tl(t1, t1);
3210 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3211 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3212 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3213 tcg_temp_free(t3);
3214 tcg_temp_free(t2);
3216 break;
3217 case R6_OPC_MODU:
3219 TCGv t2 = tcg_const_tl(0);
3220 TCGv t3 = tcg_const_tl(1);
3221 tcg_gen_ext32u_tl(t0, t0);
3222 tcg_gen_ext32u_tl(t1, t1);
3223 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3224 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3225 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3226 tcg_temp_free(t3);
3227 tcg_temp_free(t2);
3229 break;
3230 case R6_OPC_MUL:
3232 TCGv_i32 t2 = tcg_temp_new_i32();
3233 TCGv_i32 t3 = tcg_temp_new_i32();
3234 tcg_gen_trunc_tl_i32(t2, t0);
3235 tcg_gen_trunc_tl_i32(t3, t1);
3236 tcg_gen_mul_i32(t2, t2, t3);
3237 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3238 tcg_temp_free_i32(t2);
3239 tcg_temp_free_i32(t3);
3241 break;
3242 case R6_OPC_MUH:
3244 TCGv_i32 t2 = tcg_temp_new_i32();
3245 TCGv_i32 t3 = tcg_temp_new_i32();
3246 tcg_gen_trunc_tl_i32(t2, t0);
3247 tcg_gen_trunc_tl_i32(t3, t1);
3248 tcg_gen_muls2_i32(t2, t3, t2, t3);
3249 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3250 tcg_temp_free_i32(t2);
3251 tcg_temp_free_i32(t3);
3253 break;
3254 case R6_OPC_MULU:
3256 TCGv_i32 t2 = tcg_temp_new_i32();
3257 TCGv_i32 t3 = tcg_temp_new_i32();
3258 tcg_gen_trunc_tl_i32(t2, t0);
3259 tcg_gen_trunc_tl_i32(t3, t1);
3260 tcg_gen_mul_i32(t2, t2, t3);
3261 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3262 tcg_temp_free_i32(t2);
3263 tcg_temp_free_i32(t3);
3265 break;
3266 case R6_OPC_MUHU:
3268 TCGv_i32 t2 = tcg_temp_new_i32();
3269 TCGv_i32 t3 = tcg_temp_new_i32();
3270 tcg_gen_trunc_tl_i32(t2, t0);
3271 tcg_gen_trunc_tl_i32(t3, t1);
3272 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3273 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3274 tcg_temp_free_i32(t2);
3275 tcg_temp_free_i32(t3);
3277 break;
3278 #if defined(TARGET_MIPS64)
3279 case R6_OPC_DDIV:
3281 TCGv t2 = tcg_temp_new();
3282 TCGv t3 = tcg_temp_new();
3283 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3284 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3285 tcg_gen_and_tl(t2, t2, t3);
3286 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3287 tcg_gen_or_tl(t2, t2, t3);
3288 tcg_gen_movi_tl(t3, 0);
3289 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3290 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3291 tcg_temp_free(t3);
3292 tcg_temp_free(t2);
3294 break;
3295 case R6_OPC_DMOD:
3297 TCGv t2 = tcg_temp_new();
3298 TCGv t3 = tcg_temp_new();
3299 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3300 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3301 tcg_gen_and_tl(t2, t2, t3);
3302 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3303 tcg_gen_or_tl(t2, t2, t3);
3304 tcg_gen_movi_tl(t3, 0);
3305 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3306 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3307 tcg_temp_free(t3);
3308 tcg_temp_free(t2);
3310 break;
3311 case R6_OPC_DDIVU:
3313 TCGv t2 = tcg_const_tl(0);
3314 TCGv t3 = tcg_const_tl(1);
3315 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3316 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3317 tcg_temp_free(t3);
3318 tcg_temp_free(t2);
3320 break;
3321 case R6_OPC_DMODU:
3323 TCGv t2 = tcg_const_tl(0);
3324 TCGv t3 = tcg_const_tl(1);
3325 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3326 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3327 tcg_temp_free(t3);
3328 tcg_temp_free(t2);
3330 break;
3331 case R6_OPC_DMUL:
3332 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3333 break;
3334 case R6_OPC_DMUH:
3336 TCGv t2 = tcg_temp_new();
3337 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3338 tcg_temp_free(t2);
3340 break;
3341 case R6_OPC_DMULU:
3342 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3343 break;
3344 case R6_OPC_DMUHU:
3346 TCGv t2 = tcg_temp_new();
3347 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3348 tcg_temp_free(t2);
3350 break;
3351 #endif
3352 default:
3353 MIPS_INVAL("r6 mul/div");
3354 generate_exception_end(ctx, EXCP_RI);
3355 goto out;
3357 out:
3358 tcg_temp_free(t0);
3359 tcg_temp_free(t1);
3362 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3363 int acc, int rs, int rt)
3365 TCGv t0, t1;
3367 t0 = tcg_temp_new();
3368 t1 = tcg_temp_new();
3370 gen_load_gpr(t0, rs);
3371 gen_load_gpr(t1, rt);
3373 if (acc != 0) {
3374 check_dsp(ctx);
3377 switch (opc) {
3378 case OPC_DIV:
3380 TCGv t2 = tcg_temp_new();
3381 TCGv t3 = tcg_temp_new();
3382 tcg_gen_ext32s_tl(t0, t0);
3383 tcg_gen_ext32s_tl(t1, t1);
3384 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3385 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3386 tcg_gen_and_tl(t2, t2, t3);
3387 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3388 tcg_gen_or_tl(t2, t2, t3);
3389 tcg_gen_movi_tl(t3, 0);
3390 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3391 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3392 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3393 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3394 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3395 tcg_temp_free(t3);
3396 tcg_temp_free(t2);
3398 break;
3399 case OPC_DIVU:
3401 TCGv t2 = tcg_const_tl(0);
3402 TCGv t3 = tcg_const_tl(1);
3403 tcg_gen_ext32u_tl(t0, t0);
3404 tcg_gen_ext32u_tl(t1, t1);
3405 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3406 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3407 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3408 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3409 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3410 tcg_temp_free(t3);
3411 tcg_temp_free(t2);
3413 break;
3414 case OPC_MULT:
3416 TCGv_i32 t2 = tcg_temp_new_i32();
3417 TCGv_i32 t3 = tcg_temp_new_i32();
3418 tcg_gen_trunc_tl_i32(t2, t0);
3419 tcg_gen_trunc_tl_i32(t3, t1);
3420 tcg_gen_muls2_i32(t2, t3, t2, t3);
3421 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3422 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3423 tcg_temp_free_i32(t2);
3424 tcg_temp_free_i32(t3);
3426 break;
3427 case OPC_MULTU:
3429 TCGv_i32 t2 = tcg_temp_new_i32();
3430 TCGv_i32 t3 = tcg_temp_new_i32();
3431 tcg_gen_trunc_tl_i32(t2, t0);
3432 tcg_gen_trunc_tl_i32(t3, t1);
3433 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3434 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3435 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3436 tcg_temp_free_i32(t2);
3437 tcg_temp_free_i32(t3);
3439 break;
3440 #if defined(TARGET_MIPS64)
3441 case OPC_DDIV:
3443 TCGv t2 = tcg_temp_new();
3444 TCGv t3 = tcg_temp_new();
3445 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3446 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3447 tcg_gen_and_tl(t2, t2, t3);
3448 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3449 tcg_gen_or_tl(t2, t2, t3);
3450 tcg_gen_movi_tl(t3, 0);
3451 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3452 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3453 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3454 tcg_temp_free(t3);
3455 tcg_temp_free(t2);
3457 break;
3458 case OPC_DDIVU:
3460 TCGv t2 = tcg_const_tl(0);
3461 TCGv t3 = tcg_const_tl(1);
3462 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3463 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3464 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3465 tcg_temp_free(t3);
3466 tcg_temp_free(t2);
3468 break;
3469 case OPC_DMULT:
3470 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3471 break;
3472 case OPC_DMULTU:
3473 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3474 break;
3475 #endif
3476 case OPC_MADD:
3478 TCGv_i64 t2 = tcg_temp_new_i64();
3479 TCGv_i64 t3 = tcg_temp_new_i64();
3481 tcg_gen_ext_tl_i64(t2, t0);
3482 tcg_gen_ext_tl_i64(t3, t1);
3483 tcg_gen_mul_i64(t2, t2, t3);
3484 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3485 tcg_gen_add_i64(t2, t2, t3);
3486 tcg_temp_free_i64(t3);
3487 gen_move_low32(cpu_LO[acc], t2);
3488 gen_move_high32(cpu_HI[acc], t2);
3489 tcg_temp_free_i64(t2);
3491 break;
3492 case OPC_MADDU:
3494 TCGv_i64 t2 = tcg_temp_new_i64();
3495 TCGv_i64 t3 = tcg_temp_new_i64();
3497 tcg_gen_ext32u_tl(t0, t0);
3498 tcg_gen_ext32u_tl(t1, t1);
3499 tcg_gen_extu_tl_i64(t2, t0);
3500 tcg_gen_extu_tl_i64(t3, t1);
3501 tcg_gen_mul_i64(t2, t2, t3);
3502 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3503 tcg_gen_add_i64(t2, t2, t3);
3504 tcg_temp_free_i64(t3);
3505 gen_move_low32(cpu_LO[acc], t2);
3506 gen_move_high32(cpu_HI[acc], t2);
3507 tcg_temp_free_i64(t2);
3509 break;
3510 case OPC_MSUB:
3512 TCGv_i64 t2 = tcg_temp_new_i64();
3513 TCGv_i64 t3 = tcg_temp_new_i64();
3515 tcg_gen_ext_tl_i64(t2, t0);
3516 tcg_gen_ext_tl_i64(t3, t1);
3517 tcg_gen_mul_i64(t2, t2, t3);
3518 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3519 tcg_gen_sub_i64(t2, t3, t2);
3520 tcg_temp_free_i64(t3);
3521 gen_move_low32(cpu_LO[acc], t2);
3522 gen_move_high32(cpu_HI[acc], t2);
3523 tcg_temp_free_i64(t2);
3525 break;
3526 case OPC_MSUBU:
3528 TCGv_i64 t2 = tcg_temp_new_i64();
3529 TCGv_i64 t3 = tcg_temp_new_i64();
3531 tcg_gen_ext32u_tl(t0, t0);
3532 tcg_gen_ext32u_tl(t1, t1);
3533 tcg_gen_extu_tl_i64(t2, t0);
3534 tcg_gen_extu_tl_i64(t3, t1);
3535 tcg_gen_mul_i64(t2, t2, t3);
3536 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3537 tcg_gen_sub_i64(t2, t3, t2);
3538 tcg_temp_free_i64(t3);
3539 gen_move_low32(cpu_LO[acc], t2);
3540 gen_move_high32(cpu_HI[acc], t2);
3541 tcg_temp_free_i64(t2);
3543 break;
3544 default:
3545 MIPS_INVAL("mul/div");
3546 generate_exception_end(ctx, EXCP_RI);
3547 goto out;
3549 out:
3550 tcg_temp_free(t0);
3551 tcg_temp_free(t1);
3554 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3555 int rd, int rs, int rt)
3557 TCGv t0 = tcg_temp_new();
3558 TCGv t1 = tcg_temp_new();
3560 gen_load_gpr(t0, rs);
3561 gen_load_gpr(t1, rt);
3563 switch (opc) {
3564 case OPC_VR54XX_MULS:
3565 gen_helper_muls(t0, cpu_env, t0, t1);
3566 break;
3567 case OPC_VR54XX_MULSU:
3568 gen_helper_mulsu(t0, cpu_env, t0, t1);
3569 break;
3570 case OPC_VR54XX_MACC:
3571 gen_helper_macc(t0, cpu_env, t0, t1);
3572 break;
3573 case OPC_VR54XX_MACCU:
3574 gen_helper_maccu(t0, cpu_env, t0, t1);
3575 break;
3576 case OPC_VR54XX_MSAC:
3577 gen_helper_msac(t0, cpu_env, t0, t1);
3578 break;
3579 case OPC_VR54XX_MSACU:
3580 gen_helper_msacu(t0, cpu_env, t0, t1);
3581 break;
3582 case OPC_VR54XX_MULHI:
3583 gen_helper_mulhi(t0, cpu_env, t0, t1);
3584 break;
3585 case OPC_VR54XX_MULHIU:
3586 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3587 break;
3588 case OPC_VR54XX_MULSHI:
3589 gen_helper_mulshi(t0, cpu_env, t0, t1);
3590 break;
3591 case OPC_VR54XX_MULSHIU:
3592 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3593 break;
3594 case OPC_VR54XX_MACCHI:
3595 gen_helper_macchi(t0, cpu_env, t0, t1);
3596 break;
3597 case OPC_VR54XX_MACCHIU:
3598 gen_helper_macchiu(t0, cpu_env, t0, t1);
3599 break;
3600 case OPC_VR54XX_MSACHI:
3601 gen_helper_msachi(t0, cpu_env, t0, t1);
3602 break;
3603 case OPC_VR54XX_MSACHIU:
3604 gen_helper_msachiu(t0, cpu_env, t0, t1);
3605 break;
3606 default:
3607 MIPS_INVAL("mul vr54xx");
3608 generate_exception_end(ctx, EXCP_RI);
3609 goto out;
3611 gen_store_gpr(t0, rd);
3613 out:
3614 tcg_temp_free(t0);
3615 tcg_temp_free(t1);
3618 static void gen_cl (DisasContext *ctx, uint32_t opc,
3619 int rd, int rs)
3621 TCGv t0;
3623 if (rd == 0) {
3624 /* Treat as NOP. */
3625 return;
3627 t0 = tcg_temp_new();
3628 gen_load_gpr(t0, rs);
3629 switch (opc) {
3630 case OPC_CLO:
3631 case R6_OPC_CLO:
3632 gen_helper_clo(cpu_gpr[rd], t0);
3633 break;
3634 case OPC_CLZ:
3635 case R6_OPC_CLZ:
3636 gen_helper_clz(cpu_gpr[rd], t0);
3637 break;
3638 #if defined(TARGET_MIPS64)
3639 case OPC_DCLO:
3640 case R6_OPC_DCLO:
3641 gen_helper_dclo(cpu_gpr[rd], t0);
3642 break;
3643 case OPC_DCLZ:
3644 case R6_OPC_DCLZ:
3645 gen_helper_dclz(cpu_gpr[rd], t0);
3646 break;
3647 #endif
3649 tcg_temp_free(t0);
3652 /* Godson integer instructions */
3653 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3654 int rd, int rs, int rt)
3656 TCGv t0, t1;
3658 if (rd == 0) {
3659 /* Treat as NOP. */
3660 return;
3663 switch (opc) {
3664 case OPC_MULT_G_2E:
3665 case OPC_MULT_G_2F:
3666 case OPC_MULTU_G_2E:
3667 case OPC_MULTU_G_2F:
3668 #if defined(TARGET_MIPS64)
3669 case OPC_DMULT_G_2E:
3670 case OPC_DMULT_G_2F:
3671 case OPC_DMULTU_G_2E:
3672 case OPC_DMULTU_G_2F:
3673 #endif
3674 t0 = tcg_temp_new();
3675 t1 = tcg_temp_new();
3676 break;
3677 default:
3678 t0 = tcg_temp_local_new();
3679 t1 = tcg_temp_local_new();
3680 break;
3683 gen_load_gpr(t0, rs);
3684 gen_load_gpr(t1, rt);
3686 switch (opc) {
3687 case OPC_MULT_G_2E:
3688 case OPC_MULT_G_2F:
3689 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3690 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3691 break;
3692 case OPC_MULTU_G_2E:
3693 case OPC_MULTU_G_2F:
3694 tcg_gen_ext32u_tl(t0, t0);
3695 tcg_gen_ext32u_tl(t1, t1);
3696 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3697 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3698 break;
3699 case OPC_DIV_G_2E:
3700 case OPC_DIV_G_2F:
3702 TCGLabel *l1 = gen_new_label();
3703 TCGLabel *l2 = gen_new_label();
3704 TCGLabel *l3 = gen_new_label();
3705 tcg_gen_ext32s_tl(t0, t0);
3706 tcg_gen_ext32s_tl(t1, t1);
3707 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3708 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3709 tcg_gen_br(l3);
3710 gen_set_label(l1);
3711 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3712 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3713 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3714 tcg_gen_br(l3);
3715 gen_set_label(l2);
3716 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3717 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3718 gen_set_label(l3);
3720 break;
3721 case OPC_DIVU_G_2E:
3722 case OPC_DIVU_G_2F:
3724 TCGLabel *l1 = gen_new_label();
3725 TCGLabel *l2 = gen_new_label();
3726 tcg_gen_ext32u_tl(t0, t0);
3727 tcg_gen_ext32u_tl(t1, t1);
3728 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3729 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3730 tcg_gen_br(l2);
3731 gen_set_label(l1);
3732 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3733 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3734 gen_set_label(l2);
3736 break;
3737 case OPC_MOD_G_2E:
3738 case OPC_MOD_G_2F:
3740 TCGLabel *l1 = gen_new_label();
3741 TCGLabel *l2 = gen_new_label();
3742 TCGLabel *l3 = gen_new_label();
3743 tcg_gen_ext32u_tl(t0, t0);
3744 tcg_gen_ext32u_tl(t1, t1);
3745 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3746 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3747 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3748 gen_set_label(l1);
3749 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3750 tcg_gen_br(l3);
3751 gen_set_label(l2);
3752 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3753 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3754 gen_set_label(l3);
3756 break;
3757 case OPC_MODU_G_2E:
3758 case OPC_MODU_G_2F:
3760 TCGLabel *l1 = gen_new_label();
3761 TCGLabel *l2 = gen_new_label();
3762 tcg_gen_ext32u_tl(t0, t0);
3763 tcg_gen_ext32u_tl(t1, t1);
3764 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3765 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3766 tcg_gen_br(l2);
3767 gen_set_label(l1);
3768 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3769 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3770 gen_set_label(l2);
3772 break;
3773 #if defined(TARGET_MIPS64)
3774 case OPC_DMULT_G_2E:
3775 case OPC_DMULT_G_2F:
3776 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3777 break;
3778 case OPC_DMULTU_G_2E:
3779 case OPC_DMULTU_G_2F:
3780 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3781 break;
3782 case OPC_DDIV_G_2E:
3783 case OPC_DDIV_G_2F:
3785 TCGLabel *l1 = gen_new_label();
3786 TCGLabel *l2 = gen_new_label();
3787 TCGLabel *l3 = gen_new_label();
3788 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3789 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3790 tcg_gen_br(l3);
3791 gen_set_label(l1);
3792 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3793 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3794 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3795 tcg_gen_br(l3);
3796 gen_set_label(l2);
3797 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3798 gen_set_label(l3);
3800 break;
3801 case OPC_DDIVU_G_2E:
3802 case OPC_DDIVU_G_2F:
3804 TCGLabel *l1 = gen_new_label();
3805 TCGLabel *l2 = gen_new_label();
3806 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3807 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3808 tcg_gen_br(l2);
3809 gen_set_label(l1);
3810 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3811 gen_set_label(l2);
3813 break;
3814 case OPC_DMOD_G_2E:
3815 case OPC_DMOD_G_2F:
3817 TCGLabel *l1 = gen_new_label();
3818 TCGLabel *l2 = gen_new_label();
3819 TCGLabel *l3 = gen_new_label();
3820 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3821 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3822 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3823 gen_set_label(l1);
3824 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3825 tcg_gen_br(l3);
3826 gen_set_label(l2);
3827 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3828 gen_set_label(l3);
3830 break;
3831 case OPC_DMODU_G_2E:
3832 case OPC_DMODU_G_2F:
3834 TCGLabel *l1 = gen_new_label();
3835 TCGLabel *l2 = gen_new_label();
3836 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3837 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3838 tcg_gen_br(l2);
3839 gen_set_label(l1);
3840 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3841 gen_set_label(l2);
3843 break;
3844 #endif
3847 tcg_temp_free(t0);
3848 tcg_temp_free(t1);
3851 /* Loongson multimedia instructions */
3852 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3854 uint32_t opc, shift_max;
3855 TCGv_i64 t0, t1;
3857 opc = MASK_LMI(ctx->opcode);
3858 switch (opc) {
3859 case OPC_ADD_CP2:
3860 case OPC_SUB_CP2:
3861 case OPC_DADD_CP2:
3862 case OPC_DSUB_CP2:
3863 t0 = tcg_temp_local_new_i64();
3864 t1 = tcg_temp_local_new_i64();
3865 break;
3866 default:
3867 t0 = tcg_temp_new_i64();
3868 t1 = tcg_temp_new_i64();
3869 break;
3872 gen_load_fpr64(ctx, t0, rs);
3873 gen_load_fpr64(ctx, t1, rt);
3875 #define LMI_HELPER(UP, LO) \
3876 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
3877 #define LMI_HELPER_1(UP, LO) \
3878 case OPC_##UP: gen_helper_##LO(t0, t0); break
3879 #define LMI_DIRECT(UP, LO, OP) \
3880 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
3882 switch (opc) {
3883 LMI_HELPER(PADDSH, paddsh);
3884 LMI_HELPER(PADDUSH, paddush);
3885 LMI_HELPER(PADDH, paddh);
3886 LMI_HELPER(PADDW, paddw);
3887 LMI_HELPER(PADDSB, paddsb);
3888 LMI_HELPER(PADDUSB, paddusb);
3889 LMI_HELPER(PADDB, paddb);
3891 LMI_HELPER(PSUBSH, psubsh);
3892 LMI_HELPER(PSUBUSH, psubush);
3893 LMI_HELPER(PSUBH, psubh);
3894 LMI_HELPER(PSUBW, psubw);
3895 LMI_HELPER(PSUBSB, psubsb);
3896 LMI_HELPER(PSUBUSB, psubusb);
3897 LMI_HELPER(PSUBB, psubb);
3899 LMI_HELPER(PSHUFH, pshufh);
3900 LMI_HELPER(PACKSSWH, packsswh);
3901 LMI_HELPER(PACKSSHB, packsshb);
3902 LMI_HELPER(PACKUSHB, packushb);
3904 LMI_HELPER(PUNPCKLHW, punpcklhw);
3905 LMI_HELPER(PUNPCKHHW, punpckhhw);
3906 LMI_HELPER(PUNPCKLBH, punpcklbh);
3907 LMI_HELPER(PUNPCKHBH, punpckhbh);
3908 LMI_HELPER(PUNPCKLWD, punpcklwd);
3909 LMI_HELPER(PUNPCKHWD, punpckhwd);
3911 LMI_HELPER(PAVGH, pavgh);
3912 LMI_HELPER(PAVGB, pavgb);
3913 LMI_HELPER(PMAXSH, pmaxsh);
3914 LMI_HELPER(PMINSH, pminsh);
3915 LMI_HELPER(PMAXUB, pmaxub);
3916 LMI_HELPER(PMINUB, pminub);
3918 LMI_HELPER(PCMPEQW, pcmpeqw);
3919 LMI_HELPER(PCMPGTW, pcmpgtw);
3920 LMI_HELPER(PCMPEQH, pcmpeqh);
3921 LMI_HELPER(PCMPGTH, pcmpgth);
3922 LMI_HELPER(PCMPEQB, pcmpeqb);
3923 LMI_HELPER(PCMPGTB, pcmpgtb);
3925 LMI_HELPER(PSLLW, psllw);
3926 LMI_HELPER(PSLLH, psllh);
3927 LMI_HELPER(PSRLW, psrlw);
3928 LMI_HELPER(PSRLH, psrlh);
3929 LMI_HELPER(PSRAW, psraw);
3930 LMI_HELPER(PSRAH, psrah);
3932 LMI_HELPER(PMULLH, pmullh);
3933 LMI_HELPER(PMULHH, pmulhh);
3934 LMI_HELPER(PMULHUH, pmulhuh);
3935 LMI_HELPER(PMADDHW, pmaddhw);
3937 LMI_HELPER(PASUBUB, pasubub);
3938 LMI_HELPER_1(BIADD, biadd);
3939 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3941 LMI_DIRECT(PADDD, paddd, add);
3942 LMI_DIRECT(PSUBD, psubd, sub);
3943 LMI_DIRECT(XOR_CP2, xor, xor);
3944 LMI_DIRECT(NOR_CP2, nor, nor);
3945 LMI_DIRECT(AND_CP2, and, and);
3946 LMI_DIRECT(PANDN, pandn, andc);
3947 LMI_DIRECT(OR, or, or);
3949 case OPC_PINSRH_0:
3950 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3951 break;
3952 case OPC_PINSRH_1:
3953 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3954 break;
3955 case OPC_PINSRH_2:
3956 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3957 break;
3958 case OPC_PINSRH_3:
3959 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3960 break;
3962 case OPC_PEXTRH:
3963 tcg_gen_andi_i64(t1, t1, 3);
3964 tcg_gen_shli_i64(t1, t1, 4);
3965 tcg_gen_shr_i64(t0, t0, t1);
3966 tcg_gen_ext16u_i64(t0, t0);
3967 break;
3969 case OPC_ADDU_CP2:
3970 tcg_gen_add_i64(t0, t0, t1);
3971 tcg_gen_ext32s_i64(t0, t0);
3972 break;
3973 case OPC_SUBU_CP2:
3974 tcg_gen_sub_i64(t0, t0, t1);
3975 tcg_gen_ext32s_i64(t0, t0);
3976 break;
3978 case OPC_SLL_CP2:
3979 shift_max = 32;
3980 goto do_shift;
3981 case OPC_SRL_CP2:
3982 shift_max = 32;
3983 goto do_shift;
3984 case OPC_SRA_CP2:
3985 shift_max = 32;
3986 goto do_shift;
3987 case OPC_DSLL_CP2:
3988 shift_max = 64;
3989 goto do_shift;
3990 case OPC_DSRL_CP2:
3991 shift_max = 64;
3992 goto do_shift;
3993 case OPC_DSRA_CP2:
3994 shift_max = 64;
3995 goto do_shift;
3996 do_shift:
3997 /* Make sure shift count isn't TCG undefined behaviour. */
3998 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4000 switch (opc) {
4001 case OPC_SLL_CP2:
4002 case OPC_DSLL_CP2:
4003 tcg_gen_shl_i64(t0, t0, t1);
4004 break;
4005 case OPC_SRA_CP2:
4006 case OPC_DSRA_CP2:
4007 /* Since SRA is UndefinedResult without sign-extended inputs,
4008 we can treat SRA and DSRA the same. */
4009 tcg_gen_sar_i64(t0, t0, t1);
4010 break;
4011 case OPC_SRL_CP2:
4012 /* We want to shift in zeros for SRL; zero-extend first. */
4013 tcg_gen_ext32u_i64(t0, t0);
4014 /* FALLTHRU */
4015 case OPC_DSRL_CP2:
4016 tcg_gen_shr_i64(t0, t0, t1);
4017 break;
4020 if (shift_max == 32) {
4021 tcg_gen_ext32s_i64(t0, t0);
4024 /* Shifts larger than MAX produce zero. */
4025 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4026 tcg_gen_neg_i64(t1, t1);
4027 tcg_gen_and_i64(t0, t0, t1);
4028 break;
4030 case OPC_ADD_CP2:
4031 case OPC_DADD_CP2:
4033 TCGv_i64 t2 = tcg_temp_new_i64();
4034 TCGLabel *lab = gen_new_label();
4036 tcg_gen_mov_i64(t2, t0);
4037 tcg_gen_add_i64(t0, t1, t2);
4038 if (opc == OPC_ADD_CP2) {
4039 tcg_gen_ext32s_i64(t0, t0);
4041 tcg_gen_xor_i64(t1, t1, t2);
4042 tcg_gen_xor_i64(t2, t2, t0);
4043 tcg_gen_andc_i64(t1, t2, t1);
4044 tcg_temp_free_i64(t2);
4045 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4046 generate_exception(ctx, EXCP_OVERFLOW);
4047 gen_set_label(lab);
4048 break;
4051 case OPC_SUB_CP2:
4052 case OPC_DSUB_CP2:
4054 TCGv_i64 t2 = tcg_temp_new_i64();
4055 TCGLabel *lab = gen_new_label();
4057 tcg_gen_mov_i64(t2, t0);
4058 tcg_gen_sub_i64(t0, t1, t2);
4059 if (opc == OPC_SUB_CP2) {
4060 tcg_gen_ext32s_i64(t0, t0);
4062 tcg_gen_xor_i64(t1, t1, t2);
4063 tcg_gen_xor_i64(t2, t2, t0);
4064 tcg_gen_and_i64(t1, t1, t2);
4065 tcg_temp_free_i64(t2);
4066 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4067 generate_exception(ctx, EXCP_OVERFLOW);
4068 gen_set_label(lab);
4069 break;
4072 case OPC_PMULUW:
4073 tcg_gen_ext32u_i64(t0, t0);
4074 tcg_gen_ext32u_i64(t1, t1);
4075 tcg_gen_mul_i64(t0, t0, t1);
4076 break;
4078 case OPC_SEQU_CP2:
4079 case OPC_SEQ_CP2:
4080 case OPC_SLTU_CP2:
4081 case OPC_SLT_CP2:
4082 case OPC_SLEU_CP2:
4083 case OPC_SLE_CP2:
4084 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4085 FD field is the CC field? */
4086 default:
4087 MIPS_INVAL("loongson_cp2");
4088 generate_exception_end(ctx, EXCP_RI);
4089 return;
4092 #undef LMI_HELPER
4093 #undef LMI_DIRECT
4095 gen_store_fpr64(ctx, t0, rd);
4097 tcg_temp_free_i64(t0);
4098 tcg_temp_free_i64(t1);
4101 /* Traps */
4102 static void gen_trap (DisasContext *ctx, uint32_t opc,
4103 int rs, int rt, int16_t imm)
4105 int cond;
4106 TCGv t0 = tcg_temp_new();
4107 TCGv t1 = tcg_temp_new();
4109 cond = 0;
4110 /* Load needed operands */
4111 switch (opc) {
4112 case OPC_TEQ:
4113 case OPC_TGE:
4114 case OPC_TGEU:
4115 case OPC_TLT:
4116 case OPC_TLTU:
4117 case OPC_TNE:
4118 /* Compare two registers */
4119 if (rs != rt) {
4120 gen_load_gpr(t0, rs);
4121 gen_load_gpr(t1, rt);
4122 cond = 1;
4124 break;
4125 case OPC_TEQI:
4126 case OPC_TGEI:
4127 case OPC_TGEIU:
4128 case OPC_TLTI:
4129 case OPC_TLTIU:
4130 case OPC_TNEI:
4131 /* Compare register to immediate */
4132 if (rs != 0 || imm != 0) {
4133 gen_load_gpr(t0, rs);
4134 tcg_gen_movi_tl(t1, (int32_t)imm);
4135 cond = 1;
4137 break;
4139 if (cond == 0) {
4140 switch (opc) {
4141 case OPC_TEQ: /* rs == rs */
4142 case OPC_TEQI: /* r0 == 0 */
4143 case OPC_TGE: /* rs >= rs */
4144 case OPC_TGEI: /* r0 >= 0 */
4145 case OPC_TGEU: /* rs >= rs unsigned */
4146 case OPC_TGEIU: /* r0 >= 0 unsigned */
4147 /* Always trap */
4148 generate_exception_end(ctx, EXCP_TRAP);
4149 break;
4150 case OPC_TLT: /* rs < rs */
4151 case OPC_TLTI: /* r0 < 0 */
4152 case OPC_TLTU: /* rs < rs unsigned */
4153 case OPC_TLTIU: /* r0 < 0 unsigned */
4154 case OPC_TNE: /* rs != rs */
4155 case OPC_TNEI: /* r0 != 0 */
4156 /* Never trap: treat as NOP. */
4157 break;
4159 } else {
4160 TCGLabel *l1 = gen_new_label();
4162 switch (opc) {
4163 case OPC_TEQ:
4164 case OPC_TEQI:
4165 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4166 break;
4167 case OPC_TGE:
4168 case OPC_TGEI:
4169 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4170 break;
4171 case OPC_TGEU:
4172 case OPC_TGEIU:
4173 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4174 break;
4175 case OPC_TLT:
4176 case OPC_TLTI:
4177 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4178 break;
4179 case OPC_TLTU:
4180 case OPC_TLTIU:
4181 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4182 break;
4183 case OPC_TNE:
4184 case OPC_TNEI:
4185 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4186 break;
4188 generate_exception(ctx, EXCP_TRAP);
4189 gen_set_label(l1);
4191 tcg_temp_free(t0);
4192 tcg_temp_free(t1);
4195 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4197 if (unlikely(ctx->singlestep_enabled)) {
4198 return false;
4201 #ifndef CONFIG_USER_ONLY
4202 return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4203 #else
4204 return true;
4205 #endif
4208 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4210 if (use_goto_tb(ctx, dest)) {
4211 tcg_gen_goto_tb(n);
4212 gen_save_pc(dest);
4213 tcg_gen_exit_tb((uintptr_t)ctx->tb + n);
4214 } else {
4215 gen_save_pc(dest);
4216 if (ctx->singlestep_enabled) {
4217 save_cpu_state(ctx, 0);
4218 gen_helper_raise_exception_debug(cpu_env);
4220 tcg_gen_exit_tb(0);
4224 /* Branches (before delay slot) */
4225 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4226 int insn_bytes,
4227 int rs, int rt, int32_t offset,
4228 int delayslot_size)
4230 target_ulong btgt = -1;
4231 int blink = 0;
4232 int bcond_compute = 0;
4233 TCGv t0 = tcg_temp_new();
4234 TCGv t1 = tcg_temp_new();
4236 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4237 #ifdef MIPS_DEBUG_DISAS
4238 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4239 TARGET_FMT_lx "\n", ctx->pc);
4240 #endif
4241 generate_exception_end(ctx, EXCP_RI);
4242 goto out;
4245 /* Load needed operands */
4246 switch (opc) {
4247 case OPC_BEQ:
4248 case OPC_BEQL:
4249 case OPC_BNE:
4250 case OPC_BNEL:
4251 /* Compare two registers */
4252 if (rs != rt) {
4253 gen_load_gpr(t0, rs);
4254 gen_load_gpr(t1, rt);
4255 bcond_compute = 1;
4257 btgt = ctx->pc + insn_bytes + offset;
4258 break;
4259 case OPC_BGEZ:
4260 case OPC_BGEZAL:
4261 case OPC_BGEZALL:
4262 case OPC_BGEZL:
4263 case OPC_BGTZ:
4264 case OPC_BGTZL:
4265 case OPC_BLEZ:
4266 case OPC_BLEZL:
4267 case OPC_BLTZ:
4268 case OPC_BLTZAL:
4269 case OPC_BLTZALL:
4270 case OPC_BLTZL:
4271 /* Compare to zero */
4272 if (rs != 0) {
4273 gen_load_gpr(t0, rs);
4274 bcond_compute = 1;
4276 btgt = ctx->pc + insn_bytes + offset;
4277 break;
4278 case OPC_BPOSGE32:
4279 #if defined(TARGET_MIPS64)
4280 case OPC_BPOSGE64:
4281 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4282 #else
4283 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4284 #endif
4285 bcond_compute = 1;
4286 btgt = ctx->pc + insn_bytes + offset;
4287 break;
4288 case OPC_J:
4289 case OPC_JAL:
4290 case OPC_JALX:
4291 /* Jump to immediate */
4292 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4293 break;
4294 case OPC_JR:
4295 case OPC_JALR:
4296 /* Jump to register */
4297 if (offset != 0 && offset != 16) {
4298 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4299 others are reserved. */
4300 MIPS_INVAL("jump hint");
4301 generate_exception_end(ctx, EXCP_RI);
4302 goto out;
4304 gen_load_gpr(btarget, rs);
4305 break;
4306 default:
4307 MIPS_INVAL("branch/jump");
4308 generate_exception_end(ctx, EXCP_RI);
4309 goto out;
4311 if (bcond_compute == 0) {
4312 /* No condition to be computed */
4313 switch (opc) {
4314 case OPC_BEQ: /* rx == rx */
4315 case OPC_BEQL: /* rx == rx likely */
4316 case OPC_BGEZ: /* 0 >= 0 */
4317 case OPC_BGEZL: /* 0 >= 0 likely */
4318 case OPC_BLEZ: /* 0 <= 0 */
4319 case OPC_BLEZL: /* 0 <= 0 likely */
4320 /* Always take */
4321 ctx->hflags |= MIPS_HFLAG_B;
4322 break;
4323 case OPC_BGEZAL: /* 0 >= 0 */
4324 case OPC_BGEZALL: /* 0 >= 0 likely */
4325 /* Always take and link */
4326 blink = 31;
4327 ctx->hflags |= MIPS_HFLAG_B;
4328 break;
4329 case OPC_BNE: /* rx != rx */
4330 case OPC_BGTZ: /* 0 > 0 */
4331 case OPC_BLTZ: /* 0 < 0 */
4332 /* Treat as NOP. */
4333 goto out;
4334 case OPC_BLTZAL: /* 0 < 0 */
4335 /* Handle as an unconditional branch to get correct delay
4336 slot checking. */
4337 blink = 31;
4338 btgt = ctx->pc + insn_bytes + delayslot_size;
4339 ctx->hflags |= MIPS_HFLAG_B;
4340 break;
4341 case OPC_BLTZALL: /* 0 < 0 likely */
4342 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4343 /* Skip the instruction in the delay slot */
4344 ctx->pc += 4;
4345 goto out;
4346 case OPC_BNEL: /* rx != rx likely */
4347 case OPC_BGTZL: /* 0 > 0 likely */
4348 case OPC_BLTZL: /* 0 < 0 likely */
4349 /* Skip the instruction in the delay slot */
4350 ctx->pc += 4;
4351 goto out;
4352 case OPC_J:
4353 ctx->hflags |= MIPS_HFLAG_B;
4354 break;
4355 case OPC_JALX:
4356 ctx->hflags |= MIPS_HFLAG_BX;
4357 /* Fallthrough */
4358 case OPC_JAL:
4359 blink = 31;
4360 ctx->hflags |= MIPS_HFLAG_B;
4361 break;
4362 case OPC_JR:
4363 ctx->hflags |= MIPS_HFLAG_BR;
4364 break;
4365 case OPC_JALR:
4366 blink = rt;
4367 ctx->hflags |= MIPS_HFLAG_BR;
4368 break;
4369 default:
4370 MIPS_INVAL("branch/jump");
4371 generate_exception_end(ctx, EXCP_RI);
4372 goto out;
4374 } else {
4375 switch (opc) {
4376 case OPC_BEQ:
4377 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4378 goto not_likely;
4379 case OPC_BEQL:
4380 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4381 goto likely;
4382 case OPC_BNE:
4383 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4384 goto not_likely;
4385 case OPC_BNEL:
4386 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4387 goto likely;
4388 case OPC_BGEZ:
4389 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4390 goto not_likely;
4391 case OPC_BGEZL:
4392 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4393 goto likely;
4394 case OPC_BGEZAL:
4395 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4396 blink = 31;
4397 goto not_likely;
4398 case OPC_BGEZALL:
4399 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4400 blink = 31;
4401 goto likely;
4402 case OPC_BGTZ:
4403 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4404 goto not_likely;
4405 case OPC_BGTZL:
4406 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4407 goto likely;
4408 case OPC_BLEZ:
4409 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4410 goto not_likely;
4411 case OPC_BLEZL:
4412 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4413 goto likely;
4414 case OPC_BLTZ:
4415 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4416 goto not_likely;
4417 case OPC_BLTZL:
4418 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4419 goto likely;
4420 case OPC_BPOSGE32:
4421 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4422 goto not_likely;
4423 #if defined(TARGET_MIPS64)
4424 case OPC_BPOSGE64:
4425 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4426 goto not_likely;
4427 #endif
4428 case OPC_BLTZAL:
4429 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4430 blink = 31;
4431 not_likely:
4432 ctx->hflags |= MIPS_HFLAG_BC;
4433 break;
4434 case OPC_BLTZALL:
4435 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4436 blink = 31;
4437 likely:
4438 ctx->hflags |= MIPS_HFLAG_BL;
4439 break;
4440 default:
4441 MIPS_INVAL("conditional branch/jump");
4442 generate_exception_end(ctx, EXCP_RI);
4443 goto out;
4447 ctx->btarget = btgt;
4449 switch (delayslot_size) {
4450 case 2:
4451 ctx->hflags |= MIPS_HFLAG_BDS16;
4452 break;
4453 case 4:
4454 ctx->hflags |= MIPS_HFLAG_BDS32;
4455 break;
4458 if (blink > 0) {
4459 int post_delay = insn_bytes + delayslot_size;
4460 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4462 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4465 out:
4466 if (insn_bytes == 2)
4467 ctx->hflags |= MIPS_HFLAG_B16;
4468 tcg_temp_free(t0);
4469 tcg_temp_free(t1);
4472 /* special3 bitfield operations */
4473 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4474 int rs, int lsb, int msb)
4476 TCGv t0 = tcg_temp_new();
4477 TCGv t1 = tcg_temp_new();
4479 gen_load_gpr(t1, rs);
4480 switch (opc) {
4481 case OPC_EXT:
4482 if (lsb + msb > 31) {
4483 goto fail;
4485 tcg_gen_shri_tl(t0, t1, lsb);
4486 if (msb != 31) {
4487 tcg_gen_andi_tl(t0, t0, (1U << (msb + 1)) - 1);
4488 } else {
4489 tcg_gen_ext32s_tl(t0, t0);
4491 break;
4492 #if defined(TARGET_MIPS64)
4493 case OPC_DEXTU:
4494 lsb += 32;
4495 goto do_dext;
4496 case OPC_DEXTM:
4497 msb += 32;
4498 goto do_dext;
4499 case OPC_DEXT:
4500 do_dext:
4501 if (lsb + msb > 63) {
4502 goto fail;
4504 tcg_gen_shri_tl(t0, t1, lsb);
4505 if (msb != 63) {
4506 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4508 break;
4509 #endif
4510 case OPC_INS:
4511 if (lsb > msb) {
4512 goto fail;
4514 gen_load_gpr(t0, rt);
4515 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4516 tcg_gen_ext32s_tl(t0, t0);
4517 break;
4518 #if defined(TARGET_MIPS64)
4519 case OPC_DINSU:
4520 lsb += 32;
4521 /* FALLTHRU */
4522 case OPC_DINSM:
4523 msb += 32;
4524 /* FALLTHRU */
4525 case OPC_DINS:
4526 if (lsb > msb) {
4527 goto fail;
4529 gen_load_gpr(t0, rt);
4530 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4531 break;
4532 #endif
4533 default:
4534 fail:
4535 MIPS_INVAL("bitops");
4536 generate_exception_end(ctx, EXCP_RI);
4537 tcg_temp_free(t0);
4538 tcg_temp_free(t1);
4539 return;
4541 gen_store_gpr(t0, rt);
4542 tcg_temp_free(t0);
4543 tcg_temp_free(t1);
4546 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4548 TCGv t0;
4550 if (rd == 0) {
4551 /* If no destination, treat it as a NOP. */
4552 return;
4555 t0 = tcg_temp_new();
4556 gen_load_gpr(t0, rt);
4557 switch (op2) {
4558 case OPC_WSBH:
4560 TCGv t1 = tcg_temp_new();
4562 tcg_gen_shri_tl(t1, t0, 8);
4563 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4564 tcg_gen_shli_tl(t0, t0, 8);
4565 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4566 tcg_gen_or_tl(t0, t0, t1);
4567 tcg_temp_free(t1);
4568 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4570 break;
4571 case OPC_SEB:
4572 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4573 break;
4574 case OPC_SEH:
4575 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4576 break;
4577 #if defined(TARGET_MIPS64)
4578 case OPC_DSBH:
4580 TCGv t1 = tcg_temp_new();
4582 tcg_gen_shri_tl(t1, t0, 8);
4583 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4584 tcg_gen_shli_tl(t0, t0, 8);
4585 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4586 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4587 tcg_temp_free(t1);
4589 break;
4590 case OPC_DSHD:
4592 TCGv t1 = tcg_temp_new();
4594 tcg_gen_shri_tl(t1, t0, 16);
4595 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4596 tcg_gen_shli_tl(t0, t0, 16);
4597 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4598 tcg_gen_or_tl(t0, t0, t1);
4599 tcg_gen_shri_tl(t1, t0, 32);
4600 tcg_gen_shli_tl(t0, t0, 32);
4601 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4602 tcg_temp_free(t1);
4604 break;
4605 #endif
4606 default:
4607 MIPS_INVAL("bsfhl");
4608 generate_exception_end(ctx, EXCP_RI);
4609 tcg_temp_free(t0);
4610 return;
4612 tcg_temp_free(t0);
4615 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4616 int imm2)
4618 TCGv t0;
4619 TCGv t1;
4620 if (rd == 0) {
4621 /* Treat as NOP. */
4622 return;
4624 t0 = tcg_temp_new();
4625 t1 = tcg_temp_new();
4626 gen_load_gpr(t0, rs);
4627 gen_load_gpr(t1, rt);
4628 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4629 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4630 if (opc == OPC_LSA) {
4631 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4634 tcg_temp_free(t1);
4635 tcg_temp_free(t0);
4637 return;
4640 static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
4641 int bp)
4643 TCGv t0;
4644 if (rd == 0) {
4645 /* Treat as NOP. */
4646 return;
4648 t0 = tcg_temp_new();
4649 gen_load_gpr(t0, rt);
4650 if (bp == 0) {
4651 switch (opc) {
4652 case OPC_ALIGN:
4653 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4654 break;
4655 #if defined(TARGET_MIPS64)
4656 case OPC_DALIGN:
4657 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4658 break;
4659 #endif
4661 } else {
4662 TCGv t1 = tcg_temp_new();
4663 gen_load_gpr(t1, rs);
4664 switch (opc) {
4665 case OPC_ALIGN:
4667 TCGv_i64 t2 = tcg_temp_new_i64();
4668 tcg_gen_concat_tl_i64(t2, t1, t0);
4669 tcg_gen_shri_i64(t2, t2, 8 * (4 - bp));
4670 gen_move_low32(cpu_gpr[rd], t2);
4671 tcg_temp_free_i64(t2);
4673 break;
4674 #if defined(TARGET_MIPS64)
4675 case OPC_DALIGN:
4676 tcg_gen_shli_tl(t0, t0, 8 * bp);
4677 tcg_gen_shri_tl(t1, t1, 8 * (8 - bp));
4678 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4679 break;
4680 #endif
4682 tcg_temp_free(t1);
4685 tcg_temp_free(t0);
4688 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4690 TCGv t0;
4691 if (rd == 0) {
4692 /* Treat as NOP. */
4693 return;
4695 t0 = tcg_temp_new();
4696 gen_load_gpr(t0, rt);
4697 switch (opc) {
4698 case OPC_BITSWAP:
4699 gen_helper_bitswap(cpu_gpr[rd], t0);
4700 break;
4701 #if defined(TARGET_MIPS64)
4702 case OPC_DBITSWAP:
4703 gen_helper_dbitswap(cpu_gpr[rd], t0);
4704 break;
4705 #endif
4707 tcg_temp_free(t0);
4710 #ifndef CONFIG_USER_ONLY
4711 /* CP0 (MMU and control) */
4712 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4714 TCGv_i64 t0 = tcg_temp_new_i64();
4715 TCGv_i64 t1 = tcg_temp_new_i64();
4717 tcg_gen_ext_tl_i64(t0, arg);
4718 tcg_gen_ld_i64(t1, cpu_env, off);
4719 #if defined(TARGET_MIPS64)
4720 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4721 #else
4722 tcg_gen_concat32_i64(t1, t1, t0);
4723 #endif
4724 tcg_gen_st_i64(t1, cpu_env, off);
4725 tcg_temp_free_i64(t1);
4726 tcg_temp_free_i64(t0);
4729 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4731 TCGv_i64 t0 = tcg_temp_new_i64();
4732 TCGv_i64 t1 = tcg_temp_new_i64();
4734 tcg_gen_ext_tl_i64(t0, arg);
4735 tcg_gen_ld_i64(t1, cpu_env, off);
4736 tcg_gen_concat32_i64(t1, t1, t0);
4737 tcg_gen_st_i64(t1, cpu_env, off);
4738 tcg_temp_free_i64(t1);
4739 tcg_temp_free_i64(t0);
4742 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
4744 TCGv_i64 t0 = tcg_temp_new_i64();
4746 tcg_gen_ld_i64(t0, cpu_env, off);
4747 #if defined(TARGET_MIPS64)
4748 tcg_gen_shri_i64(t0, t0, 30);
4749 #else
4750 tcg_gen_shri_i64(t0, t0, 32);
4751 #endif
4752 gen_move_low32(arg, t0);
4753 tcg_temp_free_i64(t0);
4756 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
4758 TCGv_i64 t0 = tcg_temp_new_i64();
4760 tcg_gen_ld_i64(t0, cpu_env, off);
4761 tcg_gen_shri_i64(t0, t0, 32 + shift);
4762 gen_move_low32(arg, t0);
4763 tcg_temp_free_i64(t0);
4766 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4768 TCGv_i32 t0 = tcg_temp_new_i32();
4770 tcg_gen_ld_i32(t0, cpu_env, off);
4771 tcg_gen_ext_i32_tl(arg, t0);
4772 tcg_temp_free_i32(t0);
4775 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4777 tcg_gen_ld_tl(arg, cpu_env, off);
4778 tcg_gen_ext32s_tl(arg, arg);
4781 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4783 TCGv_i32 t0 = tcg_temp_new_i32();
4785 tcg_gen_trunc_tl_i32(t0, arg);
4786 tcg_gen_st_i32(t0, cpu_env, off);
4787 tcg_temp_free_i32(t0);
4790 #define CP0_CHECK(c) \
4791 do { \
4792 if (!(c)) { \
4793 goto cp0_unimplemented; \
4795 } while (0)
4797 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4799 const char *rn = "invalid";
4801 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4803 switch (reg) {
4804 case 2:
4805 switch (sel) {
4806 case 0:
4807 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4808 rn = "EntryLo0";
4809 break;
4810 default:
4811 goto cp0_unimplemented;
4813 break;
4814 case 3:
4815 switch (sel) {
4816 case 0:
4817 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4818 rn = "EntryLo1";
4819 break;
4820 default:
4821 goto cp0_unimplemented;
4823 break;
4824 case 17:
4825 switch (sel) {
4826 case 0:
4827 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
4828 ctx->CP0_LLAddr_shift);
4829 rn = "LLAddr";
4830 break;
4831 case 1:
4832 CP0_CHECK(ctx->mrp);
4833 gen_helper_mfhc0_maar(arg, cpu_env);
4834 rn = "MAAR";
4835 break;
4836 default:
4837 goto cp0_unimplemented;
4839 break;
4840 case 28:
4841 switch (sel) {
4842 case 0:
4843 case 2:
4844 case 4:
4845 case 6:
4846 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
4847 rn = "TagLo";
4848 break;
4849 default:
4850 goto cp0_unimplemented;
4852 break;
4853 default:
4854 goto cp0_unimplemented;
4857 (void)rn; /* avoid a compiler warning */
4858 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4859 return;
4861 cp0_unimplemented:
4862 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4863 tcg_gen_movi_tl(arg, 0);
4866 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4868 const char *rn = "invalid";
4869 uint64_t mask = ctx->PAMask >> 36;
4871 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4873 switch (reg) {
4874 case 2:
4875 switch (sel) {
4876 case 0:
4877 tcg_gen_andi_tl(arg, arg, mask);
4878 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4879 rn = "EntryLo0";
4880 break;
4881 default:
4882 goto cp0_unimplemented;
4884 break;
4885 case 3:
4886 switch (sel) {
4887 case 0:
4888 tcg_gen_andi_tl(arg, arg, mask);
4889 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4890 rn = "EntryLo1";
4891 break;
4892 default:
4893 goto cp0_unimplemented;
4895 break;
4896 case 17:
4897 switch (sel) {
4898 case 0:
4899 /* LLAddr is read-only (the only exception is bit 0 if LLB is
4900 supported); the CP0_LLAddr_rw_bitmask does not seem to be
4901 relevant for modern MIPS cores supporting MTHC0, therefore
4902 treating MTHC0 to LLAddr as NOP. */
4903 rn = "LLAddr";
4904 break;
4905 case 1:
4906 CP0_CHECK(ctx->mrp);
4907 gen_helper_mthc0_maar(cpu_env, arg);
4908 rn = "MAAR";
4909 break;
4910 default:
4911 goto cp0_unimplemented;
4913 break;
4914 case 28:
4915 switch (sel) {
4916 case 0:
4917 case 2:
4918 case 4:
4919 case 6:
4920 tcg_gen_andi_tl(arg, arg, mask);
4921 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
4922 rn = "TagLo";
4923 break;
4924 default:
4925 goto cp0_unimplemented;
4927 break;
4928 default:
4929 goto cp0_unimplemented;
4932 (void)rn; /* avoid a compiler warning */
4933 cp0_unimplemented:
4934 LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
4937 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
4939 if (ctx->insn_flags & ISA_MIPS32R6) {
4940 tcg_gen_movi_tl(arg, 0);
4941 } else {
4942 tcg_gen_movi_tl(arg, ~0);
4946 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4948 const char *rn = "invalid";
4950 if (sel != 0)
4951 check_insn(ctx, ISA_MIPS32);
4953 switch (reg) {
4954 case 0:
4955 switch (sel) {
4956 case 0:
4957 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4958 rn = "Index";
4959 break;
4960 case 1:
4961 CP0_CHECK(ctx->insn_flags & ASE_MT);
4962 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4963 rn = "MVPControl";
4964 break;
4965 case 2:
4966 CP0_CHECK(ctx->insn_flags & ASE_MT);
4967 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4968 rn = "MVPConf0";
4969 break;
4970 case 3:
4971 CP0_CHECK(ctx->insn_flags & ASE_MT);
4972 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4973 rn = "MVPConf1";
4974 break;
4975 case 4:
4976 CP0_CHECK(ctx->vp);
4977 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
4978 rn = "VPControl";
4979 break;
4980 default:
4981 goto cp0_unimplemented;
4983 break;
4984 case 1:
4985 switch (sel) {
4986 case 0:
4987 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
4988 gen_helper_mfc0_random(arg, cpu_env);
4989 rn = "Random";
4990 break;
4991 case 1:
4992 CP0_CHECK(ctx->insn_flags & ASE_MT);
4993 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4994 rn = "VPEControl";
4995 break;
4996 case 2:
4997 CP0_CHECK(ctx->insn_flags & ASE_MT);
4998 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
4999 rn = "VPEConf0";
5000 break;
5001 case 3:
5002 CP0_CHECK(ctx->insn_flags & ASE_MT);
5003 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5004 rn = "VPEConf1";
5005 break;
5006 case 4:
5007 CP0_CHECK(ctx->insn_flags & ASE_MT);
5008 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5009 rn = "YQMask";
5010 break;
5011 case 5:
5012 CP0_CHECK(ctx->insn_flags & ASE_MT);
5013 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5014 rn = "VPESchedule";
5015 break;
5016 case 6:
5017 CP0_CHECK(ctx->insn_flags & ASE_MT);
5018 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5019 rn = "VPEScheFBack";
5020 break;
5021 case 7:
5022 CP0_CHECK(ctx->insn_flags & ASE_MT);
5023 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5024 rn = "VPEOpt";
5025 break;
5026 default:
5027 goto cp0_unimplemented;
5029 break;
5030 case 2:
5031 switch (sel) {
5032 case 0:
5034 TCGv_i64 tmp = tcg_temp_new_i64();
5035 tcg_gen_ld_i64(tmp, cpu_env,
5036 offsetof(CPUMIPSState, CP0_EntryLo0));
5037 #if defined(TARGET_MIPS64)
5038 if (ctx->rxi) {
5039 /* Move RI/XI fields to bits 31:30 */
5040 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5041 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5043 #endif
5044 gen_move_low32(arg, tmp);
5045 tcg_temp_free_i64(tmp);
5047 rn = "EntryLo0";
5048 break;
5049 case 1:
5050 CP0_CHECK(ctx->insn_flags & ASE_MT);
5051 gen_helper_mfc0_tcstatus(arg, cpu_env);
5052 rn = "TCStatus";
5053 break;
5054 case 2:
5055 CP0_CHECK(ctx->insn_flags & ASE_MT);
5056 gen_helper_mfc0_tcbind(arg, cpu_env);
5057 rn = "TCBind";
5058 break;
5059 case 3:
5060 CP0_CHECK(ctx->insn_flags & ASE_MT);
5061 gen_helper_mfc0_tcrestart(arg, cpu_env);
5062 rn = "TCRestart";
5063 break;
5064 case 4:
5065 CP0_CHECK(ctx->insn_flags & ASE_MT);
5066 gen_helper_mfc0_tchalt(arg, cpu_env);
5067 rn = "TCHalt";
5068 break;
5069 case 5:
5070 CP0_CHECK(ctx->insn_flags & ASE_MT);
5071 gen_helper_mfc0_tccontext(arg, cpu_env);
5072 rn = "TCContext";
5073 break;
5074 case 6:
5075 CP0_CHECK(ctx->insn_flags & ASE_MT);
5076 gen_helper_mfc0_tcschedule(arg, cpu_env);
5077 rn = "TCSchedule";
5078 break;
5079 case 7:
5080 CP0_CHECK(ctx->insn_flags & ASE_MT);
5081 gen_helper_mfc0_tcschefback(arg, cpu_env);
5082 rn = "TCScheFBack";
5083 break;
5084 default:
5085 goto cp0_unimplemented;
5087 break;
5088 case 3:
5089 switch (sel) {
5090 case 0:
5092 TCGv_i64 tmp = tcg_temp_new_i64();
5093 tcg_gen_ld_i64(tmp, cpu_env,
5094 offsetof(CPUMIPSState, CP0_EntryLo1));
5095 #if defined(TARGET_MIPS64)
5096 if (ctx->rxi) {
5097 /* Move RI/XI fields to bits 31:30 */
5098 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5099 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5101 #endif
5102 gen_move_low32(arg, tmp);
5103 tcg_temp_free_i64(tmp);
5105 rn = "EntryLo1";
5106 break;
5107 case 1:
5108 CP0_CHECK(ctx->vp);
5109 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5110 rn = "GlobalNumber";
5111 break;
5112 default:
5113 goto cp0_unimplemented;
5115 break;
5116 case 4:
5117 switch (sel) {
5118 case 0:
5119 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5120 tcg_gen_ext32s_tl(arg, arg);
5121 rn = "Context";
5122 break;
5123 case 1:
5124 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5125 rn = "ContextConfig";
5126 goto cp0_unimplemented;
5127 // break;
5128 case 2:
5129 CP0_CHECK(ctx->ulri);
5130 tcg_gen_ld32s_tl(arg, cpu_env,
5131 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5132 rn = "UserLocal";
5133 break;
5134 default:
5135 goto cp0_unimplemented;
5137 break;
5138 case 5:
5139 switch (sel) {
5140 case 0:
5141 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5142 rn = "PageMask";
5143 break;
5144 case 1:
5145 check_insn(ctx, ISA_MIPS32R2);
5146 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5147 rn = "PageGrain";
5148 break;
5149 default:
5150 goto cp0_unimplemented;
5152 break;
5153 case 6:
5154 switch (sel) {
5155 case 0:
5156 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5157 rn = "Wired";
5158 break;
5159 case 1:
5160 check_insn(ctx, ISA_MIPS32R2);
5161 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5162 rn = "SRSConf0";
5163 break;
5164 case 2:
5165 check_insn(ctx, ISA_MIPS32R2);
5166 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5167 rn = "SRSConf1";
5168 break;
5169 case 3:
5170 check_insn(ctx, ISA_MIPS32R2);
5171 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5172 rn = "SRSConf2";
5173 break;
5174 case 4:
5175 check_insn(ctx, ISA_MIPS32R2);
5176 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5177 rn = "SRSConf3";
5178 break;
5179 case 5:
5180 check_insn(ctx, ISA_MIPS32R2);
5181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5182 rn = "SRSConf4";
5183 break;
5184 default:
5185 goto cp0_unimplemented;
5187 break;
5188 case 7:
5189 switch (sel) {
5190 case 0:
5191 check_insn(ctx, ISA_MIPS32R2);
5192 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5193 rn = "HWREna";
5194 break;
5195 default:
5196 goto cp0_unimplemented;
5198 break;
5199 case 8:
5200 switch (sel) {
5201 case 0:
5202 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5203 tcg_gen_ext32s_tl(arg, arg);
5204 rn = "BadVAddr";
5205 break;
5206 case 1:
5207 CP0_CHECK(ctx->bi);
5208 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5209 rn = "BadInstr";
5210 break;
5211 case 2:
5212 CP0_CHECK(ctx->bp);
5213 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5214 rn = "BadInstrP";
5215 break;
5216 default:
5217 goto cp0_unimplemented;
5219 break;
5220 case 9:
5221 switch (sel) {
5222 case 0:
5223 /* Mark as an IO operation because we read the time. */
5224 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5225 gen_io_start();
5227 gen_helper_mfc0_count(arg, cpu_env);
5228 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5229 gen_io_end();
5231 /* Break the TB to be able to take timer interrupts immediately
5232 after reading count. */
5233 ctx->bstate = BS_STOP;
5234 rn = "Count";
5235 break;
5236 /* 6,7 are implementation dependent */
5237 default:
5238 goto cp0_unimplemented;
5240 break;
5241 case 10:
5242 switch (sel) {
5243 case 0:
5244 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5245 tcg_gen_ext32s_tl(arg, arg);
5246 rn = "EntryHi";
5247 break;
5248 default:
5249 goto cp0_unimplemented;
5251 break;
5252 case 11:
5253 switch (sel) {
5254 case 0:
5255 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5256 rn = "Compare";
5257 break;
5258 /* 6,7 are implementation dependent */
5259 default:
5260 goto cp0_unimplemented;
5262 break;
5263 case 12:
5264 switch (sel) {
5265 case 0:
5266 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5267 rn = "Status";
5268 break;
5269 case 1:
5270 check_insn(ctx, ISA_MIPS32R2);
5271 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5272 rn = "IntCtl";
5273 break;
5274 case 2:
5275 check_insn(ctx, ISA_MIPS32R2);
5276 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5277 rn = "SRSCtl";
5278 break;
5279 case 3:
5280 check_insn(ctx, ISA_MIPS32R2);
5281 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5282 rn = "SRSMap";
5283 break;
5284 default:
5285 goto cp0_unimplemented;
5287 break;
5288 case 13:
5289 switch (sel) {
5290 case 0:
5291 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5292 rn = "Cause";
5293 break;
5294 default:
5295 goto cp0_unimplemented;
5297 break;
5298 case 14:
5299 switch (sel) {
5300 case 0:
5301 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5302 tcg_gen_ext32s_tl(arg, arg);
5303 rn = "EPC";
5304 break;
5305 default:
5306 goto cp0_unimplemented;
5308 break;
5309 case 15:
5310 switch (sel) {
5311 case 0:
5312 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5313 rn = "PRid";
5314 break;
5315 case 1:
5316 check_insn(ctx, ISA_MIPS32R2);
5317 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5318 rn = "EBase";
5319 break;
5320 case 3:
5321 check_insn(ctx, ISA_MIPS32R2);
5322 CP0_CHECK(ctx->cmgcr);
5323 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
5324 tcg_gen_ext32s_tl(arg, arg);
5325 rn = "CMGCRBase";
5326 break;
5327 default:
5328 goto cp0_unimplemented;
5330 break;
5331 case 16:
5332 switch (sel) {
5333 case 0:
5334 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5335 rn = "Config";
5336 break;
5337 case 1:
5338 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5339 rn = "Config1";
5340 break;
5341 case 2:
5342 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5343 rn = "Config2";
5344 break;
5345 case 3:
5346 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5347 rn = "Config3";
5348 break;
5349 case 4:
5350 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5351 rn = "Config4";
5352 break;
5353 case 5:
5354 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5355 rn = "Config5";
5356 break;
5357 /* 6,7 are implementation dependent */
5358 case 6:
5359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5360 rn = "Config6";
5361 break;
5362 case 7:
5363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5364 rn = "Config7";
5365 break;
5366 default:
5367 goto cp0_unimplemented;
5369 break;
5370 case 17:
5371 switch (sel) {
5372 case 0:
5373 gen_helper_mfc0_lladdr(arg, cpu_env);
5374 rn = "LLAddr";
5375 break;
5376 case 1:
5377 CP0_CHECK(ctx->mrp);
5378 gen_helper_mfc0_maar(arg, cpu_env);
5379 rn = "MAAR";
5380 break;
5381 case 2:
5382 CP0_CHECK(ctx->mrp);
5383 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
5384 rn = "MAARI";
5385 break;
5386 default:
5387 goto cp0_unimplemented;
5389 break;
5390 case 18:
5391 switch (sel) {
5392 case 0 ... 7:
5393 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5394 rn = "WatchLo";
5395 break;
5396 default:
5397 goto cp0_unimplemented;
5399 break;
5400 case 19:
5401 switch (sel) {
5402 case 0 ...7:
5403 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5404 rn = "WatchHi";
5405 break;
5406 default:
5407 goto cp0_unimplemented;
5409 break;
5410 case 20:
5411 switch (sel) {
5412 case 0:
5413 #if defined(TARGET_MIPS64)
5414 check_insn(ctx, ISA_MIPS3);
5415 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5416 tcg_gen_ext32s_tl(arg, arg);
5417 rn = "XContext";
5418 break;
5419 #endif
5420 default:
5421 goto cp0_unimplemented;
5423 break;
5424 case 21:
5425 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5426 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5427 switch (sel) {
5428 case 0:
5429 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5430 rn = "Framemask";
5431 break;
5432 default:
5433 goto cp0_unimplemented;
5435 break;
5436 case 22:
5437 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5438 rn = "'Diagnostic"; /* implementation dependent */
5439 break;
5440 case 23:
5441 switch (sel) {
5442 case 0:
5443 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5444 rn = "Debug";
5445 break;
5446 case 1:
5447 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5448 rn = "TraceControl";
5449 // break;
5450 case 2:
5451 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5452 rn = "TraceControl2";
5453 // break;
5454 case 3:
5455 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5456 rn = "UserTraceData";
5457 // break;
5458 case 4:
5459 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5460 rn = "TraceBPC";
5461 // break;
5462 default:
5463 goto cp0_unimplemented;
5465 break;
5466 case 24:
5467 switch (sel) {
5468 case 0:
5469 /* EJTAG support */
5470 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5471 tcg_gen_ext32s_tl(arg, arg);
5472 rn = "DEPC";
5473 break;
5474 default:
5475 goto cp0_unimplemented;
5477 break;
5478 case 25:
5479 switch (sel) {
5480 case 0:
5481 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5482 rn = "Performance0";
5483 break;
5484 case 1:
5485 // gen_helper_mfc0_performance1(arg);
5486 rn = "Performance1";
5487 // break;
5488 case 2:
5489 // gen_helper_mfc0_performance2(arg);
5490 rn = "Performance2";
5491 // break;
5492 case 3:
5493 // gen_helper_mfc0_performance3(arg);
5494 rn = "Performance3";
5495 // break;
5496 case 4:
5497 // gen_helper_mfc0_performance4(arg);
5498 rn = "Performance4";
5499 // break;
5500 case 5:
5501 // gen_helper_mfc0_performance5(arg);
5502 rn = "Performance5";
5503 // break;
5504 case 6:
5505 // gen_helper_mfc0_performance6(arg);
5506 rn = "Performance6";
5507 // break;
5508 case 7:
5509 // gen_helper_mfc0_performance7(arg);
5510 rn = "Performance7";
5511 // break;
5512 default:
5513 goto cp0_unimplemented;
5515 break;
5516 case 26:
5517 switch (sel) {
5518 case 0:
5519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
5520 rn = "ErrCtl";
5521 break;
5522 default:
5523 goto cp0_unimplemented;
5525 break;
5526 case 27:
5527 switch (sel) {
5528 case 0 ... 3:
5529 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5530 rn = "CacheErr";
5531 break;
5532 default:
5533 goto cp0_unimplemented;
5535 break;
5536 case 28:
5537 switch (sel) {
5538 case 0:
5539 case 2:
5540 case 4:
5541 case 6:
5543 TCGv_i64 tmp = tcg_temp_new_i64();
5544 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5545 gen_move_low32(arg, tmp);
5546 tcg_temp_free_i64(tmp);
5548 rn = "TagLo";
5549 break;
5550 case 1:
5551 case 3:
5552 case 5:
5553 case 7:
5554 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5555 rn = "DataLo";
5556 break;
5557 default:
5558 goto cp0_unimplemented;
5560 break;
5561 case 29:
5562 switch (sel) {
5563 case 0:
5564 case 2:
5565 case 4:
5566 case 6:
5567 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5568 rn = "TagHi";
5569 break;
5570 case 1:
5571 case 3:
5572 case 5:
5573 case 7:
5574 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5575 rn = "DataHi";
5576 break;
5577 default:
5578 goto cp0_unimplemented;
5580 break;
5581 case 30:
5582 switch (sel) {
5583 case 0:
5584 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5585 tcg_gen_ext32s_tl(arg, arg);
5586 rn = "ErrorEPC";
5587 break;
5588 default:
5589 goto cp0_unimplemented;
5591 break;
5592 case 31:
5593 switch (sel) {
5594 case 0:
5595 /* EJTAG support */
5596 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5597 rn = "DESAVE";
5598 break;
5599 case 2 ... 7:
5600 CP0_CHECK(ctx->kscrexist & (1 << sel));
5601 tcg_gen_ld_tl(arg, cpu_env,
5602 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5603 tcg_gen_ext32s_tl(arg, arg);
5604 rn = "KScratch";
5605 break;
5606 default:
5607 goto cp0_unimplemented;
5609 break;
5610 default:
5611 goto cp0_unimplemented;
5613 (void)rn; /* avoid a compiler warning */
5614 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5615 return;
5617 cp0_unimplemented:
5618 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5619 gen_mfc0_unimplemented(ctx, arg);
5622 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5624 const char *rn = "invalid";
5626 if (sel != 0)
5627 check_insn(ctx, ISA_MIPS32);
5629 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5630 gen_io_start();
5633 switch (reg) {
5634 case 0:
5635 switch (sel) {
5636 case 0:
5637 gen_helper_mtc0_index(cpu_env, arg);
5638 rn = "Index";
5639 break;
5640 case 1:
5641 CP0_CHECK(ctx->insn_flags & ASE_MT);
5642 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5643 rn = "MVPControl";
5644 break;
5645 case 2:
5646 CP0_CHECK(ctx->insn_flags & ASE_MT);
5647 /* ignored */
5648 rn = "MVPConf0";
5649 break;
5650 case 3:
5651 CP0_CHECK(ctx->insn_flags & ASE_MT);
5652 /* ignored */
5653 rn = "MVPConf1";
5654 break;
5655 case 4:
5656 CP0_CHECK(ctx->vp);
5657 /* ignored */
5658 rn = "VPControl";
5659 break;
5660 default:
5661 goto cp0_unimplemented;
5663 break;
5664 case 1:
5665 switch (sel) {
5666 case 0:
5667 /* ignored */
5668 rn = "Random";
5669 break;
5670 case 1:
5671 CP0_CHECK(ctx->insn_flags & ASE_MT);
5672 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5673 rn = "VPEControl";
5674 break;
5675 case 2:
5676 CP0_CHECK(ctx->insn_flags & ASE_MT);
5677 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5678 rn = "VPEConf0";
5679 break;
5680 case 3:
5681 CP0_CHECK(ctx->insn_flags & ASE_MT);
5682 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5683 rn = "VPEConf1";
5684 break;
5685 case 4:
5686 CP0_CHECK(ctx->insn_flags & ASE_MT);
5687 gen_helper_mtc0_yqmask(cpu_env, arg);
5688 rn = "YQMask";
5689 break;
5690 case 5:
5691 CP0_CHECK(ctx->insn_flags & ASE_MT);
5692 tcg_gen_st_tl(arg, cpu_env,
5693 offsetof(CPUMIPSState, CP0_VPESchedule));
5694 rn = "VPESchedule";
5695 break;
5696 case 6:
5697 CP0_CHECK(ctx->insn_flags & ASE_MT);
5698 tcg_gen_st_tl(arg, cpu_env,
5699 offsetof(CPUMIPSState, CP0_VPEScheFBack));
5700 rn = "VPEScheFBack";
5701 break;
5702 case 7:
5703 CP0_CHECK(ctx->insn_flags & ASE_MT);
5704 gen_helper_mtc0_vpeopt(cpu_env, arg);
5705 rn = "VPEOpt";
5706 break;
5707 default:
5708 goto cp0_unimplemented;
5710 break;
5711 case 2:
5712 switch (sel) {
5713 case 0:
5714 gen_helper_mtc0_entrylo0(cpu_env, arg);
5715 rn = "EntryLo0";
5716 break;
5717 case 1:
5718 CP0_CHECK(ctx->insn_flags & ASE_MT);
5719 gen_helper_mtc0_tcstatus(cpu_env, arg);
5720 rn = "TCStatus";
5721 break;
5722 case 2:
5723 CP0_CHECK(ctx->insn_flags & ASE_MT);
5724 gen_helper_mtc0_tcbind(cpu_env, arg);
5725 rn = "TCBind";
5726 break;
5727 case 3:
5728 CP0_CHECK(ctx->insn_flags & ASE_MT);
5729 gen_helper_mtc0_tcrestart(cpu_env, arg);
5730 rn = "TCRestart";
5731 break;
5732 case 4:
5733 CP0_CHECK(ctx->insn_flags & ASE_MT);
5734 gen_helper_mtc0_tchalt(cpu_env, arg);
5735 rn = "TCHalt";
5736 break;
5737 case 5:
5738 CP0_CHECK(ctx->insn_flags & ASE_MT);
5739 gen_helper_mtc0_tccontext(cpu_env, arg);
5740 rn = "TCContext";
5741 break;
5742 case 6:
5743 CP0_CHECK(ctx->insn_flags & ASE_MT);
5744 gen_helper_mtc0_tcschedule(cpu_env, arg);
5745 rn = "TCSchedule";
5746 break;
5747 case 7:
5748 CP0_CHECK(ctx->insn_flags & ASE_MT);
5749 gen_helper_mtc0_tcschefback(cpu_env, arg);
5750 rn = "TCScheFBack";
5751 break;
5752 default:
5753 goto cp0_unimplemented;
5755 break;
5756 case 3:
5757 switch (sel) {
5758 case 0:
5759 gen_helper_mtc0_entrylo1(cpu_env, arg);
5760 rn = "EntryLo1";
5761 break;
5762 case 1:
5763 CP0_CHECK(ctx->vp);
5764 /* ignored */
5765 rn = "GlobalNumber";
5766 break;
5767 default:
5768 goto cp0_unimplemented;
5770 break;
5771 case 4:
5772 switch (sel) {
5773 case 0:
5774 gen_helper_mtc0_context(cpu_env, arg);
5775 rn = "Context";
5776 break;
5777 case 1:
5778 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5779 rn = "ContextConfig";
5780 goto cp0_unimplemented;
5781 // break;
5782 case 2:
5783 CP0_CHECK(ctx->ulri);
5784 tcg_gen_st_tl(arg, cpu_env,
5785 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5786 rn = "UserLocal";
5787 break;
5788 default:
5789 goto cp0_unimplemented;
5791 break;
5792 case 5:
5793 switch (sel) {
5794 case 0:
5795 gen_helper_mtc0_pagemask(cpu_env, arg);
5796 rn = "PageMask";
5797 break;
5798 case 1:
5799 check_insn(ctx, ISA_MIPS32R2);
5800 gen_helper_mtc0_pagegrain(cpu_env, arg);
5801 rn = "PageGrain";
5802 ctx->bstate = BS_STOP;
5803 break;
5804 default:
5805 goto cp0_unimplemented;
5807 break;
5808 case 6:
5809 switch (sel) {
5810 case 0:
5811 gen_helper_mtc0_wired(cpu_env, arg);
5812 rn = "Wired";
5813 break;
5814 case 1:
5815 check_insn(ctx, ISA_MIPS32R2);
5816 gen_helper_mtc0_srsconf0(cpu_env, arg);
5817 rn = "SRSConf0";
5818 break;
5819 case 2:
5820 check_insn(ctx, ISA_MIPS32R2);
5821 gen_helper_mtc0_srsconf1(cpu_env, arg);
5822 rn = "SRSConf1";
5823 break;
5824 case 3:
5825 check_insn(ctx, ISA_MIPS32R2);
5826 gen_helper_mtc0_srsconf2(cpu_env, arg);
5827 rn = "SRSConf2";
5828 break;
5829 case 4:
5830 check_insn(ctx, ISA_MIPS32R2);
5831 gen_helper_mtc0_srsconf3(cpu_env, arg);
5832 rn = "SRSConf3";
5833 break;
5834 case 5:
5835 check_insn(ctx, ISA_MIPS32R2);
5836 gen_helper_mtc0_srsconf4(cpu_env, arg);
5837 rn = "SRSConf4";
5838 break;
5839 default:
5840 goto cp0_unimplemented;
5842 break;
5843 case 7:
5844 switch (sel) {
5845 case 0:
5846 check_insn(ctx, ISA_MIPS32R2);
5847 gen_helper_mtc0_hwrena(cpu_env, arg);
5848 ctx->bstate = BS_STOP;
5849 rn = "HWREna";
5850 break;
5851 default:
5852 goto cp0_unimplemented;
5854 break;
5855 case 8:
5856 switch (sel) {
5857 case 0:
5858 /* ignored */
5859 rn = "BadVAddr";
5860 break;
5861 case 1:
5862 /* ignored */
5863 rn = "BadInstr";
5864 break;
5865 case 2:
5866 /* ignored */
5867 rn = "BadInstrP";
5868 break;
5869 default:
5870 goto cp0_unimplemented;
5872 break;
5873 case 9:
5874 switch (sel) {
5875 case 0:
5876 gen_helper_mtc0_count(cpu_env, arg);
5877 rn = "Count";
5878 break;
5879 /* 6,7 are implementation dependent */
5880 default:
5881 goto cp0_unimplemented;
5883 break;
5884 case 10:
5885 switch (sel) {
5886 case 0:
5887 gen_helper_mtc0_entryhi(cpu_env, arg);
5888 rn = "EntryHi";
5889 break;
5890 default:
5891 goto cp0_unimplemented;
5893 break;
5894 case 11:
5895 switch (sel) {
5896 case 0:
5897 gen_helper_mtc0_compare(cpu_env, arg);
5898 rn = "Compare";
5899 break;
5900 /* 6,7 are implementation dependent */
5901 default:
5902 goto cp0_unimplemented;
5904 break;
5905 case 12:
5906 switch (sel) {
5907 case 0:
5908 save_cpu_state(ctx, 1);
5909 gen_helper_mtc0_status(cpu_env, arg);
5910 /* BS_STOP isn't good enough here, hflags may have changed. */
5911 gen_save_pc(ctx->pc + 4);
5912 ctx->bstate = BS_EXCP;
5913 rn = "Status";
5914 break;
5915 case 1:
5916 check_insn(ctx, ISA_MIPS32R2);
5917 gen_helper_mtc0_intctl(cpu_env, arg);
5918 /* Stop translation as we may have switched the execution mode */
5919 ctx->bstate = BS_STOP;
5920 rn = "IntCtl";
5921 break;
5922 case 2:
5923 check_insn(ctx, ISA_MIPS32R2);
5924 gen_helper_mtc0_srsctl(cpu_env, arg);
5925 /* Stop translation as we may have switched the execution mode */
5926 ctx->bstate = BS_STOP;
5927 rn = "SRSCtl";
5928 break;
5929 case 3:
5930 check_insn(ctx, ISA_MIPS32R2);
5931 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5932 /* Stop translation as we may have switched the execution mode */
5933 ctx->bstate = BS_STOP;
5934 rn = "SRSMap";
5935 break;
5936 default:
5937 goto cp0_unimplemented;
5939 break;
5940 case 13:
5941 switch (sel) {
5942 case 0:
5943 save_cpu_state(ctx, 1);
5944 gen_helper_mtc0_cause(cpu_env, arg);
5945 rn = "Cause";
5946 break;
5947 default:
5948 goto cp0_unimplemented;
5950 break;
5951 case 14:
5952 switch (sel) {
5953 case 0:
5954 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5955 rn = "EPC";
5956 break;
5957 default:
5958 goto cp0_unimplemented;
5960 break;
5961 case 15:
5962 switch (sel) {
5963 case 0:
5964 /* ignored */
5965 rn = "PRid";
5966 break;
5967 case 1:
5968 check_insn(ctx, ISA_MIPS32R2);
5969 gen_helper_mtc0_ebase(cpu_env, arg);
5970 rn = "EBase";
5971 break;
5972 default:
5973 goto cp0_unimplemented;
5975 break;
5976 case 16:
5977 switch (sel) {
5978 case 0:
5979 gen_helper_mtc0_config0(cpu_env, arg);
5980 rn = "Config";
5981 /* Stop translation as we may have switched the execution mode */
5982 ctx->bstate = BS_STOP;
5983 break;
5984 case 1:
5985 /* ignored, read only */
5986 rn = "Config1";
5987 break;
5988 case 2:
5989 gen_helper_mtc0_config2(cpu_env, arg);
5990 rn = "Config2";
5991 /* Stop translation as we may have switched the execution mode */
5992 ctx->bstate = BS_STOP;
5993 break;
5994 case 3:
5995 gen_helper_mtc0_config3(cpu_env, arg);
5996 rn = "Config3";
5997 /* Stop translation as we may have switched the execution mode */
5998 ctx->bstate = BS_STOP;
5999 break;
6000 case 4:
6001 gen_helper_mtc0_config4(cpu_env, arg);
6002 rn = "Config4";
6003 ctx->bstate = BS_STOP;
6004 break;
6005 case 5:
6006 gen_helper_mtc0_config5(cpu_env, arg);
6007 rn = "Config5";
6008 /* Stop translation as we may have switched the execution mode */
6009 ctx->bstate = BS_STOP;
6010 break;
6011 /* 6,7 are implementation dependent */
6012 case 6:
6013 /* ignored */
6014 rn = "Config6";
6015 break;
6016 case 7:
6017 /* ignored */
6018 rn = "Config7";
6019 break;
6020 default:
6021 rn = "Invalid config selector";
6022 goto cp0_unimplemented;
6024 break;
6025 case 17:
6026 switch (sel) {
6027 case 0:
6028 gen_helper_mtc0_lladdr(cpu_env, arg);
6029 rn = "LLAddr";
6030 break;
6031 case 1:
6032 CP0_CHECK(ctx->mrp);
6033 gen_helper_mtc0_maar(cpu_env, arg);
6034 rn = "MAAR";
6035 break;
6036 case 2:
6037 CP0_CHECK(ctx->mrp);
6038 gen_helper_mtc0_maari(cpu_env, arg);
6039 rn = "MAARI";
6040 break;
6041 default:
6042 goto cp0_unimplemented;
6044 break;
6045 case 18:
6046 switch (sel) {
6047 case 0 ... 7:
6048 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6049 rn = "WatchLo";
6050 break;
6051 default:
6052 goto cp0_unimplemented;
6054 break;
6055 case 19:
6056 switch (sel) {
6057 case 0 ... 7:
6058 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6059 rn = "WatchHi";
6060 break;
6061 default:
6062 goto cp0_unimplemented;
6064 break;
6065 case 20:
6066 switch (sel) {
6067 case 0:
6068 #if defined(TARGET_MIPS64)
6069 check_insn(ctx, ISA_MIPS3);
6070 gen_helper_mtc0_xcontext(cpu_env, arg);
6071 rn = "XContext";
6072 break;
6073 #endif
6074 default:
6075 goto cp0_unimplemented;
6077 break;
6078 case 21:
6079 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6080 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6081 switch (sel) {
6082 case 0:
6083 gen_helper_mtc0_framemask(cpu_env, arg);
6084 rn = "Framemask";
6085 break;
6086 default:
6087 goto cp0_unimplemented;
6089 break;
6090 case 22:
6091 /* ignored */
6092 rn = "Diagnostic"; /* implementation dependent */
6093 break;
6094 case 23:
6095 switch (sel) {
6096 case 0:
6097 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6098 /* BS_STOP isn't good enough here, hflags may have changed. */
6099 gen_save_pc(ctx->pc + 4);
6100 ctx->bstate = BS_EXCP;
6101 rn = "Debug";
6102 break;
6103 case 1:
6104 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6105 rn = "TraceControl";
6106 /* Stop translation as we may have switched the execution mode */
6107 ctx->bstate = BS_STOP;
6108 // break;
6109 case 2:
6110 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6111 rn = "TraceControl2";
6112 /* Stop translation as we may have switched the execution mode */
6113 ctx->bstate = BS_STOP;
6114 // break;
6115 case 3:
6116 /* Stop translation as we may have switched the execution mode */
6117 ctx->bstate = BS_STOP;
6118 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6119 rn = "UserTraceData";
6120 /* Stop translation as we may have switched the execution mode */
6121 ctx->bstate = BS_STOP;
6122 // break;
6123 case 4:
6124 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6125 /* Stop translation as we may have switched the execution mode */
6126 ctx->bstate = BS_STOP;
6127 rn = "TraceBPC";
6128 // break;
6129 default:
6130 goto cp0_unimplemented;
6132 break;
6133 case 24:
6134 switch (sel) {
6135 case 0:
6136 /* EJTAG support */
6137 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6138 rn = "DEPC";
6139 break;
6140 default:
6141 goto cp0_unimplemented;
6143 break;
6144 case 25:
6145 switch (sel) {
6146 case 0:
6147 gen_helper_mtc0_performance0(cpu_env, arg);
6148 rn = "Performance0";
6149 break;
6150 case 1:
6151 // gen_helper_mtc0_performance1(arg);
6152 rn = "Performance1";
6153 // break;
6154 case 2:
6155 // gen_helper_mtc0_performance2(arg);
6156 rn = "Performance2";
6157 // break;
6158 case 3:
6159 // gen_helper_mtc0_performance3(arg);
6160 rn = "Performance3";
6161 // break;
6162 case 4:
6163 // gen_helper_mtc0_performance4(arg);
6164 rn = "Performance4";
6165 // break;
6166 case 5:
6167 // gen_helper_mtc0_performance5(arg);
6168 rn = "Performance5";
6169 // break;
6170 case 6:
6171 // gen_helper_mtc0_performance6(arg);
6172 rn = "Performance6";
6173 // break;
6174 case 7:
6175 // gen_helper_mtc0_performance7(arg);
6176 rn = "Performance7";
6177 // break;
6178 default:
6179 goto cp0_unimplemented;
6181 break;
6182 case 26:
6183 switch (sel) {
6184 case 0:
6185 gen_helper_mtc0_errctl(cpu_env, arg);
6186 ctx->bstate = BS_STOP;
6187 rn = "ErrCtl";
6188 break;
6189 default:
6190 goto cp0_unimplemented;
6192 break;
6193 case 27:
6194 switch (sel) {
6195 case 0 ... 3:
6196 /* ignored */
6197 rn = "CacheErr";
6198 break;
6199 default:
6200 goto cp0_unimplemented;
6202 break;
6203 case 28:
6204 switch (sel) {
6205 case 0:
6206 case 2:
6207 case 4:
6208 case 6:
6209 gen_helper_mtc0_taglo(cpu_env, arg);
6210 rn = "TagLo";
6211 break;
6212 case 1:
6213 case 3:
6214 case 5:
6215 case 7:
6216 gen_helper_mtc0_datalo(cpu_env, arg);
6217 rn = "DataLo";
6218 break;
6219 default:
6220 goto cp0_unimplemented;
6222 break;
6223 case 29:
6224 switch (sel) {
6225 case 0:
6226 case 2:
6227 case 4:
6228 case 6:
6229 gen_helper_mtc0_taghi(cpu_env, arg);
6230 rn = "TagHi";
6231 break;
6232 case 1:
6233 case 3:
6234 case 5:
6235 case 7:
6236 gen_helper_mtc0_datahi(cpu_env, arg);
6237 rn = "DataHi";
6238 break;
6239 default:
6240 rn = "invalid sel";
6241 goto cp0_unimplemented;
6243 break;
6244 case 30:
6245 switch (sel) {
6246 case 0:
6247 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6248 rn = "ErrorEPC";
6249 break;
6250 default:
6251 goto cp0_unimplemented;
6253 break;
6254 case 31:
6255 switch (sel) {
6256 case 0:
6257 /* EJTAG support */
6258 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6259 rn = "DESAVE";
6260 break;
6261 case 2 ... 7:
6262 CP0_CHECK(ctx->kscrexist & (1 << sel));
6263 tcg_gen_st_tl(arg, cpu_env,
6264 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6265 rn = "KScratch";
6266 break;
6267 default:
6268 goto cp0_unimplemented;
6270 /* Stop translation as we may have switched the execution mode */
6271 ctx->bstate = BS_STOP;
6272 break;
6273 default:
6274 goto cp0_unimplemented;
6276 (void)rn; /* avoid a compiler warning */
6277 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6278 /* For simplicity assume that all writes can cause interrupts. */
6279 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6280 gen_io_end();
6281 ctx->bstate = BS_STOP;
6283 return;
6285 cp0_unimplemented:
6286 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6289 #if defined(TARGET_MIPS64)
6290 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6292 const char *rn = "invalid";
6294 if (sel != 0)
6295 check_insn(ctx, ISA_MIPS64);
6297 switch (reg) {
6298 case 0:
6299 switch (sel) {
6300 case 0:
6301 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6302 rn = "Index";
6303 break;
6304 case 1:
6305 CP0_CHECK(ctx->insn_flags & ASE_MT);
6306 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6307 rn = "MVPControl";
6308 break;
6309 case 2:
6310 CP0_CHECK(ctx->insn_flags & ASE_MT);
6311 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6312 rn = "MVPConf0";
6313 break;
6314 case 3:
6315 CP0_CHECK(ctx->insn_flags & ASE_MT);
6316 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6317 rn = "MVPConf1";
6318 break;
6319 case 4:
6320 CP0_CHECK(ctx->vp);
6321 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6322 rn = "VPControl";
6323 break;
6324 default:
6325 goto cp0_unimplemented;
6327 break;
6328 case 1:
6329 switch (sel) {
6330 case 0:
6331 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6332 gen_helper_mfc0_random(arg, cpu_env);
6333 rn = "Random";
6334 break;
6335 case 1:
6336 CP0_CHECK(ctx->insn_flags & ASE_MT);
6337 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6338 rn = "VPEControl";
6339 break;
6340 case 2:
6341 CP0_CHECK(ctx->insn_flags & ASE_MT);
6342 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6343 rn = "VPEConf0";
6344 break;
6345 case 3:
6346 CP0_CHECK(ctx->insn_flags & ASE_MT);
6347 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6348 rn = "VPEConf1";
6349 break;
6350 case 4:
6351 CP0_CHECK(ctx->insn_flags & ASE_MT);
6352 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6353 rn = "YQMask";
6354 break;
6355 case 5:
6356 CP0_CHECK(ctx->insn_flags & ASE_MT);
6357 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6358 rn = "VPESchedule";
6359 break;
6360 case 6:
6361 CP0_CHECK(ctx->insn_flags & ASE_MT);
6362 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6363 rn = "VPEScheFBack";
6364 break;
6365 case 7:
6366 CP0_CHECK(ctx->insn_flags & ASE_MT);
6367 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6368 rn = "VPEOpt";
6369 break;
6370 default:
6371 goto cp0_unimplemented;
6373 break;
6374 case 2:
6375 switch (sel) {
6376 case 0:
6377 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6378 rn = "EntryLo0";
6379 break;
6380 case 1:
6381 CP0_CHECK(ctx->insn_flags & ASE_MT);
6382 gen_helper_mfc0_tcstatus(arg, cpu_env);
6383 rn = "TCStatus";
6384 break;
6385 case 2:
6386 CP0_CHECK(ctx->insn_flags & ASE_MT);
6387 gen_helper_mfc0_tcbind(arg, cpu_env);
6388 rn = "TCBind";
6389 break;
6390 case 3:
6391 CP0_CHECK(ctx->insn_flags & ASE_MT);
6392 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6393 rn = "TCRestart";
6394 break;
6395 case 4:
6396 CP0_CHECK(ctx->insn_flags & ASE_MT);
6397 gen_helper_dmfc0_tchalt(arg, cpu_env);
6398 rn = "TCHalt";
6399 break;
6400 case 5:
6401 CP0_CHECK(ctx->insn_flags & ASE_MT);
6402 gen_helper_dmfc0_tccontext(arg, cpu_env);
6403 rn = "TCContext";
6404 break;
6405 case 6:
6406 CP0_CHECK(ctx->insn_flags & ASE_MT);
6407 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6408 rn = "TCSchedule";
6409 break;
6410 case 7:
6411 CP0_CHECK(ctx->insn_flags & ASE_MT);
6412 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6413 rn = "TCScheFBack";
6414 break;
6415 default:
6416 goto cp0_unimplemented;
6418 break;
6419 case 3:
6420 switch (sel) {
6421 case 0:
6422 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6423 rn = "EntryLo1";
6424 break;
6425 case 1:
6426 CP0_CHECK(ctx->vp);
6427 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6428 rn = "GlobalNumber";
6429 break;
6430 default:
6431 goto cp0_unimplemented;
6433 break;
6434 case 4:
6435 switch (sel) {
6436 case 0:
6437 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6438 rn = "Context";
6439 break;
6440 case 1:
6441 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6442 rn = "ContextConfig";
6443 goto cp0_unimplemented;
6444 // break;
6445 case 2:
6446 CP0_CHECK(ctx->ulri);
6447 tcg_gen_ld_tl(arg, cpu_env,
6448 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6449 rn = "UserLocal";
6450 break;
6451 default:
6452 goto cp0_unimplemented;
6454 break;
6455 case 5:
6456 switch (sel) {
6457 case 0:
6458 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6459 rn = "PageMask";
6460 break;
6461 case 1:
6462 check_insn(ctx, ISA_MIPS32R2);
6463 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6464 rn = "PageGrain";
6465 break;
6466 default:
6467 goto cp0_unimplemented;
6469 break;
6470 case 6:
6471 switch (sel) {
6472 case 0:
6473 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6474 rn = "Wired";
6475 break;
6476 case 1:
6477 check_insn(ctx, ISA_MIPS32R2);
6478 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6479 rn = "SRSConf0";
6480 break;
6481 case 2:
6482 check_insn(ctx, ISA_MIPS32R2);
6483 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6484 rn = "SRSConf1";
6485 break;
6486 case 3:
6487 check_insn(ctx, ISA_MIPS32R2);
6488 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6489 rn = "SRSConf2";
6490 break;
6491 case 4:
6492 check_insn(ctx, ISA_MIPS32R2);
6493 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6494 rn = "SRSConf3";
6495 break;
6496 case 5:
6497 check_insn(ctx, ISA_MIPS32R2);
6498 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6499 rn = "SRSConf4";
6500 break;
6501 default:
6502 goto cp0_unimplemented;
6504 break;
6505 case 7:
6506 switch (sel) {
6507 case 0:
6508 check_insn(ctx, ISA_MIPS32R2);
6509 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6510 rn = "HWREna";
6511 break;
6512 default:
6513 goto cp0_unimplemented;
6515 break;
6516 case 8:
6517 switch (sel) {
6518 case 0:
6519 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6520 rn = "BadVAddr";
6521 break;
6522 case 1:
6523 CP0_CHECK(ctx->bi);
6524 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6525 rn = "BadInstr";
6526 break;
6527 case 2:
6528 CP0_CHECK(ctx->bp);
6529 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6530 rn = "BadInstrP";
6531 break;
6532 default:
6533 goto cp0_unimplemented;
6535 break;
6536 case 9:
6537 switch (sel) {
6538 case 0:
6539 /* Mark as an IO operation because we read the time. */
6540 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6541 gen_io_start();
6543 gen_helper_mfc0_count(arg, cpu_env);
6544 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6545 gen_io_end();
6547 /* Break the TB to be able to take timer interrupts immediately
6548 after reading count. */
6549 ctx->bstate = BS_STOP;
6550 rn = "Count";
6551 break;
6552 /* 6,7 are implementation dependent */
6553 default:
6554 goto cp0_unimplemented;
6556 break;
6557 case 10:
6558 switch (sel) {
6559 case 0:
6560 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6561 rn = "EntryHi";
6562 break;
6563 default:
6564 goto cp0_unimplemented;
6566 break;
6567 case 11:
6568 switch (sel) {
6569 case 0:
6570 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6571 rn = "Compare";
6572 break;
6573 /* 6,7 are implementation dependent */
6574 default:
6575 goto cp0_unimplemented;
6577 break;
6578 case 12:
6579 switch (sel) {
6580 case 0:
6581 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6582 rn = "Status";
6583 break;
6584 case 1:
6585 check_insn(ctx, ISA_MIPS32R2);
6586 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6587 rn = "IntCtl";
6588 break;
6589 case 2:
6590 check_insn(ctx, ISA_MIPS32R2);
6591 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6592 rn = "SRSCtl";
6593 break;
6594 case 3:
6595 check_insn(ctx, ISA_MIPS32R2);
6596 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6597 rn = "SRSMap";
6598 break;
6599 default:
6600 goto cp0_unimplemented;
6602 break;
6603 case 13:
6604 switch (sel) {
6605 case 0:
6606 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6607 rn = "Cause";
6608 break;
6609 default:
6610 goto cp0_unimplemented;
6612 break;
6613 case 14:
6614 switch (sel) {
6615 case 0:
6616 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6617 rn = "EPC";
6618 break;
6619 default:
6620 goto cp0_unimplemented;
6622 break;
6623 case 15:
6624 switch (sel) {
6625 case 0:
6626 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6627 rn = "PRid";
6628 break;
6629 case 1:
6630 check_insn(ctx, ISA_MIPS32R2);
6631 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6632 rn = "EBase";
6633 break;
6634 case 3:
6635 check_insn(ctx, ISA_MIPS32R2);
6636 CP0_CHECK(ctx->cmgcr);
6637 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6638 rn = "CMGCRBase";
6639 break;
6640 default:
6641 goto cp0_unimplemented;
6643 break;
6644 case 16:
6645 switch (sel) {
6646 case 0:
6647 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6648 rn = "Config";
6649 break;
6650 case 1:
6651 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6652 rn = "Config1";
6653 break;
6654 case 2:
6655 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6656 rn = "Config2";
6657 break;
6658 case 3:
6659 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6660 rn = "Config3";
6661 break;
6662 case 4:
6663 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6664 rn = "Config4";
6665 break;
6666 case 5:
6667 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6668 rn = "Config5";
6669 break;
6670 /* 6,7 are implementation dependent */
6671 case 6:
6672 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6673 rn = "Config6";
6674 break;
6675 case 7:
6676 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6677 rn = "Config7";
6678 break;
6679 default:
6680 goto cp0_unimplemented;
6682 break;
6683 case 17:
6684 switch (sel) {
6685 case 0:
6686 gen_helper_dmfc0_lladdr(arg, cpu_env);
6687 rn = "LLAddr";
6688 break;
6689 case 1:
6690 CP0_CHECK(ctx->mrp);
6691 gen_helper_dmfc0_maar(arg, cpu_env);
6692 rn = "MAAR";
6693 break;
6694 case 2:
6695 CP0_CHECK(ctx->mrp);
6696 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6697 rn = "MAARI";
6698 break;
6699 default:
6700 goto cp0_unimplemented;
6702 break;
6703 case 18:
6704 switch (sel) {
6705 case 0 ... 7:
6706 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6707 rn = "WatchLo";
6708 break;
6709 default:
6710 goto cp0_unimplemented;
6712 break;
6713 case 19:
6714 switch (sel) {
6715 case 0 ... 7:
6716 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6717 rn = "WatchHi";
6718 break;
6719 default:
6720 goto cp0_unimplemented;
6722 break;
6723 case 20:
6724 switch (sel) {
6725 case 0:
6726 check_insn(ctx, ISA_MIPS3);
6727 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6728 rn = "XContext";
6729 break;
6730 default:
6731 goto cp0_unimplemented;
6733 break;
6734 case 21:
6735 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6736 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6737 switch (sel) {
6738 case 0:
6739 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6740 rn = "Framemask";
6741 break;
6742 default:
6743 goto cp0_unimplemented;
6745 break;
6746 case 22:
6747 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6748 rn = "'Diagnostic"; /* implementation dependent */
6749 break;
6750 case 23:
6751 switch (sel) {
6752 case 0:
6753 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6754 rn = "Debug";
6755 break;
6756 case 1:
6757 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6758 rn = "TraceControl";
6759 // break;
6760 case 2:
6761 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6762 rn = "TraceControl2";
6763 // break;
6764 case 3:
6765 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6766 rn = "UserTraceData";
6767 // break;
6768 case 4:
6769 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6770 rn = "TraceBPC";
6771 // break;
6772 default:
6773 goto cp0_unimplemented;
6775 break;
6776 case 24:
6777 switch (sel) {
6778 case 0:
6779 /* EJTAG support */
6780 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6781 rn = "DEPC";
6782 break;
6783 default:
6784 goto cp0_unimplemented;
6786 break;
6787 case 25:
6788 switch (sel) {
6789 case 0:
6790 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6791 rn = "Performance0";
6792 break;
6793 case 1:
6794 // gen_helper_dmfc0_performance1(arg);
6795 rn = "Performance1";
6796 // break;
6797 case 2:
6798 // gen_helper_dmfc0_performance2(arg);
6799 rn = "Performance2";
6800 // break;
6801 case 3:
6802 // gen_helper_dmfc0_performance3(arg);
6803 rn = "Performance3";
6804 // break;
6805 case 4:
6806 // gen_helper_dmfc0_performance4(arg);
6807 rn = "Performance4";
6808 // break;
6809 case 5:
6810 // gen_helper_dmfc0_performance5(arg);
6811 rn = "Performance5";
6812 // break;
6813 case 6:
6814 // gen_helper_dmfc0_performance6(arg);
6815 rn = "Performance6";
6816 // break;
6817 case 7:
6818 // gen_helper_dmfc0_performance7(arg);
6819 rn = "Performance7";
6820 // break;
6821 default:
6822 goto cp0_unimplemented;
6824 break;
6825 case 26:
6826 switch (sel) {
6827 case 0:
6828 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6829 rn = "ErrCtl";
6830 break;
6831 default:
6832 goto cp0_unimplemented;
6834 break;
6835 case 27:
6836 switch (sel) {
6837 /* ignored */
6838 case 0 ... 3:
6839 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6840 rn = "CacheErr";
6841 break;
6842 default:
6843 goto cp0_unimplemented;
6845 break;
6846 case 28:
6847 switch (sel) {
6848 case 0:
6849 case 2:
6850 case 4:
6851 case 6:
6852 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
6853 rn = "TagLo";
6854 break;
6855 case 1:
6856 case 3:
6857 case 5:
6858 case 7:
6859 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6860 rn = "DataLo";
6861 break;
6862 default:
6863 goto cp0_unimplemented;
6865 break;
6866 case 29:
6867 switch (sel) {
6868 case 0:
6869 case 2:
6870 case 4:
6871 case 6:
6872 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6873 rn = "TagHi";
6874 break;
6875 case 1:
6876 case 3:
6877 case 5:
6878 case 7:
6879 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6880 rn = "DataHi";
6881 break;
6882 default:
6883 goto cp0_unimplemented;
6885 break;
6886 case 30:
6887 switch (sel) {
6888 case 0:
6889 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6890 rn = "ErrorEPC";
6891 break;
6892 default:
6893 goto cp0_unimplemented;
6895 break;
6896 case 31:
6897 switch (sel) {
6898 case 0:
6899 /* EJTAG support */
6900 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6901 rn = "DESAVE";
6902 break;
6903 case 2 ... 7:
6904 CP0_CHECK(ctx->kscrexist & (1 << sel));
6905 tcg_gen_ld_tl(arg, cpu_env,
6906 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6907 rn = "KScratch";
6908 break;
6909 default:
6910 goto cp0_unimplemented;
6912 break;
6913 default:
6914 goto cp0_unimplemented;
6916 (void)rn; /* avoid a compiler warning */
6917 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6918 return;
6920 cp0_unimplemented:
6921 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6922 gen_mfc0_unimplemented(ctx, arg);
6925 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6927 const char *rn = "invalid";
6929 if (sel != 0)
6930 check_insn(ctx, ISA_MIPS64);
6932 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6933 gen_io_start();
6936 switch (reg) {
6937 case 0:
6938 switch (sel) {
6939 case 0:
6940 gen_helper_mtc0_index(cpu_env, arg);
6941 rn = "Index";
6942 break;
6943 case 1:
6944 CP0_CHECK(ctx->insn_flags & ASE_MT);
6945 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6946 rn = "MVPControl";
6947 break;
6948 case 2:
6949 CP0_CHECK(ctx->insn_flags & ASE_MT);
6950 /* ignored */
6951 rn = "MVPConf0";
6952 break;
6953 case 3:
6954 CP0_CHECK(ctx->insn_flags & ASE_MT);
6955 /* ignored */
6956 rn = "MVPConf1";
6957 break;
6958 case 4:
6959 CP0_CHECK(ctx->vp);
6960 /* ignored */
6961 rn = "VPControl";
6962 break;
6963 default:
6964 goto cp0_unimplemented;
6966 break;
6967 case 1:
6968 switch (sel) {
6969 case 0:
6970 /* ignored */
6971 rn = "Random";
6972 break;
6973 case 1:
6974 CP0_CHECK(ctx->insn_flags & ASE_MT);
6975 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6976 rn = "VPEControl";
6977 break;
6978 case 2:
6979 CP0_CHECK(ctx->insn_flags & ASE_MT);
6980 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6981 rn = "VPEConf0";
6982 break;
6983 case 3:
6984 CP0_CHECK(ctx->insn_flags & ASE_MT);
6985 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6986 rn = "VPEConf1";
6987 break;
6988 case 4:
6989 CP0_CHECK(ctx->insn_flags & ASE_MT);
6990 gen_helper_mtc0_yqmask(cpu_env, arg);
6991 rn = "YQMask";
6992 break;
6993 case 5:
6994 CP0_CHECK(ctx->insn_flags & ASE_MT);
6995 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6996 rn = "VPESchedule";
6997 break;
6998 case 6:
6999 CP0_CHECK(ctx->insn_flags & ASE_MT);
7000 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7001 rn = "VPEScheFBack";
7002 break;
7003 case 7:
7004 CP0_CHECK(ctx->insn_flags & ASE_MT);
7005 gen_helper_mtc0_vpeopt(cpu_env, arg);
7006 rn = "VPEOpt";
7007 break;
7008 default:
7009 goto cp0_unimplemented;
7011 break;
7012 case 2:
7013 switch (sel) {
7014 case 0:
7015 gen_helper_dmtc0_entrylo0(cpu_env, arg);
7016 rn = "EntryLo0";
7017 break;
7018 case 1:
7019 CP0_CHECK(ctx->insn_flags & ASE_MT);
7020 gen_helper_mtc0_tcstatus(cpu_env, arg);
7021 rn = "TCStatus";
7022 break;
7023 case 2:
7024 CP0_CHECK(ctx->insn_flags & ASE_MT);
7025 gen_helper_mtc0_tcbind(cpu_env, arg);
7026 rn = "TCBind";
7027 break;
7028 case 3:
7029 CP0_CHECK(ctx->insn_flags & ASE_MT);
7030 gen_helper_mtc0_tcrestart(cpu_env, arg);
7031 rn = "TCRestart";
7032 break;
7033 case 4:
7034 CP0_CHECK(ctx->insn_flags & ASE_MT);
7035 gen_helper_mtc0_tchalt(cpu_env, arg);
7036 rn = "TCHalt";
7037 break;
7038 case 5:
7039 CP0_CHECK(ctx->insn_flags & ASE_MT);
7040 gen_helper_mtc0_tccontext(cpu_env, arg);
7041 rn = "TCContext";
7042 break;
7043 case 6:
7044 CP0_CHECK(ctx->insn_flags & ASE_MT);
7045 gen_helper_mtc0_tcschedule(cpu_env, arg);
7046 rn = "TCSchedule";
7047 break;
7048 case 7:
7049 CP0_CHECK(ctx->insn_flags & ASE_MT);
7050 gen_helper_mtc0_tcschefback(cpu_env, arg);
7051 rn = "TCScheFBack";
7052 break;
7053 default:
7054 goto cp0_unimplemented;
7056 break;
7057 case 3:
7058 switch (sel) {
7059 case 0:
7060 gen_helper_dmtc0_entrylo1(cpu_env, arg);
7061 rn = "EntryLo1";
7062 break;
7063 case 1:
7064 CP0_CHECK(ctx->vp);
7065 /* ignored */
7066 rn = "GlobalNumber";
7067 break;
7068 default:
7069 goto cp0_unimplemented;
7071 break;
7072 case 4:
7073 switch (sel) {
7074 case 0:
7075 gen_helper_mtc0_context(cpu_env, arg);
7076 rn = "Context";
7077 break;
7078 case 1:
7079 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7080 rn = "ContextConfig";
7081 goto cp0_unimplemented;
7082 // break;
7083 case 2:
7084 CP0_CHECK(ctx->ulri);
7085 tcg_gen_st_tl(arg, cpu_env,
7086 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7087 rn = "UserLocal";
7088 break;
7089 default:
7090 goto cp0_unimplemented;
7092 break;
7093 case 5:
7094 switch (sel) {
7095 case 0:
7096 gen_helper_mtc0_pagemask(cpu_env, arg);
7097 rn = "PageMask";
7098 break;
7099 case 1:
7100 check_insn(ctx, ISA_MIPS32R2);
7101 gen_helper_mtc0_pagegrain(cpu_env, arg);
7102 rn = "PageGrain";
7103 break;
7104 default:
7105 goto cp0_unimplemented;
7107 break;
7108 case 6:
7109 switch (sel) {
7110 case 0:
7111 gen_helper_mtc0_wired(cpu_env, arg);
7112 rn = "Wired";
7113 break;
7114 case 1:
7115 check_insn(ctx, ISA_MIPS32R2);
7116 gen_helper_mtc0_srsconf0(cpu_env, arg);
7117 rn = "SRSConf0";
7118 break;
7119 case 2:
7120 check_insn(ctx, ISA_MIPS32R2);
7121 gen_helper_mtc0_srsconf1(cpu_env, arg);
7122 rn = "SRSConf1";
7123 break;
7124 case 3:
7125 check_insn(ctx, ISA_MIPS32R2);
7126 gen_helper_mtc0_srsconf2(cpu_env, arg);
7127 rn = "SRSConf2";
7128 break;
7129 case 4:
7130 check_insn(ctx, ISA_MIPS32R2);
7131 gen_helper_mtc0_srsconf3(cpu_env, arg);
7132 rn = "SRSConf3";
7133 break;
7134 case 5:
7135 check_insn(ctx, ISA_MIPS32R2);
7136 gen_helper_mtc0_srsconf4(cpu_env, arg);
7137 rn = "SRSConf4";
7138 break;
7139 default:
7140 goto cp0_unimplemented;
7142 break;
7143 case 7:
7144 switch (sel) {
7145 case 0:
7146 check_insn(ctx, ISA_MIPS32R2);
7147 gen_helper_mtc0_hwrena(cpu_env, arg);
7148 ctx->bstate = BS_STOP;
7149 rn = "HWREna";
7150 break;
7151 default:
7152 goto cp0_unimplemented;
7154 break;
7155 case 8:
7156 switch (sel) {
7157 case 0:
7158 /* ignored */
7159 rn = "BadVAddr";
7160 break;
7161 case 1:
7162 /* ignored */
7163 rn = "BadInstr";
7164 break;
7165 case 2:
7166 /* ignored */
7167 rn = "BadInstrP";
7168 break;
7169 default:
7170 goto cp0_unimplemented;
7172 break;
7173 case 9:
7174 switch (sel) {
7175 case 0:
7176 gen_helper_mtc0_count(cpu_env, arg);
7177 rn = "Count";
7178 break;
7179 /* 6,7 are implementation dependent */
7180 default:
7181 goto cp0_unimplemented;
7183 /* Stop translation as we may have switched the execution mode */
7184 ctx->bstate = BS_STOP;
7185 break;
7186 case 10:
7187 switch (sel) {
7188 case 0:
7189 gen_helper_mtc0_entryhi(cpu_env, arg);
7190 rn = "EntryHi";
7191 break;
7192 default:
7193 goto cp0_unimplemented;
7195 break;
7196 case 11:
7197 switch (sel) {
7198 case 0:
7199 gen_helper_mtc0_compare(cpu_env, arg);
7200 rn = "Compare";
7201 break;
7202 /* 6,7 are implementation dependent */
7203 default:
7204 goto cp0_unimplemented;
7206 /* Stop translation as we may have switched the execution mode */
7207 ctx->bstate = BS_STOP;
7208 break;
7209 case 12:
7210 switch (sel) {
7211 case 0:
7212 save_cpu_state(ctx, 1);
7213 gen_helper_mtc0_status(cpu_env, arg);
7214 /* BS_STOP isn't good enough here, hflags may have changed. */
7215 gen_save_pc(ctx->pc + 4);
7216 ctx->bstate = BS_EXCP;
7217 rn = "Status";
7218 break;
7219 case 1:
7220 check_insn(ctx, ISA_MIPS32R2);
7221 gen_helper_mtc0_intctl(cpu_env, arg);
7222 /* Stop translation as we may have switched the execution mode */
7223 ctx->bstate = BS_STOP;
7224 rn = "IntCtl";
7225 break;
7226 case 2:
7227 check_insn(ctx, ISA_MIPS32R2);
7228 gen_helper_mtc0_srsctl(cpu_env, arg);
7229 /* Stop translation as we may have switched the execution mode */
7230 ctx->bstate = BS_STOP;
7231 rn = "SRSCtl";
7232 break;
7233 case 3:
7234 check_insn(ctx, ISA_MIPS32R2);
7235 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7236 /* Stop translation as we may have switched the execution mode */
7237 ctx->bstate = BS_STOP;
7238 rn = "SRSMap";
7239 break;
7240 default:
7241 goto cp0_unimplemented;
7243 break;
7244 case 13:
7245 switch (sel) {
7246 case 0:
7247 save_cpu_state(ctx, 1);
7248 /* Mark as an IO operation because we may trigger a software
7249 interrupt. */
7250 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7251 gen_io_start();
7253 gen_helper_mtc0_cause(cpu_env, arg);
7254 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7255 gen_io_end();
7257 /* Stop translation as we may have triggered an intetrupt */
7258 ctx->bstate = BS_STOP;
7259 rn = "Cause";
7260 break;
7261 default:
7262 goto cp0_unimplemented;
7264 break;
7265 case 14:
7266 switch (sel) {
7267 case 0:
7268 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7269 rn = "EPC";
7270 break;
7271 default:
7272 goto cp0_unimplemented;
7274 break;
7275 case 15:
7276 switch (sel) {
7277 case 0:
7278 /* ignored */
7279 rn = "PRid";
7280 break;
7281 case 1:
7282 check_insn(ctx, ISA_MIPS32R2);
7283 gen_helper_mtc0_ebase(cpu_env, arg);
7284 rn = "EBase";
7285 break;
7286 default:
7287 goto cp0_unimplemented;
7289 break;
7290 case 16:
7291 switch (sel) {
7292 case 0:
7293 gen_helper_mtc0_config0(cpu_env, arg);
7294 rn = "Config";
7295 /* Stop translation as we may have switched the execution mode */
7296 ctx->bstate = BS_STOP;
7297 break;
7298 case 1:
7299 /* ignored, read only */
7300 rn = "Config1";
7301 break;
7302 case 2:
7303 gen_helper_mtc0_config2(cpu_env, arg);
7304 rn = "Config2";
7305 /* Stop translation as we may have switched the execution mode */
7306 ctx->bstate = BS_STOP;
7307 break;
7308 case 3:
7309 gen_helper_mtc0_config3(cpu_env, arg);
7310 rn = "Config3";
7311 /* Stop translation as we may have switched the execution mode */
7312 ctx->bstate = BS_STOP;
7313 break;
7314 case 4:
7315 /* currently ignored */
7316 rn = "Config4";
7317 break;
7318 case 5:
7319 gen_helper_mtc0_config5(cpu_env, arg);
7320 rn = "Config5";
7321 /* Stop translation as we may have switched the execution mode */
7322 ctx->bstate = BS_STOP;
7323 break;
7324 /* 6,7 are implementation dependent */
7325 default:
7326 rn = "Invalid config selector";
7327 goto cp0_unimplemented;
7329 break;
7330 case 17:
7331 switch (sel) {
7332 case 0:
7333 gen_helper_mtc0_lladdr(cpu_env, arg);
7334 rn = "LLAddr";
7335 break;
7336 case 1:
7337 CP0_CHECK(ctx->mrp);
7338 gen_helper_mtc0_maar(cpu_env, arg);
7339 rn = "MAAR";
7340 break;
7341 case 2:
7342 CP0_CHECK(ctx->mrp);
7343 gen_helper_mtc0_maari(cpu_env, arg);
7344 rn = "MAARI";
7345 break;
7346 default:
7347 goto cp0_unimplemented;
7349 break;
7350 case 18:
7351 switch (sel) {
7352 case 0 ... 7:
7353 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7354 rn = "WatchLo";
7355 break;
7356 default:
7357 goto cp0_unimplemented;
7359 break;
7360 case 19:
7361 switch (sel) {
7362 case 0 ... 7:
7363 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7364 rn = "WatchHi";
7365 break;
7366 default:
7367 goto cp0_unimplemented;
7369 break;
7370 case 20:
7371 switch (sel) {
7372 case 0:
7373 check_insn(ctx, ISA_MIPS3);
7374 gen_helper_mtc0_xcontext(cpu_env, arg);
7375 rn = "XContext";
7376 break;
7377 default:
7378 goto cp0_unimplemented;
7380 break;
7381 case 21:
7382 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7383 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7384 switch (sel) {
7385 case 0:
7386 gen_helper_mtc0_framemask(cpu_env, arg);
7387 rn = "Framemask";
7388 break;
7389 default:
7390 goto cp0_unimplemented;
7392 break;
7393 case 22:
7394 /* ignored */
7395 rn = "Diagnostic"; /* implementation dependent */
7396 break;
7397 case 23:
7398 switch (sel) {
7399 case 0:
7400 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7401 /* BS_STOP isn't good enough here, hflags may have changed. */
7402 gen_save_pc(ctx->pc + 4);
7403 ctx->bstate = BS_EXCP;
7404 rn = "Debug";
7405 break;
7406 case 1:
7407 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7408 /* Stop translation as we may have switched the execution mode */
7409 ctx->bstate = BS_STOP;
7410 rn = "TraceControl";
7411 // break;
7412 case 2:
7413 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7414 /* Stop translation as we may have switched the execution mode */
7415 ctx->bstate = BS_STOP;
7416 rn = "TraceControl2";
7417 // break;
7418 case 3:
7419 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7420 /* Stop translation as we may have switched the execution mode */
7421 ctx->bstate = BS_STOP;
7422 rn = "UserTraceData";
7423 // break;
7424 case 4:
7425 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7426 /* Stop translation as we may have switched the execution mode */
7427 ctx->bstate = BS_STOP;
7428 rn = "TraceBPC";
7429 // break;
7430 default:
7431 goto cp0_unimplemented;
7433 break;
7434 case 24:
7435 switch (sel) {
7436 case 0:
7437 /* EJTAG support */
7438 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7439 rn = "DEPC";
7440 break;
7441 default:
7442 goto cp0_unimplemented;
7444 break;
7445 case 25:
7446 switch (sel) {
7447 case 0:
7448 gen_helper_mtc0_performance0(cpu_env, arg);
7449 rn = "Performance0";
7450 break;
7451 case 1:
7452 // gen_helper_mtc0_performance1(cpu_env, arg);
7453 rn = "Performance1";
7454 // break;
7455 case 2:
7456 // gen_helper_mtc0_performance2(cpu_env, arg);
7457 rn = "Performance2";
7458 // break;
7459 case 3:
7460 // gen_helper_mtc0_performance3(cpu_env, arg);
7461 rn = "Performance3";
7462 // break;
7463 case 4:
7464 // gen_helper_mtc0_performance4(cpu_env, arg);
7465 rn = "Performance4";
7466 // break;
7467 case 5:
7468 // gen_helper_mtc0_performance5(cpu_env, arg);
7469 rn = "Performance5";
7470 // break;
7471 case 6:
7472 // gen_helper_mtc0_performance6(cpu_env, arg);
7473 rn = "Performance6";
7474 // break;
7475 case 7:
7476 // gen_helper_mtc0_performance7(cpu_env, arg);
7477 rn = "Performance7";
7478 // break;
7479 default:
7480 goto cp0_unimplemented;
7482 break;
7483 case 26:
7484 switch (sel) {
7485 case 0:
7486 gen_helper_mtc0_errctl(cpu_env, arg);
7487 ctx->bstate = BS_STOP;
7488 rn = "ErrCtl";
7489 break;
7490 default:
7491 goto cp0_unimplemented;
7493 break;
7494 case 27:
7495 switch (sel) {
7496 case 0 ... 3:
7497 /* ignored */
7498 rn = "CacheErr";
7499 break;
7500 default:
7501 goto cp0_unimplemented;
7503 break;
7504 case 28:
7505 switch (sel) {
7506 case 0:
7507 case 2:
7508 case 4:
7509 case 6:
7510 gen_helper_mtc0_taglo(cpu_env, arg);
7511 rn = "TagLo";
7512 break;
7513 case 1:
7514 case 3:
7515 case 5:
7516 case 7:
7517 gen_helper_mtc0_datalo(cpu_env, arg);
7518 rn = "DataLo";
7519 break;
7520 default:
7521 goto cp0_unimplemented;
7523 break;
7524 case 29:
7525 switch (sel) {
7526 case 0:
7527 case 2:
7528 case 4:
7529 case 6:
7530 gen_helper_mtc0_taghi(cpu_env, arg);
7531 rn = "TagHi";
7532 break;
7533 case 1:
7534 case 3:
7535 case 5:
7536 case 7:
7537 gen_helper_mtc0_datahi(cpu_env, arg);
7538 rn = "DataHi";
7539 break;
7540 default:
7541 rn = "invalid sel";
7542 goto cp0_unimplemented;
7544 break;
7545 case 30:
7546 switch (sel) {
7547 case 0:
7548 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7549 rn = "ErrorEPC";
7550 break;
7551 default:
7552 goto cp0_unimplemented;
7554 break;
7555 case 31:
7556 switch (sel) {
7557 case 0:
7558 /* EJTAG support */
7559 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7560 rn = "DESAVE";
7561 break;
7562 case 2 ... 7:
7563 CP0_CHECK(ctx->kscrexist & (1 << sel));
7564 tcg_gen_st_tl(arg, cpu_env,
7565 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7566 rn = "KScratch";
7567 break;
7568 default:
7569 goto cp0_unimplemented;
7571 /* Stop translation as we may have switched the execution mode */
7572 ctx->bstate = BS_STOP;
7573 break;
7574 default:
7575 goto cp0_unimplemented;
7577 (void)rn; /* avoid a compiler warning */
7578 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7579 /* For simplicity assume that all writes can cause interrupts. */
7580 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7581 gen_io_end();
7582 ctx->bstate = BS_STOP;
7584 return;
7586 cp0_unimplemented:
7587 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7589 #endif /* TARGET_MIPS64 */
7591 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7592 int u, int sel, int h)
7594 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7595 TCGv t0 = tcg_temp_local_new();
7597 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7598 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7599 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7600 tcg_gen_movi_tl(t0, -1);
7601 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7602 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7603 tcg_gen_movi_tl(t0, -1);
7604 else if (u == 0) {
7605 switch (rt) {
7606 case 1:
7607 switch (sel) {
7608 case 1:
7609 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7610 break;
7611 case 2:
7612 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7613 break;
7614 default:
7615 goto die;
7616 break;
7618 break;
7619 case 2:
7620 switch (sel) {
7621 case 1:
7622 gen_helper_mftc0_tcstatus(t0, cpu_env);
7623 break;
7624 case 2:
7625 gen_helper_mftc0_tcbind(t0, cpu_env);
7626 break;
7627 case 3:
7628 gen_helper_mftc0_tcrestart(t0, cpu_env);
7629 break;
7630 case 4:
7631 gen_helper_mftc0_tchalt(t0, cpu_env);
7632 break;
7633 case 5:
7634 gen_helper_mftc0_tccontext(t0, cpu_env);
7635 break;
7636 case 6:
7637 gen_helper_mftc0_tcschedule(t0, cpu_env);
7638 break;
7639 case 7:
7640 gen_helper_mftc0_tcschefback(t0, cpu_env);
7641 break;
7642 default:
7643 gen_mfc0(ctx, t0, rt, sel);
7644 break;
7646 break;
7647 case 10:
7648 switch (sel) {
7649 case 0:
7650 gen_helper_mftc0_entryhi(t0, cpu_env);
7651 break;
7652 default:
7653 gen_mfc0(ctx, t0, rt, sel);
7654 break;
7656 case 12:
7657 switch (sel) {
7658 case 0:
7659 gen_helper_mftc0_status(t0, cpu_env);
7660 break;
7661 default:
7662 gen_mfc0(ctx, t0, rt, sel);
7663 break;
7665 case 13:
7666 switch (sel) {
7667 case 0:
7668 gen_helper_mftc0_cause(t0, cpu_env);
7669 break;
7670 default:
7671 goto die;
7672 break;
7674 break;
7675 case 14:
7676 switch (sel) {
7677 case 0:
7678 gen_helper_mftc0_epc(t0, cpu_env);
7679 break;
7680 default:
7681 goto die;
7682 break;
7684 break;
7685 case 15:
7686 switch (sel) {
7687 case 1:
7688 gen_helper_mftc0_ebase(t0, cpu_env);
7689 break;
7690 default:
7691 goto die;
7692 break;
7694 break;
7695 case 16:
7696 switch (sel) {
7697 case 0 ... 7:
7698 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7699 break;
7700 default:
7701 goto die;
7702 break;
7704 break;
7705 case 23:
7706 switch (sel) {
7707 case 0:
7708 gen_helper_mftc0_debug(t0, cpu_env);
7709 break;
7710 default:
7711 gen_mfc0(ctx, t0, rt, sel);
7712 break;
7714 break;
7715 default:
7716 gen_mfc0(ctx, t0, rt, sel);
7718 } else switch (sel) {
7719 /* GPR registers. */
7720 case 0:
7721 gen_helper_1e0i(mftgpr, t0, rt);
7722 break;
7723 /* Auxiliary CPU registers */
7724 case 1:
7725 switch (rt) {
7726 case 0:
7727 gen_helper_1e0i(mftlo, t0, 0);
7728 break;
7729 case 1:
7730 gen_helper_1e0i(mfthi, t0, 0);
7731 break;
7732 case 2:
7733 gen_helper_1e0i(mftacx, t0, 0);
7734 break;
7735 case 4:
7736 gen_helper_1e0i(mftlo, t0, 1);
7737 break;
7738 case 5:
7739 gen_helper_1e0i(mfthi, t0, 1);
7740 break;
7741 case 6:
7742 gen_helper_1e0i(mftacx, t0, 1);
7743 break;
7744 case 8:
7745 gen_helper_1e0i(mftlo, t0, 2);
7746 break;
7747 case 9:
7748 gen_helper_1e0i(mfthi, t0, 2);
7749 break;
7750 case 10:
7751 gen_helper_1e0i(mftacx, t0, 2);
7752 break;
7753 case 12:
7754 gen_helper_1e0i(mftlo, t0, 3);
7755 break;
7756 case 13:
7757 gen_helper_1e0i(mfthi, t0, 3);
7758 break;
7759 case 14:
7760 gen_helper_1e0i(mftacx, t0, 3);
7761 break;
7762 case 16:
7763 gen_helper_mftdsp(t0, cpu_env);
7764 break;
7765 default:
7766 goto die;
7768 break;
7769 /* Floating point (COP1). */
7770 case 2:
7771 /* XXX: For now we support only a single FPU context. */
7772 if (h == 0) {
7773 TCGv_i32 fp0 = tcg_temp_new_i32();
7775 gen_load_fpr32(ctx, fp0, rt);
7776 tcg_gen_ext_i32_tl(t0, fp0);
7777 tcg_temp_free_i32(fp0);
7778 } else {
7779 TCGv_i32 fp0 = tcg_temp_new_i32();
7781 gen_load_fpr32h(ctx, fp0, rt);
7782 tcg_gen_ext_i32_tl(t0, fp0);
7783 tcg_temp_free_i32(fp0);
7785 break;
7786 case 3:
7787 /* XXX: For now we support only a single FPU context. */
7788 gen_helper_1e0i(cfc1, t0, rt);
7789 break;
7790 /* COP2: Not implemented. */
7791 case 4:
7792 case 5:
7793 /* fall through */
7794 default:
7795 goto die;
7797 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7798 gen_store_gpr(t0, rd);
7799 tcg_temp_free(t0);
7800 return;
7802 die:
7803 tcg_temp_free(t0);
7804 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7805 generate_exception_end(ctx, EXCP_RI);
7808 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7809 int u, int sel, int h)
7811 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7812 TCGv t0 = tcg_temp_local_new();
7814 gen_load_gpr(t0, rt);
7815 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7816 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7817 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7818 /* NOP */ ;
7819 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7820 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7821 /* NOP */ ;
7822 else if (u == 0) {
7823 switch (rd) {
7824 case 1:
7825 switch (sel) {
7826 case 1:
7827 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7828 break;
7829 case 2:
7830 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7831 break;
7832 default:
7833 goto die;
7834 break;
7836 break;
7837 case 2:
7838 switch (sel) {
7839 case 1:
7840 gen_helper_mttc0_tcstatus(cpu_env, t0);
7841 break;
7842 case 2:
7843 gen_helper_mttc0_tcbind(cpu_env, t0);
7844 break;
7845 case 3:
7846 gen_helper_mttc0_tcrestart(cpu_env, t0);
7847 break;
7848 case 4:
7849 gen_helper_mttc0_tchalt(cpu_env, t0);
7850 break;
7851 case 5:
7852 gen_helper_mttc0_tccontext(cpu_env, t0);
7853 break;
7854 case 6:
7855 gen_helper_mttc0_tcschedule(cpu_env, t0);
7856 break;
7857 case 7:
7858 gen_helper_mttc0_tcschefback(cpu_env, t0);
7859 break;
7860 default:
7861 gen_mtc0(ctx, t0, rd, sel);
7862 break;
7864 break;
7865 case 10:
7866 switch (sel) {
7867 case 0:
7868 gen_helper_mttc0_entryhi(cpu_env, t0);
7869 break;
7870 default:
7871 gen_mtc0(ctx, t0, rd, sel);
7872 break;
7874 case 12:
7875 switch (sel) {
7876 case 0:
7877 gen_helper_mttc0_status(cpu_env, t0);
7878 break;
7879 default:
7880 gen_mtc0(ctx, t0, rd, sel);
7881 break;
7883 case 13:
7884 switch (sel) {
7885 case 0:
7886 gen_helper_mttc0_cause(cpu_env, t0);
7887 break;
7888 default:
7889 goto die;
7890 break;
7892 break;
7893 case 15:
7894 switch (sel) {
7895 case 1:
7896 gen_helper_mttc0_ebase(cpu_env, t0);
7897 break;
7898 default:
7899 goto die;
7900 break;
7902 break;
7903 case 23:
7904 switch (sel) {
7905 case 0:
7906 gen_helper_mttc0_debug(cpu_env, t0);
7907 break;
7908 default:
7909 gen_mtc0(ctx, t0, rd, sel);
7910 break;
7912 break;
7913 default:
7914 gen_mtc0(ctx, t0, rd, sel);
7916 } else switch (sel) {
7917 /* GPR registers. */
7918 case 0:
7919 gen_helper_0e1i(mttgpr, t0, rd);
7920 break;
7921 /* Auxiliary CPU registers */
7922 case 1:
7923 switch (rd) {
7924 case 0:
7925 gen_helper_0e1i(mttlo, t0, 0);
7926 break;
7927 case 1:
7928 gen_helper_0e1i(mtthi, t0, 0);
7929 break;
7930 case 2:
7931 gen_helper_0e1i(mttacx, t0, 0);
7932 break;
7933 case 4:
7934 gen_helper_0e1i(mttlo, t0, 1);
7935 break;
7936 case 5:
7937 gen_helper_0e1i(mtthi, t0, 1);
7938 break;
7939 case 6:
7940 gen_helper_0e1i(mttacx, t0, 1);
7941 break;
7942 case 8:
7943 gen_helper_0e1i(mttlo, t0, 2);
7944 break;
7945 case 9:
7946 gen_helper_0e1i(mtthi, t0, 2);
7947 break;
7948 case 10:
7949 gen_helper_0e1i(mttacx, t0, 2);
7950 break;
7951 case 12:
7952 gen_helper_0e1i(mttlo, t0, 3);
7953 break;
7954 case 13:
7955 gen_helper_0e1i(mtthi, t0, 3);
7956 break;
7957 case 14:
7958 gen_helper_0e1i(mttacx, t0, 3);
7959 break;
7960 case 16:
7961 gen_helper_mttdsp(cpu_env, t0);
7962 break;
7963 default:
7964 goto die;
7966 break;
7967 /* Floating point (COP1). */
7968 case 2:
7969 /* XXX: For now we support only a single FPU context. */
7970 if (h == 0) {
7971 TCGv_i32 fp0 = tcg_temp_new_i32();
7973 tcg_gen_trunc_tl_i32(fp0, t0);
7974 gen_store_fpr32(ctx, fp0, rd);
7975 tcg_temp_free_i32(fp0);
7976 } else {
7977 TCGv_i32 fp0 = tcg_temp_new_i32();
7979 tcg_gen_trunc_tl_i32(fp0, t0);
7980 gen_store_fpr32h(ctx, fp0, rd);
7981 tcg_temp_free_i32(fp0);
7983 break;
7984 case 3:
7985 /* XXX: For now we support only a single FPU context. */
7987 TCGv_i32 fs_tmp = tcg_const_i32(rd);
7989 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7990 tcg_temp_free_i32(fs_tmp);
7992 /* Stop translation as we may have changed hflags */
7993 ctx->bstate = BS_STOP;
7994 break;
7995 /* COP2: Not implemented. */
7996 case 4:
7997 case 5:
7998 /* fall through */
7999 default:
8000 goto die;
8002 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8003 tcg_temp_free(t0);
8004 return;
8006 die:
8007 tcg_temp_free(t0);
8008 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8009 generate_exception_end(ctx, EXCP_RI);
8012 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
8014 const char *opn = "ldst";
8016 check_cp0_enabled(ctx);
8017 switch (opc) {
8018 case OPC_MFC0:
8019 if (rt == 0) {
8020 /* Treat as NOP. */
8021 return;
8023 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8024 opn = "mfc0";
8025 break;
8026 case OPC_MTC0:
8028 TCGv t0 = tcg_temp_new();
8030 gen_load_gpr(t0, rt);
8031 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8032 tcg_temp_free(t0);
8034 opn = "mtc0";
8035 break;
8036 #if defined(TARGET_MIPS64)
8037 case OPC_DMFC0:
8038 check_insn(ctx, ISA_MIPS3);
8039 if (rt == 0) {
8040 /* Treat as NOP. */
8041 return;
8043 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8044 opn = "dmfc0";
8045 break;
8046 case OPC_DMTC0:
8047 check_insn(ctx, ISA_MIPS3);
8049 TCGv t0 = tcg_temp_new();
8051 gen_load_gpr(t0, rt);
8052 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8053 tcg_temp_free(t0);
8055 opn = "dmtc0";
8056 break;
8057 #endif
8058 case OPC_MFHC0:
8059 check_mvh(ctx);
8060 if (rt == 0) {
8061 /* Treat as NOP. */
8062 return;
8064 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8065 opn = "mfhc0";
8066 break;
8067 case OPC_MTHC0:
8068 check_mvh(ctx);
8070 TCGv t0 = tcg_temp_new();
8071 gen_load_gpr(t0, rt);
8072 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8073 tcg_temp_free(t0);
8075 opn = "mthc0";
8076 break;
8077 case OPC_MFTR:
8078 check_insn(ctx, ASE_MT);
8079 if (rd == 0) {
8080 /* Treat as NOP. */
8081 return;
8083 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8084 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8085 opn = "mftr";
8086 break;
8087 case OPC_MTTR:
8088 check_insn(ctx, ASE_MT);
8089 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8090 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8091 opn = "mttr";
8092 break;
8093 case OPC_TLBWI:
8094 opn = "tlbwi";
8095 if (!env->tlb->helper_tlbwi)
8096 goto die;
8097 gen_helper_tlbwi(cpu_env);
8098 break;
8099 case OPC_TLBINV:
8100 opn = "tlbinv";
8101 if (ctx->ie >= 2) {
8102 if (!env->tlb->helper_tlbinv) {
8103 goto die;
8105 gen_helper_tlbinv(cpu_env);
8106 } /* treat as nop if TLBINV not supported */
8107 break;
8108 case OPC_TLBINVF:
8109 opn = "tlbinvf";
8110 if (ctx->ie >= 2) {
8111 if (!env->tlb->helper_tlbinvf) {
8112 goto die;
8114 gen_helper_tlbinvf(cpu_env);
8115 } /* treat as nop if TLBINV not supported */
8116 break;
8117 case OPC_TLBWR:
8118 opn = "tlbwr";
8119 if (!env->tlb->helper_tlbwr)
8120 goto die;
8121 gen_helper_tlbwr(cpu_env);
8122 break;
8123 case OPC_TLBP:
8124 opn = "tlbp";
8125 if (!env->tlb->helper_tlbp)
8126 goto die;
8127 gen_helper_tlbp(cpu_env);
8128 break;
8129 case OPC_TLBR:
8130 opn = "tlbr";
8131 if (!env->tlb->helper_tlbr)
8132 goto die;
8133 gen_helper_tlbr(cpu_env);
8134 break;
8135 case OPC_ERET: /* OPC_ERETNC */
8136 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8137 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8138 goto die;
8139 } else {
8140 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8141 if (ctx->opcode & (1 << bit_shift)) {
8142 /* OPC_ERETNC */
8143 opn = "eretnc";
8144 check_insn(ctx, ISA_MIPS32R5);
8145 gen_helper_eretnc(cpu_env);
8146 } else {
8147 /* OPC_ERET */
8148 opn = "eret";
8149 check_insn(ctx, ISA_MIPS2);
8150 gen_helper_eret(cpu_env);
8152 ctx->bstate = BS_EXCP;
8154 break;
8155 case OPC_DERET:
8156 opn = "deret";
8157 check_insn(ctx, ISA_MIPS32);
8158 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8159 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8160 goto die;
8162 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8163 MIPS_INVAL(opn);
8164 generate_exception_end(ctx, EXCP_RI);
8165 } else {
8166 gen_helper_deret(cpu_env);
8167 ctx->bstate = BS_EXCP;
8169 break;
8170 case OPC_WAIT:
8171 opn = "wait";
8172 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8173 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8174 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8175 goto die;
8177 /* If we get an exception, we want to restart at next instruction */
8178 ctx->pc += 4;
8179 save_cpu_state(ctx, 1);
8180 ctx->pc -= 4;
8181 gen_helper_wait(cpu_env);
8182 ctx->bstate = BS_EXCP;
8183 break;
8184 default:
8185 die:
8186 MIPS_INVAL(opn);
8187 generate_exception_end(ctx, EXCP_RI);
8188 return;
8190 (void)opn; /* avoid a compiler warning */
8192 #endif /* !CONFIG_USER_ONLY */
8194 /* CP1 Branches (before delay slot) */
8195 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8196 int32_t cc, int32_t offset)
8198 target_ulong btarget;
8199 TCGv_i32 t0 = tcg_temp_new_i32();
8201 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8202 generate_exception_end(ctx, EXCP_RI);
8203 goto out;
8206 if (cc != 0)
8207 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8209 btarget = ctx->pc + 4 + offset;
8211 switch (op) {
8212 case OPC_BC1F:
8213 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8214 tcg_gen_not_i32(t0, t0);
8215 tcg_gen_andi_i32(t0, t0, 1);
8216 tcg_gen_extu_i32_tl(bcond, t0);
8217 goto not_likely;
8218 case OPC_BC1FL:
8219 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8220 tcg_gen_not_i32(t0, t0);
8221 tcg_gen_andi_i32(t0, t0, 1);
8222 tcg_gen_extu_i32_tl(bcond, t0);
8223 goto likely;
8224 case OPC_BC1T:
8225 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8226 tcg_gen_andi_i32(t0, t0, 1);
8227 tcg_gen_extu_i32_tl(bcond, t0);
8228 goto not_likely;
8229 case OPC_BC1TL:
8230 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8231 tcg_gen_andi_i32(t0, t0, 1);
8232 tcg_gen_extu_i32_tl(bcond, t0);
8233 likely:
8234 ctx->hflags |= MIPS_HFLAG_BL;
8235 break;
8236 case OPC_BC1FANY2:
8238 TCGv_i32 t1 = tcg_temp_new_i32();
8239 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8240 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8241 tcg_gen_nand_i32(t0, t0, t1);
8242 tcg_temp_free_i32(t1);
8243 tcg_gen_andi_i32(t0, t0, 1);
8244 tcg_gen_extu_i32_tl(bcond, t0);
8246 goto not_likely;
8247 case OPC_BC1TANY2:
8249 TCGv_i32 t1 = tcg_temp_new_i32();
8250 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8251 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8252 tcg_gen_or_i32(t0, t0, t1);
8253 tcg_temp_free_i32(t1);
8254 tcg_gen_andi_i32(t0, t0, 1);
8255 tcg_gen_extu_i32_tl(bcond, t0);
8257 goto not_likely;
8258 case OPC_BC1FANY4:
8260 TCGv_i32 t1 = tcg_temp_new_i32();
8261 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8262 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8263 tcg_gen_and_i32(t0, t0, t1);
8264 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8265 tcg_gen_and_i32(t0, t0, t1);
8266 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8267 tcg_gen_nand_i32(t0, t0, t1);
8268 tcg_temp_free_i32(t1);
8269 tcg_gen_andi_i32(t0, t0, 1);
8270 tcg_gen_extu_i32_tl(bcond, t0);
8272 goto not_likely;
8273 case OPC_BC1TANY4:
8275 TCGv_i32 t1 = tcg_temp_new_i32();
8276 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8277 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8278 tcg_gen_or_i32(t0, t0, t1);
8279 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8280 tcg_gen_or_i32(t0, t0, t1);
8281 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8282 tcg_gen_or_i32(t0, t0, t1);
8283 tcg_temp_free_i32(t1);
8284 tcg_gen_andi_i32(t0, t0, 1);
8285 tcg_gen_extu_i32_tl(bcond, t0);
8287 not_likely:
8288 ctx->hflags |= MIPS_HFLAG_BC;
8289 break;
8290 default:
8291 MIPS_INVAL("cp1 cond branch");
8292 generate_exception_end(ctx, EXCP_RI);
8293 goto out;
8295 ctx->btarget = btarget;
8296 ctx->hflags |= MIPS_HFLAG_BDS32;
8297 out:
8298 tcg_temp_free_i32(t0);
8301 /* R6 CP1 Branches */
8302 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8303 int32_t ft, int32_t offset,
8304 int delayslot_size)
8306 target_ulong btarget;
8307 TCGv_i64 t0 = tcg_temp_new_i64();
8309 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8310 #ifdef MIPS_DEBUG_DISAS
8311 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8312 "\n", ctx->pc);
8313 #endif
8314 generate_exception_end(ctx, EXCP_RI);
8315 goto out;
8318 gen_load_fpr64(ctx, t0, ft);
8319 tcg_gen_andi_i64(t0, t0, 1);
8321 btarget = addr_add(ctx, ctx->pc + 4, offset);
8323 switch (op) {
8324 case OPC_BC1EQZ:
8325 tcg_gen_xori_i64(t0, t0, 1);
8326 ctx->hflags |= MIPS_HFLAG_BC;
8327 break;
8328 case OPC_BC1NEZ:
8329 /* t0 already set */
8330 ctx->hflags |= MIPS_HFLAG_BC;
8331 break;
8332 default:
8333 MIPS_INVAL("cp1 cond branch");
8334 generate_exception_end(ctx, EXCP_RI);
8335 goto out;
8338 tcg_gen_trunc_i64_tl(bcond, t0);
8340 ctx->btarget = btarget;
8342 switch (delayslot_size) {
8343 case 2:
8344 ctx->hflags |= MIPS_HFLAG_BDS16;
8345 break;
8346 case 4:
8347 ctx->hflags |= MIPS_HFLAG_BDS32;
8348 break;
8351 out:
8352 tcg_temp_free_i64(t0);
8355 /* Coprocessor 1 (FPU) */
8357 #define FOP(func, fmt) (((fmt) << 21) | (func))
8359 enum fopcode {
8360 OPC_ADD_S = FOP(0, FMT_S),
8361 OPC_SUB_S = FOP(1, FMT_S),
8362 OPC_MUL_S = FOP(2, FMT_S),
8363 OPC_DIV_S = FOP(3, FMT_S),
8364 OPC_SQRT_S = FOP(4, FMT_S),
8365 OPC_ABS_S = FOP(5, FMT_S),
8366 OPC_MOV_S = FOP(6, FMT_S),
8367 OPC_NEG_S = FOP(7, FMT_S),
8368 OPC_ROUND_L_S = FOP(8, FMT_S),
8369 OPC_TRUNC_L_S = FOP(9, FMT_S),
8370 OPC_CEIL_L_S = FOP(10, FMT_S),
8371 OPC_FLOOR_L_S = FOP(11, FMT_S),
8372 OPC_ROUND_W_S = FOP(12, FMT_S),
8373 OPC_TRUNC_W_S = FOP(13, FMT_S),
8374 OPC_CEIL_W_S = FOP(14, FMT_S),
8375 OPC_FLOOR_W_S = FOP(15, FMT_S),
8376 OPC_SEL_S = FOP(16, FMT_S),
8377 OPC_MOVCF_S = FOP(17, FMT_S),
8378 OPC_MOVZ_S = FOP(18, FMT_S),
8379 OPC_MOVN_S = FOP(19, FMT_S),
8380 OPC_SELEQZ_S = FOP(20, FMT_S),
8381 OPC_RECIP_S = FOP(21, FMT_S),
8382 OPC_RSQRT_S = FOP(22, FMT_S),
8383 OPC_SELNEZ_S = FOP(23, FMT_S),
8384 OPC_MADDF_S = FOP(24, FMT_S),
8385 OPC_MSUBF_S = FOP(25, FMT_S),
8386 OPC_RINT_S = FOP(26, FMT_S),
8387 OPC_CLASS_S = FOP(27, FMT_S),
8388 OPC_MIN_S = FOP(28, FMT_S),
8389 OPC_RECIP2_S = FOP(28, FMT_S),
8390 OPC_MINA_S = FOP(29, FMT_S),
8391 OPC_RECIP1_S = FOP(29, FMT_S),
8392 OPC_MAX_S = FOP(30, FMT_S),
8393 OPC_RSQRT1_S = FOP(30, FMT_S),
8394 OPC_MAXA_S = FOP(31, FMT_S),
8395 OPC_RSQRT2_S = FOP(31, FMT_S),
8396 OPC_CVT_D_S = FOP(33, FMT_S),
8397 OPC_CVT_W_S = FOP(36, FMT_S),
8398 OPC_CVT_L_S = FOP(37, FMT_S),
8399 OPC_CVT_PS_S = FOP(38, FMT_S),
8400 OPC_CMP_F_S = FOP (48, FMT_S),
8401 OPC_CMP_UN_S = FOP (49, FMT_S),
8402 OPC_CMP_EQ_S = FOP (50, FMT_S),
8403 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8404 OPC_CMP_OLT_S = FOP (52, FMT_S),
8405 OPC_CMP_ULT_S = FOP (53, FMT_S),
8406 OPC_CMP_OLE_S = FOP (54, FMT_S),
8407 OPC_CMP_ULE_S = FOP (55, FMT_S),
8408 OPC_CMP_SF_S = FOP (56, FMT_S),
8409 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8410 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8411 OPC_CMP_NGL_S = FOP (59, FMT_S),
8412 OPC_CMP_LT_S = FOP (60, FMT_S),
8413 OPC_CMP_NGE_S = FOP (61, FMT_S),
8414 OPC_CMP_LE_S = FOP (62, FMT_S),
8415 OPC_CMP_NGT_S = FOP (63, FMT_S),
8417 OPC_ADD_D = FOP(0, FMT_D),
8418 OPC_SUB_D = FOP(1, FMT_D),
8419 OPC_MUL_D = FOP(2, FMT_D),
8420 OPC_DIV_D = FOP(3, FMT_D),
8421 OPC_SQRT_D = FOP(4, FMT_D),
8422 OPC_ABS_D = FOP(5, FMT_D),
8423 OPC_MOV_D = FOP(6, FMT_D),
8424 OPC_NEG_D = FOP(7, FMT_D),
8425 OPC_ROUND_L_D = FOP(8, FMT_D),
8426 OPC_TRUNC_L_D = FOP(9, FMT_D),
8427 OPC_CEIL_L_D = FOP(10, FMT_D),
8428 OPC_FLOOR_L_D = FOP(11, FMT_D),
8429 OPC_ROUND_W_D = FOP(12, FMT_D),
8430 OPC_TRUNC_W_D = FOP(13, FMT_D),
8431 OPC_CEIL_W_D = FOP(14, FMT_D),
8432 OPC_FLOOR_W_D = FOP(15, FMT_D),
8433 OPC_SEL_D = FOP(16, FMT_D),
8434 OPC_MOVCF_D = FOP(17, FMT_D),
8435 OPC_MOVZ_D = FOP(18, FMT_D),
8436 OPC_MOVN_D = FOP(19, FMT_D),
8437 OPC_SELEQZ_D = FOP(20, FMT_D),
8438 OPC_RECIP_D = FOP(21, FMT_D),
8439 OPC_RSQRT_D = FOP(22, FMT_D),
8440 OPC_SELNEZ_D = FOP(23, FMT_D),
8441 OPC_MADDF_D = FOP(24, FMT_D),
8442 OPC_MSUBF_D = FOP(25, FMT_D),
8443 OPC_RINT_D = FOP(26, FMT_D),
8444 OPC_CLASS_D = FOP(27, FMT_D),
8445 OPC_MIN_D = FOP(28, FMT_D),
8446 OPC_RECIP2_D = FOP(28, FMT_D),
8447 OPC_MINA_D = FOP(29, FMT_D),
8448 OPC_RECIP1_D = FOP(29, FMT_D),
8449 OPC_MAX_D = FOP(30, FMT_D),
8450 OPC_RSQRT1_D = FOP(30, FMT_D),
8451 OPC_MAXA_D = FOP(31, FMT_D),
8452 OPC_RSQRT2_D = FOP(31, FMT_D),
8453 OPC_CVT_S_D = FOP(32, FMT_D),
8454 OPC_CVT_W_D = FOP(36, FMT_D),
8455 OPC_CVT_L_D = FOP(37, FMT_D),
8456 OPC_CMP_F_D = FOP (48, FMT_D),
8457 OPC_CMP_UN_D = FOP (49, FMT_D),
8458 OPC_CMP_EQ_D = FOP (50, FMT_D),
8459 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8460 OPC_CMP_OLT_D = FOP (52, FMT_D),
8461 OPC_CMP_ULT_D = FOP (53, FMT_D),
8462 OPC_CMP_OLE_D = FOP (54, FMT_D),
8463 OPC_CMP_ULE_D = FOP (55, FMT_D),
8464 OPC_CMP_SF_D = FOP (56, FMT_D),
8465 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8466 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8467 OPC_CMP_NGL_D = FOP (59, FMT_D),
8468 OPC_CMP_LT_D = FOP (60, FMT_D),
8469 OPC_CMP_NGE_D = FOP (61, FMT_D),
8470 OPC_CMP_LE_D = FOP (62, FMT_D),
8471 OPC_CMP_NGT_D = FOP (63, FMT_D),
8473 OPC_CVT_S_W = FOP(32, FMT_W),
8474 OPC_CVT_D_W = FOP(33, FMT_W),
8475 OPC_CVT_S_L = FOP(32, FMT_L),
8476 OPC_CVT_D_L = FOP(33, FMT_L),
8477 OPC_CVT_PS_PW = FOP(38, FMT_W),
8479 OPC_ADD_PS = FOP(0, FMT_PS),
8480 OPC_SUB_PS = FOP(1, FMT_PS),
8481 OPC_MUL_PS = FOP(2, FMT_PS),
8482 OPC_DIV_PS = FOP(3, FMT_PS),
8483 OPC_ABS_PS = FOP(5, FMT_PS),
8484 OPC_MOV_PS = FOP(6, FMT_PS),
8485 OPC_NEG_PS = FOP(7, FMT_PS),
8486 OPC_MOVCF_PS = FOP(17, FMT_PS),
8487 OPC_MOVZ_PS = FOP(18, FMT_PS),
8488 OPC_MOVN_PS = FOP(19, FMT_PS),
8489 OPC_ADDR_PS = FOP(24, FMT_PS),
8490 OPC_MULR_PS = FOP(26, FMT_PS),
8491 OPC_RECIP2_PS = FOP(28, FMT_PS),
8492 OPC_RECIP1_PS = FOP(29, FMT_PS),
8493 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8494 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8496 OPC_CVT_S_PU = FOP(32, FMT_PS),
8497 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8498 OPC_CVT_S_PL = FOP(40, FMT_PS),
8499 OPC_PLL_PS = FOP(44, FMT_PS),
8500 OPC_PLU_PS = FOP(45, FMT_PS),
8501 OPC_PUL_PS = FOP(46, FMT_PS),
8502 OPC_PUU_PS = FOP(47, FMT_PS),
8503 OPC_CMP_F_PS = FOP (48, FMT_PS),
8504 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8505 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8506 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8507 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8508 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8509 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8510 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8511 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8512 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8513 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8514 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8515 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8516 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8517 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8518 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8521 enum r6_f_cmp_op {
8522 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8523 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8524 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8525 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8526 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8527 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8528 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8529 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8530 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8531 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8532 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8533 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8534 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8535 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8536 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8537 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8538 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8539 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8540 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8541 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8542 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8543 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8545 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8546 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8547 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8548 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8549 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8550 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8551 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8552 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8553 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8554 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8555 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8556 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8557 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8558 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8559 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8560 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8561 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8562 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8563 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8564 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8565 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8566 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8568 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8570 TCGv t0 = tcg_temp_new();
8572 switch (opc) {
8573 case OPC_MFC1:
8575 TCGv_i32 fp0 = tcg_temp_new_i32();
8577 gen_load_fpr32(ctx, fp0, fs);
8578 tcg_gen_ext_i32_tl(t0, fp0);
8579 tcg_temp_free_i32(fp0);
8581 gen_store_gpr(t0, rt);
8582 break;
8583 case OPC_MTC1:
8584 gen_load_gpr(t0, rt);
8586 TCGv_i32 fp0 = tcg_temp_new_i32();
8588 tcg_gen_trunc_tl_i32(fp0, t0);
8589 gen_store_fpr32(ctx, fp0, fs);
8590 tcg_temp_free_i32(fp0);
8592 break;
8593 case OPC_CFC1:
8594 gen_helper_1e0i(cfc1, t0, fs);
8595 gen_store_gpr(t0, rt);
8596 break;
8597 case OPC_CTC1:
8598 gen_load_gpr(t0, rt);
8599 save_cpu_state(ctx, 0);
8601 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8603 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8604 tcg_temp_free_i32(fs_tmp);
8606 /* Stop translation as we may have changed hflags */
8607 ctx->bstate = BS_STOP;
8608 break;
8609 #if defined(TARGET_MIPS64)
8610 case OPC_DMFC1:
8611 gen_load_fpr64(ctx, t0, fs);
8612 gen_store_gpr(t0, rt);
8613 break;
8614 case OPC_DMTC1:
8615 gen_load_gpr(t0, rt);
8616 gen_store_fpr64(ctx, t0, fs);
8617 break;
8618 #endif
8619 case OPC_MFHC1:
8621 TCGv_i32 fp0 = tcg_temp_new_i32();
8623 gen_load_fpr32h(ctx, fp0, fs);
8624 tcg_gen_ext_i32_tl(t0, fp0);
8625 tcg_temp_free_i32(fp0);
8627 gen_store_gpr(t0, rt);
8628 break;
8629 case OPC_MTHC1:
8630 gen_load_gpr(t0, rt);
8632 TCGv_i32 fp0 = tcg_temp_new_i32();
8634 tcg_gen_trunc_tl_i32(fp0, t0);
8635 gen_store_fpr32h(ctx, fp0, fs);
8636 tcg_temp_free_i32(fp0);
8638 break;
8639 default:
8640 MIPS_INVAL("cp1 move");
8641 generate_exception_end(ctx, EXCP_RI);
8642 goto out;
8645 out:
8646 tcg_temp_free(t0);
8649 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8651 TCGLabel *l1;
8652 TCGCond cond;
8653 TCGv_i32 t0;
8655 if (rd == 0) {
8656 /* Treat as NOP. */
8657 return;
8660 if (tf)
8661 cond = TCG_COND_EQ;
8662 else
8663 cond = TCG_COND_NE;
8665 l1 = gen_new_label();
8666 t0 = tcg_temp_new_i32();
8667 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8668 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8669 tcg_temp_free_i32(t0);
8670 if (rs == 0) {
8671 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8672 } else {
8673 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8675 gen_set_label(l1);
8678 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
8679 int tf)
8681 int cond;
8682 TCGv_i32 t0 = tcg_temp_new_i32();
8683 TCGLabel *l1 = gen_new_label();
8685 if (tf)
8686 cond = TCG_COND_EQ;
8687 else
8688 cond = TCG_COND_NE;
8690 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8691 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8692 gen_load_fpr32(ctx, t0, fs);
8693 gen_store_fpr32(ctx, t0, fd);
8694 gen_set_label(l1);
8695 tcg_temp_free_i32(t0);
8698 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8700 int cond;
8701 TCGv_i32 t0 = tcg_temp_new_i32();
8702 TCGv_i64 fp0;
8703 TCGLabel *l1 = gen_new_label();
8705 if (tf)
8706 cond = TCG_COND_EQ;
8707 else
8708 cond = TCG_COND_NE;
8710 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8711 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8712 tcg_temp_free_i32(t0);
8713 fp0 = tcg_temp_new_i64();
8714 gen_load_fpr64(ctx, fp0, fs);
8715 gen_store_fpr64(ctx, fp0, fd);
8716 tcg_temp_free_i64(fp0);
8717 gen_set_label(l1);
8720 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8721 int cc, int tf)
8723 int cond;
8724 TCGv_i32 t0 = tcg_temp_new_i32();
8725 TCGLabel *l1 = gen_new_label();
8726 TCGLabel *l2 = gen_new_label();
8728 if (tf)
8729 cond = TCG_COND_EQ;
8730 else
8731 cond = TCG_COND_NE;
8733 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8734 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8735 gen_load_fpr32(ctx, t0, fs);
8736 gen_store_fpr32(ctx, t0, fd);
8737 gen_set_label(l1);
8739 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8740 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8741 gen_load_fpr32h(ctx, t0, fs);
8742 gen_store_fpr32h(ctx, t0, fd);
8743 tcg_temp_free_i32(t0);
8744 gen_set_label(l2);
8747 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8748 int fs)
8750 TCGv_i32 t1 = tcg_const_i32(0);
8751 TCGv_i32 fp0 = tcg_temp_new_i32();
8752 TCGv_i32 fp1 = tcg_temp_new_i32();
8753 TCGv_i32 fp2 = tcg_temp_new_i32();
8754 gen_load_fpr32(ctx, fp0, fd);
8755 gen_load_fpr32(ctx, fp1, ft);
8756 gen_load_fpr32(ctx, fp2, fs);
8758 switch (op1) {
8759 case OPC_SEL_S:
8760 tcg_gen_andi_i32(fp0, fp0, 1);
8761 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8762 break;
8763 case OPC_SELEQZ_S:
8764 tcg_gen_andi_i32(fp1, fp1, 1);
8765 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8766 break;
8767 case OPC_SELNEZ_S:
8768 tcg_gen_andi_i32(fp1, fp1, 1);
8769 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8770 break;
8771 default:
8772 MIPS_INVAL("gen_sel_s");
8773 generate_exception_end(ctx, EXCP_RI);
8774 break;
8777 gen_store_fpr32(ctx, fp0, fd);
8778 tcg_temp_free_i32(fp2);
8779 tcg_temp_free_i32(fp1);
8780 tcg_temp_free_i32(fp0);
8781 tcg_temp_free_i32(t1);
8784 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8785 int fs)
8787 TCGv_i64 t1 = tcg_const_i64(0);
8788 TCGv_i64 fp0 = tcg_temp_new_i64();
8789 TCGv_i64 fp1 = tcg_temp_new_i64();
8790 TCGv_i64 fp2 = tcg_temp_new_i64();
8791 gen_load_fpr64(ctx, fp0, fd);
8792 gen_load_fpr64(ctx, fp1, ft);
8793 gen_load_fpr64(ctx, fp2, fs);
8795 switch (op1) {
8796 case OPC_SEL_D:
8797 tcg_gen_andi_i64(fp0, fp0, 1);
8798 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8799 break;
8800 case OPC_SELEQZ_D:
8801 tcg_gen_andi_i64(fp1, fp1, 1);
8802 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8803 break;
8804 case OPC_SELNEZ_D:
8805 tcg_gen_andi_i64(fp1, fp1, 1);
8806 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8807 break;
8808 default:
8809 MIPS_INVAL("gen_sel_d");
8810 generate_exception_end(ctx, EXCP_RI);
8811 break;
8814 gen_store_fpr64(ctx, fp0, fd);
8815 tcg_temp_free_i64(fp2);
8816 tcg_temp_free_i64(fp1);
8817 tcg_temp_free_i64(fp0);
8818 tcg_temp_free_i64(t1);
8821 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8822 int ft, int fs, int fd, int cc)
8824 uint32_t func = ctx->opcode & 0x3f;
8825 switch (op1) {
8826 case OPC_ADD_S:
8828 TCGv_i32 fp0 = tcg_temp_new_i32();
8829 TCGv_i32 fp1 = tcg_temp_new_i32();
8831 gen_load_fpr32(ctx, fp0, fs);
8832 gen_load_fpr32(ctx, fp1, ft);
8833 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
8834 tcg_temp_free_i32(fp1);
8835 gen_store_fpr32(ctx, fp0, fd);
8836 tcg_temp_free_i32(fp0);
8838 break;
8839 case OPC_SUB_S:
8841 TCGv_i32 fp0 = tcg_temp_new_i32();
8842 TCGv_i32 fp1 = tcg_temp_new_i32();
8844 gen_load_fpr32(ctx, fp0, fs);
8845 gen_load_fpr32(ctx, fp1, ft);
8846 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
8847 tcg_temp_free_i32(fp1);
8848 gen_store_fpr32(ctx, fp0, fd);
8849 tcg_temp_free_i32(fp0);
8851 break;
8852 case OPC_MUL_S:
8854 TCGv_i32 fp0 = tcg_temp_new_i32();
8855 TCGv_i32 fp1 = tcg_temp_new_i32();
8857 gen_load_fpr32(ctx, fp0, fs);
8858 gen_load_fpr32(ctx, fp1, ft);
8859 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
8860 tcg_temp_free_i32(fp1);
8861 gen_store_fpr32(ctx, fp0, fd);
8862 tcg_temp_free_i32(fp0);
8864 break;
8865 case OPC_DIV_S:
8867 TCGv_i32 fp0 = tcg_temp_new_i32();
8868 TCGv_i32 fp1 = tcg_temp_new_i32();
8870 gen_load_fpr32(ctx, fp0, fs);
8871 gen_load_fpr32(ctx, fp1, ft);
8872 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
8873 tcg_temp_free_i32(fp1);
8874 gen_store_fpr32(ctx, fp0, fd);
8875 tcg_temp_free_i32(fp0);
8877 break;
8878 case OPC_SQRT_S:
8880 TCGv_i32 fp0 = tcg_temp_new_i32();
8882 gen_load_fpr32(ctx, fp0, fs);
8883 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
8884 gen_store_fpr32(ctx, fp0, fd);
8885 tcg_temp_free_i32(fp0);
8887 break;
8888 case OPC_ABS_S:
8890 TCGv_i32 fp0 = tcg_temp_new_i32();
8892 gen_load_fpr32(ctx, fp0, fs);
8893 gen_helper_float_abs_s(fp0, fp0);
8894 gen_store_fpr32(ctx, fp0, fd);
8895 tcg_temp_free_i32(fp0);
8897 break;
8898 case OPC_MOV_S:
8900 TCGv_i32 fp0 = tcg_temp_new_i32();
8902 gen_load_fpr32(ctx, fp0, fs);
8903 gen_store_fpr32(ctx, fp0, fd);
8904 tcg_temp_free_i32(fp0);
8906 break;
8907 case OPC_NEG_S:
8909 TCGv_i32 fp0 = tcg_temp_new_i32();
8911 gen_load_fpr32(ctx, fp0, fs);
8912 gen_helper_float_chs_s(fp0, fp0);
8913 gen_store_fpr32(ctx, fp0, fd);
8914 tcg_temp_free_i32(fp0);
8916 break;
8917 case OPC_ROUND_L_S:
8918 check_cp1_64bitmode(ctx);
8920 TCGv_i32 fp32 = tcg_temp_new_i32();
8921 TCGv_i64 fp64 = tcg_temp_new_i64();
8923 gen_load_fpr32(ctx, fp32, fs);
8924 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
8925 tcg_temp_free_i32(fp32);
8926 gen_store_fpr64(ctx, fp64, fd);
8927 tcg_temp_free_i64(fp64);
8929 break;
8930 case OPC_TRUNC_L_S:
8931 check_cp1_64bitmode(ctx);
8933 TCGv_i32 fp32 = tcg_temp_new_i32();
8934 TCGv_i64 fp64 = tcg_temp_new_i64();
8936 gen_load_fpr32(ctx, fp32, fs);
8937 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
8938 tcg_temp_free_i32(fp32);
8939 gen_store_fpr64(ctx, fp64, fd);
8940 tcg_temp_free_i64(fp64);
8942 break;
8943 case OPC_CEIL_L_S:
8944 check_cp1_64bitmode(ctx);
8946 TCGv_i32 fp32 = tcg_temp_new_i32();
8947 TCGv_i64 fp64 = tcg_temp_new_i64();
8949 gen_load_fpr32(ctx, fp32, fs);
8950 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
8951 tcg_temp_free_i32(fp32);
8952 gen_store_fpr64(ctx, fp64, fd);
8953 tcg_temp_free_i64(fp64);
8955 break;
8956 case OPC_FLOOR_L_S:
8957 check_cp1_64bitmode(ctx);
8959 TCGv_i32 fp32 = tcg_temp_new_i32();
8960 TCGv_i64 fp64 = tcg_temp_new_i64();
8962 gen_load_fpr32(ctx, fp32, fs);
8963 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
8964 tcg_temp_free_i32(fp32);
8965 gen_store_fpr64(ctx, fp64, fd);
8966 tcg_temp_free_i64(fp64);
8968 break;
8969 case OPC_ROUND_W_S:
8971 TCGv_i32 fp0 = tcg_temp_new_i32();
8973 gen_load_fpr32(ctx, fp0, fs);
8974 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
8975 gen_store_fpr32(ctx, fp0, fd);
8976 tcg_temp_free_i32(fp0);
8978 break;
8979 case OPC_TRUNC_W_S:
8981 TCGv_i32 fp0 = tcg_temp_new_i32();
8983 gen_load_fpr32(ctx, fp0, fs);
8984 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
8985 gen_store_fpr32(ctx, fp0, fd);
8986 tcg_temp_free_i32(fp0);
8988 break;
8989 case OPC_CEIL_W_S:
8991 TCGv_i32 fp0 = tcg_temp_new_i32();
8993 gen_load_fpr32(ctx, fp0, fs);
8994 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
8995 gen_store_fpr32(ctx, fp0, fd);
8996 tcg_temp_free_i32(fp0);
8998 break;
8999 case OPC_FLOOR_W_S:
9001 TCGv_i32 fp0 = tcg_temp_new_i32();
9003 gen_load_fpr32(ctx, fp0, fs);
9004 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
9005 gen_store_fpr32(ctx, fp0, fd);
9006 tcg_temp_free_i32(fp0);
9008 break;
9009 case OPC_SEL_S:
9010 check_insn(ctx, ISA_MIPS32R6);
9011 gen_sel_s(ctx, op1, fd, ft, fs);
9012 break;
9013 case OPC_SELEQZ_S:
9014 check_insn(ctx, ISA_MIPS32R6);
9015 gen_sel_s(ctx, op1, fd, ft, fs);
9016 break;
9017 case OPC_SELNEZ_S:
9018 check_insn(ctx, ISA_MIPS32R6);
9019 gen_sel_s(ctx, op1, fd, ft, fs);
9020 break;
9021 case OPC_MOVCF_S:
9022 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9023 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9024 break;
9025 case OPC_MOVZ_S:
9026 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9028 TCGLabel *l1 = gen_new_label();
9029 TCGv_i32 fp0;
9031 if (ft != 0) {
9032 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9034 fp0 = tcg_temp_new_i32();
9035 gen_load_fpr32(ctx, fp0, fs);
9036 gen_store_fpr32(ctx, fp0, fd);
9037 tcg_temp_free_i32(fp0);
9038 gen_set_label(l1);
9040 break;
9041 case OPC_MOVN_S:
9042 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9044 TCGLabel *l1 = gen_new_label();
9045 TCGv_i32 fp0;
9047 if (ft != 0) {
9048 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9049 fp0 = tcg_temp_new_i32();
9050 gen_load_fpr32(ctx, fp0, fs);
9051 gen_store_fpr32(ctx, fp0, fd);
9052 tcg_temp_free_i32(fp0);
9053 gen_set_label(l1);
9056 break;
9057 case OPC_RECIP_S:
9059 TCGv_i32 fp0 = tcg_temp_new_i32();
9061 gen_load_fpr32(ctx, fp0, fs);
9062 gen_helper_float_recip_s(fp0, cpu_env, fp0);
9063 gen_store_fpr32(ctx, fp0, fd);
9064 tcg_temp_free_i32(fp0);
9066 break;
9067 case OPC_RSQRT_S:
9069 TCGv_i32 fp0 = tcg_temp_new_i32();
9071 gen_load_fpr32(ctx, fp0, fs);
9072 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
9073 gen_store_fpr32(ctx, fp0, fd);
9074 tcg_temp_free_i32(fp0);
9076 break;
9077 case OPC_MADDF_S:
9078 check_insn(ctx, ISA_MIPS32R6);
9080 TCGv_i32 fp0 = tcg_temp_new_i32();
9081 TCGv_i32 fp1 = tcg_temp_new_i32();
9082 TCGv_i32 fp2 = tcg_temp_new_i32();
9083 gen_load_fpr32(ctx, fp0, fs);
9084 gen_load_fpr32(ctx, fp1, ft);
9085 gen_load_fpr32(ctx, fp2, fd);
9086 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
9087 gen_store_fpr32(ctx, fp2, fd);
9088 tcg_temp_free_i32(fp2);
9089 tcg_temp_free_i32(fp1);
9090 tcg_temp_free_i32(fp0);
9092 break;
9093 case OPC_MSUBF_S:
9094 check_insn(ctx, ISA_MIPS32R6);
9096 TCGv_i32 fp0 = tcg_temp_new_i32();
9097 TCGv_i32 fp1 = tcg_temp_new_i32();
9098 TCGv_i32 fp2 = tcg_temp_new_i32();
9099 gen_load_fpr32(ctx, fp0, fs);
9100 gen_load_fpr32(ctx, fp1, ft);
9101 gen_load_fpr32(ctx, fp2, fd);
9102 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9103 gen_store_fpr32(ctx, fp2, fd);
9104 tcg_temp_free_i32(fp2);
9105 tcg_temp_free_i32(fp1);
9106 tcg_temp_free_i32(fp0);
9108 break;
9109 case OPC_RINT_S:
9110 check_insn(ctx, ISA_MIPS32R6);
9112 TCGv_i32 fp0 = tcg_temp_new_i32();
9113 gen_load_fpr32(ctx, fp0, fs);
9114 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9115 gen_store_fpr32(ctx, fp0, fd);
9116 tcg_temp_free_i32(fp0);
9118 break;
9119 case OPC_CLASS_S:
9120 check_insn(ctx, ISA_MIPS32R6);
9122 TCGv_i32 fp0 = tcg_temp_new_i32();
9123 gen_load_fpr32(ctx, fp0, fs);
9124 gen_helper_float_class_s(fp0, fp0);
9125 gen_store_fpr32(ctx, fp0, fd);
9126 tcg_temp_free_i32(fp0);
9128 break;
9129 case OPC_MIN_S: /* OPC_RECIP2_S */
9130 if (ctx->insn_flags & ISA_MIPS32R6) {
9131 /* OPC_MIN_S */
9132 TCGv_i32 fp0 = tcg_temp_new_i32();
9133 TCGv_i32 fp1 = tcg_temp_new_i32();
9134 TCGv_i32 fp2 = tcg_temp_new_i32();
9135 gen_load_fpr32(ctx, fp0, fs);
9136 gen_load_fpr32(ctx, fp1, ft);
9137 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9138 gen_store_fpr32(ctx, fp2, fd);
9139 tcg_temp_free_i32(fp2);
9140 tcg_temp_free_i32(fp1);
9141 tcg_temp_free_i32(fp0);
9142 } else {
9143 /* OPC_RECIP2_S */
9144 check_cp1_64bitmode(ctx);
9146 TCGv_i32 fp0 = tcg_temp_new_i32();
9147 TCGv_i32 fp1 = tcg_temp_new_i32();
9149 gen_load_fpr32(ctx, fp0, fs);
9150 gen_load_fpr32(ctx, fp1, ft);
9151 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9152 tcg_temp_free_i32(fp1);
9153 gen_store_fpr32(ctx, fp0, fd);
9154 tcg_temp_free_i32(fp0);
9157 break;
9158 case OPC_MINA_S: /* OPC_RECIP1_S */
9159 if (ctx->insn_flags & ISA_MIPS32R6) {
9160 /* OPC_MINA_S */
9161 TCGv_i32 fp0 = tcg_temp_new_i32();
9162 TCGv_i32 fp1 = tcg_temp_new_i32();
9163 TCGv_i32 fp2 = tcg_temp_new_i32();
9164 gen_load_fpr32(ctx, fp0, fs);
9165 gen_load_fpr32(ctx, fp1, ft);
9166 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9167 gen_store_fpr32(ctx, fp2, fd);
9168 tcg_temp_free_i32(fp2);
9169 tcg_temp_free_i32(fp1);
9170 tcg_temp_free_i32(fp0);
9171 } else {
9172 /* OPC_RECIP1_S */
9173 check_cp1_64bitmode(ctx);
9175 TCGv_i32 fp0 = tcg_temp_new_i32();
9177 gen_load_fpr32(ctx, fp0, fs);
9178 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9179 gen_store_fpr32(ctx, fp0, fd);
9180 tcg_temp_free_i32(fp0);
9183 break;
9184 case OPC_MAX_S: /* OPC_RSQRT1_S */
9185 if (ctx->insn_flags & ISA_MIPS32R6) {
9186 /* OPC_MAX_S */
9187 TCGv_i32 fp0 = tcg_temp_new_i32();
9188 TCGv_i32 fp1 = tcg_temp_new_i32();
9189 gen_load_fpr32(ctx, fp0, fs);
9190 gen_load_fpr32(ctx, fp1, ft);
9191 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9192 gen_store_fpr32(ctx, fp1, fd);
9193 tcg_temp_free_i32(fp1);
9194 tcg_temp_free_i32(fp0);
9195 } else {
9196 /* OPC_RSQRT1_S */
9197 check_cp1_64bitmode(ctx);
9199 TCGv_i32 fp0 = tcg_temp_new_i32();
9201 gen_load_fpr32(ctx, fp0, fs);
9202 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9203 gen_store_fpr32(ctx, fp0, fd);
9204 tcg_temp_free_i32(fp0);
9207 break;
9208 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9209 if (ctx->insn_flags & ISA_MIPS32R6) {
9210 /* OPC_MAXA_S */
9211 TCGv_i32 fp0 = tcg_temp_new_i32();
9212 TCGv_i32 fp1 = tcg_temp_new_i32();
9213 gen_load_fpr32(ctx, fp0, fs);
9214 gen_load_fpr32(ctx, fp1, ft);
9215 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9216 gen_store_fpr32(ctx, fp1, fd);
9217 tcg_temp_free_i32(fp1);
9218 tcg_temp_free_i32(fp0);
9219 } else {
9220 /* OPC_RSQRT2_S */
9221 check_cp1_64bitmode(ctx);
9223 TCGv_i32 fp0 = tcg_temp_new_i32();
9224 TCGv_i32 fp1 = tcg_temp_new_i32();
9226 gen_load_fpr32(ctx, fp0, fs);
9227 gen_load_fpr32(ctx, fp1, ft);
9228 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9229 tcg_temp_free_i32(fp1);
9230 gen_store_fpr32(ctx, fp0, fd);
9231 tcg_temp_free_i32(fp0);
9234 break;
9235 case OPC_CVT_D_S:
9236 check_cp1_registers(ctx, fd);
9238 TCGv_i32 fp32 = tcg_temp_new_i32();
9239 TCGv_i64 fp64 = tcg_temp_new_i64();
9241 gen_load_fpr32(ctx, fp32, fs);
9242 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9243 tcg_temp_free_i32(fp32);
9244 gen_store_fpr64(ctx, fp64, fd);
9245 tcg_temp_free_i64(fp64);
9247 break;
9248 case OPC_CVT_W_S:
9250 TCGv_i32 fp0 = tcg_temp_new_i32();
9252 gen_load_fpr32(ctx, fp0, fs);
9253 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
9254 gen_store_fpr32(ctx, fp0, fd);
9255 tcg_temp_free_i32(fp0);
9257 break;
9258 case OPC_CVT_L_S:
9259 check_cp1_64bitmode(ctx);
9261 TCGv_i32 fp32 = tcg_temp_new_i32();
9262 TCGv_i64 fp64 = tcg_temp_new_i64();
9264 gen_load_fpr32(ctx, fp32, fs);
9265 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
9266 tcg_temp_free_i32(fp32);
9267 gen_store_fpr64(ctx, fp64, fd);
9268 tcg_temp_free_i64(fp64);
9270 break;
9271 case OPC_CVT_PS_S:
9272 check_ps(ctx);
9274 TCGv_i64 fp64 = tcg_temp_new_i64();
9275 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9276 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9278 gen_load_fpr32(ctx, fp32_0, fs);
9279 gen_load_fpr32(ctx, fp32_1, ft);
9280 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9281 tcg_temp_free_i32(fp32_1);
9282 tcg_temp_free_i32(fp32_0);
9283 gen_store_fpr64(ctx, fp64, fd);
9284 tcg_temp_free_i64(fp64);
9286 break;
9287 case OPC_CMP_F_S:
9288 case OPC_CMP_UN_S:
9289 case OPC_CMP_EQ_S:
9290 case OPC_CMP_UEQ_S:
9291 case OPC_CMP_OLT_S:
9292 case OPC_CMP_ULT_S:
9293 case OPC_CMP_OLE_S:
9294 case OPC_CMP_ULE_S:
9295 case OPC_CMP_SF_S:
9296 case OPC_CMP_NGLE_S:
9297 case OPC_CMP_SEQ_S:
9298 case OPC_CMP_NGL_S:
9299 case OPC_CMP_LT_S:
9300 case OPC_CMP_NGE_S:
9301 case OPC_CMP_LE_S:
9302 case OPC_CMP_NGT_S:
9303 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9304 if (ctx->opcode & (1 << 6)) {
9305 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9306 } else {
9307 gen_cmp_s(ctx, func-48, ft, fs, cc);
9309 break;
9310 case OPC_ADD_D:
9311 check_cp1_registers(ctx, fs | ft | fd);
9313 TCGv_i64 fp0 = tcg_temp_new_i64();
9314 TCGv_i64 fp1 = tcg_temp_new_i64();
9316 gen_load_fpr64(ctx, fp0, fs);
9317 gen_load_fpr64(ctx, fp1, ft);
9318 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9319 tcg_temp_free_i64(fp1);
9320 gen_store_fpr64(ctx, fp0, fd);
9321 tcg_temp_free_i64(fp0);
9323 break;
9324 case OPC_SUB_D:
9325 check_cp1_registers(ctx, fs | ft | fd);
9327 TCGv_i64 fp0 = tcg_temp_new_i64();
9328 TCGv_i64 fp1 = tcg_temp_new_i64();
9330 gen_load_fpr64(ctx, fp0, fs);
9331 gen_load_fpr64(ctx, fp1, ft);
9332 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9333 tcg_temp_free_i64(fp1);
9334 gen_store_fpr64(ctx, fp0, fd);
9335 tcg_temp_free_i64(fp0);
9337 break;
9338 case OPC_MUL_D:
9339 check_cp1_registers(ctx, fs | ft | fd);
9341 TCGv_i64 fp0 = tcg_temp_new_i64();
9342 TCGv_i64 fp1 = tcg_temp_new_i64();
9344 gen_load_fpr64(ctx, fp0, fs);
9345 gen_load_fpr64(ctx, fp1, ft);
9346 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9347 tcg_temp_free_i64(fp1);
9348 gen_store_fpr64(ctx, fp0, fd);
9349 tcg_temp_free_i64(fp0);
9351 break;
9352 case OPC_DIV_D:
9353 check_cp1_registers(ctx, fs | ft | fd);
9355 TCGv_i64 fp0 = tcg_temp_new_i64();
9356 TCGv_i64 fp1 = tcg_temp_new_i64();
9358 gen_load_fpr64(ctx, fp0, fs);
9359 gen_load_fpr64(ctx, fp1, ft);
9360 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9361 tcg_temp_free_i64(fp1);
9362 gen_store_fpr64(ctx, fp0, fd);
9363 tcg_temp_free_i64(fp0);
9365 break;
9366 case OPC_SQRT_D:
9367 check_cp1_registers(ctx, fs | fd);
9369 TCGv_i64 fp0 = tcg_temp_new_i64();
9371 gen_load_fpr64(ctx, fp0, fs);
9372 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9373 gen_store_fpr64(ctx, fp0, fd);
9374 tcg_temp_free_i64(fp0);
9376 break;
9377 case OPC_ABS_D:
9378 check_cp1_registers(ctx, fs | fd);
9380 TCGv_i64 fp0 = tcg_temp_new_i64();
9382 gen_load_fpr64(ctx, fp0, fs);
9383 gen_helper_float_abs_d(fp0, fp0);
9384 gen_store_fpr64(ctx, fp0, fd);
9385 tcg_temp_free_i64(fp0);
9387 break;
9388 case OPC_MOV_D:
9389 check_cp1_registers(ctx, fs | fd);
9391 TCGv_i64 fp0 = tcg_temp_new_i64();
9393 gen_load_fpr64(ctx, fp0, fs);
9394 gen_store_fpr64(ctx, fp0, fd);
9395 tcg_temp_free_i64(fp0);
9397 break;
9398 case OPC_NEG_D:
9399 check_cp1_registers(ctx, fs | fd);
9401 TCGv_i64 fp0 = tcg_temp_new_i64();
9403 gen_load_fpr64(ctx, fp0, fs);
9404 gen_helper_float_chs_d(fp0, fp0);
9405 gen_store_fpr64(ctx, fp0, fd);
9406 tcg_temp_free_i64(fp0);
9408 break;
9409 case OPC_ROUND_L_D:
9410 check_cp1_64bitmode(ctx);
9412 TCGv_i64 fp0 = tcg_temp_new_i64();
9414 gen_load_fpr64(ctx, fp0, fs);
9415 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
9416 gen_store_fpr64(ctx, fp0, fd);
9417 tcg_temp_free_i64(fp0);
9419 break;
9420 case OPC_TRUNC_L_D:
9421 check_cp1_64bitmode(ctx);
9423 TCGv_i64 fp0 = tcg_temp_new_i64();
9425 gen_load_fpr64(ctx, fp0, fs);
9426 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
9427 gen_store_fpr64(ctx, fp0, fd);
9428 tcg_temp_free_i64(fp0);
9430 break;
9431 case OPC_CEIL_L_D:
9432 check_cp1_64bitmode(ctx);
9434 TCGv_i64 fp0 = tcg_temp_new_i64();
9436 gen_load_fpr64(ctx, fp0, fs);
9437 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
9438 gen_store_fpr64(ctx, fp0, fd);
9439 tcg_temp_free_i64(fp0);
9441 break;
9442 case OPC_FLOOR_L_D:
9443 check_cp1_64bitmode(ctx);
9445 TCGv_i64 fp0 = tcg_temp_new_i64();
9447 gen_load_fpr64(ctx, fp0, fs);
9448 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
9449 gen_store_fpr64(ctx, fp0, fd);
9450 tcg_temp_free_i64(fp0);
9452 break;
9453 case OPC_ROUND_W_D:
9454 check_cp1_registers(ctx, fs);
9456 TCGv_i32 fp32 = tcg_temp_new_i32();
9457 TCGv_i64 fp64 = tcg_temp_new_i64();
9459 gen_load_fpr64(ctx, fp64, fs);
9460 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
9461 tcg_temp_free_i64(fp64);
9462 gen_store_fpr32(ctx, fp32, fd);
9463 tcg_temp_free_i32(fp32);
9465 break;
9466 case OPC_TRUNC_W_D:
9467 check_cp1_registers(ctx, fs);
9469 TCGv_i32 fp32 = tcg_temp_new_i32();
9470 TCGv_i64 fp64 = tcg_temp_new_i64();
9472 gen_load_fpr64(ctx, fp64, fs);
9473 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
9474 tcg_temp_free_i64(fp64);
9475 gen_store_fpr32(ctx, fp32, fd);
9476 tcg_temp_free_i32(fp32);
9478 break;
9479 case OPC_CEIL_W_D:
9480 check_cp1_registers(ctx, fs);
9482 TCGv_i32 fp32 = tcg_temp_new_i32();
9483 TCGv_i64 fp64 = tcg_temp_new_i64();
9485 gen_load_fpr64(ctx, fp64, fs);
9486 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
9487 tcg_temp_free_i64(fp64);
9488 gen_store_fpr32(ctx, fp32, fd);
9489 tcg_temp_free_i32(fp32);
9491 break;
9492 case OPC_FLOOR_W_D:
9493 check_cp1_registers(ctx, fs);
9495 TCGv_i32 fp32 = tcg_temp_new_i32();
9496 TCGv_i64 fp64 = tcg_temp_new_i64();
9498 gen_load_fpr64(ctx, fp64, fs);
9499 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
9500 tcg_temp_free_i64(fp64);
9501 gen_store_fpr32(ctx, fp32, fd);
9502 tcg_temp_free_i32(fp32);
9504 break;
9505 case OPC_SEL_D:
9506 check_insn(ctx, ISA_MIPS32R6);
9507 gen_sel_d(ctx, op1, fd, ft, fs);
9508 break;
9509 case OPC_SELEQZ_D:
9510 check_insn(ctx, ISA_MIPS32R6);
9511 gen_sel_d(ctx, op1, fd, ft, fs);
9512 break;
9513 case OPC_SELNEZ_D:
9514 check_insn(ctx, ISA_MIPS32R6);
9515 gen_sel_d(ctx, op1, fd, ft, fs);
9516 break;
9517 case OPC_MOVCF_D:
9518 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9519 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9520 break;
9521 case OPC_MOVZ_D:
9522 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9524 TCGLabel *l1 = gen_new_label();
9525 TCGv_i64 fp0;
9527 if (ft != 0) {
9528 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9530 fp0 = tcg_temp_new_i64();
9531 gen_load_fpr64(ctx, fp0, fs);
9532 gen_store_fpr64(ctx, fp0, fd);
9533 tcg_temp_free_i64(fp0);
9534 gen_set_label(l1);
9536 break;
9537 case OPC_MOVN_D:
9538 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9540 TCGLabel *l1 = gen_new_label();
9541 TCGv_i64 fp0;
9543 if (ft != 0) {
9544 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9545 fp0 = tcg_temp_new_i64();
9546 gen_load_fpr64(ctx, fp0, fs);
9547 gen_store_fpr64(ctx, fp0, fd);
9548 tcg_temp_free_i64(fp0);
9549 gen_set_label(l1);
9552 break;
9553 case OPC_RECIP_D:
9554 check_cp1_registers(ctx, fs | fd);
9556 TCGv_i64 fp0 = tcg_temp_new_i64();
9558 gen_load_fpr64(ctx, fp0, fs);
9559 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9560 gen_store_fpr64(ctx, fp0, fd);
9561 tcg_temp_free_i64(fp0);
9563 break;
9564 case OPC_RSQRT_D:
9565 check_cp1_registers(ctx, fs | fd);
9567 TCGv_i64 fp0 = tcg_temp_new_i64();
9569 gen_load_fpr64(ctx, fp0, fs);
9570 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9571 gen_store_fpr64(ctx, fp0, fd);
9572 tcg_temp_free_i64(fp0);
9574 break;
9575 case OPC_MADDF_D:
9576 check_insn(ctx, ISA_MIPS32R6);
9578 TCGv_i64 fp0 = tcg_temp_new_i64();
9579 TCGv_i64 fp1 = tcg_temp_new_i64();
9580 TCGv_i64 fp2 = tcg_temp_new_i64();
9581 gen_load_fpr64(ctx, fp0, fs);
9582 gen_load_fpr64(ctx, fp1, ft);
9583 gen_load_fpr64(ctx, fp2, fd);
9584 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9585 gen_store_fpr64(ctx, fp2, fd);
9586 tcg_temp_free_i64(fp2);
9587 tcg_temp_free_i64(fp1);
9588 tcg_temp_free_i64(fp0);
9590 break;
9591 case OPC_MSUBF_D:
9592 check_insn(ctx, ISA_MIPS32R6);
9594 TCGv_i64 fp0 = tcg_temp_new_i64();
9595 TCGv_i64 fp1 = tcg_temp_new_i64();
9596 TCGv_i64 fp2 = tcg_temp_new_i64();
9597 gen_load_fpr64(ctx, fp0, fs);
9598 gen_load_fpr64(ctx, fp1, ft);
9599 gen_load_fpr64(ctx, fp2, fd);
9600 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9601 gen_store_fpr64(ctx, fp2, fd);
9602 tcg_temp_free_i64(fp2);
9603 tcg_temp_free_i64(fp1);
9604 tcg_temp_free_i64(fp0);
9606 break;
9607 case OPC_RINT_D:
9608 check_insn(ctx, ISA_MIPS32R6);
9610 TCGv_i64 fp0 = tcg_temp_new_i64();
9611 gen_load_fpr64(ctx, fp0, fs);
9612 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9613 gen_store_fpr64(ctx, fp0, fd);
9614 tcg_temp_free_i64(fp0);
9616 break;
9617 case OPC_CLASS_D:
9618 check_insn(ctx, ISA_MIPS32R6);
9620 TCGv_i64 fp0 = tcg_temp_new_i64();
9621 gen_load_fpr64(ctx, fp0, fs);
9622 gen_helper_float_class_d(fp0, fp0);
9623 gen_store_fpr64(ctx, fp0, fd);
9624 tcg_temp_free_i64(fp0);
9626 break;
9627 case OPC_MIN_D: /* OPC_RECIP2_D */
9628 if (ctx->insn_flags & ISA_MIPS32R6) {
9629 /* OPC_MIN_D */
9630 TCGv_i64 fp0 = tcg_temp_new_i64();
9631 TCGv_i64 fp1 = tcg_temp_new_i64();
9632 gen_load_fpr64(ctx, fp0, fs);
9633 gen_load_fpr64(ctx, fp1, ft);
9634 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9635 gen_store_fpr64(ctx, fp1, fd);
9636 tcg_temp_free_i64(fp1);
9637 tcg_temp_free_i64(fp0);
9638 } else {
9639 /* OPC_RECIP2_D */
9640 check_cp1_64bitmode(ctx);
9642 TCGv_i64 fp0 = tcg_temp_new_i64();
9643 TCGv_i64 fp1 = tcg_temp_new_i64();
9645 gen_load_fpr64(ctx, fp0, fs);
9646 gen_load_fpr64(ctx, fp1, ft);
9647 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9648 tcg_temp_free_i64(fp1);
9649 gen_store_fpr64(ctx, fp0, fd);
9650 tcg_temp_free_i64(fp0);
9653 break;
9654 case OPC_MINA_D: /* OPC_RECIP1_D */
9655 if (ctx->insn_flags & ISA_MIPS32R6) {
9656 /* OPC_MINA_D */
9657 TCGv_i64 fp0 = tcg_temp_new_i64();
9658 TCGv_i64 fp1 = tcg_temp_new_i64();
9659 gen_load_fpr64(ctx, fp0, fs);
9660 gen_load_fpr64(ctx, fp1, ft);
9661 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9662 gen_store_fpr64(ctx, fp1, fd);
9663 tcg_temp_free_i64(fp1);
9664 tcg_temp_free_i64(fp0);
9665 } else {
9666 /* OPC_RECIP1_D */
9667 check_cp1_64bitmode(ctx);
9669 TCGv_i64 fp0 = tcg_temp_new_i64();
9671 gen_load_fpr64(ctx, fp0, fs);
9672 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9673 gen_store_fpr64(ctx, fp0, fd);
9674 tcg_temp_free_i64(fp0);
9677 break;
9678 case OPC_MAX_D: /* OPC_RSQRT1_D */
9679 if (ctx->insn_flags & ISA_MIPS32R6) {
9680 /* OPC_MAX_D */
9681 TCGv_i64 fp0 = tcg_temp_new_i64();
9682 TCGv_i64 fp1 = tcg_temp_new_i64();
9683 gen_load_fpr64(ctx, fp0, fs);
9684 gen_load_fpr64(ctx, fp1, ft);
9685 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9686 gen_store_fpr64(ctx, fp1, fd);
9687 tcg_temp_free_i64(fp1);
9688 tcg_temp_free_i64(fp0);
9689 } else {
9690 /* OPC_RSQRT1_D */
9691 check_cp1_64bitmode(ctx);
9693 TCGv_i64 fp0 = tcg_temp_new_i64();
9695 gen_load_fpr64(ctx, fp0, fs);
9696 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9697 gen_store_fpr64(ctx, fp0, fd);
9698 tcg_temp_free_i64(fp0);
9701 break;
9702 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9703 if (ctx->insn_flags & ISA_MIPS32R6) {
9704 /* OPC_MAXA_D */
9705 TCGv_i64 fp0 = tcg_temp_new_i64();
9706 TCGv_i64 fp1 = tcg_temp_new_i64();
9707 gen_load_fpr64(ctx, fp0, fs);
9708 gen_load_fpr64(ctx, fp1, ft);
9709 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9710 gen_store_fpr64(ctx, fp1, fd);
9711 tcg_temp_free_i64(fp1);
9712 tcg_temp_free_i64(fp0);
9713 } else {
9714 /* OPC_RSQRT2_D */
9715 check_cp1_64bitmode(ctx);
9717 TCGv_i64 fp0 = tcg_temp_new_i64();
9718 TCGv_i64 fp1 = tcg_temp_new_i64();
9720 gen_load_fpr64(ctx, fp0, fs);
9721 gen_load_fpr64(ctx, fp1, ft);
9722 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9723 tcg_temp_free_i64(fp1);
9724 gen_store_fpr64(ctx, fp0, fd);
9725 tcg_temp_free_i64(fp0);
9728 break;
9729 case OPC_CMP_F_D:
9730 case OPC_CMP_UN_D:
9731 case OPC_CMP_EQ_D:
9732 case OPC_CMP_UEQ_D:
9733 case OPC_CMP_OLT_D:
9734 case OPC_CMP_ULT_D:
9735 case OPC_CMP_OLE_D:
9736 case OPC_CMP_ULE_D:
9737 case OPC_CMP_SF_D:
9738 case OPC_CMP_NGLE_D:
9739 case OPC_CMP_SEQ_D:
9740 case OPC_CMP_NGL_D:
9741 case OPC_CMP_LT_D:
9742 case OPC_CMP_NGE_D:
9743 case OPC_CMP_LE_D:
9744 case OPC_CMP_NGT_D:
9745 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9746 if (ctx->opcode & (1 << 6)) {
9747 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9748 } else {
9749 gen_cmp_d(ctx, func-48, ft, fs, cc);
9751 break;
9752 case OPC_CVT_S_D:
9753 check_cp1_registers(ctx, fs);
9755 TCGv_i32 fp32 = tcg_temp_new_i32();
9756 TCGv_i64 fp64 = tcg_temp_new_i64();
9758 gen_load_fpr64(ctx, fp64, fs);
9759 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
9760 tcg_temp_free_i64(fp64);
9761 gen_store_fpr32(ctx, fp32, fd);
9762 tcg_temp_free_i32(fp32);
9764 break;
9765 case OPC_CVT_W_D:
9766 check_cp1_registers(ctx, fs);
9768 TCGv_i32 fp32 = tcg_temp_new_i32();
9769 TCGv_i64 fp64 = tcg_temp_new_i64();
9771 gen_load_fpr64(ctx, fp64, fs);
9772 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
9773 tcg_temp_free_i64(fp64);
9774 gen_store_fpr32(ctx, fp32, fd);
9775 tcg_temp_free_i32(fp32);
9777 break;
9778 case OPC_CVT_L_D:
9779 check_cp1_64bitmode(ctx);
9781 TCGv_i64 fp0 = tcg_temp_new_i64();
9783 gen_load_fpr64(ctx, fp0, fs);
9784 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
9785 gen_store_fpr64(ctx, fp0, fd);
9786 tcg_temp_free_i64(fp0);
9788 break;
9789 case OPC_CVT_S_W:
9791 TCGv_i32 fp0 = tcg_temp_new_i32();
9793 gen_load_fpr32(ctx, fp0, fs);
9794 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
9795 gen_store_fpr32(ctx, fp0, fd);
9796 tcg_temp_free_i32(fp0);
9798 break;
9799 case OPC_CVT_D_W:
9800 check_cp1_registers(ctx, fd);
9802 TCGv_i32 fp32 = tcg_temp_new_i32();
9803 TCGv_i64 fp64 = tcg_temp_new_i64();
9805 gen_load_fpr32(ctx, fp32, fs);
9806 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
9807 tcg_temp_free_i32(fp32);
9808 gen_store_fpr64(ctx, fp64, fd);
9809 tcg_temp_free_i64(fp64);
9811 break;
9812 case OPC_CVT_S_L:
9813 check_cp1_64bitmode(ctx);
9815 TCGv_i32 fp32 = tcg_temp_new_i32();
9816 TCGv_i64 fp64 = tcg_temp_new_i64();
9818 gen_load_fpr64(ctx, fp64, fs);
9819 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
9820 tcg_temp_free_i64(fp64);
9821 gen_store_fpr32(ctx, fp32, fd);
9822 tcg_temp_free_i32(fp32);
9824 break;
9825 case OPC_CVT_D_L:
9826 check_cp1_64bitmode(ctx);
9828 TCGv_i64 fp0 = tcg_temp_new_i64();
9830 gen_load_fpr64(ctx, fp0, fs);
9831 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
9832 gen_store_fpr64(ctx, fp0, fd);
9833 tcg_temp_free_i64(fp0);
9835 break;
9836 case OPC_CVT_PS_PW:
9837 check_ps(ctx);
9839 TCGv_i64 fp0 = tcg_temp_new_i64();
9841 gen_load_fpr64(ctx, fp0, fs);
9842 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
9843 gen_store_fpr64(ctx, fp0, fd);
9844 tcg_temp_free_i64(fp0);
9846 break;
9847 case OPC_ADD_PS:
9848 check_ps(ctx);
9850 TCGv_i64 fp0 = tcg_temp_new_i64();
9851 TCGv_i64 fp1 = tcg_temp_new_i64();
9853 gen_load_fpr64(ctx, fp0, fs);
9854 gen_load_fpr64(ctx, fp1, ft);
9855 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
9856 tcg_temp_free_i64(fp1);
9857 gen_store_fpr64(ctx, fp0, fd);
9858 tcg_temp_free_i64(fp0);
9860 break;
9861 case OPC_SUB_PS:
9862 check_ps(ctx);
9864 TCGv_i64 fp0 = tcg_temp_new_i64();
9865 TCGv_i64 fp1 = tcg_temp_new_i64();
9867 gen_load_fpr64(ctx, fp0, fs);
9868 gen_load_fpr64(ctx, fp1, ft);
9869 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
9870 tcg_temp_free_i64(fp1);
9871 gen_store_fpr64(ctx, fp0, fd);
9872 tcg_temp_free_i64(fp0);
9874 break;
9875 case OPC_MUL_PS:
9876 check_ps(ctx);
9878 TCGv_i64 fp0 = tcg_temp_new_i64();
9879 TCGv_i64 fp1 = tcg_temp_new_i64();
9881 gen_load_fpr64(ctx, fp0, fs);
9882 gen_load_fpr64(ctx, fp1, ft);
9883 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
9884 tcg_temp_free_i64(fp1);
9885 gen_store_fpr64(ctx, fp0, fd);
9886 tcg_temp_free_i64(fp0);
9888 break;
9889 case OPC_ABS_PS:
9890 check_ps(ctx);
9892 TCGv_i64 fp0 = tcg_temp_new_i64();
9894 gen_load_fpr64(ctx, fp0, fs);
9895 gen_helper_float_abs_ps(fp0, fp0);
9896 gen_store_fpr64(ctx, fp0, fd);
9897 tcg_temp_free_i64(fp0);
9899 break;
9900 case OPC_MOV_PS:
9901 check_ps(ctx);
9903 TCGv_i64 fp0 = tcg_temp_new_i64();
9905 gen_load_fpr64(ctx, fp0, fs);
9906 gen_store_fpr64(ctx, fp0, fd);
9907 tcg_temp_free_i64(fp0);
9909 break;
9910 case OPC_NEG_PS:
9911 check_ps(ctx);
9913 TCGv_i64 fp0 = tcg_temp_new_i64();
9915 gen_load_fpr64(ctx, fp0, fs);
9916 gen_helper_float_chs_ps(fp0, fp0);
9917 gen_store_fpr64(ctx, fp0, fd);
9918 tcg_temp_free_i64(fp0);
9920 break;
9921 case OPC_MOVCF_PS:
9922 check_ps(ctx);
9923 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9924 break;
9925 case OPC_MOVZ_PS:
9926 check_ps(ctx);
9928 TCGLabel *l1 = gen_new_label();
9929 TCGv_i64 fp0;
9931 if (ft != 0)
9932 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9933 fp0 = tcg_temp_new_i64();
9934 gen_load_fpr64(ctx, fp0, fs);
9935 gen_store_fpr64(ctx, fp0, fd);
9936 tcg_temp_free_i64(fp0);
9937 gen_set_label(l1);
9939 break;
9940 case OPC_MOVN_PS:
9941 check_ps(ctx);
9943 TCGLabel *l1 = gen_new_label();
9944 TCGv_i64 fp0;
9946 if (ft != 0) {
9947 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9948 fp0 = tcg_temp_new_i64();
9949 gen_load_fpr64(ctx, fp0, fs);
9950 gen_store_fpr64(ctx, fp0, fd);
9951 tcg_temp_free_i64(fp0);
9952 gen_set_label(l1);
9955 break;
9956 case OPC_ADDR_PS:
9957 check_ps(ctx);
9959 TCGv_i64 fp0 = tcg_temp_new_i64();
9960 TCGv_i64 fp1 = tcg_temp_new_i64();
9962 gen_load_fpr64(ctx, fp0, ft);
9963 gen_load_fpr64(ctx, fp1, fs);
9964 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
9965 tcg_temp_free_i64(fp1);
9966 gen_store_fpr64(ctx, fp0, fd);
9967 tcg_temp_free_i64(fp0);
9969 break;
9970 case OPC_MULR_PS:
9971 check_ps(ctx);
9973 TCGv_i64 fp0 = tcg_temp_new_i64();
9974 TCGv_i64 fp1 = tcg_temp_new_i64();
9976 gen_load_fpr64(ctx, fp0, ft);
9977 gen_load_fpr64(ctx, fp1, fs);
9978 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
9979 tcg_temp_free_i64(fp1);
9980 gen_store_fpr64(ctx, fp0, fd);
9981 tcg_temp_free_i64(fp0);
9983 break;
9984 case OPC_RECIP2_PS:
9985 check_ps(ctx);
9987 TCGv_i64 fp0 = tcg_temp_new_i64();
9988 TCGv_i64 fp1 = tcg_temp_new_i64();
9990 gen_load_fpr64(ctx, fp0, fs);
9991 gen_load_fpr64(ctx, fp1, ft);
9992 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
9993 tcg_temp_free_i64(fp1);
9994 gen_store_fpr64(ctx, fp0, fd);
9995 tcg_temp_free_i64(fp0);
9997 break;
9998 case OPC_RECIP1_PS:
9999 check_ps(ctx);
10001 TCGv_i64 fp0 = tcg_temp_new_i64();
10003 gen_load_fpr64(ctx, fp0, fs);
10004 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
10005 gen_store_fpr64(ctx, fp0, fd);
10006 tcg_temp_free_i64(fp0);
10008 break;
10009 case OPC_RSQRT1_PS:
10010 check_ps(ctx);
10012 TCGv_i64 fp0 = tcg_temp_new_i64();
10014 gen_load_fpr64(ctx, fp0, fs);
10015 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
10016 gen_store_fpr64(ctx, fp0, fd);
10017 tcg_temp_free_i64(fp0);
10019 break;
10020 case OPC_RSQRT2_PS:
10021 check_ps(ctx);
10023 TCGv_i64 fp0 = tcg_temp_new_i64();
10024 TCGv_i64 fp1 = tcg_temp_new_i64();
10026 gen_load_fpr64(ctx, fp0, fs);
10027 gen_load_fpr64(ctx, fp1, ft);
10028 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
10029 tcg_temp_free_i64(fp1);
10030 gen_store_fpr64(ctx, fp0, fd);
10031 tcg_temp_free_i64(fp0);
10033 break;
10034 case OPC_CVT_S_PU:
10035 check_cp1_64bitmode(ctx);
10037 TCGv_i32 fp0 = tcg_temp_new_i32();
10039 gen_load_fpr32h(ctx, fp0, fs);
10040 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
10041 gen_store_fpr32(ctx, fp0, fd);
10042 tcg_temp_free_i32(fp0);
10044 break;
10045 case OPC_CVT_PW_PS:
10046 check_ps(ctx);
10048 TCGv_i64 fp0 = tcg_temp_new_i64();
10050 gen_load_fpr64(ctx, fp0, fs);
10051 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
10052 gen_store_fpr64(ctx, fp0, fd);
10053 tcg_temp_free_i64(fp0);
10055 break;
10056 case OPC_CVT_S_PL:
10057 check_cp1_64bitmode(ctx);
10059 TCGv_i32 fp0 = tcg_temp_new_i32();
10061 gen_load_fpr32(ctx, fp0, fs);
10062 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10063 gen_store_fpr32(ctx, fp0, fd);
10064 tcg_temp_free_i32(fp0);
10066 break;
10067 case OPC_PLL_PS:
10068 check_ps(ctx);
10070 TCGv_i32 fp0 = tcg_temp_new_i32();
10071 TCGv_i32 fp1 = tcg_temp_new_i32();
10073 gen_load_fpr32(ctx, fp0, fs);
10074 gen_load_fpr32(ctx, fp1, ft);
10075 gen_store_fpr32h(ctx, fp0, fd);
10076 gen_store_fpr32(ctx, fp1, fd);
10077 tcg_temp_free_i32(fp0);
10078 tcg_temp_free_i32(fp1);
10080 break;
10081 case OPC_PLU_PS:
10082 check_ps(ctx);
10084 TCGv_i32 fp0 = tcg_temp_new_i32();
10085 TCGv_i32 fp1 = tcg_temp_new_i32();
10087 gen_load_fpr32(ctx, fp0, fs);
10088 gen_load_fpr32h(ctx, fp1, ft);
10089 gen_store_fpr32(ctx, fp1, fd);
10090 gen_store_fpr32h(ctx, fp0, fd);
10091 tcg_temp_free_i32(fp0);
10092 tcg_temp_free_i32(fp1);
10094 break;
10095 case OPC_PUL_PS:
10096 check_ps(ctx);
10098 TCGv_i32 fp0 = tcg_temp_new_i32();
10099 TCGv_i32 fp1 = tcg_temp_new_i32();
10101 gen_load_fpr32h(ctx, fp0, fs);
10102 gen_load_fpr32(ctx, fp1, ft);
10103 gen_store_fpr32(ctx, fp1, fd);
10104 gen_store_fpr32h(ctx, fp0, fd);
10105 tcg_temp_free_i32(fp0);
10106 tcg_temp_free_i32(fp1);
10108 break;
10109 case OPC_PUU_PS:
10110 check_ps(ctx);
10112 TCGv_i32 fp0 = tcg_temp_new_i32();
10113 TCGv_i32 fp1 = tcg_temp_new_i32();
10115 gen_load_fpr32h(ctx, fp0, fs);
10116 gen_load_fpr32h(ctx, fp1, ft);
10117 gen_store_fpr32(ctx, fp1, fd);
10118 gen_store_fpr32h(ctx, fp0, fd);
10119 tcg_temp_free_i32(fp0);
10120 tcg_temp_free_i32(fp1);
10122 break;
10123 case OPC_CMP_F_PS:
10124 case OPC_CMP_UN_PS:
10125 case OPC_CMP_EQ_PS:
10126 case OPC_CMP_UEQ_PS:
10127 case OPC_CMP_OLT_PS:
10128 case OPC_CMP_ULT_PS:
10129 case OPC_CMP_OLE_PS:
10130 case OPC_CMP_ULE_PS:
10131 case OPC_CMP_SF_PS:
10132 case OPC_CMP_NGLE_PS:
10133 case OPC_CMP_SEQ_PS:
10134 case OPC_CMP_NGL_PS:
10135 case OPC_CMP_LT_PS:
10136 case OPC_CMP_NGE_PS:
10137 case OPC_CMP_LE_PS:
10138 case OPC_CMP_NGT_PS:
10139 if (ctx->opcode & (1 << 6)) {
10140 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10141 } else {
10142 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10144 break;
10145 default:
10146 MIPS_INVAL("farith");
10147 generate_exception_end(ctx, EXCP_RI);
10148 return;
10152 /* Coprocessor 3 (FPU) */
10153 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10154 int fd, int fs, int base, int index)
10156 TCGv t0 = tcg_temp_new();
10158 if (base == 0) {
10159 gen_load_gpr(t0, index);
10160 } else if (index == 0) {
10161 gen_load_gpr(t0, base);
10162 } else {
10163 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10165 /* Don't do NOP if destination is zero: we must perform the actual
10166 memory access. */
10167 switch (opc) {
10168 case OPC_LWXC1:
10169 check_cop1x(ctx);
10171 TCGv_i32 fp0 = tcg_temp_new_i32();
10173 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10174 tcg_gen_trunc_tl_i32(fp0, t0);
10175 gen_store_fpr32(ctx, fp0, fd);
10176 tcg_temp_free_i32(fp0);
10178 break;
10179 case OPC_LDXC1:
10180 check_cop1x(ctx);
10181 check_cp1_registers(ctx, fd);
10183 TCGv_i64 fp0 = tcg_temp_new_i64();
10184 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10185 gen_store_fpr64(ctx, fp0, fd);
10186 tcg_temp_free_i64(fp0);
10188 break;
10189 case OPC_LUXC1:
10190 check_cp1_64bitmode(ctx);
10191 tcg_gen_andi_tl(t0, t0, ~0x7);
10193 TCGv_i64 fp0 = tcg_temp_new_i64();
10195 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10196 gen_store_fpr64(ctx, fp0, fd);
10197 tcg_temp_free_i64(fp0);
10199 break;
10200 case OPC_SWXC1:
10201 check_cop1x(ctx);
10203 TCGv_i32 fp0 = tcg_temp_new_i32();
10204 gen_load_fpr32(ctx, fp0, fs);
10205 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10206 tcg_temp_free_i32(fp0);
10208 break;
10209 case OPC_SDXC1:
10210 check_cop1x(ctx);
10211 check_cp1_registers(ctx, fs);
10213 TCGv_i64 fp0 = tcg_temp_new_i64();
10214 gen_load_fpr64(ctx, fp0, fs);
10215 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10216 tcg_temp_free_i64(fp0);
10218 break;
10219 case OPC_SUXC1:
10220 check_cp1_64bitmode(ctx);
10221 tcg_gen_andi_tl(t0, t0, ~0x7);
10223 TCGv_i64 fp0 = tcg_temp_new_i64();
10224 gen_load_fpr64(ctx, fp0, fs);
10225 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10226 tcg_temp_free_i64(fp0);
10228 break;
10230 tcg_temp_free(t0);
10233 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10234 int fd, int fr, int fs, int ft)
10236 switch (opc) {
10237 case OPC_ALNV_PS:
10238 check_ps(ctx);
10240 TCGv t0 = tcg_temp_local_new();
10241 TCGv_i32 fp = tcg_temp_new_i32();
10242 TCGv_i32 fph = tcg_temp_new_i32();
10243 TCGLabel *l1 = gen_new_label();
10244 TCGLabel *l2 = gen_new_label();
10246 gen_load_gpr(t0, fr);
10247 tcg_gen_andi_tl(t0, t0, 0x7);
10249 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10250 gen_load_fpr32(ctx, fp, fs);
10251 gen_load_fpr32h(ctx, fph, fs);
10252 gen_store_fpr32(ctx, fp, fd);
10253 gen_store_fpr32h(ctx, fph, fd);
10254 tcg_gen_br(l2);
10255 gen_set_label(l1);
10256 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10257 tcg_temp_free(t0);
10258 #ifdef TARGET_WORDS_BIGENDIAN
10259 gen_load_fpr32(ctx, fp, fs);
10260 gen_load_fpr32h(ctx, fph, ft);
10261 gen_store_fpr32h(ctx, fp, fd);
10262 gen_store_fpr32(ctx, fph, fd);
10263 #else
10264 gen_load_fpr32h(ctx, fph, fs);
10265 gen_load_fpr32(ctx, fp, ft);
10266 gen_store_fpr32(ctx, fph, fd);
10267 gen_store_fpr32h(ctx, fp, fd);
10268 #endif
10269 gen_set_label(l2);
10270 tcg_temp_free_i32(fp);
10271 tcg_temp_free_i32(fph);
10273 break;
10274 case OPC_MADD_S:
10275 check_cop1x(ctx);
10277 TCGv_i32 fp0 = tcg_temp_new_i32();
10278 TCGv_i32 fp1 = tcg_temp_new_i32();
10279 TCGv_i32 fp2 = tcg_temp_new_i32();
10281 gen_load_fpr32(ctx, fp0, fs);
10282 gen_load_fpr32(ctx, fp1, ft);
10283 gen_load_fpr32(ctx, fp2, fr);
10284 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10285 tcg_temp_free_i32(fp0);
10286 tcg_temp_free_i32(fp1);
10287 gen_store_fpr32(ctx, fp2, fd);
10288 tcg_temp_free_i32(fp2);
10290 break;
10291 case OPC_MADD_D:
10292 check_cop1x(ctx);
10293 check_cp1_registers(ctx, fd | fs | ft | fr);
10295 TCGv_i64 fp0 = tcg_temp_new_i64();
10296 TCGv_i64 fp1 = tcg_temp_new_i64();
10297 TCGv_i64 fp2 = tcg_temp_new_i64();
10299 gen_load_fpr64(ctx, fp0, fs);
10300 gen_load_fpr64(ctx, fp1, ft);
10301 gen_load_fpr64(ctx, fp2, fr);
10302 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10303 tcg_temp_free_i64(fp0);
10304 tcg_temp_free_i64(fp1);
10305 gen_store_fpr64(ctx, fp2, fd);
10306 tcg_temp_free_i64(fp2);
10308 break;
10309 case OPC_MADD_PS:
10310 check_ps(ctx);
10312 TCGv_i64 fp0 = tcg_temp_new_i64();
10313 TCGv_i64 fp1 = tcg_temp_new_i64();
10314 TCGv_i64 fp2 = tcg_temp_new_i64();
10316 gen_load_fpr64(ctx, fp0, fs);
10317 gen_load_fpr64(ctx, fp1, ft);
10318 gen_load_fpr64(ctx, fp2, fr);
10319 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10320 tcg_temp_free_i64(fp0);
10321 tcg_temp_free_i64(fp1);
10322 gen_store_fpr64(ctx, fp2, fd);
10323 tcg_temp_free_i64(fp2);
10325 break;
10326 case OPC_MSUB_S:
10327 check_cop1x(ctx);
10329 TCGv_i32 fp0 = tcg_temp_new_i32();
10330 TCGv_i32 fp1 = tcg_temp_new_i32();
10331 TCGv_i32 fp2 = tcg_temp_new_i32();
10333 gen_load_fpr32(ctx, fp0, fs);
10334 gen_load_fpr32(ctx, fp1, ft);
10335 gen_load_fpr32(ctx, fp2, fr);
10336 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10337 tcg_temp_free_i32(fp0);
10338 tcg_temp_free_i32(fp1);
10339 gen_store_fpr32(ctx, fp2, fd);
10340 tcg_temp_free_i32(fp2);
10342 break;
10343 case OPC_MSUB_D:
10344 check_cop1x(ctx);
10345 check_cp1_registers(ctx, fd | fs | ft | fr);
10347 TCGv_i64 fp0 = tcg_temp_new_i64();
10348 TCGv_i64 fp1 = tcg_temp_new_i64();
10349 TCGv_i64 fp2 = tcg_temp_new_i64();
10351 gen_load_fpr64(ctx, fp0, fs);
10352 gen_load_fpr64(ctx, fp1, ft);
10353 gen_load_fpr64(ctx, fp2, fr);
10354 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10355 tcg_temp_free_i64(fp0);
10356 tcg_temp_free_i64(fp1);
10357 gen_store_fpr64(ctx, fp2, fd);
10358 tcg_temp_free_i64(fp2);
10360 break;
10361 case OPC_MSUB_PS:
10362 check_ps(ctx);
10364 TCGv_i64 fp0 = tcg_temp_new_i64();
10365 TCGv_i64 fp1 = tcg_temp_new_i64();
10366 TCGv_i64 fp2 = tcg_temp_new_i64();
10368 gen_load_fpr64(ctx, fp0, fs);
10369 gen_load_fpr64(ctx, fp1, ft);
10370 gen_load_fpr64(ctx, fp2, fr);
10371 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10372 tcg_temp_free_i64(fp0);
10373 tcg_temp_free_i64(fp1);
10374 gen_store_fpr64(ctx, fp2, fd);
10375 tcg_temp_free_i64(fp2);
10377 break;
10378 case OPC_NMADD_S:
10379 check_cop1x(ctx);
10381 TCGv_i32 fp0 = tcg_temp_new_i32();
10382 TCGv_i32 fp1 = tcg_temp_new_i32();
10383 TCGv_i32 fp2 = tcg_temp_new_i32();
10385 gen_load_fpr32(ctx, fp0, fs);
10386 gen_load_fpr32(ctx, fp1, ft);
10387 gen_load_fpr32(ctx, fp2, fr);
10388 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10389 tcg_temp_free_i32(fp0);
10390 tcg_temp_free_i32(fp1);
10391 gen_store_fpr32(ctx, fp2, fd);
10392 tcg_temp_free_i32(fp2);
10394 break;
10395 case OPC_NMADD_D:
10396 check_cop1x(ctx);
10397 check_cp1_registers(ctx, fd | fs | ft | fr);
10399 TCGv_i64 fp0 = tcg_temp_new_i64();
10400 TCGv_i64 fp1 = tcg_temp_new_i64();
10401 TCGv_i64 fp2 = tcg_temp_new_i64();
10403 gen_load_fpr64(ctx, fp0, fs);
10404 gen_load_fpr64(ctx, fp1, ft);
10405 gen_load_fpr64(ctx, fp2, fr);
10406 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10407 tcg_temp_free_i64(fp0);
10408 tcg_temp_free_i64(fp1);
10409 gen_store_fpr64(ctx, fp2, fd);
10410 tcg_temp_free_i64(fp2);
10412 break;
10413 case OPC_NMADD_PS:
10414 check_ps(ctx);
10416 TCGv_i64 fp0 = tcg_temp_new_i64();
10417 TCGv_i64 fp1 = tcg_temp_new_i64();
10418 TCGv_i64 fp2 = tcg_temp_new_i64();
10420 gen_load_fpr64(ctx, fp0, fs);
10421 gen_load_fpr64(ctx, fp1, ft);
10422 gen_load_fpr64(ctx, fp2, fr);
10423 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10424 tcg_temp_free_i64(fp0);
10425 tcg_temp_free_i64(fp1);
10426 gen_store_fpr64(ctx, fp2, fd);
10427 tcg_temp_free_i64(fp2);
10429 break;
10430 case OPC_NMSUB_S:
10431 check_cop1x(ctx);
10433 TCGv_i32 fp0 = tcg_temp_new_i32();
10434 TCGv_i32 fp1 = tcg_temp_new_i32();
10435 TCGv_i32 fp2 = tcg_temp_new_i32();
10437 gen_load_fpr32(ctx, fp0, fs);
10438 gen_load_fpr32(ctx, fp1, ft);
10439 gen_load_fpr32(ctx, fp2, fr);
10440 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10441 tcg_temp_free_i32(fp0);
10442 tcg_temp_free_i32(fp1);
10443 gen_store_fpr32(ctx, fp2, fd);
10444 tcg_temp_free_i32(fp2);
10446 break;
10447 case OPC_NMSUB_D:
10448 check_cop1x(ctx);
10449 check_cp1_registers(ctx, fd | fs | ft | fr);
10451 TCGv_i64 fp0 = tcg_temp_new_i64();
10452 TCGv_i64 fp1 = tcg_temp_new_i64();
10453 TCGv_i64 fp2 = tcg_temp_new_i64();
10455 gen_load_fpr64(ctx, fp0, fs);
10456 gen_load_fpr64(ctx, fp1, ft);
10457 gen_load_fpr64(ctx, fp2, fr);
10458 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10459 tcg_temp_free_i64(fp0);
10460 tcg_temp_free_i64(fp1);
10461 gen_store_fpr64(ctx, fp2, fd);
10462 tcg_temp_free_i64(fp2);
10464 break;
10465 case OPC_NMSUB_PS:
10466 check_ps(ctx);
10468 TCGv_i64 fp0 = tcg_temp_new_i64();
10469 TCGv_i64 fp1 = tcg_temp_new_i64();
10470 TCGv_i64 fp2 = tcg_temp_new_i64();
10472 gen_load_fpr64(ctx, fp0, fs);
10473 gen_load_fpr64(ctx, fp1, ft);
10474 gen_load_fpr64(ctx, fp2, fr);
10475 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10476 tcg_temp_free_i64(fp0);
10477 tcg_temp_free_i64(fp1);
10478 gen_store_fpr64(ctx, fp2, fd);
10479 tcg_temp_free_i64(fp2);
10481 break;
10482 default:
10483 MIPS_INVAL("flt3_arith");
10484 generate_exception_end(ctx, EXCP_RI);
10485 return;
10489 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
10491 TCGv t0;
10493 #if !defined(CONFIG_USER_ONLY)
10494 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10495 Therefore only check the ISA in system mode. */
10496 check_insn(ctx, ISA_MIPS32R2);
10497 #endif
10498 t0 = tcg_temp_new();
10500 switch (rd) {
10501 case 0:
10502 gen_helper_rdhwr_cpunum(t0, cpu_env);
10503 gen_store_gpr(t0, rt);
10504 break;
10505 case 1:
10506 gen_helper_rdhwr_synci_step(t0, cpu_env);
10507 gen_store_gpr(t0, rt);
10508 break;
10509 case 2:
10510 gen_helper_rdhwr_cc(t0, cpu_env);
10511 gen_store_gpr(t0, rt);
10512 break;
10513 case 3:
10514 gen_helper_rdhwr_ccres(t0, cpu_env);
10515 gen_store_gpr(t0, rt);
10516 break;
10517 case 4:
10518 check_insn(ctx, ISA_MIPS32R6);
10519 if (sel != 0) {
10520 /* Performance counter registers are not implemented other than
10521 * control register 0.
10523 generate_exception(ctx, EXCP_RI);
10525 gen_helper_rdhwr_performance(t0, cpu_env);
10526 gen_store_gpr(t0, rt);
10527 break;
10528 case 5:
10529 check_insn(ctx, ISA_MIPS32R6);
10530 gen_helper_rdhwr_xnp(t0, cpu_env);
10531 gen_store_gpr(t0, rt);
10532 break;
10533 case 29:
10534 #if defined(CONFIG_USER_ONLY)
10535 tcg_gen_ld_tl(t0, cpu_env,
10536 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10537 gen_store_gpr(t0, rt);
10538 break;
10539 #else
10540 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10541 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10542 tcg_gen_ld_tl(t0, cpu_env,
10543 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10544 gen_store_gpr(t0, rt);
10545 } else {
10546 generate_exception_end(ctx, EXCP_RI);
10548 break;
10549 #endif
10550 default: /* Invalid */
10551 MIPS_INVAL("rdhwr");
10552 generate_exception_end(ctx, EXCP_RI);
10553 break;
10555 tcg_temp_free(t0);
10558 static inline void clear_branch_hflags(DisasContext *ctx)
10560 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10561 if (ctx->bstate == BS_NONE) {
10562 save_cpu_state(ctx, 0);
10563 } else {
10564 /* it is not safe to save ctx->hflags as hflags may be changed
10565 in execution time by the instruction in delay / forbidden slot. */
10566 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10570 static void gen_branch(DisasContext *ctx, int insn_bytes)
10572 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10573 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10574 /* Branches completion */
10575 clear_branch_hflags(ctx);
10576 ctx->bstate = BS_BRANCH;
10577 /* FIXME: Need to clear can_do_io. */
10578 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10579 case MIPS_HFLAG_FBNSLOT:
10580 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10581 break;
10582 case MIPS_HFLAG_B:
10583 /* unconditional branch */
10584 if (proc_hflags & MIPS_HFLAG_BX) {
10585 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10587 gen_goto_tb(ctx, 0, ctx->btarget);
10588 break;
10589 case MIPS_HFLAG_BL:
10590 /* blikely taken case */
10591 gen_goto_tb(ctx, 0, ctx->btarget);
10592 break;
10593 case MIPS_HFLAG_BC:
10594 /* Conditional branch */
10596 TCGLabel *l1 = gen_new_label();
10598 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10599 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10600 gen_set_label(l1);
10601 gen_goto_tb(ctx, 0, ctx->btarget);
10603 break;
10604 case MIPS_HFLAG_BR:
10605 /* unconditional branch to register */
10606 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10607 TCGv t0 = tcg_temp_new();
10608 TCGv_i32 t1 = tcg_temp_new_i32();
10610 tcg_gen_andi_tl(t0, btarget, 0x1);
10611 tcg_gen_trunc_tl_i32(t1, t0);
10612 tcg_temp_free(t0);
10613 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10614 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10615 tcg_gen_or_i32(hflags, hflags, t1);
10616 tcg_temp_free_i32(t1);
10618 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10619 } else {
10620 tcg_gen_mov_tl(cpu_PC, btarget);
10622 if (ctx->singlestep_enabled) {
10623 save_cpu_state(ctx, 0);
10624 gen_helper_raise_exception_debug(cpu_env);
10626 tcg_gen_exit_tb(0);
10627 break;
10628 default:
10629 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
10630 abort();
10635 /* Compact Branches */
10636 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
10637 int rs, int rt, int32_t offset)
10639 int bcond_compute = 0;
10640 TCGv t0 = tcg_temp_new();
10641 TCGv t1 = tcg_temp_new();
10642 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
10644 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10645 #ifdef MIPS_DEBUG_DISAS
10646 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10647 "\n", ctx->pc);
10648 #endif
10649 generate_exception_end(ctx, EXCP_RI);
10650 goto out;
10653 /* Load needed operands and calculate btarget */
10654 switch (opc) {
10655 /* compact branch */
10656 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10657 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10658 gen_load_gpr(t0, rs);
10659 gen_load_gpr(t1, rt);
10660 bcond_compute = 1;
10661 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10662 if (rs <= rt && rs == 0) {
10663 /* OPC_BEQZALC, OPC_BNEZALC */
10664 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10666 break;
10667 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10668 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10669 gen_load_gpr(t0, rs);
10670 gen_load_gpr(t1, rt);
10671 bcond_compute = 1;
10672 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10673 break;
10674 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10675 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10676 if (rs == 0 || rs == rt) {
10677 /* OPC_BLEZALC, OPC_BGEZALC */
10678 /* OPC_BGTZALC, OPC_BLTZALC */
10679 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10681 gen_load_gpr(t0, rs);
10682 gen_load_gpr(t1, rt);
10683 bcond_compute = 1;
10684 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10685 break;
10686 case OPC_BC:
10687 case OPC_BALC:
10688 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10689 break;
10690 case OPC_BEQZC:
10691 case OPC_BNEZC:
10692 if (rs != 0) {
10693 /* OPC_BEQZC, OPC_BNEZC */
10694 gen_load_gpr(t0, rs);
10695 bcond_compute = 1;
10696 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10697 } else {
10698 /* OPC_JIC, OPC_JIALC */
10699 TCGv tbase = tcg_temp_new();
10700 TCGv toffset = tcg_temp_new();
10702 gen_load_gpr(tbase, rt);
10703 tcg_gen_movi_tl(toffset, offset);
10704 gen_op_addr_add(ctx, btarget, tbase, toffset);
10705 tcg_temp_free(tbase);
10706 tcg_temp_free(toffset);
10708 break;
10709 default:
10710 MIPS_INVAL("Compact branch/jump");
10711 generate_exception_end(ctx, EXCP_RI);
10712 goto out;
10715 if (bcond_compute == 0) {
10716 /* Uncoditional compact branch */
10717 switch (opc) {
10718 case OPC_JIALC:
10719 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10720 /* Fallthrough */
10721 case OPC_JIC:
10722 ctx->hflags |= MIPS_HFLAG_BR;
10723 break;
10724 case OPC_BALC:
10725 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10726 /* Fallthrough */
10727 case OPC_BC:
10728 ctx->hflags |= MIPS_HFLAG_B;
10729 break;
10730 default:
10731 MIPS_INVAL("Compact branch/jump");
10732 generate_exception_end(ctx, EXCP_RI);
10733 goto out;
10736 /* Generating branch here as compact branches don't have delay slot */
10737 gen_branch(ctx, 4);
10738 } else {
10739 /* Conditional compact branch */
10740 TCGLabel *fs = gen_new_label();
10741 save_cpu_state(ctx, 0);
10743 switch (opc) {
10744 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10745 if (rs == 0 && rt != 0) {
10746 /* OPC_BLEZALC */
10747 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10748 } else if (rs != 0 && rt != 0 && rs == rt) {
10749 /* OPC_BGEZALC */
10750 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10751 } else {
10752 /* OPC_BGEUC */
10753 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
10755 break;
10756 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10757 if (rs == 0 && rt != 0) {
10758 /* OPC_BGTZALC */
10759 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10760 } else if (rs != 0 && rt != 0 && rs == rt) {
10761 /* OPC_BLTZALC */
10762 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10763 } else {
10764 /* OPC_BLTUC */
10765 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
10767 break;
10768 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10769 if (rs == 0 && rt != 0) {
10770 /* OPC_BLEZC */
10771 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10772 } else if (rs != 0 && rt != 0 && rs == rt) {
10773 /* OPC_BGEZC */
10774 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10775 } else {
10776 /* OPC_BGEC */
10777 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
10779 break;
10780 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10781 if (rs == 0 && rt != 0) {
10782 /* OPC_BGTZC */
10783 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10784 } else if (rs != 0 && rt != 0 && rs == rt) {
10785 /* OPC_BLTZC */
10786 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10787 } else {
10788 /* OPC_BLTC */
10789 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
10791 break;
10792 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10793 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10794 if (rs >= rt) {
10795 /* OPC_BOVC, OPC_BNVC */
10796 TCGv t2 = tcg_temp_new();
10797 TCGv t3 = tcg_temp_new();
10798 TCGv t4 = tcg_temp_new();
10799 TCGv input_overflow = tcg_temp_new();
10801 gen_load_gpr(t0, rs);
10802 gen_load_gpr(t1, rt);
10803 tcg_gen_ext32s_tl(t2, t0);
10804 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
10805 tcg_gen_ext32s_tl(t3, t1);
10806 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
10807 tcg_gen_or_tl(input_overflow, input_overflow, t4);
10809 tcg_gen_add_tl(t4, t2, t3);
10810 tcg_gen_ext32s_tl(t4, t4);
10811 tcg_gen_xor_tl(t2, t2, t3);
10812 tcg_gen_xor_tl(t3, t4, t3);
10813 tcg_gen_andc_tl(t2, t3, t2);
10814 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
10815 tcg_gen_or_tl(t4, t4, input_overflow);
10816 if (opc == OPC_BOVC) {
10817 /* OPC_BOVC */
10818 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
10819 } else {
10820 /* OPC_BNVC */
10821 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
10823 tcg_temp_free(input_overflow);
10824 tcg_temp_free(t4);
10825 tcg_temp_free(t3);
10826 tcg_temp_free(t2);
10827 } else if (rs < rt && rs == 0) {
10828 /* OPC_BEQZALC, OPC_BNEZALC */
10829 if (opc == OPC_BEQZALC) {
10830 /* OPC_BEQZALC */
10831 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
10832 } else {
10833 /* OPC_BNEZALC */
10834 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
10836 } else {
10837 /* OPC_BEQC, OPC_BNEC */
10838 if (opc == OPC_BEQC) {
10839 /* OPC_BEQC */
10840 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
10841 } else {
10842 /* OPC_BNEC */
10843 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
10846 break;
10847 case OPC_BEQZC:
10848 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
10849 break;
10850 case OPC_BNEZC:
10851 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
10852 break;
10853 default:
10854 MIPS_INVAL("Compact conditional branch/jump");
10855 generate_exception_end(ctx, EXCP_RI);
10856 goto out;
10859 /* Generating branch here as compact branches don't have delay slot */
10860 gen_goto_tb(ctx, 1, ctx->btarget);
10861 gen_set_label(fs);
10863 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
10866 out:
10867 tcg_temp_free(t0);
10868 tcg_temp_free(t1);
10871 /* ISA extensions (ASEs) */
10872 /* MIPS16 extension to MIPS32 */
10874 /* MIPS16 major opcodes */
10875 enum {
10876 M16_OPC_ADDIUSP = 0x00,
10877 M16_OPC_ADDIUPC = 0x01,
10878 M16_OPC_B = 0x02,
10879 M16_OPC_JAL = 0x03,
10880 M16_OPC_BEQZ = 0x04,
10881 M16_OPC_BNEQZ = 0x05,
10882 M16_OPC_SHIFT = 0x06,
10883 M16_OPC_LD = 0x07,
10884 M16_OPC_RRIA = 0x08,
10885 M16_OPC_ADDIU8 = 0x09,
10886 M16_OPC_SLTI = 0x0a,
10887 M16_OPC_SLTIU = 0x0b,
10888 M16_OPC_I8 = 0x0c,
10889 M16_OPC_LI = 0x0d,
10890 M16_OPC_CMPI = 0x0e,
10891 M16_OPC_SD = 0x0f,
10892 M16_OPC_LB = 0x10,
10893 M16_OPC_LH = 0x11,
10894 M16_OPC_LWSP = 0x12,
10895 M16_OPC_LW = 0x13,
10896 M16_OPC_LBU = 0x14,
10897 M16_OPC_LHU = 0x15,
10898 M16_OPC_LWPC = 0x16,
10899 M16_OPC_LWU = 0x17,
10900 M16_OPC_SB = 0x18,
10901 M16_OPC_SH = 0x19,
10902 M16_OPC_SWSP = 0x1a,
10903 M16_OPC_SW = 0x1b,
10904 M16_OPC_RRR = 0x1c,
10905 M16_OPC_RR = 0x1d,
10906 M16_OPC_EXTEND = 0x1e,
10907 M16_OPC_I64 = 0x1f
10910 /* I8 funct field */
10911 enum {
10912 I8_BTEQZ = 0x0,
10913 I8_BTNEZ = 0x1,
10914 I8_SWRASP = 0x2,
10915 I8_ADJSP = 0x3,
10916 I8_SVRS = 0x4,
10917 I8_MOV32R = 0x5,
10918 I8_MOVR32 = 0x7
10921 /* RRR f field */
10922 enum {
10923 RRR_DADDU = 0x0,
10924 RRR_ADDU = 0x1,
10925 RRR_DSUBU = 0x2,
10926 RRR_SUBU = 0x3
10929 /* RR funct field */
10930 enum {
10931 RR_JR = 0x00,
10932 RR_SDBBP = 0x01,
10933 RR_SLT = 0x02,
10934 RR_SLTU = 0x03,
10935 RR_SLLV = 0x04,
10936 RR_BREAK = 0x05,
10937 RR_SRLV = 0x06,
10938 RR_SRAV = 0x07,
10939 RR_DSRL = 0x08,
10940 RR_CMP = 0x0a,
10941 RR_NEG = 0x0b,
10942 RR_AND = 0x0c,
10943 RR_OR = 0x0d,
10944 RR_XOR = 0x0e,
10945 RR_NOT = 0x0f,
10946 RR_MFHI = 0x10,
10947 RR_CNVT = 0x11,
10948 RR_MFLO = 0x12,
10949 RR_DSRA = 0x13,
10950 RR_DSLLV = 0x14,
10951 RR_DSRLV = 0x16,
10952 RR_DSRAV = 0x17,
10953 RR_MULT = 0x18,
10954 RR_MULTU = 0x19,
10955 RR_DIV = 0x1a,
10956 RR_DIVU = 0x1b,
10957 RR_DMULT = 0x1c,
10958 RR_DMULTU = 0x1d,
10959 RR_DDIV = 0x1e,
10960 RR_DDIVU = 0x1f
10963 /* I64 funct field */
10964 enum {
10965 I64_LDSP = 0x0,
10966 I64_SDSP = 0x1,
10967 I64_SDRASP = 0x2,
10968 I64_DADJSP = 0x3,
10969 I64_LDPC = 0x4,
10970 I64_DADDIU5 = 0x5,
10971 I64_DADDIUPC = 0x6,
10972 I64_DADDIUSP = 0x7
10975 /* RR ry field for CNVT */
10976 enum {
10977 RR_RY_CNVT_ZEB = 0x0,
10978 RR_RY_CNVT_ZEH = 0x1,
10979 RR_RY_CNVT_ZEW = 0x2,
10980 RR_RY_CNVT_SEB = 0x4,
10981 RR_RY_CNVT_SEH = 0x5,
10982 RR_RY_CNVT_SEW = 0x6,
10985 static int xlat (int r)
10987 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10989 return map[r];
10992 static void gen_mips16_save (DisasContext *ctx,
10993 int xsregs, int aregs,
10994 int do_ra, int do_s0, int do_s1,
10995 int framesize)
10997 TCGv t0 = tcg_temp_new();
10998 TCGv t1 = tcg_temp_new();
10999 TCGv t2 = tcg_temp_new();
11000 int args, astatic;
11002 switch (aregs) {
11003 case 0:
11004 case 1:
11005 case 2:
11006 case 3:
11007 case 11:
11008 args = 0;
11009 break;
11010 case 4:
11011 case 5:
11012 case 6:
11013 case 7:
11014 args = 1;
11015 break;
11016 case 8:
11017 case 9:
11018 case 10:
11019 args = 2;
11020 break;
11021 case 12:
11022 case 13:
11023 args = 3;
11024 break;
11025 case 14:
11026 args = 4;
11027 break;
11028 default:
11029 generate_exception_end(ctx, EXCP_RI);
11030 return;
11033 switch (args) {
11034 case 4:
11035 gen_base_offset_addr(ctx, t0, 29, 12);
11036 gen_load_gpr(t1, 7);
11037 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11038 /* Fall through */
11039 case 3:
11040 gen_base_offset_addr(ctx, t0, 29, 8);
11041 gen_load_gpr(t1, 6);
11042 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11043 /* Fall through */
11044 case 2:
11045 gen_base_offset_addr(ctx, t0, 29, 4);
11046 gen_load_gpr(t1, 5);
11047 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11048 /* Fall through */
11049 case 1:
11050 gen_base_offset_addr(ctx, t0, 29, 0);
11051 gen_load_gpr(t1, 4);
11052 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11055 gen_load_gpr(t0, 29);
11057 #define DECR_AND_STORE(reg) do { \
11058 tcg_gen_movi_tl(t2, -4); \
11059 gen_op_addr_add(ctx, t0, t0, t2); \
11060 gen_load_gpr(t1, reg); \
11061 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
11062 } while (0)
11064 if (do_ra) {
11065 DECR_AND_STORE(31);
11068 switch (xsregs) {
11069 case 7:
11070 DECR_AND_STORE(30);
11071 /* Fall through */
11072 case 6:
11073 DECR_AND_STORE(23);
11074 /* Fall through */
11075 case 5:
11076 DECR_AND_STORE(22);
11077 /* Fall through */
11078 case 4:
11079 DECR_AND_STORE(21);
11080 /* Fall through */
11081 case 3:
11082 DECR_AND_STORE(20);
11083 /* Fall through */
11084 case 2:
11085 DECR_AND_STORE(19);
11086 /* Fall through */
11087 case 1:
11088 DECR_AND_STORE(18);
11091 if (do_s1) {
11092 DECR_AND_STORE(17);
11094 if (do_s0) {
11095 DECR_AND_STORE(16);
11098 switch (aregs) {
11099 case 0:
11100 case 4:
11101 case 8:
11102 case 12:
11103 case 14:
11104 astatic = 0;
11105 break;
11106 case 1:
11107 case 5:
11108 case 9:
11109 case 13:
11110 astatic = 1;
11111 break;
11112 case 2:
11113 case 6:
11114 case 10:
11115 astatic = 2;
11116 break;
11117 case 3:
11118 case 7:
11119 astatic = 3;
11120 break;
11121 case 11:
11122 astatic = 4;
11123 break;
11124 default:
11125 generate_exception_end(ctx, EXCP_RI);
11126 return;
11129 if (astatic > 0) {
11130 DECR_AND_STORE(7);
11131 if (astatic > 1) {
11132 DECR_AND_STORE(6);
11133 if (astatic > 2) {
11134 DECR_AND_STORE(5);
11135 if (astatic > 3) {
11136 DECR_AND_STORE(4);
11141 #undef DECR_AND_STORE
11143 tcg_gen_movi_tl(t2, -framesize);
11144 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11145 tcg_temp_free(t0);
11146 tcg_temp_free(t1);
11147 tcg_temp_free(t2);
11150 static void gen_mips16_restore (DisasContext *ctx,
11151 int xsregs, int aregs,
11152 int do_ra, int do_s0, int do_s1,
11153 int framesize)
11155 int astatic;
11156 TCGv t0 = tcg_temp_new();
11157 TCGv t1 = tcg_temp_new();
11158 TCGv t2 = tcg_temp_new();
11160 tcg_gen_movi_tl(t2, framesize);
11161 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11163 #define DECR_AND_LOAD(reg) do { \
11164 tcg_gen_movi_tl(t2, -4); \
11165 gen_op_addr_add(ctx, t0, t0, t2); \
11166 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11167 gen_store_gpr(t1, reg); \
11168 } while (0)
11170 if (do_ra) {
11171 DECR_AND_LOAD(31);
11174 switch (xsregs) {
11175 case 7:
11176 DECR_AND_LOAD(30);
11177 /* Fall through */
11178 case 6:
11179 DECR_AND_LOAD(23);
11180 /* Fall through */
11181 case 5:
11182 DECR_AND_LOAD(22);
11183 /* Fall through */
11184 case 4:
11185 DECR_AND_LOAD(21);
11186 /* Fall through */
11187 case 3:
11188 DECR_AND_LOAD(20);
11189 /* Fall through */
11190 case 2:
11191 DECR_AND_LOAD(19);
11192 /* Fall through */
11193 case 1:
11194 DECR_AND_LOAD(18);
11197 if (do_s1) {
11198 DECR_AND_LOAD(17);
11200 if (do_s0) {
11201 DECR_AND_LOAD(16);
11204 switch (aregs) {
11205 case 0:
11206 case 4:
11207 case 8:
11208 case 12:
11209 case 14:
11210 astatic = 0;
11211 break;
11212 case 1:
11213 case 5:
11214 case 9:
11215 case 13:
11216 astatic = 1;
11217 break;
11218 case 2:
11219 case 6:
11220 case 10:
11221 astatic = 2;
11222 break;
11223 case 3:
11224 case 7:
11225 astatic = 3;
11226 break;
11227 case 11:
11228 astatic = 4;
11229 break;
11230 default:
11231 generate_exception_end(ctx, EXCP_RI);
11232 return;
11235 if (astatic > 0) {
11236 DECR_AND_LOAD(7);
11237 if (astatic > 1) {
11238 DECR_AND_LOAD(6);
11239 if (astatic > 2) {
11240 DECR_AND_LOAD(5);
11241 if (astatic > 3) {
11242 DECR_AND_LOAD(4);
11247 #undef DECR_AND_LOAD
11249 tcg_gen_movi_tl(t2, framesize);
11250 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11251 tcg_temp_free(t0);
11252 tcg_temp_free(t1);
11253 tcg_temp_free(t2);
11256 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11257 int is_64_bit, int extended)
11259 TCGv t0;
11261 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11262 generate_exception_end(ctx, EXCP_RI);
11263 return;
11266 t0 = tcg_temp_new();
11268 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11269 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11270 if (!is_64_bit) {
11271 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11274 tcg_temp_free(t0);
11277 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
11278 int16_t offset)
11280 TCGv_i32 t0 = tcg_const_i32(op);
11281 TCGv t1 = tcg_temp_new();
11282 gen_base_offset_addr(ctx, t1, base, offset);
11283 gen_helper_cache(cpu_env, t1, t0);
11286 #if defined(TARGET_MIPS64)
11287 static void decode_i64_mips16 (DisasContext *ctx,
11288 int ry, int funct, int16_t offset,
11289 int extended)
11291 switch (funct) {
11292 case I64_LDSP:
11293 check_insn(ctx, ISA_MIPS3);
11294 check_mips_64(ctx);
11295 offset = extended ? offset : offset << 3;
11296 gen_ld(ctx, OPC_LD, ry, 29, offset);
11297 break;
11298 case I64_SDSP:
11299 check_insn(ctx, ISA_MIPS3);
11300 check_mips_64(ctx);
11301 offset = extended ? offset : offset << 3;
11302 gen_st(ctx, OPC_SD, ry, 29, offset);
11303 break;
11304 case I64_SDRASP:
11305 check_insn(ctx, ISA_MIPS3);
11306 check_mips_64(ctx);
11307 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11308 gen_st(ctx, OPC_SD, 31, 29, offset);
11309 break;
11310 case I64_DADJSP:
11311 check_insn(ctx, ISA_MIPS3);
11312 check_mips_64(ctx);
11313 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11314 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11315 break;
11316 case I64_LDPC:
11317 check_insn(ctx, ISA_MIPS3);
11318 check_mips_64(ctx);
11319 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11320 generate_exception_end(ctx, EXCP_RI);
11321 } else {
11322 offset = extended ? offset : offset << 3;
11323 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11325 break;
11326 case I64_DADDIU5:
11327 check_insn(ctx, ISA_MIPS3);
11328 check_mips_64(ctx);
11329 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11330 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11331 break;
11332 case I64_DADDIUPC:
11333 check_insn(ctx, ISA_MIPS3);
11334 check_mips_64(ctx);
11335 offset = extended ? offset : offset << 2;
11336 gen_addiupc(ctx, ry, offset, 1, extended);
11337 break;
11338 case I64_DADDIUSP:
11339 check_insn(ctx, ISA_MIPS3);
11340 check_mips_64(ctx);
11341 offset = extended ? offset : offset << 2;
11342 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11343 break;
11346 #endif
11348 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11350 int extend = cpu_lduw_code(env, ctx->pc + 2);
11351 int op, rx, ry, funct, sa;
11352 int16_t imm, offset;
11354 ctx->opcode = (ctx->opcode << 16) | extend;
11355 op = (ctx->opcode >> 11) & 0x1f;
11356 sa = (ctx->opcode >> 22) & 0x1f;
11357 funct = (ctx->opcode >> 8) & 0x7;
11358 rx = xlat((ctx->opcode >> 8) & 0x7);
11359 ry = xlat((ctx->opcode >> 5) & 0x7);
11360 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11361 | ((ctx->opcode >> 21) & 0x3f) << 5
11362 | (ctx->opcode & 0x1f));
11364 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11365 counterparts. */
11366 switch (op) {
11367 case M16_OPC_ADDIUSP:
11368 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11369 break;
11370 case M16_OPC_ADDIUPC:
11371 gen_addiupc(ctx, rx, imm, 0, 1);
11372 break;
11373 case M16_OPC_B:
11374 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11375 /* No delay slot, so just process as a normal instruction */
11376 break;
11377 case M16_OPC_BEQZ:
11378 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11379 /* No delay slot, so just process as a normal instruction */
11380 break;
11381 case M16_OPC_BNEQZ:
11382 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11383 /* No delay slot, so just process as a normal instruction */
11384 break;
11385 case M16_OPC_SHIFT:
11386 switch (ctx->opcode & 0x3) {
11387 case 0x0:
11388 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11389 break;
11390 case 0x1:
11391 #if defined(TARGET_MIPS64)
11392 check_mips_64(ctx);
11393 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11394 #else
11395 generate_exception_end(ctx, EXCP_RI);
11396 #endif
11397 break;
11398 case 0x2:
11399 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11400 break;
11401 case 0x3:
11402 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11403 break;
11405 break;
11406 #if defined(TARGET_MIPS64)
11407 case M16_OPC_LD:
11408 check_insn(ctx, ISA_MIPS3);
11409 check_mips_64(ctx);
11410 gen_ld(ctx, OPC_LD, ry, rx, offset);
11411 break;
11412 #endif
11413 case M16_OPC_RRIA:
11414 imm = ctx->opcode & 0xf;
11415 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11416 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11417 imm = (int16_t) (imm << 1) >> 1;
11418 if ((ctx->opcode >> 4) & 0x1) {
11419 #if defined(TARGET_MIPS64)
11420 check_mips_64(ctx);
11421 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11422 #else
11423 generate_exception_end(ctx, EXCP_RI);
11424 #endif
11425 } else {
11426 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11428 break;
11429 case M16_OPC_ADDIU8:
11430 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11431 break;
11432 case M16_OPC_SLTI:
11433 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11434 break;
11435 case M16_OPC_SLTIU:
11436 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11437 break;
11438 case M16_OPC_I8:
11439 switch (funct) {
11440 case I8_BTEQZ:
11441 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11442 break;
11443 case I8_BTNEZ:
11444 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11445 break;
11446 case I8_SWRASP:
11447 gen_st(ctx, OPC_SW, 31, 29, imm);
11448 break;
11449 case I8_ADJSP:
11450 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11451 break;
11452 case I8_SVRS:
11453 check_insn(ctx, ISA_MIPS32);
11455 int xsregs = (ctx->opcode >> 24) & 0x7;
11456 int aregs = (ctx->opcode >> 16) & 0xf;
11457 int do_ra = (ctx->opcode >> 6) & 0x1;
11458 int do_s0 = (ctx->opcode >> 5) & 0x1;
11459 int do_s1 = (ctx->opcode >> 4) & 0x1;
11460 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11461 | (ctx->opcode & 0xf)) << 3;
11463 if (ctx->opcode & (1 << 7)) {
11464 gen_mips16_save(ctx, xsregs, aregs,
11465 do_ra, do_s0, do_s1,
11466 framesize);
11467 } else {
11468 gen_mips16_restore(ctx, xsregs, aregs,
11469 do_ra, do_s0, do_s1,
11470 framesize);
11473 break;
11474 default:
11475 generate_exception_end(ctx, EXCP_RI);
11476 break;
11478 break;
11479 case M16_OPC_LI:
11480 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11481 break;
11482 case M16_OPC_CMPI:
11483 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11484 break;
11485 #if defined(TARGET_MIPS64)
11486 case M16_OPC_SD:
11487 check_insn(ctx, ISA_MIPS3);
11488 check_mips_64(ctx);
11489 gen_st(ctx, OPC_SD, ry, rx, offset);
11490 break;
11491 #endif
11492 case M16_OPC_LB:
11493 gen_ld(ctx, OPC_LB, ry, rx, offset);
11494 break;
11495 case M16_OPC_LH:
11496 gen_ld(ctx, OPC_LH, ry, rx, offset);
11497 break;
11498 case M16_OPC_LWSP:
11499 gen_ld(ctx, OPC_LW, rx, 29, offset);
11500 break;
11501 case M16_OPC_LW:
11502 gen_ld(ctx, OPC_LW, ry, rx, offset);
11503 break;
11504 case M16_OPC_LBU:
11505 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11506 break;
11507 case M16_OPC_LHU:
11508 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11509 break;
11510 case M16_OPC_LWPC:
11511 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11512 break;
11513 #if defined(TARGET_MIPS64)
11514 case M16_OPC_LWU:
11515 check_insn(ctx, ISA_MIPS3);
11516 check_mips_64(ctx);
11517 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11518 break;
11519 #endif
11520 case M16_OPC_SB:
11521 gen_st(ctx, OPC_SB, ry, rx, offset);
11522 break;
11523 case M16_OPC_SH:
11524 gen_st(ctx, OPC_SH, ry, rx, offset);
11525 break;
11526 case M16_OPC_SWSP:
11527 gen_st(ctx, OPC_SW, rx, 29, offset);
11528 break;
11529 case M16_OPC_SW:
11530 gen_st(ctx, OPC_SW, ry, rx, offset);
11531 break;
11532 #if defined(TARGET_MIPS64)
11533 case M16_OPC_I64:
11534 decode_i64_mips16(ctx, ry, funct, offset, 1);
11535 break;
11536 #endif
11537 default:
11538 generate_exception_end(ctx, EXCP_RI);
11539 break;
11542 return 4;
11545 static inline bool is_uhi(int sdbbp_code)
11547 #ifdef CONFIG_USER_ONLY
11548 return false;
11549 #else
11550 return semihosting_enabled() && sdbbp_code == 1;
11551 #endif
11554 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11556 int rx, ry;
11557 int sa;
11558 int op, cnvt_op, op1, offset;
11559 int funct;
11560 int n_bytes;
11562 op = (ctx->opcode >> 11) & 0x1f;
11563 sa = (ctx->opcode >> 2) & 0x7;
11564 sa = sa == 0 ? 8 : sa;
11565 rx = xlat((ctx->opcode >> 8) & 0x7);
11566 cnvt_op = (ctx->opcode >> 5) & 0x7;
11567 ry = xlat((ctx->opcode >> 5) & 0x7);
11568 op1 = offset = ctx->opcode & 0x1f;
11570 n_bytes = 2;
11572 switch (op) {
11573 case M16_OPC_ADDIUSP:
11575 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11577 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11579 break;
11580 case M16_OPC_ADDIUPC:
11581 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11582 break;
11583 case M16_OPC_B:
11584 offset = (ctx->opcode & 0x7ff) << 1;
11585 offset = (int16_t)(offset << 4) >> 4;
11586 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11587 /* No delay slot, so just process as a normal instruction */
11588 break;
11589 case M16_OPC_JAL:
11590 offset = cpu_lduw_code(env, ctx->pc + 2);
11591 offset = (((ctx->opcode & 0x1f) << 21)
11592 | ((ctx->opcode >> 5) & 0x1f) << 16
11593 | offset) << 2;
11594 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11595 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11596 n_bytes = 4;
11597 break;
11598 case M16_OPC_BEQZ:
11599 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11600 ((int8_t)ctx->opcode) << 1, 0);
11601 /* No delay slot, so just process as a normal instruction */
11602 break;
11603 case M16_OPC_BNEQZ:
11604 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11605 ((int8_t)ctx->opcode) << 1, 0);
11606 /* No delay slot, so just process as a normal instruction */
11607 break;
11608 case M16_OPC_SHIFT:
11609 switch (ctx->opcode & 0x3) {
11610 case 0x0:
11611 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11612 break;
11613 case 0x1:
11614 #if defined(TARGET_MIPS64)
11615 check_insn(ctx, ISA_MIPS3);
11616 check_mips_64(ctx);
11617 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11618 #else
11619 generate_exception_end(ctx, EXCP_RI);
11620 #endif
11621 break;
11622 case 0x2:
11623 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11624 break;
11625 case 0x3:
11626 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11627 break;
11629 break;
11630 #if defined(TARGET_MIPS64)
11631 case M16_OPC_LD:
11632 check_insn(ctx, ISA_MIPS3);
11633 check_mips_64(ctx);
11634 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
11635 break;
11636 #endif
11637 case M16_OPC_RRIA:
11639 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
11641 if ((ctx->opcode >> 4) & 1) {
11642 #if defined(TARGET_MIPS64)
11643 check_insn(ctx, ISA_MIPS3);
11644 check_mips_64(ctx);
11645 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11646 #else
11647 generate_exception_end(ctx, EXCP_RI);
11648 #endif
11649 } else {
11650 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11653 break;
11654 case M16_OPC_ADDIU8:
11656 int16_t imm = (int8_t) ctx->opcode;
11658 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11660 break;
11661 case M16_OPC_SLTI:
11663 int16_t imm = (uint8_t) ctx->opcode;
11664 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11666 break;
11667 case M16_OPC_SLTIU:
11669 int16_t imm = (uint8_t) ctx->opcode;
11670 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11672 break;
11673 case M16_OPC_I8:
11675 int reg32;
11677 funct = (ctx->opcode >> 8) & 0x7;
11678 switch (funct) {
11679 case I8_BTEQZ:
11680 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
11681 ((int8_t)ctx->opcode) << 1, 0);
11682 break;
11683 case I8_BTNEZ:
11684 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
11685 ((int8_t)ctx->opcode) << 1, 0);
11686 break;
11687 case I8_SWRASP:
11688 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
11689 break;
11690 case I8_ADJSP:
11691 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
11692 ((int8_t)ctx->opcode) << 3);
11693 break;
11694 case I8_SVRS:
11695 check_insn(ctx, ISA_MIPS32);
11697 int do_ra = ctx->opcode & (1 << 6);
11698 int do_s0 = ctx->opcode & (1 << 5);
11699 int do_s1 = ctx->opcode & (1 << 4);
11700 int framesize = ctx->opcode & 0xf;
11702 if (framesize == 0) {
11703 framesize = 128;
11704 } else {
11705 framesize = framesize << 3;
11708 if (ctx->opcode & (1 << 7)) {
11709 gen_mips16_save(ctx, 0, 0,
11710 do_ra, do_s0, do_s1, framesize);
11711 } else {
11712 gen_mips16_restore(ctx, 0, 0,
11713 do_ra, do_s0, do_s1, framesize);
11716 break;
11717 case I8_MOV32R:
11719 int rz = xlat(ctx->opcode & 0x7);
11721 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
11722 ((ctx->opcode >> 5) & 0x7);
11723 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
11725 break;
11726 case I8_MOVR32:
11727 reg32 = ctx->opcode & 0x1f;
11728 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
11729 break;
11730 default:
11731 generate_exception_end(ctx, EXCP_RI);
11732 break;
11735 break;
11736 case M16_OPC_LI:
11738 int16_t imm = (uint8_t) ctx->opcode;
11740 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
11742 break;
11743 case M16_OPC_CMPI:
11745 int16_t imm = (uint8_t) ctx->opcode;
11746 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
11748 break;
11749 #if defined(TARGET_MIPS64)
11750 case M16_OPC_SD:
11751 check_insn(ctx, ISA_MIPS3);
11752 check_mips_64(ctx);
11753 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
11754 break;
11755 #endif
11756 case M16_OPC_LB:
11757 gen_ld(ctx, OPC_LB, ry, rx, offset);
11758 break;
11759 case M16_OPC_LH:
11760 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
11761 break;
11762 case M16_OPC_LWSP:
11763 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11764 break;
11765 case M16_OPC_LW:
11766 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
11767 break;
11768 case M16_OPC_LBU:
11769 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11770 break;
11771 case M16_OPC_LHU:
11772 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
11773 break;
11774 case M16_OPC_LWPC:
11775 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
11776 break;
11777 #if defined (TARGET_MIPS64)
11778 case M16_OPC_LWU:
11779 check_insn(ctx, ISA_MIPS3);
11780 check_mips_64(ctx);
11781 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
11782 break;
11783 #endif
11784 case M16_OPC_SB:
11785 gen_st(ctx, OPC_SB, ry, rx, offset);
11786 break;
11787 case M16_OPC_SH:
11788 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
11789 break;
11790 case M16_OPC_SWSP:
11791 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11792 break;
11793 case M16_OPC_SW:
11794 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
11795 break;
11796 case M16_OPC_RRR:
11798 int rz = xlat((ctx->opcode >> 2) & 0x7);
11799 int mips32_op;
11801 switch (ctx->opcode & 0x3) {
11802 case RRR_ADDU:
11803 mips32_op = OPC_ADDU;
11804 break;
11805 case RRR_SUBU:
11806 mips32_op = OPC_SUBU;
11807 break;
11808 #if defined(TARGET_MIPS64)
11809 case RRR_DADDU:
11810 mips32_op = OPC_DADDU;
11811 check_insn(ctx, ISA_MIPS3);
11812 check_mips_64(ctx);
11813 break;
11814 case RRR_DSUBU:
11815 mips32_op = OPC_DSUBU;
11816 check_insn(ctx, ISA_MIPS3);
11817 check_mips_64(ctx);
11818 break;
11819 #endif
11820 default:
11821 generate_exception_end(ctx, EXCP_RI);
11822 goto done;
11825 gen_arith(ctx, mips32_op, rz, rx, ry);
11826 done:
11829 break;
11830 case M16_OPC_RR:
11831 switch (op1) {
11832 case RR_JR:
11834 int nd = (ctx->opcode >> 7) & 0x1;
11835 int link = (ctx->opcode >> 6) & 0x1;
11836 int ra = (ctx->opcode >> 5) & 0x1;
11838 if (nd) {
11839 check_insn(ctx, ISA_MIPS32);
11842 if (link) {
11843 op = OPC_JALR;
11844 } else {
11845 op = OPC_JR;
11848 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
11849 (nd ? 0 : 2));
11851 break;
11852 case RR_SDBBP:
11853 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
11854 gen_helper_do_semihosting(cpu_env);
11855 } else {
11856 /* XXX: not clear which exception should be raised
11857 * when in debug mode...
11859 check_insn(ctx, ISA_MIPS32);
11860 generate_exception_end(ctx, EXCP_DBp);
11862 break;
11863 case RR_SLT:
11864 gen_slt(ctx, OPC_SLT, 24, rx, ry);
11865 break;
11866 case RR_SLTU:
11867 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
11868 break;
11869 case RR_BREAK:
11870 generate_exception_end(ctx, EXCP_BREAK);
11871 break;
11872 case RR_SLLV:
11873 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
11874 break;
11875 case RR_SRLV:
11876 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
11877 break;
11878 case RR_SRAV:
11879 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
11880 break;
11881 #if defined (TARGET_MIPS64)
11882 case RR_DSRL:
11883 check_insn(ctx, ISA_MIPS3);
11884 check_mips_64(ctx);
11885 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
11886 break;
11887 #endif
11888 case RR_CMP:
11889 gen_logic(ctx, OPC_XOR, 24, rx, ry);
11890 break;
11891 case RR_NEG:
11892 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
11893 break;
11894 case RR_AND:
11895 gen_logic(ctx, OPC_AND, rx, rx, ry);
11896 break;
11897 case RR_OR:
11898 gen_logic(ctx, OPC_OR, rx, rx, ry);
11899 break;
11900 case RR_XOR:
11901 gen_logic(ctx, OPC_XOR, rx, rx, ry);
11902 break;
11903 case RR_NOT:
11904 gen_logic(ctx, OPC_NOR, rx, ry, 0);
11905 break;
11906 case RR_MFHI:
11907 gen_HILO(ctx, OPC_MFHI, 0, rx);
11908 break;
11909 case RR_CNVT:
11910 check_insn(ctx, ISA_MIPS32);
11911 switch (cnvt_op) {
11912 case RR_RY_CNVT_ZEB:
11913 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11914 break;
11915 case RR_RY_CNVT_ZEH:
11916 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11917 break;
11918 case RR_RY_CNVT_SEB:
11919 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11920 break;
11921 case RR_RY_CNVT_SEH:
11922 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11923 break;
11924 #if defined (TARGET_MIPS64)
11925 case RR_RY_CNVT_ZEW:
11926 check_insn(ctx, ISA_MIPS64);
11927 check_mips_64(ctx);
11928 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11929 break;
11930 case RR_RY_CNVT_SEW:
11931 check_insn(ctx, ISA_MIPS64);
11932 check_mips_64(ctx);
11933 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11934 break;
11935 #endif
11936 default:
11937 generate_exception_end(ctx, EXCP_RI);
11938 break;
11940 break;
11941 case RR_MFLO:
11942 gen_HILO(ctx, OPC_MFLO, 0, rx);
11943 break;
11944 #if defined (TARGET_MIPS64)
11945 case RR_DSRA:
11946 check_insn(ctx, ISA_MIPS3);
11947 check_mips_64(ctx);
11948 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
11949 break;
11950 case RR_DSLLV:
11951 check_insn(ctx, ISA_MIPS3);
11952 check_mips_64(ctx);
11953 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
11954 break;
11955 case RR_DSRLV:
11956 check_insn(ctx, ISA_MIPS3);
11957 check_mips_64(ctx);
11958 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
11959 break;
11960 case RR_DSRAV:
11961 check_insn(ctx, ISA_MIPS3);
11962 check_mips_64(ctx);
11963 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
11964 break;
11965 #endif
11966 case RR_MULT:
11967 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
11968 break;
11969 case RR_MULTU:
11970 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
11971 break;
11972 case RR_DIV:
11973 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
11974 break;
11975 case RR_DIVU:
11976 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
11977 break;
11978 #if defined (TARGET_MIPS64)
11979 case RR_DMULT:
11980 check_insn(ctx, ISA_MIPS3);
11981 check_mips_64(ctx);
11982 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
11983 break;
11984 case RR_DMULTU:
11985 check_insn(ctx, ISA_MIPS3);
11986 check_mips_64(ctx);
11987 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
11988 break;
11989 case RR_DDIV:
11990 check_insn(ctx, ISA_MIPS3);
11991 check_mips_64(ctx);
11992 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
11993 break;
11994 case RR_DDIVU:
11995 check_insn(ctx, ISA_MIPS3);
11996 check_mips_64(ctx);
11997 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
11998 break;
11999 #endif
12000 default:
12001 generate_exception_end(ctx, EXCP_RI);
12002 break;
12004 break;
12005 case M16_OPC_EXTEND:
12006 decode_extended_mips16_opc(env, ctx);
12007 n_bytes = 4;
12008 break;
12009 #if defined(TARGET_MIPS64)
12010 case M16_OPC_I64:
12011 funct = (ctx->opcode >> 8) & 0x7;
12012 decode_i64_mips16(ctx, ry, funct, offset, 0);
12013 break;
12014 #endif
12015 default:
12016 generate_exception_end(ctx, EXCP_RI);
12017 break;
12020 return n_bytes;
12023 /* microMIPS extension to MIPS32/MIPS64 */
12026 * microMIPS32/microMIPS64 major opcodes
12028 * 1. MIPS Architecture for Programmers Volume II-B:
12029 * The microMIPS32 Instruction Set (Revision 3.05)
12031 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12033 * 2. MIPS Architecture For Programmers Volume II-A:
12034 * The MIPS64 Instruction Set (Revision 3.51)
12037 enum {
12038 POOL32A = 0x00,
12039 POOL16A = 0x01,
12040 LBU16 = 0x02,
12041 MOVE16 = 0x03,
12042 ADDI32 = 0x04,
12043 R6_LUI = 0x04,
12044 AUI = 0x04,
12045 LBU32 = 0x05,
12046 SB32 = 0x06,
12047 LB32 = 0x07,
12049 POOL32B = 0x08,
12050 POOL16B = 0x09,
12051 LHU16 = 0x0a,
12052 ANDI16 = 0x0b,
12053 ADDIU32 = 0x0c,
12054 LHU32 = 0x0d,
12055 SH32 = 0x0e,
12056 LH32 = 0x0f,
12058 POOL32I = 0x10,
12059 POOL16C = 0x11,
12060 LWSP16 = 0x12,
12061 POOL16D = 0x13,
12062 ORI32 = 0x14,
12063 POOL32F = 0x15,
12064 POOL32S = 0x16, /* MIPS64 */
12065 DADDIU32 = 0x17, /* MIPS64 */
12067 POOL32C = 0x18,
12068 LWGP16 = 0x19,
12069 LW16 = 0x1a,
12070 POOL16E = 0x1b,
12071 XORI32 = 0x1c,
12072 JALS32 = 0x1d,
12073 BOVC = 0x1d,
12074 BEQC = 0x1d,
12075 BEQZALC = 0x1d,
12076 ADDIUPC = 0x1e,
12077 PCREL = 0x1e,
12078 BNVC = 0x1f,
12079 BNEC = 0x1f,
12080 BNEZALC = 0x1f,
12082 R6_BEQZC = 0x20,
12083 JIC = 0x20,
12084 POOL16F = 0x21,
12085 SB16 = 0x22,
12086 BEQZ16 = 0x23,
12087 BEQZC16 = 0x23,
12088 SLTI32 = 0x24,
12089 BEQ32 = 0x25,
12090 BC = 0x25,
12091 SWC132 = 0x26,
12092 LWC132 = 0x27,
12094 /* 0x29 is reserved */
12095 RES_29 = 0x29,
12096 R6_BNEZC = 0x28,
12097 JIALC = 0x28,
12098 SH16 = 0x2a,
12099 BNEZ16 = 0x2b,
12100 BNEZC16 = 0x2b,
12101 SLTIU32 = 0x2c,
12102 BNE32 = 0x2d,
12103 BALC = 0x2d,
12104 SDC132 = 0x2e,
12105 LDC132 = 0x2f,
12107 /* 0x31 is reserved */
12108 RES_31 = 0x31,
12109 BLEZALC = 0x30,
12110 BGEZALC = 0x30,
12111 BGEUC = 0x30,
12112 SWSP16 = 0x32,
12113 B16 = 0x33,
12114 BC16 = 0x33,
12115 ANDI32 = 0x34,
12116 J32 = 0x35,
12117 BGTZC = 0x35,
12118 BLTZC = 0x35,
12119 BLTC = 0x35,
12120 SD32 = 0x36, /* MIPS64 */
12121 LD32 = 0x37, /* MIPS64 */
12123 /* 0x39 is reserved */
12124 RES_39 = 0x39,
12125 BGTZALC = 0x38,
12126 BLTZALC = 0x38,
12127 BLTUC = 0x38,
12128 SW16 = 0x3a,
12129 LI16 = 0x3b,
12130 JALX32 = 0x3c,
12131 JAL32 = 0x3d,
12132 BLEZC = 0x3d,
12133 BGEZC = 0x3d,
12134 BGEC = 0x3d,
12135 SW32 = 0x3e,
12136 LW32 = 0x3f
12139 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12140 enum {
12141 ADDIUPC_00 = 0x00,
12142 ADDIUPC_07 = 0x07,
12143 AUIPC = 0x1e,
12144 ALUIPC = 0x1f,
12145 LWPC_08 = 0x08,
12146 LWPC_0F = 0x0F,
12149 /* POOL32A encoding of minor opcode field */
12151 enum {
12152 /* These opcodes are distinguished only by bits 9..6; those bits are
12153 * what are recorded below. */
12154 SLL32 = 0x0,
12155 SRL32 = 0x1,
12156 SRA = 0x2,
12157 ROTR = 0x3,
12158 SELEQZ = 0x5,
12159 SELNEZ = 0x6,
12160 R6_RDHWR = 0x7,
12162 SLLV = 0x0,
12163 SRLV = 0x1,
12164 SRAV = 0x2,
12165 ROTRV = 0x3,
12166 ADD = 0x4,
12167 ADDU32 = 0x5,
12168 SUB = 0x6,
12169 SUBU32 = 0x7,
12170 MUL = 0x8,
12171 AND = 0x9,
12172 OR32 = 0xa,
12173 NOR = 0xb,
12174 XOR32 = 0xc,
12175 SLT = 0xd,
12176 SLTU = 0xe,
12178 MOVN = 0x0,
12179 R6_MUL = 0x0,
12180 MOVZ = 0x1,
12181 MUH = 0x1,
12182 MULU = 0x2,
12183 MUHU = 0x3,
12184 LWXS = 0x4,
12185 R6_DIV = 0x4,
12186 MOD = 0x5,
12187 R6_DIVU = 0x6,
12188 MODU = 0x7,
12190 /* The following can be distinguished by their lower 6 bits. */
12191 BREAK32 = 0x07,
12192 INS = 0x0c,
12193 LSA = 0x0f,
12194 ALIGN = 0x1f,
12195 EXT = 0x2c,
12196 POOL32AXF = 0x3c,
12197 SIGRIE = 0x3f
12200 /* POOL32AXF encoding of minor opcode field extension */
12203 * 1. MIPS Architecture for Programmers Volume II-B:
12204 * The microMIPS32 Instruction Set (Revision 3.05)
12206 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12208 * 2. MIPS Architecture for Programmers VolumeIV-e:
12209 * The MIPS DSP Application-Specific Extension
12210 * to the microMIPS32 Architecture (Revision 2.34)
12212 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12215 enum {
12216 /* bits 11..6 */
12217 TEQ = 0x00,
12218 TGE = 0x08,
12219 TGEU = 0x10,
12220 TLT = 0x20,
12221 TLTU = 0x28,
12222 TNE = 0x30,
12224 MFC0 = 0x03,
12225 MTC0 = 0x0b,
12227 /* begin of microMIPS32 DSP */
12229 /* bits 13..12 for 0x01 */
12230 MFHI_ACC = 0x0,
12231 MFLO_ACC = 0x1,
12232 MTHI_ACC = 0x2,
12233 MTLO_ACC = 0x3,
12235 /* bits 13..12 for 0x2a */
12236 MADD_ACC = 0x0,
12237 MADDU_ACC = 0x1,
12238 MSUB_ACC = 0x2,
12239 MSUBU_ACC = 0x3,
12241 /* bits 13..12 for 0x32 */
12242 MULT_ACC = 0x0,
12243 MULTU_ACC = 0x1,
12245 /* end of microMIPS32 DSP */
12247 /* bits 15..12 for 0x2c */
12248 BITSWAP = 0x0,
12249 SEB = 0x2,
12250 SEH = 0x3,
12251 CLO = 0x4,
12252 CLZ = 0x5,
12253 RDHWR = 0x6,
12254 WSBH = 0x7,
12255 MULT = 0x8,
12256 MULTU = 0x9,
12257 DIV = 0xa,
12258 DIVU = 0xb,
12259 MADD = 0xc,
12260 MADDU = 0xd,
12261 MSUB = 0xe,
12262 MSUBU = 0xf,
12264 /* bits 15..12 for 0x34 */
12265 MFC2 = 0x4,
12266 MTC2 = 0x5,
12267 MFHC2 = 0x8,
12268 MTHC2 = 0x9,
12269 CFC2 = 0xc,
12270 CTC2 = 0xd,
12272 /* bits 15..12 for 0x3c */
12273 JALR = 0x0,
12274 JR = 0x0, /* alias */
12275 JALRC = 0x0,
12276 JRC = 0x0,
12277 JALR_HB = 0x1,
12278 JALRC_HB = 0x1,
12279 JALRS = 0x4,
12280 JALRS_HB = 0x5,
12282 /* bits 15..12 for 0x05 */
12283 RDPGPR = 0xe,
12284 WRPGPR = 0xf,
12286 /* bits 15..12 for 0x0d */
12287 TLBP = 0x0,
12288 TLBR = 0x1,
12289 TLBWI = 0x2,
12290 TLBWR = 0x3,
12291 TLBINV = 0x4,
12292 TLBINVF = 0x5,
12293 WAIT = 0x9,
12294 IRET = 0xd,
12295 DERET = 0xe,
12296 ERET = 0xf,
12298 /* bits 15..12 for 0x15 */
12299 DMT = 0x0,
12300 DVPE = 0x1,
12301 EMT = 0x2,
12302 EVPE = 0x3,
12304 /* bits 15..12 for 0x1d */
12305 DI = 0x4,
12306 EI = 0x5,
12308 /* bits 15..12 for 0x2d */
12309 SYNC = 0x6,
12310 SYSCALL = 0x8,
12311 SDBBP = 0xd,
12313 /* bits 15..12 for 0x35 */
12314 MFHI32 = 0x0,
12315 MFLO32 = 0x1,
12316 MTHI32 = 0x2,
12317 MTLO32 = 0x3,
12320 /* POOL32B encoding of minor opcode field (bits 15..12) */
12322 enum {
12323 LWC2 = 0x0,
12324 LWP = 0x1,
12325 LDP = 0x4,
12326 LWM32 = 0x5,
12327 CACHE = 0x6,
12328 LDM = 0x7,
12329 SWC2 = 0x8,
12330 SWP = 0x9,
12331 SDP = 0xc,
12332 SWM32 = 0xd,
12333 SDM = 0xf
12336 /* POOL32C encoding of minor opcode field (bits 15..12) */
12338 enum {
12339 LWL = 0x0,
12340 SWL = 0x8,
12341 LWR = 0x1,
12342 SWR = 0x9,
12343 PREF = 0x2,
12344 /* 0xa is reserved */
12345 LL = 0x3,
12346 SC = 0xb,
12347 LDL = 0x4,
12348 SDL = 0xc,
12349 LDR = 0x5,
12350 SDR = 0xd,
12351 /* 0x6 is reserved */
12352 LWU = 0xe,
12353 LLD = 0x7,
12354 SCD = 0xf
12357 /* POOL32F encoding of minor opcode field (bits 5..0) */
12359 enum {
12360 /* These are the bit 7..6 values */
12361 ADD_FMT = 0x0,
12363 SUB_FMT = 0x1,
12365 MUL_FMT = 0x2,
12367 DIV_FMT = 0x3,
12369 /* These are the bit 8..6 values */
12370 MOVN_FMT = 0x0,
12371 RSQRT2_FMT = 0x0,
12372 MOVF_FMT = 0x0,
12373 RINT_FMT = 0x0,
12374 SELNEZ_FMT = 0x0,
12376 MOVZ_FMT = 0x1,
12377 LWXC1 = 0x1,
12378 MOVT_FMT = 0x1,
12379 CLASS_FMT = 0x1,
12380 SELEQZ_FMT = 0x1,
12382 PLL_PS = 0x2,
12383 SWXC1 = 0x2,
12384 SEL_FMT = 0x2,
12386 PLU_PS = 0x3,
12387 LDXC1 = 0x3,
12389 MOVN_FMT_04 = 0x4,
12390 PUL_PS = 0x4,
12391 SDXC1 = 0x4,
12392 RECIP2_FMT = 0x4,
12394 MOVZ_FMT_05 = 0x05,
12395 PUU_PS = 0x5,
12396 LUXC1 = 0x5,
12398 CVT_PS_S = 0x6,
12399 SUXC1 = 0x6,
12400 ADDR_PS = 0x6,
12401 PREFX = 0x6,
12402 MADDF_FMT = 0x6,
12404 MULR_PS = 0x7,
12405 MSUBF_FMT = 0x7,
12407 MADD_S = 0x01,
12408 MADD_D = 0x09,
12409 MADD_PS = 0x11,
12410 ALNV_PS = 0x19,
12411 MSUB_S = 0x21,
12412 MSUB_D = 0x29,
12413 MSUB_PS = 0x31,
12415 NMADD_S = 0x02,
12416 NMADD_D = 0x0a,
12417 NMADD_PS = 0x12,
12418 NMSUB_S = 0x22,
12419 NMSUB_D = 0x2a,
12420 NMSUB_PS = 0x32,
12422 MIN_FMT = 0x3,
12423 MAX_FMT = 0xb,
12424 MINA_FMT = 0x23,
12425 MAXA_FMT = 0x2b,
12426 POOL32FXF = 0x3b,
12428 CABS_COND_FMT = 0x1c, /* MIPS3D */
12429 C_COND_FMT = 0x3c,
12431 CMP_CONDN_S = 0x5,
12432 CMP_CONDN_D = 0x15
12435 /* POOL32Fxf encoding of minor opcode extension field */
12437 enum {
12438 CVT_L = 0x04,
12439 RSQRT_FMT = 0x08,
12440 FLOOR_L = 0x0c,
12441 CVT_PW_PS = 0x1c,
12442 CVT_W = 0x24,
12443 SQRT_FMT = 0x28,
12444 FLOOR_W = 0x2c,
12445 CVT_PS_PW = 0x3c,
12446 CFC1 = 0x40,
12447 RECIP_FMT = 0x48,
12448 CEIL_L = 0x4c,
12449 CTC1 = 0x60,
12450 CEIL_W = 0x6c,
12451 MFC1 = 0x80,
12452 CVT_S_PL = 0x84,
12453 TRUNC_L = 0x8c,
12454 MTC1 = 0xa0,
12455 CVT_S_PU = 0xa4,
12456 TRUNC_W = 0xac,
12457 MFHC1 = 0xc0,
12458 ROUND_L = 0xcc,
12459 MTHC1 = 0xe0,
12460 ROUND_W = 0xec,
12462 MOV_FMT = 0x01,
12463 MOVF = 0x05,
12464 ABS_FMT = 0x0d,
12465 RSQRT1_FMT = 0x1d,
12466 MOVT = 0x25,
12467 NEG_FMT = 0x2d,
12468 CVT_D = 0x4d,
12469 RECIP1_FMT = 0x5d,
12470 CVT_S = 0x6d
12473 /* POOL32I encoding of minor opcode field (bits 25..21) */
12475 enum {
12476 BLTZ = 0x00,
12477 BLTZAL = 0x01,
12478 BGEZ = 0x02,
12479 BGEZAL = 0x03,
12480 BLEZ = 0x04,
12481 BNEZC = 0x05,
12482 BGTZ = 0x06,
12483 BEQZC = 0x07,
12484 TLTI = 0x08,
12485 BC1EQZC = 0x08,
12486 TGEI = 0x09,
12487 BC1NEZC = 0x09,
12488 TLTIU = 0x0a,
12489 BC2EQZC = 0x0a,
12490 TGEIU = 0x0b,
12491 BC2NEZC = 0x0a,
12492 TNEI = 0x0c,
12493 R6_SYNCI = 0x0c,
12494 LUI = 0x0d,
12495 TEQI = 0x0e,
12496 SYNCI = 0x10,
12497 BLTZALS = 0x11,
12498 BGEZALS = 0x13,
12499 BC2F = 0x14,
12500 BC2T = 0x15,
12501 BPOSGE64 = 0x1a,
12502 BPOSGE32 = 0x1b,
12503 /* These overlap and are distinguished by bit16 of the instruction */
12504 BC1F = 0x1c,
12505 BC1T = 0x1d,
12506 BC1ANY2F = 0x1c,
12507 BC1ANY2T = 0x1d,
12508 BC1ANY4F = 0x1e,
12509 BC1ANY4T = 0x1f
12512 /* POOL16A encoding of minor opcode field */
12514 enum {
12515 ADDU16 = 0x0,
12516 SUBU16 = 0x1
12519 /* POOL16B encoding of minor opcode field */
12521 enum {
12522 SLL16 = 0x0,
12523 SRL16 = 0x1
12526 /* POOL16C encoding of minor opcode field */
12528 enum {
12529 NOT16 = 0x00,
12530 XOR16 = 0x04,
12531 AND16 = 0x08,
12532 OR16 = 0x0c,
12533 LWM16 = 0x10,
12534 SWM16 = 0x14,
12535 JR16 = 0x18,
12536 JRC16 = 0x1a,
12537 JALR16 = 0x1c,
12538 JALR16S = 0x1e,
12539 MFHI16 = 0x20,
12540 MFLO16 = 0x24,
12541 BREAK16 = 0x28,
12542 SDBBP16 = 0x2c,
12543 JRADDIUSP = 0x30
12546 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
12548 enum {
12549 R6_NOT16 = 0x00,
12550 R6_AND16 = 0x01,
12551 R6_LWM16 = 0x02,
12552 R6_JRC16 = 0x03,
12553 MOVEP = 0x04,
12554 MOVEP_07 = 0x07,
12555 R6_XOR16 = 0x08,
12556 R6_OR16 = 0x09,
12557 R6_SWM16 = 0x0a,
12558 JALRC16 = 0x0b,
12559 MOVEP_0C = 0x0c,
12560 MOVEP_0F = 0x0f,
12561 JRCADDIUSP = 0x13,
12562 R6_BREAK16 = 0x1b,
12563 R6_SDBBP16 = 0x3b
12566 /* POOL16D encoding of minor opcode field */
12568 enum {
12569 ADDIUS5 = 0x0,
12570 ADDIUSP = 0x1
12573 /* POOL16E encoding of minor opcode field */
12575 enum {
12576 ADDIUR2 = 0x0,
12577 ADDIUR1SP = 0x1
12580 static int mmreg (int r)
12582 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12584 return map[r];
12587 /* Used for 16-bit store instructions. */
12588 static int mmreg2 (int r)
12590 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12592 return map[r];
12595 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12596 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12597 #define uMIPS_RS2(op) uMIPS_RS(op)
12598 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12599 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12600 #define uMIPS_RS5(op) (op & 0x1f)
12602 /* Signed immediate */
12603 #define SIMM(op, start, width) \
12604 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12605 << (32-width)) \
12606 >> (32-width))
12607 /* Zero-extended immediate */
12608 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12610 static void gen_addiur1sp(DisasContext *ctx)
12612 int rd = mmreg(uMIPS_RD(ctx->opcode));
12614 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12617 static void gen_addiur2(DisasContext *ctx)
12619 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12620 int rd = mmreg(uMIPS_RD(ctx->opcode));
12621 int rs = mmreg(uMIPS_RS(ctx->opcode));
12623 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12626 static void gen_addiusp(DisasContext *ctx)
12628 int encoded = ZIMM(ctx->opcode, 1, 9);
12629 int decoded;
12631 if (encoded <= 1) {
12632 decoded = 256 + encoded;
12633 } else if (encoded <= 255) {
12634 decoded = encoded;
12635 } else if (encoded <= 509) {
12636 decoded = encoded - 512;
12637 } else {
12638 decoded = encoded - 768;
12641 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
12644 static void gen_addius5(DisasContext *ctx)
12646 int imm = SIMM(ctx->opcode, 1, 4);
12647 int rd = (ctx->opcode >> 5) & 0x1f;
12649 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
12652 static void gen_andi16(DisasContext *ctx)
12654 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
12655 31, 32, 63, 64, 255, 32768, 65535 };
12656 int rd = mmreg(uMIPS_RD(ctx->opcode));
12657 int rs = mmreg(uMIPS_RS(ctx->opcode));
12658 int encoded = ZIMM(ctx->opcode, 0, 4);
12660 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
12663 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
12664 int base, int16_t offset)
12666 TCGv t0, t1;
12667 TCGv_i32 t2;
12669 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12670 generate_exception_end(ctx, EXCP_RI);
12671 return;
12674 t0 = tcg_temp_new();
12676 gen_base_offset_addr(ctx, t0, base, offset);
12678 t1 = tcg_const_tl(reglist);
12679 t2 = tcg_const_i32(ctx->mem_idx);
12681 save_cpu_state(ctx, 1);
12682 switch (opc) {
12683 case LWM32:
12684 gen_helper_lwm(cpu_env, t0, t1, t2);
12685 break;
12686 case SWM32:
12687 gen_helper_swm(cpu_env, t0, t1, t2);
12688 break;
12689 #ifdef TARGET_MIPS64
12690 case LDM:
12691 gen_helper_ldm(cpu_env, t0, t1, t2);
12692 break;
12693 case SDM:
12694 gen_helper_sdm(cpu_env, t0, t1, t2);
12695 break;
12696 #endif
12698 tcg_temp_free(t0);
12699 tcg_temp_free(t1);
12700 tcg_temp_free_i32(t2);
12704 static void gen_pool16c_insn(DisasContext *ctx)
12706 int rd = mmreg((ctx->opcode >> 3) & 0x7);
12707 int rs = mmreg(ctx->opcode & 0x7);
12709 switch (((ctx->opcode) >> 4) & 0x3f) {
12710 case NOT16 + 0:
12711 case NOT16 + 1:
12712 case NOT16 + 2:
12713 case NOT16 + 3:
12714 gen_logic(ctx, OPC_NOR, rd, rs, 0);
12715 break;
12716 case XOR16 + 0:
12717 case XOR16 + 1:
12718 case XOR16 + 2:
12719 case XOR16 + 3:
12720 gen_logic(ctx, OPC_XOR, rd, rd, rs);
12721 break;
12722 case AND16 + 0:
12723 case AND16 + 1:
12724 case AND16 + 2:
12725 case AND16 + 3:
12726 gen_logic(ctx, OPC_AND, rd, rd, rs);
12727 break;
12728 case OR16 + 0:
12729 case OR16 + 1:
12730 case OR16 + 2:
12731 case OR16 + 3:
12732 gen_logic(ctx, OPC_OR, rd, rd, rs);
12733 break;
12734 case LWM16 + 0:
12735 case LWM16 + 1:
12736 case LWM16 + 2:
12737 case LWM16 + 3:
12739 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12740 int offset = ZIMM(ctx->opcode, 0, 4);
12742 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
12743 29, offset << 2);
12745 break;
12746 case SWM16 + 0:
12747 case SWM16 + 1:
12748 case SWM16 + 2:
12749 case SWM16 + 3:
12751 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12752 int offset = ZIMM(ctx->opcode, 0, 4);
12754 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
12755 29, offset << 2);
12757 break;
12758 case JR16 + 0:
12759 case JR16 + 1:
12761 int reg = ctx->opcode & 0x1f;
12763 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
12765 break;
12766 case JRC16 + 0:
12767 case JRC16 + 1:
12769 int reg = ctx->opcode & 0x1f;
12770 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
12771 /* Let normal delay slot handling in our caller take us
12772 to the branch target. */
12774 break;
12775 case JALR16 + 0:
12776 case JALR16 + 1:
12777 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
12778 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12779 break;
12780 case JALR16S + 0:
12781 case JALR16S + 1:
12782 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
12783 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12784 break;
12785 case MFHI16 + 0:
12786 case MFHI16 + 1:
12787 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
12788 break;
12789 case MFLO16 + 0:
12790 case MFLO16 + 1:
12791 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
12792 break;
12793 case BREAK16:
12794 generate_exception_end(ctx, EXCP_BREAK);
12795 break;
12796 case SDBBP16:
12797 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
12798 gen_helper_do_semihosting(cpu_env);
12799 } else {
12800 /* XXX: not clear which exception should be raised
12801 * when in debug mode...
12803 check_insn(ctx, ISA_MIPS32);
12804 generate_exception_end(ctx, EXCP_DBp);
12806 break;
12807 case JRADDIUSP + 0:
12808 case JRADDIUSP + 1:
12810 int imm = ZIMM(ctx->opcode, 0, 5);
12811 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12812 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12813 /* Let normal delay slot handling in our caller take us
12814 to the branch target. */
12816 break;
12817 default:
12818 generate_exception_end(ctx, EXCP_RI);
12819 break;
12823 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
12824 int enc_rs)
12826 int rd, rs, re, rt;
12827 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
12828 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
12829 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
12830 rd = rd_enc[enc_dest];
12831 re = re_enc[enc_dest];
12832 rs = rs_rt_enc[enc_rs];
12833 rt = rs_rt_enc[enc_rt];
12834 if (rs) {
12835 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
12836 } else {
12837 tcg_gen_movi_tl(cpu_gpr[rd], 0);
12839 if (rt) {
12840 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
12841 } else {
12842 tcg_gen_movi_tl(cpu_gpr[re], 0);
12846 static void gen_pool16c_r6_insn(DisasContext *ctx)
12848 int rt = mmreg((ctx->opcode >> 7) & 0x7);
12849 int rs = mmreg((ctx->opcode >> 4) & 0x7);
12851 switch (ctx->opcode & 0xf) {
12852 case R6_NOT16:
12853 gen_logic(ctx, OPC_NOR, rt, rs, 0);
12854 break;
12855 case R6_AND16:
12856 gen_logic(ctx, OPC_AND, rt, rt, rs);
12857 break;
12858 case R6_LWM16:
12860 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
12861 int offset = extract32(ctx->opcode, 4, 4);
12862 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
12864 break;
12865 case R6_JRC16: /* JRCADDIUSP */
12866 if ((ctx->opcode >> 4) & 1) {
12867 /* JRCADDIUSP */
12868 int imm = extract32(ctx->opcode, 5, 5);
12869 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12870 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12871 } else {
12872 /* JRC16 */
12873 int rs = extract32(ctx->opcode, 5, 5);
12874 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
12876 break;
12877 case MOVEP ... MOVEP_07:
12878 case MOVEP_0C ... MOVEP_0F:
12880 int enc_dest = uMIPS_RD(ctx->opcode);
12881 int enc_rt = uMIPS_RS2(ctx->opcode);
12882 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
12883 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
12885 break;
12886 case R6_XOR16:
12887 gen_logic(ctx, OPC_XOR, rt, rt, rs);
12888 break;
12889 case R6_OR16:
12890 gen_logic(ctx, OPC_OR, rt, rt, rs);
12891 break;
12892 case R6_SWM16:
12894 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
12895 int offset = extract32(ctx->opcode, 4, 4);
12896 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
12898 break;
12899 case JALRC16: /* BREAK16, SDBBP16 */
12900 switch (ctx->opcode & 0x3f) {
12901 case JALRC16:
12902 case JALRC16 + 0x20:
12903 /* JALRC16 */
12904 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
12905 31, 0, 0);
12906 break;
12907 case R6_BREAK16:
12908 /* BREAK16 */
12909 generate_exception(ctx, EXCP_BREAK);
12910 break;
12911 case R6_SDBBP16:
12912 /* SDBBP16 */
12913 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
12914 gen_helper_do_semihosting(cpu_env);
12915 } else {
12916 if (ctx->hflags & MIPS_HFLAG_SBRI) {
12917 generate_exception(ctx, EXCP_RI);
12918 } else {
12919 generate_exception(ctx, EXCP_DBp);
12922 break;
12924 break;
12925 default:
12926 generate_exception(ctx, EXCP_RI);
12927 break;
12931 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
12933 TCGv t0 = tcg_temp_new();
12934 TCGv t1 = tcg_temp_new();
12936 gen_load_gpr(t0, base);
12938 if (index != 0) {
12939 gen_load_gpr(t1, index);
12940 tcg_gen_shli_tl(t1, t1, 2);
12941 gen_op_addr_add(ctx, t0, t1, t0);
12944 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12945 gen_store_gpr(t1, rd);
12947 tcg_temp_free(t0);
12948 tcg_temp_free(t1);
12951 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
12952 int base, int16_t offset)
12954 TCGv t0, t1;
12956 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
12957 generate_exception_end(ctx, EXCP_RI);
12958 return;
12961 t0 = tcg_temp_new();
12962 t1 = tcg_temp_new();
12964 gen_base_offset_addr(ctx, t0, base, offset);
12966 switch (opc) {
12967 case LWP:
12968 if (rd == base) {
12969 generate_exception_end(ctx, EXCP_RI);
12970 return;
12972 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12973 gen_store_gpr(t1, rd);
12974 tcg_gen_movi_tl(t1, 4);
12975 gen_op_addr_add(ctx, t0, t0, t1);
12976 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12977 gen_store_gpr(t1, rd+1);
12978 break;
12979 case SWP:
12980 gen_load_gpr(t1, rd);
12981 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12982 tcg_gen_movi_tl(t1, 4);
12983 gen_op_addr_add(ctx, t0, t0, t1);
12984 gen_load_gpr(t1, rd+1);
12985 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12986 break;
12987 #ifdef TARGET_MIPS64
12988 case LDP:
12989 if (rd == base) {
12990 generate_exception_end(ctx, EXCP_RI);
12991 return;
12993 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12994 gen_store_gpr(t1, rd);
12995 tcg_gen_movi_tl(t1, 8);
12996 gen_op_addr_add(ctx, t0, t0, t1);
12997 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12998 gen_store_gpr(t1, rd+1);
12999 break;
13000 case SDP:
13001 gen_load_gpr(t1, rd);
13002 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13003 tcg_gen_movi_tl(t1, 8);
13004 gen_op_addr_add(ctx, t0, t0, t1);
13005 gen_load_gpr(t1, rd+1);
13006 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13007 break;
13008 #endif
13010 tcg_temp_free(t0);
13011 tcg_temp_free(t1);
13014 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
13016 int extension = (ctx->opcode >> 6) & 0x3f;
13017 int minor = (ctx->opcode >> 12) & 0xf;
13018 uint32_t mips32_op;
13020 switch (extension) {
13021 case TEQ:
13022 mips32_op = OPC_TEQ;
13023 goto do_trap;
13024 case TGE:
13025 mips32_op = OPC_TGE;
13026 goto do_trap;
13027 case TGEU:
13028 mips32_op = OPC_TGEU;
13029 goto do_trap;
13030 case TLT:
13031 mips32_op = OPC_TLT;
13032 goto do_trap;
13033 case TLTU:
13034 mips32_op = OPC_TLTU;
13035 goto do_trap;
13036 case TNE:
13037 mips32_op = OPC_TNE;
13038 do_trap:
13039 gen_trap(ctx, mips32_op, rs, rt, -1);
13040 break;
13041 #ifndef CONFIG_USER_ONLY
13042 case MFC0:
13043 case MFC0 + 32:
13044 check_cp0_enabled(ctx);
13045 if (rt == 0) {
13046 /* Treat as NOP. */
13047 break;
13049 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
13050 break;
13051 case MTC0:
13052 case MTC0 + 32:
13053 check_cp0_enabled(ctx);
13055 TCGv t0 = tcg_temp_new();
13057 gen_load_gpr(t0, rt);
13058 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
13059 tcg_temp_free(t0);
13061 break;
13062 #endif
13063 case 0x2a:
13064 switch (minor & 3) {
13065 case MADD_ACC:
13066 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
13067 break;
13068 case MADDU_ACC:
13069 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
13070 break;
13071 case MSUB_ACC:
13072 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
13073 break;
13074 case MSUBU_ACC:
13075 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
13076 break;
13077 default:
13078 goto pool32axf_invalid;
13080 break;
13081 case 0x32:
13082 switch (minor & 3) {
13083 case MULT_ACC:
13084 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
13085 break;
13086 case MULTU_ACC:
13087 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
13088 break;
13089 default:
13090 goto pool32axf_invalid;
13092 break;
13093 case 0x2c:
13094 switch (minor) {
13095 case BITSWAP:
13096 check_insn(ctx, ISA_MIPS32R6);
13097 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
13098 break;
13099 case SEB:
13100 gen_bshfl(ctx, OPC_SEB, rs, rt);
13101 break;
13102 case SEH:
13103 gen_bshfl(ctx, OPC_SEH, rs, rt);
13104 break;
13105 case CLO:
13106 mips32_op = OPC_CLO;
13107 goto do_cl;
13108 case CLZ:
13109 mips32_op = OPC_CLZ;
13110 do_cl:
13111 check_insn(ctx, ISA_MIPS32);
13112 gen_cl(ctx, mips32_op, rt, rs);
13113 break;
13114 case RDHWR:
13115 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13116 gen_rdhwr(ctx, rt, rs, 0);
13117 break;
13118 case WSBH:
13119 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13120 break;
13121 case MULT:
13122 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13123 mips32_op = OPC_MULT;
13124 goto do_mul;
13125 case MULTU:
13126 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13127 mips32_op = OPC_MULTU;
13128 goto do_mul;
13129 case DIV:
13130 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13131 mips32_op = OPC_DIV;
13132 goto do_div;
13133 case DIVU:
13134 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13135 mips32_op = OPC_DIVU;
13136 goto do_div;
13137 do_div:
13138 check_insn(ctx, ISA_MIPS32);
13139 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13140 break;
13141 case MADD:
13142 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13143 mips32_op = OPC_MADD;
13144 goto do_mul;
13145 case MADDU:
13146 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13147 mips32_op = OPC_MADDU;
13148 goto do_mul;
13149 case MSUB:
13150 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13151 mips32_op = OPC_MSUB;
13152 goto do_mul;
13153 case MSUBU:
13154 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13155 mips32_op = OPC_MSUBU;
13156 do_mul:
13157 check_insn(ctx, ISA_MIPS32);
13158 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13159 break;
13160 default:
13161 goto pool32axf_invalid;
13163 break;
13164 case 0x34:
13165 switch (minor) {
13166 case MFC2:
13167 case MTC2:
13168 case MFHC2:
13169 case MTHC2:
13170 case CFC2:
13171 case CTC2:
13172 generate_exception_err(ctx, EXCP_CpU, 2);
13173 break;
13174 default:
13175 goto pool32axf_invalid;
13177 break;
13178 case 0x3c:
13179 switch (minor) {
13180 case JALR: /* JALRC */
13181 case JALR_HB: /* JALRC_HB */
13182 if (ctx->insn_flags & ISA_MIPS32R6) {
13183 /* JALRC, JALRC_HB */
13184 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13185 } else {
13186 /* JALR, JALR_HB */
13187 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13188 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13190 break;
13191 case JALRS:
13192 case JALRS_HB:
13193 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13194 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13195 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13196 break;
13197 default:
13198 goto pool32axf_invalid;
13200 break;
13201 case 0x05:
13202 switch (minor) {
13203 case RDPGPR:
13204 check_cp0_enabled(ctx);
13205 check_insn(ctx, ISA_MIPS32R2);
13206 gen_load_srsgpr(rs, rt);
13207 break;
13208 case WRPGPR:
13209 check_cp0_enabled(ctx);
13210 check_insn(ctx, ISA_MIPS32R2);
13211 gen_store_srsgpr(rs, rt);
13212 break;
13213 default:
13214 goto pool32axf_invalid;
13216 break;
13217 #ifndef CONFIG_USER_ONLY
13218 case 0x0d:
13219 switch (minor) {
13220 case TLBP:
13221 mips32_op = OPC_TLBP;
13222 goto do_cp0;
13223 case TLBR:
13224 mips32_op = OPC_TLBR;
13225 goto do_cp0;
13226 case TLBWI:
13227 mips32_op = OPC_TLBWI;
13228 goto do_cp0;
13229 case TLBWR:
13230 mips32_op = OPC_TLBWR;
13231 goto do_cp0;
13232 case TLBINV:
13233 mips32_op = OPC_TLBINV;
13234 goto do_cp0;
13235 case TLBINVF:
13236 mips32_op = OPC_TLBINVF;
13237 goto do_cp0;
13238 case WAIT:
13239 mips32_op = OPC_WAIT;
13240 goto do_cp0;
13241 case DERET:
13242 mips32_op = OPC_DERET;
13243 goto do_cp0;
13244 case ERET:
13245 mips32_op = OPC_ERET;
13246 do_cp0:
13247 gen_cp0(env, ctx, mips32_op, rt, rs);
13248 break;
13249 default:
13250 goto pool32axf_invalid;
13252 break;
13253 case 0x1d:
13254 switch (minor) {
13255 case DI:
13256 check_cp0_enabled(ctx);
13258 TCGv t0 = tcg_temp_new();
13260 save_cpu_state(ctx, 1);
13261 gen_helper_di(t0, cpu_env);
13262 gen_store_gpr(t0, rs);
13263 /* Stop translation as we may have switched the execution mode */
13264 ctx->bstate = BS_STOP;
13265 tcg_temp_free(t0);
13267 break;
13268 case EI:
13269 check_cp0_enabled(ctx);
13271 TCGv t0 = tcg_temp_new();
13273 save_cpu_state(ctx, 1);
13274 gen_helper_ei(t0, cpu_env);
13275 gen_store_gpr(t0, rs);
13276 /* Stop translation as we may have switched the execution mode */
13277 ctx->bstate = BS_STOP;
13278 tcg_temp_free(t0);
13280 break;
13281 default:
13282 goto pool32axf_invalid;
13284 break;
13285 #endif
13286 case 0x2d:
13287 switch (minor) {
13288 case SYNC:
13289 /* NOP */
13290 break;
13291 case SYSCALL:
13292 generate_exception_end(ctx, EXCP_SYSCALL);
13293 break;
13294 case SDBBP:
13295 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
13296 gen_helper_do_semihosting(cpu_env);
13297 } else {
13298 check_insn(ctx, ISA_MIPS32);
13299 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13300 generate_exception_end(ctx, EXCP_RI);
13301 } else {
13302 generate_exception_end(ctx, EXCP_DBp);
13305 break;
13306 default:
13307 goto pool32axf_invalid;
13309 break;
13310 case 0x01:
13311 switch (minor & 3) {
13312 case MFHI_ACC:
13313 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
13314 break;
13315 case MFLO_ACC:
13316 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
13317 break;
13318 case MTHI_ACC:
13319 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
13320 break;
13321 case MTLO_ACC:
13322 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
13323 break;
13324 default:
13325 goto pool32axf_invalid;
13327 break;
13328 case 0x35:
13329 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13330 switch (minor) {
13331 case MFHI32:
13332 gen_HILO(ctx, OPC_MFHI, 0, rs);
13333 break;
13334 case MFLO32:
13335 gen_HILO(ctx, OPC_MFLO, 0, rs);
13336 break;
13337 case MTHI32:
13338 gen_HILO(ctx, OPC_MTHI, 0, rs);
13339 break;
13340 case MTLO32:
13341 gen_HILO(ctx, OPC_MTLO, 0, rs);
13342 break;
13343 default:
13344 goto pool32axf_invalid;
13346 break;
13347 default:
13348 pool32axf_invalid:
13349 MIPS_INVAL("pool32axf");
13350 generate_exception_end(ctx, EXCP_RI);
13351 break;
13355 /* Values for microMIPS fmt field. Variable-width, depending on which
13356 formats the instruction supports. */
13358 enum {
13359 FMT_SD_S = 0,
13360 FMT_SD_D = 1,
13362 FMT_SDPS_S = 0,
13363 FMT_SDPS_D = 1,
13364 FMT_SDPS_PS = 2,
13366 FMT_SWL_S = 0,
13367 FMT_SWL_W = 1,
13368 FMT_SWL_L = 2,
13370 FMT_DWL_D = 0,
13371 FMT_DWL_W = 1,
13372 FMT_DWL_L = 2
13375 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
13377 int extension = (ctx->opcode >> 6) & 0x3ff;
13378 uint32_t mips32_op;
13380 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
13381 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
13382 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
13384 switch (extension) {
13385 case FLOAT_1BIT_FMT(CFC1, 0):
13386 mips32_op = OPC_CFC1;
13387 goto do_cp1;
13388 case FLOAT_1BIT_FMT(CTC1, 0):
13389 mips32_op = OPC_CTC1;
13390 goto do_cp1;
13391 case FLOAT_1BIT_FMT(MFC1, 0):
13392 mips32_op = OPC_MFC1;
13393 goto do_cp1;
13394 case FLOAT_1BIT_FMT(MTC1, 0):
13395 mips32_op = OPC_MTC1;
13396 goto do_cp1;
13397 case FLOAT_1BIT_FMT(MFHC1, 0):
13398 mips32_op = OPC_MFHC1;
13399 goto do_cp1;
13400 case FLOAT_1BIT_FMT(MTHC1, 0):
13401 mips32_op = OPC_MTHC1;
13402 do_cp1:
13403 gen_cp1(ctx, mips32_op, rt, rs);
13404 break;
13406 /* Reciprocal square root */
13407 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
13408 mips32_op = OPC_RSQRT_S;
13409 goto do_unaryfp;
13410 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
13411 mips32_op = OPC_RSQRT_D;
13412 goto do_unaryfp;
13414 /* Square root */
13415 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
13416 mips32_op = OPC_SQRT_S;
13417 goto do_unaryfp;
13418 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
13419 mips32_op = OPC_SQRT_D;
13420 goto do_unaryfp;
13422 /* Reciprocal */
13423 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
13424 mips32_op = OPC_RECIP_S;
13425 goto do_unaryfp;
13426 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
13427 mips32_op = OPC_RECIP_D;
13428 goto do_unaryfp;
13430 /* Floor */
13431 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
13432 mips32_op = OPC_FLOOR_L_S;
13433 goto do_unaryfp;
13434 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
13435 mips32_op = OPC_FLOOR_L_D;
13436 goto do_unaryfp;
13437 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
13438 mips32_op = OPC_FLOOR_W_S;
13439 goto do_unaryfp;
13440 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
13441 mips32_op = OPC_FLOOR_W_D;
13442 goto do_unaryfp;
13444 /* Ceiling */
13445 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
13446 mips32_op = OPC_CEIL_L_S;
13447 goto do_unaryfp;
13448 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
13449 mips32_op = OPC_CEIL_L_D;
13450 goto do_unaryfp;
13451 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
13452 mips32_op = OPC_CEIL_W_S;
13453 goto do_unaryfp;
13454 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
13455 mips32_op = OPC_CEIL_W_D;
13456 goto do_unaryfp;
13458 /* Truncation */
13459 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
13460 mips32_op = OPC_TRUNC_L_S;
13461 goto do_unaryfp;
13462 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
13463 mips32_op = OPC_TRUNC_L_D;
13464 goto do_unaryfp;
13465 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
13466 mips32_op = OPC_TRUNC_W_S;
13467 goto do_unaryfp;
13468 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
13469 mips32_op = OPC_TRUNC_W_D;
13470 goto do_unaryfp;
13472 /* Round */
13473 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
13474 mips32_op = OPC_ROUND_L_S;
13475 goto do_unaryfp;
13476 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
13477 mips32_op = OPC_ROUND_L_D;
13478 goto do_unaryfp;
13479 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
13480 mips32_op = OPC_ROUND_W_S;
13481 goto do_unaryfp;
13482 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
13483 mips32_op = OPC_ROUND_W_D;
13484 goto do_unaryfp;
13486 /* Integer to floating-point conversion */
13487 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
13488 mips32_op = OPC_CVT_L_S;
13489 goto do_unaryfp;
13490 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
13491 mips32_op = OPC_CVT_L_D;
13492 goto do_unaryfp;
13493 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
13494 mips32_op = OPC_CVT_W_S;
13495 goto do_unaryfp;
13496 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
13497 mips32_op = OPC_CVT_W_D;
13498 goto do_unaryfp;
13500 /* Paired-foo conversions */
13501 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
13502 mips32_op = OPC_CVT_S_PL;
13503 goto do_unaryfp;
13504 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13505 mips32_op = OPC_CVT_S_PU;
13506 goto do_unaryfp;
13507 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13508 mips32_op = OPC_CVT_PW_PS;
13509 goto do_unaryfp;
13510 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13511 mips32_op = OPC_CVT_PS_PW;
13512 goto do_unaryfp;
13514 /* Floating-point moves */
13515 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13516 mips32_op = OPC_MOV_S;
13517 goto do_unaryfp;
13518 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13519 mips32_op = OPC_MOV_D;
13520 goto do_unaryfp;
13521 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13522 mips32_op = OPC_MOV_PS;
13523 goto do_unaryfp;
13525 /* Absolute value */
13526 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13527 mips32_op = OPC_ABS_S;
13528 goto do_unaryfp;
13529 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13530 mips32_op = OPC_ABS_D;
13531 goto do_unaryfp;
13532 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13533 mips32_op = OPC_ABS_PS;
13534 goto do_unaryfp;
13536 /* Negation */
13537 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13538 mips32_op = OPC_NEG_S;
13539 goto do_unaryfp;
13540 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13541 mips32_op = OPC_NEG_D;
13542 goto do_unaryfp;
13543 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13544 mips32_op = OPC_NEG_PS;
13545 goto do_unaryfp;
13547 /* Reciprocal square root step */
13548 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13549 mips32_op = OPC_RSQRT1_S;
13550 goto do_unaryfp;
13551 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13552 mips32_op = OPC_RSQRT1_D;
13553 goto do_unaryfp;
13554 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13555 mips32_op = OPC_RSQRT1_PS;
13556 goto do_unaryfp;
13558 /* Reciprocal step */
13559 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13560 mips32_op = OPC_RECIP1_S;
13561 goto do_unaryfp;
13562 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13563 mips32_op = OPC_RECIP1_S;
13564 goto do_unaryfp;
13565 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13566 mips32_op = OPC_RECIP1_PS;
13567 goto do_unaryfp;
13569 /* Conversions from double */
13570 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13571 mips32_op = OPC_CVT_D_S;
13572 goto do_unaryfp;
13573 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13574 mips32_op = OPC_CVT_D_W;
13575 goto do_unaryfp;
13576 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13577 mips32_op = OPC_CVT_D_L;
13578 goto do_unaryfp;
13580 /* Conversions from single */
13581 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13582 mips32_op = OPC_CVT_S_D;
13583 goto do_unaryfp;
13584 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13585 mips32_op = OPC_CVT_S_W;
13586 goto do_unaryfp;
13587 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13588 mips32_op = OPC_CVT_S_L;
13589 do_unaryfp:
13590 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13591 break;
13593 /* Conditional moves on floating-point codes */
13594 case COND_FLOAT_MOV(MOVT, 0):
13595 case COND_FLOAT_MOV(MOVT, 1):
13596 case COND_FLOAT_MOV(MOVT, 2):
13597 case COND_FLOAT_MOV(MOVT, 3):
13598 case COND_FLOAT_MOV(MOVT, 4):
13599 case COND_FLOAT_MOV(MOVT, 5):
13600 case COND_FLOAT_MOV(MOVT, 6):
13601 case COND_FLOAT_MOV(MOVT, 7):
13602 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13603 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13604 break;
13605 case COND_FLOAT_MOV(MOVF, 0):
13606 case COND_FLOAT_MOV(MOVF, 1):
13607 case COND_FLOAT_MOV(MOVF, 2):
13608 case COND_FLOAT_MOV(MOVF, 3):
13609 case COND_FLOAT_MOV(MOVF, 4):
13610 case COND_FLOAT_MOV(MOVF, 5):
13611 case COND_FLOAT_MOV(MOVF, 6):
13612 case COND_FLOAT_MOV(MOVF, 7):
13613 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13614 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13615 break;
13616 default:
13617 MIPS_INVAL("pool32fxf");
13618 generate_exception_end(ctx, EXCP_RI);
13619 break;
13623 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
13625 int32_t offset;
13626 uint16_t insn;
13627 int rt, rs, rd, rr;
13628 int16_t imm;
13629 uint32_t op, minor, mips32_op;
13630 uint32_t cond, fmt, cc;
13632 insn = cpu_lduw_code(env, ctx->pc + 2);
13633 ctx->opcode = (ctx->opcode << 16) | insn;
13635 rt = (ctx->opcode >> 21) & 0x1f;
13636 rs = (ctx->opcode >> 16) & 0x1f;
13637 rd = (ctx->opcode >> 11) & 0x1f;
13638 rr = (ctx->opcode >> 6) & 0x1f;
13639 imm = (int16_t) ctx->opcode;
13641 op = (ctx->opcode >> 26) & 0x3f;
13642 switch (op) {
13643 case POOL32A:
13644 minor = ctx->opcode & 0x3f;
13645 switch (minor) {
13646 case 0x00:
13647 minor = (ctx->opcode >> 6) & 0xf;
13648 switch (minor) {
13649 case SLL32:
13650 mips32_op = OPC_SLL;
13651 goto do_shifti;
13652 case SRA:
13653 mips32_op = OPC_SRA;
13654 goto do_shifti;
13655 case SRL32:
13656 mips32_op = OPC_SRL;
13657 goto do_shifti;
13658 case ROTR:
13659 mips32_op = OPC_ROTR;
13660 do_shifti:
13661 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
13662 break;
13663 case SELEQZ:
13664 check_insn(ctx, ISA_MIPS32R6);
13665 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
13666 break;
13667 case SELNEZ:
13668 check_insn(ctx, ISA_MIPS32R6);
13669 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
13670 break;
13671 case R6_RDHWR:
13672 check_insn(ctx, ISA_MIPS32R6);
13673 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
13674 break;
13675 default:
13676 goto pool32a_invalid;
13678 break;
13679 case 0x10:
13680 minor = (ctx->opcode >> 6) & 0xf;
13681 switch (minor) {
13682 /* Arithmetic */
13683 case ADD:
13684 mips32_op = OPC_ADD;
13685 goto do_arith;
13686 case ADDU32:
13687 mips32_op = OPC_ADDU;
13688 goto do_arith;
13689 case SUB:
13690 mips32_op = OPC_SUB;
13691 goto do_arith;
13692 case SUBU32:
13693 mips32_op = OPC_SUBU;
13694 goto do_arith;
13695 case MUL:
13696 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13697 mips32_op = OPC_MUL;
13698 do_arith:
13699 gen_arith(ctx, mips32_op, rd, rs, rt);
13700 break;
13701 /* Shifts */
13702 case SLLV:
13703 mips32_op = OPC_SLLV;
13704 goto do_shift;
13705 case SRLV:
13706 mips32_op = OPC_SRLV;
13707 goto do_shift;
13708 case SRAV:
13709 mips32_op = OPC_SRAV;
13710 goto do_shift;
13711 case ROTRV:
13712 mips32_op = OPC_ROTRV;
13713 do_shift:
13714 gen_shift(ctx, mips32_op, rd, rs, rt);
13715 break;
13716 /* Logical operations */
13717 case AND:
13718 mips32_op = OPC_AND;
13719 goto do_logic;
13720 case OR32:
13721 mips32_op = OPC_OR;
13722 goto do_logic;
13723 case NOR:
13724 mips32_op = OPC_NOR;
13725 goto do_logic;
13726 case XOR32:
13727 mips32_op = OPC_XOR;
13728 do_logic:
13729 gen_logic(ctx, mips32_op, rd, rs, rt);
13730 break;
13731 /* Set less than */
13732 case SLT:
13733 mips32_op = OPC_SLT;
13734 goto do_slt;
13735 case SLTU:
13736 mips32_op = OPC_SLTU;
13737 do_slt:
13738 gen_slt(ctx, mips32_op, rd, rs, rt);
13739 break;
13740 default:
13741 goto pool32a_invalid;
13743 break;
13744 case 0x18:
13745 minor = (ctx->opcode >> 6) & 0xf;
13746 switch (minor) {
13747 /* Conditional moves */
13748 case MOVN: /* MUL */
13749 if (ctx->insn_flags & ISA_MIPS32R6) {
13750 /* MUL */
13751 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
13752 } else {
13753 /* MOVN */
13754 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
13756 break;
13757 case MOVZ: /* MUH */
13758 if (ctx->insn_flags & ISA_MIPS32R6) {
13759 /* MUH */
13760 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
13761 } else {
13762 /* MOVZ */
13763 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
13765 break;
13766 case MULU:
13767 check_insn(ctx, ISA_MIPS32R6);
13768 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
13769 break;
13770 case MUHU:
13771 check_insn(ctx, ISA_MIPS32R6);
13772 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
13773 break;
13774 case LWXS: /* DIV */
13775 if (ctx->insn_flags & ISA_MIPS32R6) {
13776 /* DIV */
13777 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
13778 } else {
13779 /* LWXS */
13780 gen_ldxs(ctx, rs, rt, rd);
13782 break;
13783 case MOD:
13784 check_insn(ctx, ISA_MIPS32R6);
13785 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
13786 break;
13787 case R6_DIVU:
13788 check_insn(ctx, ISA_MIPS32R6);
13789 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
13790 break;
13791 case MODU:
13792 check_insn(ctx, ISA_MIPS32R6);
13793 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
13794 break;
13795 default:
13796 goto pool32a_invalid;
13798 break;
13799 case INS:
13800 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
13801 return;
13802 case LSA:
13803 check_insn(ctx, ISA_MIPS32R6);
13804 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
13805 extract32(ctx->opcode, 9, 2));
13806 break;
13807 case ALIGN:
13808 check_insn(ctx, ISA_MIPS32R6);
13809 gen_align(ctx, OPC_ALIGN, rd, rs, rt,
13810 extract32(ctx->opcode, 9, 2));
13811 break;
13812 case EXT:
13813 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
13814 return;
13815 case POOL32AXF:
13816 gen_pool32axf(env, ctx, rt, rs);
13817 break;
13818 case BREAK32:
13819 generate_exception_end(ctx, EXCP_BREAK);
13820 break;
13821 case SIGRIE:
13822 check_insn(ctx, ISA_MIPS32R6);
13823 generate_exception_end(ctx, EXCP_RI);
13824 break;
13825 default:
13826 pool32a_invalid:
13827 MIPS_INVAL("pool32a");
13828 generate_exception_end(ctx, EXCP_RI);
13829 break;
13831 break;
13832 case POOL32B:
13833 minor = (ctx->opcode >> 12) & 0xf;
13834 switch (minor) {
13835 case CACHE:
13836 check_cp0_enabled(ctx);
13837 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
13838 gen_cache_operation(ctx, rt, rs, imm);
13840 break;
13841 case LWC2:
13842 case SWC2:
13843 /* COP2: Not implemented. */
13844 generate_exception_err(ctx, EXCP_CpU, 2);
13845 break;
13846 #ifdef TARGET_MIPS64
13847 case LDP:
13848 case SDP:
13849 check_insn(ctx, ISA_MIPS3);
13850 check_mips_64(ctx);
13851 /* Fallthrough */
13852 #endif
13853 case LWP:
13854 case SWP:
13855 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13856 break;
13857 #ifdef TARGET_MIPS64
13858 case LDM:
13859 case SDM:
13860 check_insn(ctx, ISA_MIPS3);
13861 check_mips_64(ctx);
13862 /* Fallthrough */
13863 #endif
13864 case LWM32:
13865 case SWM32:
13866 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13867 break;
13868 default:
13869 MIPS_INVAL("pool32b");
13870 generate_exception_end(ctx, EXCP_RI);
13871 break;
13873 break;
13874 case POOL32F:
13875 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
13876 minor = ctx->opcode & 0x3f;
13877 check_cp1_enabled(ctx);
13878 switch (minor) {
13879 case ALNV_PS:
13880 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13881 mips32_op = OPC_ALNV_PS;
13882 goto do_madd;
13883 case MADD_S:
13884 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13885 mips32_op = OPC_MADD_S;
13886 goto do_madd;
13887 case MADD_D:
13888 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13889 mips32_op = OPC_MADD_D;
13890 goto do_madd;
13891 case MADD_PS:
13892 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13893 mips32_op = OPC_MADD_PS;
13894 goto do_madd;
13895 case MSUB_S:
13896 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13897 mips32_op = OPC_MSUB_S;
13898 goto do_madd;
13899 case MSUB_D:
13900 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13901 mips32_op = OPC_MSUB_D;
13902 goto do_madd;
13903 case MSUB_PS:
13904 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13905 mips32_op = OPC_MSUB_PS;
13906 goto do_madd;
13907 case NMADD_S:
13908 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13909 mips32_op = OPC_NMADD_S;
13910 goto do_madd;
13911 case NMADD_D:
13912 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13913 mips32_op = OPC_NMADD_D;
13914 goto do_madd;
13915 case NMADD_PS:
13916 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13917 mips32_op = OPC_NMADD_PS;
13918 goto do_madd;
13919 case NMSUB_S:
13920 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13921 mips32_op = OPC_NMSUB_S;
13922 goto do_madd;
13923 case NMSUB_D:
13924 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13925 mips32_op = OPC_NMSUB_D;
13926 goto do_madd;
13927 case NMSUB_PS:
13928 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13929 mips32_op = OPC_NMSUB_PS;
13930 do_madd:
13931 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
13932 break;
13933 case CABS_COND_FMT:
13934 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13935 cond = (ctx->opcode >> 6) & 0xf;
13936 cc = (ctx->opcode >> 13) & 0x7;
13937 fmt = (ctx->opcode >> 10) & 0x3;
13938 switch (fmt) {
13939 case 0x0:
13940 gen_cmpabs_s(ctx, cond, rt, rs, cc);
13941 break;
13942 case 0x1:
13943 gen_cmpabs_d(ctx, cond, rt, rs, cc);
13944 break;
13945 case 0x2:
13946 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
13947 break;
13948 default:
13949 goto pool32f_invalid;
13951 break;
13952 case C_COND_FMT:
13953 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13954 cond = (ctx->opcode >> 6) & 0xf;
13955 cc = (ctx->opcode >> 13) & 0x7;
13956 fmt = (ctx->opcode >> 10) & 0x3;
13957 switch (fmt) {
13958 case 0x0:
13959 gen_cmp_s(ctx, cond, rt, rs, cc);
13960 break;
13961 case 0x1:
13962 gen_cmp_d(ctx, cond, rt, rs, cc);
13963 break;
13964 case 0x2:
13965 gen_cmp_ps(ctx, cond, rt, rs, cc);
13966 break;
13967 default:
13968 goto pool32f_invalid;
13970 break;
13971 case CMP_CONDN_S:
13972 check_insn(ctx, ISA_MIPS32R6);
13973 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
13974 break;
13975 case CMP_CONDN_D:
13976 check_insn(ctx, ISA_MIPS32R6);
13977 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
13978 break;
13979 case POOL32FXF:
13980 gen_pool32fxf(ctx, rt, rs);
13981 break;
13982 case 0x00:
13983 /* PLL foo */
13984 switch ((ctx->opcode >> 6) & 0x7) {
13985 case PLL_PS:
13986 mips32_op = OPC_PLL_PS;
13987 goto do_ps;
13988 case PLU_PS:
13989 mips32_op = OPC_PLU_PS;
13990 goto do_ps;
13991 case PUL_PS:
13992 mips32_op = OPC_PUL_PS;
13993 goto do_ps;
13994 case PUU_PS:
13995 mips32_op = OPC_PUU_PS;
13996 goto do_ps;
13997 case CVT_PS_S:
13998 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13999 mips32_op = OPC_CVT_PS_S;
14000 do_ps:
14001 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14002 break;
14003 default:
14004 goto pool32f_invalid;
14006 break;
14007 case MIN_FMT:
14008 check_insn(ctx, ISA_MIPS32R6);
14009 switch ((ctx->opcode >> 9) & 0x3) {
14010 case FMT_SDPS_S:
14011 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
14012 break;
14013 case FMT_SDPS_D:
14014 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
14015 break;
14016 default:
14017 goto pool32f_invalid;
14019 break;
14020 case 0x08:
14021 /* [LS][WDU]XC1 */
14022 switch ((ctx->opcode >> 6) & 0x7) {
14023 case LWXC1:
14024 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14025 mips32_op = OPC_LWXC1;
14026 goto do_ldst_cp1;
14027 case SWXC1:
14028 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14029 mips32_op = OPC_SWXC1;
14030 goto do_ldst_cp1;
14031 case LDXC1:
14032 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14033 mips32_op = OPC_LDXC1;
14034 goto do_ldst_cp1;
14035 case SDXC1:
14036 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14037 mips32_op = OPC_SDXC1;
14038 goto do_ldst_cp1;
14039 case LUXC1:
14040 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14041 mips32_op = OPC_LUXC1;
14042 goto do_ldst_cp1;
14043 case SUXC1:
14044 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14045 mips32_op = OPC_SUXC1;
14046 do_ldst_cp1:
14047 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
14048 break;
14049 default:
14050 goto pool32f_invalid;
14052 break;
14053 case MAX_FMT:
14054 check_insn(ctx, ISA_MIPS32R6);
14055 switch ((ctx->opcode >> 9) & 0x3) {
14056 case FMT_SDPS_S:
14057 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
14058 break;
14059 case FMT_SDPS_D:
14060 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
14061 break;
14062 default:
14063 goto pool32f_invalid;
14065 break;
14066 case 0x18:
14067 /* 3D insns */
14068 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14069 fmt = (ctx->opcode >> 9) & 0x3;
14070 switch ((ctx->opcode >> 6) & 0x7) {
14071 case RSQRT2_FMT:
14072 switch (fmt) {
14073 case FMT_SDPS_S:
14074 mips32_op = OPC_RSQRT2_S;
14075 goto do_3d;
14076 case FMT_SDPS_D:
14077 mips32_op = OPC_RSQRT2_D;
14078 goto do_3d;
14079 case FMT_SDPS_PS:
14080 mips32_op = OPC_RSQRT2_PS;
14081 goto do_3d;
14082 default:
14083 goto pool32f_invalid;
14085 break;
14086 case RECIP2_FMT:
14087 switch (fmt) {
14088 case FMT_SDPS_S:
14089 mips32_op = OPC_RECIP2_S;
14090 goto do_3d;
14091 case FMT_SDPS_D:
14092 mips32_op = OPC_RECIP2_D;
14093 goto do_3d;
14094 case FMT_SDPS_PS:
14095 mips32_op = OPC_RECIP2_PS;
14096 goto do_3d;
14097 default:
14098 goto pool32f_invalid;
14100 break;
14101 case ADDR_PS:
14102 mips32_op = OPC_ADDR_PS;
14103 goto do_3d;
14104 case MULR_PS:
14105 mips32_op = OPC_MULR_PS;
14106 do_3d:
14107 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14108 break;
14109 default:
14110 goto pool32f_invalid;
14112 break;
14113 case 0x20:
14114 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
14115 cc = (ctx->opcode >> 13) & 0x7;
14116 fmt = (ctx->opcode >> 9) & 0x3;
14117 switch ((ctx->opcode >> 6) & 0x7) {
14118 case MOVF_FMT: /* RINT_FMT */
14119 if (ctx->insn_flags & ISA_MIPS32R6) {
14120 /* RINT_FMT */
14121 switch (fmt) {
14122 case FMT_SDPS_S:
14123 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14124 break;
14125 case FMT_SDPS_D:
14126 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14127 break;
14128 default:
14129 goto pool32f_invalid;
14131 } else {
14132 /* MOVF_FMT */
14133 switch (fmt) {
14134 case FMT_SDPS_S:
14135 gen_movcf_s(ctx, rs, rt, cc, 0);
14136 break;
14137 case FMT_SDPS_D:
14138 gen_movcf_d(ctx, rs, rt, cc, 0);
14139 break;
14140 case FMT_SDPS_PS:
14141 check_ps(ctx);
14142 gen_movcf_ps(ctx, rs, rt, cc, 0);
14143 break;
14144 default:
14145 goto pool32f_invalid;
14148 break;
14149 case MOVT_FMT: /* CLASS_FMT */
14150 if (ctx->insn_flags & ISA_MIPS32R6) {
14151 /* CLASS_FMT */
14152 switch (fmt) {
14153 case FMT_SDPS_S:
14154 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14155 break;
14156 case FMT_SDPS_D:
14157 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14158 break;
14159 default:
14160 goto pool32f_invalid;
14162 } else {
14163 /* MOVT_FMT */
14164 switch (fmt) {
14165 case FMT_SDPS_S:
14166 gen_movcf_s(ctx, rs, rt, cc, 1);
14167 break;
14168 case FMT_SDPS_D:
14169 gen_movcf_d(ctx, rs, rt, cc, 1);
14170 break;
14171 case FMT_SDPS_PS:
14172 check_ps(ctx);
14173 gen_movcf_ps(ctx, rs, rt, cc, 1);
14174 break;
14175 default:
14176 goto pool32f_invalid;
14179 break;
14180 case PREFX:
14181 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14182 break;
14183 default:
14184 goto pool32f_invalid;
14186 break;
14187 #define FINSN_3ARG_SDPS(prfx) \
14188 switch ((ctx->opcode >> 8) & 0x3) { \
14189 case FMT_SDPS_S: \
14190 mips32_op = OPC_##prfx##_S; \
14191 goto do_fpop; \
14192 case FMT_SDPS_D: \
14193 mips32_op = OPC_##prfx##_D; \
14194 goto do_fpop; \
14195 case FMT_SDPS_PS: \
14196 check_ps(ctx); \
14197 mips32_op = OPC_##prfx##_PS; \
14198 goto do_fpop; \
14199 default: \
14200 goto pool32f_invalid; \
14202 case MINA_FMT:
14203 check_insn(ctx, ISA_MIPS32R6);
14204 switch ((ctx->opcode >> 9) & 0x3) {
14205 case FMT_SDPS_S:
14206 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14207 break;
14208 case FMT_SDPS_D:
14209 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14210 break;
14211 default:
14212 goto pool32f_invalid;
14214 break;
14215 case MAXA_FMT:
14216 check_insn(ctx, ISA_MIPS32R6);
14217 switch ((ctx->opcode >> 9) & 0x3) {
14218 case FMT_SDPS_S:
14219 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14220 break;
14221 case FMT_SDPS_D:
14222 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14223 break;
14224 default:
14225 goto pool32f_invalid;
14227 break;
14228 case 0x30:
14229 /* regular FP ops */
14230 switch ((ctx->opcode >> 6) & 0x3) {
14231 case ADD_FMT:
14232 FINSN_3ARG_SDPS(ADD);
14233 break;
14234 case SUB_FMT:
14235 FINSN_3ARG_SDPS(SUB);
14236 break;
14237 case MUL_FMT:
14238 FINSN_3ARG_SDPS(MUL);
14239 break;
14240 case DIV_FMT:
14241 fmt = (ctx->opcode >> 8) & 0x3;
14242 if (fmt == 1) {
14243 mips32_op = OPC_DIV_D;
14244 } else if (fmt == 0) {
14245 mips32_op = OPC_DIV_S;
14246 } else {
14247 goto pool32f_invalid;
14249 goto do_fpop;
14250 default:
14251 goto pool32f_invalid;
14253 break;
14254 case 0x38:
14255 /* cmovs */
14256 switch ((ctx->opcode >> 6) & 0x7) {
14257 case MOVN_FMT: /* SELNEZ_FMT */
14258 if (ctx->insn_flags & ISA_MIPS32R6) {
14259 /* SELNEZ_FMT */
14260 switch ((ctx->opcode >> 9) & 0x3) {
14261 case FMT_SDPS_S:
14262 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14263 break;
14264 case FMT_SDPS_D:
14265 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
14266 break;
14267 default:
14268 goto pool32f_invalid;
14270 } else {
14271 /* MOVN_FMT */
14272 FINSN_3ARG_SDPS(MOVN);
14274 break;
14275 case MOVN_FMT_04:
14276 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14277 FINSN_3ARG_SDPS(MOVN);
14278 break;
14279 case MOVZ_FMT: /* SELEQZ_FMT */
14280 if (ctx->insn_flags & ISA_MIPS32R6) {
14281 /* SELEQZ_FMT */
14282 switch ((ctx->opcode >> 9) & 0x3) {
14283 case FMT_SDPS_S:
14284 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
14285 break;
14286 case FMT_SDPS_D:
14287 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
14288 break;
14289 default:
14290 goto pool32f_invalid;
14292 } else {
14293 /* MOVZ_FMT */
14294 FINSN_3ARG_SDPS(MOVZ);
14296 break;
14297 case MOVZ_FMT_05:
14298 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14299 FINSN_3ARG_SDPS(MOVZ);
14300 break;
14301 case SEL_FMT:
14302 check_insn(ctx, ISA_MIPS32R6);
14303 switch ((ctx->opcode >> 9) & 0x3) {
14304 case FMT_SDPS_S:
14305 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
14306 break;
14307 case FMT_SDPS_D:
14308 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
14309 break;
14310 default:
14311 goto pool32f_invalid;
14313 break;
14314 case MADDF_FMT:
14315 check_insn(ctx, ISA_MIPS32R6);
14316 switch ((ctx->opcode >> 9) & 0x3) {
14317 case FMT_SDPS_S:
14318 mips32_op = OPC_MADDF_S;
14319 goto do_fpop;
14320 case FMT_SDPS_D:
14321 mips32_op = OPC_MADDF_D;
14322 goto do_fpop;
14323 default:
14324 goto pool32f_invalid;
14326 break;
14327 case MSUBF_FMT:
14328 check_insn(ctx, ISA_MIPS32R6);
14329 switch ((ctx->opcode >> 9) & 0x3) {
14330 case FMT_SDPS_S:
14331 mips32_op = OPC_MSUBF_S;
14332 goto do_fpop;
14333 case FMT_SDPS_D:
14334 mips32_op = OPC_MSUBF_D;
14335 goto do_fpop;
14336 default:
14337 goto pool32f_invalid;
14339 break;
14340 default:
14341 goto pool32f_invalid;
14343 break;
14344 do_fpop:
14345 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14346 break;
14347 default:
14348 pool32f_invalid:
14349 MIPS_INVAL("pool32f");
14350 generate_exception_end(ctx, EXCP_RI);
14351 break;
14353 } else {
14354 generate_exception_err(ctx, EXCP_CpU, 1);
14356 break;
14357 case POOL32I:
14358 minor = (ctx->opcode >> 21) & 0x1f;
14359 switch (minor) {
14360 case BLTZ:
14361 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14362 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
14363 break;
14364 case BLTZAL:
14365 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14366 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
14367 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14368 break;
14369 case BLTZALS:
14370 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14371 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
14372 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14373 break;
14374 case BGEZ:
14375 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14376 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
14377 break;
14378 case BGEZAL:
14379 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14380 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
14381 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14382 break;
14383 case BGEZALS:
14384 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14385 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
14386 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14387 break;
14388 case BLEZ:
14389 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14390 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
14391 break;
14392 case BGTZ:
14393 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14394 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
14395 break;
14397 /* Traps */
14398 case TLTI: /* BC1EQZC */
14399 if (ctx->insn_flags & ISA_MIPS32R6) {
14400 /* BC1EQZC */
14401 check_cp1_enabled(ctx);
14402 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
14403 } else {
14404 /* TLTI */
14405 mips32_op = OPC_TLTI;
14406 goto do_trapi;
14408 break;
14409 case TGEI: /* BC1NEZC */
14410 if (ctx->insn_flags & ISA_MIPS32R6) {
14411 /* BC1NEZC */
14412 check_cp1_enabled(ctx);
14413 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
14414 } else {
14415 /* TGEI */
14416 mips32_op = OPC_TGEI;
14417 goto do_trapi;
14419 break;
14420 case TLTIU:
14421 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14422 mips32_op = OPC_TLTIU;
14423 goto do_trapi;
14424 case TGEIU:
14425 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14426 mips32_op = OPC_TGEIU;
14427 goto do_trapi;
14428 case TNEI: /* SYNCI */
14429 if (ctx->insn_flags & ISA_MIPS32R6) {
14430 /* SYNCI */
14431 /* Break the TB to be able to sync copied instructions
14432 immediately */
14433 ctx->bstate = BS_STOP;
14434 } else {
14435 /* TNEI */
14436 mips32_op = OPC_TNEI;
14437 goto do_trapi;
14439 break;
14440 case TEQI:
14441 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14442 mips32_op = OPC_TEQI;
14443 do_trapi:
14444 gen_trap(ctx, mips32_op, rs, -1, imm);
14445 break;
14447 case BNEZC:
14448 case BEQZC:
14449 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14450 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
14451 4, rs, 0, imm << 1, 0);
14452 /* Compact branches don't have a delay slot, so just let
14453 the normal delay slot handling take us to the branch
14454 target. */
14455 break;
14456 case LUI:
14457 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14458 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
14459 break;
14460 case SYNCI:
14461 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14462 /* Break the TB to be able to sync copied instructions
14463 immediately */
14464 ctx->bstate = BS_STOP;
14465 break;
14466 case BC2F:
14467 case BC2T:
14468 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14469 /* COP2: Not implemented. */
14470 generate_exception_err(ctx, EXCP_CpU, 2);
14471 break;
14472 case BC1F:
14473 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14474 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
14475 goto do_cp1branch;
14476 case BC1T:
14477 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14478 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
14479 goto do_cp1branch;
14480 case BC1ANY4F:
14481 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14482 mips32_op = OPC_BC1FANY4;
14483 goto do_cp1mips3d;
14484 case BC1ANY4T:
14485 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14486 mips32_op = OPC_BC1TANY4;
14487 do_cp1mips3d:
14488 check_cop1x(ctx);
14489 check_insn(ctx, ASE_MIPS3D);
14490 /* Fall through */
14491 do_cp1branch:
14492 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14493 check_cp1_enabled(ctx);
14494 gen_compute_branch1(ctx, mips32_op,
14495 (ctx->opcode >> 18) & 0x7, imm << 1);
14496 } else {
14497 generate_exception_err(ctx, EXCP_CpU, 1);
14499 break;
14500 case BPOSGE64:
14501 case BPOSGE32:
14502 /* MIPS DSP: not implemented */
14503 /* Fall through */
14504 default:
14505 MIPS_INVAL("pool32i");
14506 generate_exception_end(ctx, EXCP_RI);
14507 break;
14509 break;
14510 case POOL32C:
14511 minor = (ctx->opcode >> 12) & 0xf;
14512 offset = sextract32(ctx->opcode, 0,
14513 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
14514 switch (minor) {
14515 case LWL:
14516 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14517 mips32_op = OPC_LWL;
14518 goto do_ld_lr;
14519 case SWL:
14520 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14521 mips32_op = OPC_SWL;
14522 goto do_st_lr;
14523 case LWR:
14524 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14525 mips32_op = OPC_LWR;
14526 goto do_ld_lr;
14527 case SWR:
14528 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14529 mips32_op = OPC_SWR;
14530 goto do_st_lr;
14531 #if defined(TARGET_MIPS64)
14532 case LDL:
14533 check_insn(ctx, ISA_MIPS3);
14534 check_mips_64(ctx);
14535 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14536 mips32_op = OPC_LDL;
14537 goto do_ld_lr;
14538 case SDL:
14539 check_insn(ctx, ISA_MIPS3);
14540 check_mips_64(ctx);
14541 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14542 mips32_op = OPC_SDL;
14543 goto do_st_lr;
14544 case LDR:
14545 check_insn(ctx, ISA_MIPS3);
14546 check_mips_64(ctx);
14547 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14548 mips32_op = OPC_LDR;
14549 goto do_ld_lr;
14550 case SDR:
14551 check_insn(ctx, ISA_MIPS3);
14552 check_mips_64(ctx);
14553 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14554 mips32_op = OPC_SDR;
14555 goto do_st_lr;
14556 case LWU:
14557 check_insn(ctx, ISA_MIPS3);
14558 check_mips_64(ctx);
14559 mips32_op = OPC_LWU;
14560 goto do_ld_lr;
14561 case LLD:
14562 check_insn(ctx, ISA_MIPS3);
14563 check_mips_64(ctx);
14564 mips32_op = OPC_LLD;
14565 goto do_ld_lr;
14566 #endif
14567 case LL:
14568 mips32_op = OPC_LL;
14569 goto do_ld_lr;
14570 do_ld_lr:
14571 gen_ld(ctx, mips32_op, rt, rs, offset);
14572 break;
14573 do_st_lr:
14574 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
14575 break;
14576 case SC:
14577 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
14578 break;
14579 #if defined(TARGET_MIPS64)
14580 case SCD:
14581 check_insn(ctx, ISA_MIPS3);
14582 check_mips_64(ctx);
14583 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
14584 break;
14585 #endif
14586 case PREF:
14587 /* Treat as no-op */
14588 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
14589 /* hint codes 24-31 are reserved and signal RI */
14590 generate_exception(ctx, EXCP_RI);
14592 break;
14593 default:
14594 MIPS_INVAL("pool32c");
14595 generate_exception_end(ctx, EXCP_RI);
14596 break;
14598 break;
14599 case ADDI32: /* AUI, LUI */
14600 if (ctx->insn_flags & ISA_MIPS32R6) {
14601 /* AUI, LUI */
14602 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
14603 } else {
14604 /* ADDI32 */
14605 mips32_op = OPC_ADDI;
14606 goto do_addi;
14608 break;
14609 case ADDIU32:
14610 mips32_op = OPC_ADDIU;
14611 do_addi:
14612 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
14613 break;
14615 /* Logical operations */
14616 case ORI32:
14617 mips32_op = OPC_ORI;
14618 goto do_logici;
14619 case XORI32:
14620 mips32_op = OPC_XORI;
14621 goto do_logici;
14622 case ANDI32:
14623 mips32_op = OPC_ANDI;
14624 do_logici:
14625 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
14626 break;
14628 /* Set less than immediate */
14629 case SLTI32:
14630 mips32_op = OPC_SLTI;
14631 goto do_slti;
14632 case SLTIU32:
14633 mips32_op = OPC_SLTIU;
14634 do_slti:
14635 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
14636 break;
14637 case JALX32:
14638 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14639 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14640 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
14641 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14642 break;
14643 case JALS32: /* BOVC, BEQC, BEQZALC */
14644 if (ctx->insn_flags & ISA_MIPS32R6) {
14645 if (rs >= rt) {
14646 /* BOVC */
14647 mips32_op = OPC_BOVC;
14648 } else if (rs < rt && rs == 0) {
14649 /* BEQZALC */
14650 mips32_op = OPC_BEQZALC;
14651 } else {
14652 /* BEQC */
14653 mips32_op = OPC_BEQC;
14655 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14656 } else {
14657 /* JALS32 */
14658 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
14659 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
14660 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14662 break;
14663 case BEQ32: /* BC */
14664 if (ctx->insn_flags & ISA_MIPS32R6) {
14665 /* BC */
14666 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
14667 sextract32(ctx->opcode << 1, 0, 27));
14668 } else {
14669 /* BEQ32 */
14670 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
14672 break;
14673 case BNE32: /* BALC */
14674 if (ctx->insn_flags & ISA_MIPS32R6) {
14675 /* BALC */
14676 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
14677 sextract32(ctx->opcode << 1, 0, 27));
14678 } else {
14679 /* BNE32 */
14680 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
14682 break;
14683 case J32: /* BGTZC, BLTZC, BLTC */
14684 if (ctx->insn_flags & ISA_MIPS32R6) {
14685 if (rs == 0 && rt != 0) {
14686 /* BGTZC */
14687 mips32_op = OPC_BGTZC;
14688 } else if (rs != 0 && rt != 0 && rs == rt) {
14689 /* BLTZC */
14690 mips32_op = OPC_BLTZC;
14691 } else {
14692 /* BLTC */
14693 mips32_op = OPC_BLTC;
14695 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14696 } else {
14697 /* J32 */
14698 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
14699 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14701 break;
14702 case JAL32: /* BLEZC, BGEZC, BGEC */
14703 if (ctx->insn_flags & ISA_MIPS32R6) {
14704 if (rs == 0 && rt != 0) {
14705 /* BLEZC */
14706 mips32_op = OPC_BLEZC;
14707 } else if (rs != 0 && rt != 0 && rs == rt) {
14708 /* BGEZC */
14709 mips32_op = OPC_BGEZC;
14710 } else {
14711 /* BGEC */
14712 mips32_op = OPC_BGEC;
14714 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14715 } else {
14716 /* JAL32 */
14717 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
14718 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14719 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14721 break;
14722 /* Floating point (COP1) */
14723 case LWC132:
14724 mips32_op = OPC_LWC1;
14725 goto do_cop1;
14726 case LDC132:
14727 mips32_op = OPC_LDC1;
14728 goto do_cop1;
14729 case SWC132:
14730 mips32_op = OPC_SWC1;
14731 goto do_cop1;
14732 case SDC132:
14733 mips32_op = OPC_SDC1;
14734 do_cop1:
14735 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
14736 break;
14737 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14738 if (ctx->insn_flags & ISA_MIPS32R6) {
14739 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14740 switch ((ctx->opcode >> 16) & 0x1f) {
14741 case ADDIUPC_00 ... ADDIUPC_07:
14742 gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
14743 break;
14744 case AUIPC:
14745 gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
14746 break;
14747 case ALUIPC:
14748 gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
14749 break;
14750 case LWPC_08 ... LWPC_0F:
14751 gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
14752 break;
14753 default:
14754 generate_exception(ctx, EXCP_RI);
14755 break;
14757 } else {
14758 /* ADDIUPC */
14759 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
14760 int offset = SIMM(ctx->opcode, 0, 23) << 2;
14762 gen_addiupc(ctx, reg, offset, 0, 0);
14764 break;
14765 case BNVC: /* BNEC, BNEZALC */
14766 check_insn(ctx, ISA_MIPS32R6);
14767 if (rs >= rt) {
14768 /* BNVC */
14769 mips32_op = OPC_BNVC;
14770 } else if (rs < rt && rs == 0) {
14771 /* BNEZALC */
14772 mips32_op = OPC_BNEZALC;
14773 } else {
14774 /* BNEC */
14775 mips32_op = OPC_BNEC;
14777 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14778 break;
14779 case R6_BNEZC: /* JIALC */
14780 check_insn(ctx, ISA_MIPS32R6);
14781 if (rt != 0) {
14782 /* BNEZC */
14783 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
14784 sextract32(ctx->opcode << 1, 0, 22));
14785 } else {
14786 /* JIALC */
14787 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
14789 break;
14790 case R6_BEQZC: /* JIC */
14791 check_insn(ctx, ISA_MIPS32R6);
14792 if (rt != 0) {
14793 /* BEQZC */
14794 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
14795 sextract32(ctx->opcode << 1, 0, 22));
14796 } else {
14797 /* JIC */
14798 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
14800 break;
14801 case BLEZALC: /* BGEZALC, BGEUC */
14802 check_insn(ctx, ISA_MIPS32R6);
14803 if (rs == 0 && rt != 0) {
14804 /* BLEZALC */
14805 mips32_op = OPC_BLEZALC;
14806 } else if (rs != 0 && rt != 0 && rs == rt) {
14807 /* BGEZALC */
14808 mips32_op = OPC_BGEZALC;
14809 } else {
14810 /* BGEUC */
14811 mips32_op = OPC_BGEUC;
14813 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14814 break;
14815 case BGTZALC: /* BLTZALC, BLTUC */
14816 check_insn(ctx, ISA_MIPS32R6);
14817 if (rs == 0 && rt != 0) {
14818 /* BGTZALC */
14819 mips32_op = OPC_BGTZALC;
14820 } else if (rs != 0 && rt != 0 && rs == rt) {
14821 /* BLTZALC */
14822 mips32_op = OPC_BLTZALC;
14823 } else {
14824 /* BLTUC */
14825 mips32_op = OPC_BLTUC;
14827 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14828 break;
14829 /* Loads and stores */
14830 case LB32:
14831 mips32_op = OPC_LB;
14832 goto do_ld;
14833 case LBU32:
14834 mips32_op = OPC_LBU;
14835 goto do_ld;
14836 case LH32:
14837 mips32_op = OPC_LH;
14838 goto do_ld;
14839 case LHU32:
14840 mips32_op = OPC_LHU;
14841 goto do_ld;
14842 case LW32:
14843 mips32_op = OPC_LW;
14844 goto do_ld;
14845 #ifdef TARGET_MIPS64
14846 case LD32:
14847 check_insn(ctx, ISA_MIPS3);
14848 check_mips_64(ctx);
14849 mips32_op = OPC_LD;
14850 goto do_ld;
14851 case SD32:
14852 check_insn(ctx, ISA_MIPS3);
14853 check_mips_64(ctx);
14854 mips32_op = OPC_SD;
14855 goto do_st;
14856 #endif
14857 case SB32:
14858 mips32_op = OPC_SB;
14859 goto do_st;
14860 case SH32:
14861 mips32_op = OPC_SH;
14862 goto do_st;
14863 case SW32:
14864 mips32_op = OPC_SW;
14865 goto do_st;
14866 do_ld:
14867 gen_ld(ctx, mips32_op, rt, rs, imm);
14868 break;
14869 do_st:
14870 gen_st(ctx, mips32_op, rt, rs, imm);
14871 break;
14872 default:
14873 generate_exception_end(ctx, EXCP_RI);
14874 break;
14878 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
14880 uint32_t op;
14882 /* make sure instructions are on a halfword boundary */
14883 if (ctx->pc & 0x1) {
14884 env->CP0_BadVAddr = ctx->pc;
14885 generate_exception_end(ctx, EXCP_AdEL);
14886 return 2;
14889 op = (ctx->opcode >> 10) & 0x3f;
14890 /* Enforce properly-sized instructions in a delay slot */
14891 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
14892 switch (op & 0x7) { /* MSB-3..MSB-5 */
14893 case 0:
14894 /* POOL32A, POOL32B, POOL32I, POOL32C */
14895 case 4:
14896 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
14897 case 5:
14898 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
14899 case 6:
14900 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
14901 case 7:
14902 /* LB32, LH32, LWC132, LDC132, LW32 */
14903 if (ctx->hflags & MIPS_HFLAG_BDS16) {
14904 generate_exception_end(ctx, EXCP_RI);
14905 return 2;
14907 break;
14908 case 1:
14909 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
14910 case 2:
14911 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
14912 case 3:
14913 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
14914 if (ctx->hflags & MIPS_HFLAG_BDS32) {
14915 generate_exception_end(ctx, EXCP_RI);
14916 return 2;
14918 break;
14922 switch (op) {
14923 case POOL16A:
14925 int rd = mmreg(uMIPS_RD(ctx->opcode));
14926 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
14927 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
14928 uint32_t opc = 0;
14930 switch (ctx->opcode & 0x1) {
14931 case ADDU16:
14932 opc = OPC_ADDU;
14933 break;
14934 case SUBU16:
14935 opc = OPC_SUBU;
14936 break;
14938 if (ctx->insn_flags & ISA_MIPS32R6) {
14939 /* In the Release 6 the register number location in
14940 * the instruction encoding has changed.
14942 gen_arith(ctx, opc, rs1, rd, rs2);
14943 } else {
14944 gen_arith(ctx, opc, rd, rs1, rs2);
14947 break;
14948 case POOL16B:
14950 int rd = mmreg(uMIPS_RD(ctx->opcode));
14951 int rs = mmreg(uMIPS_RS(ctx->opcode));
14952 int amount = (ctx->opcode >> 1) & 0x7;
14953 uint32_t opc = 0;
14954 amount = amount == 0 ? 8 : amount;
14956 switch (ctx->opcode & 0x1) {
14957 case SLL16:
14958 opc = OPC_SLL;
14959 break;
14960 case SRL16:
14961 opc = OPC_SRL;
14962 break;
14965 gen_shift_imm(ctx, opc, rd, rs, amount);
14967 break;
14968 case POOL16C:
14969 if (ctx->insn_flags & ISA_MIPS32R6) {
14970 gen_pool16c_r6_insn(ctx);
14971 } else {
14972 gen_pool16c_insn(ctx);
14974 break;
14975 case LWGP16:
14977 int rd = mmreg(uMIPS_RD(ctx->opcode));
14978 int rb = 28; /* GP */
14979 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
14981 gen_ld(ctx, OPC_LW, rd, rb, offset);
14983 break;
14984 case POOL16F:
14985 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14986 if (ctx->opcode & 1) {
14987 generate_exception_end(ctx, EXCP_RI);
14988 } else {
14989 /* MOVEP */
14990 int enc_dest = uMIPS_RD(ctx->opcode);
14991 int enc_rt = uMIPS_RS2(ctx->opcode);
14992 int enc_rs = uMIPS_RS1(ctx->opcode);
14993 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14995 break;
14996 case LBU16:
14998 int rd = mmreg(uMIPS_RD(ctx->opcode));
14999 int rb = mmreg(uMIPS_RS(ctx->opcode));
15000 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15001 offset = (offset == 0xf ? -1 : offset);
15003 gen_ld(ctx, OPC_LBU, rd, rb, offset);
15005 break;
15006 case LHU16:
15008 int rd = mmreg(uMIPS_RD(ctx->opcode));
15009 int rb = mmreg(uMIPS_RS(ctx->opcode));
15010 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15012 gen_ld(ctx, OPC_LHU, rd, rb, offset);
15014 break;
15015 case LWSP16:
15017 int rd = (ctx->opcode >> 5) & 0x1f;
15018 int rb = 29; /* SP */
15019 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15021 gen_ld(ctx, OPC_LW, rd, rb, offset);
15023 break;
15024 case LW16:
15026 int rd = mmreg(uMIPS_RD(ctx->opcode));
15027 int rb = mmreg(uMIPS_RS(ctx->opcode));
15028 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15030 gen_ld(ctx, OPC_LW, rd, rb, offset);
15032 break;
15033 case SB16:
15035 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15036 int rb = mmreg(uMIPS_RS(ctx->opcode));
15037 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15039 gen_st(ctx, OPC_SB, rd, rb, offset);
15041 break;
15042 case SH16:
15044 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15045 int rb = mmreg(uMIPS_RS(ctx->opcode));
15046 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15048 gen_st(ctx, OPC_SH, rd, rb, offset);
15050 break;
15051 case SWSP16:
15053 int rd = (ctx->opcode >> 5) & 0x1f;
15054 int rb = 29; /* SP */
15055 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15057 gen_st(ctx, OPC_SW, rd, rb, offset);
15059 break;
15060 case SW16:
15062 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15063 int rb = mmreg(uMIPS_RS(ctx->opcode));
15064 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15066 gen_st(ctx, OPC_SW, rd, rb, offset);
15068 break;
15069 case MOVE16:
15071 int rd = uMIPS_RD5(ctx->opcode);
15072 int rs = uMIPS_RS5(ctx->opcode);
15074 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
15076 break;
15077 case ANDI16:
15078 gen_andi16(ctx);
15079 break;
15080 case POOL16D:
15081 switch (ctx->opcode & 0x1) {
15082 case ADDIUS5:
15083 gen_addius5(ctx);
15084 break;
15085 case ADDIUSP:
15086 gen_addiusp(ctx);
15087 break;
15089 break;
15090 case POOL16E:
15091 switch (ctx->opcode & 0x1) {
15092 case ADDIUR2:
15093 gen_addiur2(ctx);
15094 break;
15095 case ADDIUR1SP:
15096 gen_addiur1sp(ctx);
15097 break;
15099 break;
15100 case B16: /* BC16 */
15101 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
15102 sextract32(ctx->opcode, 0, 10) << 1,
15103 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15104 break;
15105 case BNEZ16: /* BNEZC16 */
15106 case BEQZ16: /* BEQZC16 */
15107 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
15108 mmreg(uMIPS_RD(ctx->opcode)),
15109 0, sextract32(ctx->opcode, 0, 7) << 1,
15110 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15112 break;
15113 case LI16:
15115 int reg = mmreg(uMIPS_RD(ctx->opcode));
15116 int imm = ZIMM(ctx->opcode, 0, 7);
15118 imm = (imm == 0x7f ? -1 : imm);
15119 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15121 break;
15122 case RES_29:
15123 case RES_31:
15124 case RES_39:
15125 generate_exception_end(ctx, EXCP_RI);
15126 break;
15127 default:
15128 decode_micromips32_opc(env, ctx);
15129 return 4;
15132 return 2;
15135 /* SmartMIPS extension to MIPS32 */
15137 #if defined(TARGET_MIPS64)
15139 /* MDMX extension to MIPS64 */
15141 #endif
15143 /* MIPSDSP functions. */
15144 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
15145 int rd, int base, int offset)
15147 TCGv t0;
15149 check_dsp(ctx);
15150 t0 = tcg_temp_new();
15152 if (base == 0) {
15153 gen_load_gpr(t0, offset);
15154 } else if (offset == 0) {
15155 gen_load_gpr(t0, base);
15156 } else {
15157 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
15160 switch (opc) {
15161 case OPC_LBUX:
15162 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
15163 gen_store_gpr(t0, rd);
15164 break;
15165 case OPC_LHX:
15166 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
15167 gen_store_gpr(t0, rd);
15168 break;
15169 case OPC_LWX:
15170 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
15171 gen_store_gpr(t0, rd);
15172 break;
15173 #if defined(TARGET_MIPS64)
15174 case OPC_LDX:
15175 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
15176 gen_store_gpr(t0, rd);
15177 break;
15178 #endif
15180 tcg_temp_free(t0);
15183 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
15184 int ret, int v1, int v2)
15186 TCGv v1_t;
15187 TCGv v2_t;
15189 if (ret == 0) {
15190 /* Treat as NOP. */
15191 return;
15194 v1_t = tcg_temp_new();
15195 v2_t = tcg_temp_new();
15197 gen_load_gpr(v1_t, v1);
15198 gen_load_gpr(v2_t, v2);
15200 switch (op1) {
15201 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
15202 case OPC_MULT_G_2E:
15203 check_dspr2(ctx);
15204 switch (op2) {
15205 case OPC_ADDUH_QB:
15206 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
15207 break;
15208 case OPC_ADDUH_R_QB:
15209 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15210 break;
15211 case OPC_ADDQH_PH:
15212 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
15213 break;
15214 case OPC_ADDQH_R_PH:
15215 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15216 break;
15217 case OPC_ADDQH_W:
15218 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
15219 break;
15220 case OPC_ADDQH_R_W:
15221 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15222 break;
15223 case OPC_SUBUH_QB:
15224 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
15225 break;
15226 case OPC_SUBUH_R_QB:
15227 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15228 break;
15229 case OPC_SUBQH_PH:
15230 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
15231 break;
15232 case OPC_SUBQH_R_PH:
15233 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15234 break;
15235 case OPC_SUBQH_W:
15236 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
15237 break;
15238 case OPC_SUBQH_R_W:
15239 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15240 break;
15242 break;
15243 case OPC_ABSQ_S_PH_DSP:
15244 switch (op2) {
15245 case OPC_ABSQ_S_QB:
15246 check_dspr2(ctx);
15247 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
15248 break;
15249 case OPC_ABSQ_S_PH:
15250 check_dsp(ctx);
15251 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
15252 break;
15253 case OPC_ABSQ_S_W:
15254 check_dsp(ctx);
15255 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
15256 break;
15257 case OPC_PRECEQ_W_PHL:
15258 check_dsp(ctx);
15259 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
15260 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15261 break;
15262 case OPC_PRECEQ_W_PHR:
15263 check_dsp(ctx);
15264 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
15265 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
15266 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15267 break;
15268 case OPC_PRECEQU_PH_QBL:
15269 check_dsp(ctx);
15270 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
15271 break;
15272 case OPC_PRECEQU_PH_QBR:
15273 check_dsp(ctx);
15274 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
15275 break;
15276 case OPC_PRECEQU_PH_QBLA:
15277 check_dsp(ctx);
15278 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
15279 break;
15280 case OPC_PRECEQU_PH_QBRA:
15281 check_dsp(ctx);
15282 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
15283 break;
15284 case OPC_PRECEU_PH_QBL:
15285 check_dsp(ctx);
15286 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
15287 break;
15288 case OPC_PRECEU_PH_QBR:
15289 check_dsp(ctx);
15290 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
15291 break;
15292 case OPC_PRECEU_PH_QBLA:
15293 check_dsp(ctx);
15294 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
15295 break;
15296 case OPC_PRECEU_PH_QBRA:
15297 check_dsp(ctx);
15298 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
15299 break;
15301 break;
15302 case OPC_ADDU_QB_DSP:
15303 switch (op2) {
15304 case OPC_ADDQ_PH:
15305 check_dsp(ctx);
15306 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15307 break;
15308 case OPC_ADDQ_S_PH:
15309 check_dsp(ctx);
15310 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15311 break;
15312 case OPC_ADDQ_S_W:
15313 check_dsp(ctx);
15314 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15315 break;
15316 case OPC_ADDU_QB:
15317 check_dsp(ctx);
15318 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15319 break;
15320 case OPC_ADDU_S_QB:
15321 check_dsp(ctx);
15322 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15323 break;
15324 case OPC_ADDU_PH:
15325 check_dspr2(ctx);
15326 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15327 break;
15328 case OPC_ADDU_S_PH:
15329 check_dspr2(ctx);
15330 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15331 break;
15332 case OPC_SUBQ_PH:
15333 check_dsp(ctx);
15334 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15335 break;
15336 case OPC_SUBQ_S_PH:
15337 check_dsp(ctx);
15338 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15339 break;
15340 case OPC_SUBQ_S_W:
15341 check_dsp(ctx);
15342 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15343 break;
15344 case OPC_SUBU_QB:
15345 check_dsp(ctx);
15346 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15347 break;
15348 case OPC_SUBU_S_QB:
15349 check_dsp(ctx);
15350 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15351 break;
15352 case OPC_SUBU_PH:
15353 check_dspr2(ctx);
15354 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15355 break;
15356 case OPC_SUBU_S_PH:
15357 check_dspr2(ctx);
15358 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15359 break;
15360 case OPC_ADDSC:
15361 check_dsp(ctx);
15362 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15363 break;
15364 case OPC_ADDWC:
15365 check_dsp(ctx);
15366 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15367 break;
15368 case OPC_MODSUB:
15369 check_dsp(ctx);
15370 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
15371 break;
15372 case OPC_RADDU_W_QB:
15373 check_dsp(ctx);
15374 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
15375 break;
15377 break;
15378 case OPC_CMPU_EQ_QB_DSP:
15379 switch (op2) {
15380 case OPC_PRECR_QB_PH:
15381 check_dspr2(ctx);
15382 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15383 break;
15384 case OPC_PRECRQ_QB_PH:
15385 check_dsp(ctx);
15386 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15387 break;
15388 case OPC_PRECR_SRA_PH_W:
15389 check_dspr2(ctx);
15391 TCGv_i32 sa_t = tcg_const_i32(v2);
15392 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
15393 cpu_gpr[ret]);
15394 tcg_temp_free_i32(sa_t);
15395 break;
15397 case OPC_PRECR_SRA_R_PH_W:
15398 check_dspr2(ctx);
15400 TCGv_i32 sa_t = tcg_const_i32(v2);
15401 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
15402 cpu_gpr[ret]);
15403 tcg_temp_free_i32(sa_t);
15404 break;
15406 case OPC_PRECRQ_PH_W:
15407 check_dsp(ctx);
15408 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
15409 break;
15410 case OPC_PRECRQ_RS_PH_W:
15411 check_dsp(ctx);
15412 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15413 break;
15414 case OPC_PRECRQU_S_QB_PH:
15415 check_dsp(ctx);
15416 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15417 break;
15419 break;
15420 #ifdef TARGET_MIPS64
15421 case OPC_ABSQ_S_QH_DSP:
15422 switch (op2) {
15423 case OPC_PRECEQ_L_PWL:
15424 check_dsp(ctx);
15425 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
15426 break;
15427 case OPC_PRECEQ_L_PWR:
15428 check_dsp(ctx);
15429 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
15430 break;
15431 case OPC_PRECEQ_PW_QHL:
15432 check_dsp(ctx);
15433 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
15434 break;
15435 case OPC_PRECEQ_PW_QHR:
15436 check_dsp(ctx);
15437 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
15438 break;
15439 case OPC_PRECEQ_PW_QHLA:
15440 check_dsp(ctx);
15441 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
15442 break;
15443 case OPC_PRECEQ_PW_QHRA:
15444 check_dsp(ctx);
15445 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
15446 break;
15447 case OPC_PRECEQU_QH_OBL:
15448 check_dsp(ctx);
15449 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
15450 break;
15451 case OPC_PRECEQU_QH_OBR:
15452 check_dsp(ctx);
15453 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
15454 break;
15455 case OPC_PRECEQU_QH_OBLA:
15456 check_dsp(ctx);
15457 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
15458 break;
15459 case OPC_PRECEQU_QH_OBRA:
15460 check_dsp(ctx);
15461 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
15462 break;
15463 case OPC_PRECEU_QH_OBL:
15464 check_dsp(ctx);
15465 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
15466 break;
15467 case OPC_PRECEU_QH_OBR:
15468 check_dsp(ctx);
15469 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
15470 break;
15471 case OPC_PRECEU_QH_OBLA:
15472 check_dsp(ctx);
15473 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
15474 break;
15475 case OPC_PRECEU_QH_OBRA:
15476 check_dsp(ctx);
15477 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
15478 break;
15479 case OPC_ABSQ_S_OB:
15480 check_dspr2(ctx);
15481 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
15482 break;
15483 case OPC_ABSQ_S_PW:
15484 check_dsp(ctx);
15485 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
15486 break;
15487 case OPC_ABSQ_S_QH:
15488 check_dsp(ctx);
15489 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
15490 break;
15492 break;
15493 case OPC_ADDU_OB_DSP:
15494 switch (op2) {
15495 case OPC_RADDU_L_OB:
15496 check_dsp(ctx);
15497 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
15498 break;
15499 case OPC_SUBQ_PW:
15500 check_dsp(ctx);
15501 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15502 break;
15503 case OPC_SUBQ_S_PW:
15504 check_dsp(ctx);
15505 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15506 break;
15507 case OPC_SUBQ_QH:
15508 check_dsp(ctx);
15509 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15510 break;
15511 case OPC_SUBQ_S_QH:
15512 check_dsp(ctx);
15513 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15514 break;
15515 case OPC_SUBU_OB:
15516 check_dsp(ctx);
15517 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15518 break;
15519 case OPC_SUBU_S_OB:
15520 check_dsp(ctx);
15521 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15522 break;
15523 case OPC_SUBU_QH:
15524 check_dspr2(ctx);
15525 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15526 break;
15527 case OPC_SUBU_S_QH:
15528 check_dspr2(ctx);
15529 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15530 break;
15531 case OPC_SUBUH_OB:
15532 check_dspr2(ctx);
15533 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
15534 break;
15535 case OPC_SUBUH_R_OB:
15536 check_dspr2(ctx);
15537 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15538 break;
15539 case OPC_ADDQ_PW:
15540 check_dsp(ctx);
15541 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15542 break;
15543 case OPC_ADDQ_S_PW:
15544 check_dsp(ctx);
15545 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15546 break;
15547 case OPC_ADDQ_QH:
15548 check_dsp(ctx);
15549 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15550 break;
15551 case OPC_ADDQ_S_QH:
15552 check_dsp(ctx);
15553 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15554 break;
15555 case OPC_ADDU_OB:
15556 check_dsp(ctx);
15557 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15558 break;
15559 case OPC_ADDU_S_OB:
15560 check_dsp(ctx);
15561 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15562 break;
15563 case OPC_ADDU_QH:
15564 check_dspr2(ctx);
15565 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15566 break;
15567 case OPC_ADDU_S_QH:
15568 check_dspr2(ctx);
15569 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15570 break;
15571 case OPC_ADDUH_OB:
15572 check_dspr2(ctx);
15573 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
15574 break;
15575 case OPC_ADDUH_R_OB:
15576 check_dspr2(ctx);
15577 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15578 break;
15580 break;
15581 case OPC_CMPU_EQ_OB_DSP:
15582 switch (op2) {
15583 case OPC_PRECR_OB_QH:
15584 check_dspr2(ctx);
15585 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15586 break;
15587 case OPC_PRECR_SRA_QH_PW:
15588 check_dspr2(ctx);
15590 TCGv_i32 ret_t = tcg_const_i32(ret);
15591 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
15592 tcg_temp_free_i32(ret_t);
15593 break;
15595 case OPC_PRECR_SRA_R_QH_PW:
15596 check_dspr2(ctx);
15598 TCGv_i32 sa_v = tcg_const_i32(ret);
15599 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
15600 tcg_temp_free_i32(sa_v);
15601 break;
15603 case OPC_PRECRQ_OB_QH:
15604 check_dsp(ctx);
15605 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15606 break;
15607 case OPC_PRECRQ_PW_L:
15608 check_dsp(ctx);
15609 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
15610 break;
15611 case OPC_PRECRQ_QH_PW:
15612 check_dsp(ctx);
15613 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
15614 break;
15615 case OPC_PRECRQ_RS_QH_PW:
15616 check_dsp(ctx);
15617 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15618 break;
15619 case OPC_PRECRQU_S_OB_QH:
15620 check_dsp(ctx);
15621 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15622 break;
15624 break;
15625 #endif
15628 tcg_temp_free(v1_t);
15629 tcg_temp_free(v2_t);
15632 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
15633 int ret, int v1, int v2)
15635 uint32_t op2;
15636 TCGv t0;
15637 TCGv v1_t;
15638 TCGv v2_t;
15640 if (ret == 0) {
15641 /* Treat as NOP. */
15642 return;
15645 t0 = tcg_temp_new();
15646 v1_t = tcg_temp_new();
15647 v2_t = tcg_temp_new();
15649 tcg_gen_movi_tl(t0, v1);
15650 gen_load_gpr(v1_t, v1);
15651 gen_load_gpr(v2_t, v2);
15653 switch (opc) {
15654 case OPC_SHLL_QB_DSP:
15656 op2 = MASK_SHLL_QB(ctx->opcode);
15657 switch (op2) {
15658 case OPC_SHLL_QB:
15659 check_dsp(ctx);
15660 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
15661 break;
15662 case OPC_SHLLV_QB:
15663 check_dsp(ctx);
15664 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15665 break;
15666 case OPC_SHLL_PH:
15667 check_dsp(ctx);
15668 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15669 break;
15670 case OPC_SHLLV_PH:
15671 check_dsp(ctx);
15672 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15673 break;
15674 case OPC_SHLL_S_PH:
15675 check_dsp(ctx);
15676 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15677 break;
15678 case OPC_SHLLV_S_PH:
15679 check_dsp(ctx);
15680 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15681 break;
15682 case OPC_SHLL_S_W:
15683 check_dsp(ctx);
15684 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
15685 break;
15686 case OPC_SHLLV_S_W:
15687 check_dsp(ctx);
15688 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15689 break;
15690 case OPC_SHRL_QB:
15691 check_dsp(ctx);
15692 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
15693 break;
15694 case OPC_SHRLV_QB:
15695 check_dsp(ctx);
15696 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
15697 break;
15698 case OPC_SHRL_PH:
15699 check_dspr2(ctx);
15700 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
15701 break;
15702 case OPC_SHRLV_PH:
15703 check_dspr2(ctx);
15704 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
15705 break;
15706 case OPC_SHRA_QB:
15707 check_dspr2(ctx);
15708 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
15709 break;
15710 case OPC_SHRA_R_QB:
15711 check_dspr2(ctx);
15712 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
15713 break;
15714 case OPC_SHRAV_QB:
15715 check_dspr2(ctx);
15716 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
15717 break;
15718 case OPC_SHRAV_R_QB:
15719 check_dspr2(ctx);
15720 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
15721 break;
15722 case OPC_SHRA_PH:
15723 check_dsp(ctx);
15724 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
15725 break;
15726 case OPC_SHRA_R_PH:
15727 check_dsp(ctx);
15728 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
15729 break;
15730 case OPC_SHRAV_PH:
15731 check_dsp(ctx);
15732 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
15733 break;
15734 case OPC_SHRAV_R_PH:
15735 check_dsp(ctx);
15736 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
15737 break;
15738 case OPC_SHRA_R_W:
15739 check_dsp(ctx);
15740 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
15741 break;
15742 case OPC_SHRAV_R_W:
15743 check_dsp(ctx);
15744 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
15745 break;
15746 default: /* Invalid */
15747 MIPS_INVAL("MASK SHLL.QB");
15748 generate_exception_end(ctx, EXCP_RI);
15749 break;
15751 break;
15753 #ifdef TARGET_MIPS64
15754 case OPC_SHLL_OB_DSP:
15755 op2 = MASK_SHLL_OB(ctx->opcode);
15756 switch (op2) {
15757 case OPC_SHLL_PW:
15758 check_dsp(ctx);
15759 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15760 break;
15761 case OPC_SHLLV_PW:
15762 check_dsp(ctx);
15763 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15764 break;
15765 case OPC_SHLL_S_PW:
15766 check_dsp(ctx);
15767 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15768 break;
15769 case OPC_SHLLV_S_PW:
15770 check_dsp(ctx);
15771 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15772 break;
15773 case OPC_SHLL_OB:
15774 check_dsp(ctx);
15775 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
15776 break;
15777 case OPC_SHLLV_OB:
15778 check_dsp(ctx);
15779 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15780 break;
15781 case OPC_SHLL_QH:
15782 check_dsp(ctx);
15783 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15784 break;
15785 case OPC_SHLLV_QH:
15786 check_dsp(ctx);
15787 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15788 break;
15789 case OPC_SHLL_S_QH:
15790 check_dsp(ctx);
15791 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15792 break;
15793 case OPC_SHLLV_S_QH:
15794 check_dsp(ctx);
15795 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15796 break;
15797 case OPC_SHRA_OB:
15798 check_dspr2(ctx);
15799 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
15800 break;
15801 case OPC_SHRAV_OB:
15802 check_dspr2(ctx);
15803 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
15804 break;
15805 case OPC_SHRA_R_OB:
15806 check_dspr2(ctx);
15807 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
15808 break;
15809 case OPC_SHRAV_R_OB:
15810 check_dspr2(ctx);
15811 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
15812 break;
15813 case OPC_SHRA_PW:
15814 check_dsp(ctx);
15815 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
15816 break;
15817 case OPC_SHRAV_PW:
15818 check_dsp(ctx);
15819 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
15820 break;
15821 case OPC_SHRA_R_PW:
15822 check_dsp(ctx);
15823 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
15824 break;
15825 case OPC_SHRAV_R_PW:
15826 check_dsp(ctx);
15827 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
15828 break;
15829 case OPC_SHRA_QH:
15830 check_dsp(ctx);
15831 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
15832 break;
15833 case OPC_SHRAV_QH:
15834 check_dsp(ctx);
15835 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
15836 break;
15837 case OPC_SHRA_R_QH:
15838 check_dsp(ctx);
15839 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
15840 break;
15841 case OPC_SHRAV_R_QH:
15842 check_dsp(ctx);
15843 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
15844 break;
15845 case OPC_SHRL_OB:
15846 check_dsp(ctx);
15847 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
15848 break;
15849 case OPC_SHRLV_OB:
15850 check_dsp(ctx);
15851 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
15852 break;
15853 case OPC_SHRL_QH:
15854 check_dspr2(ctx);
15855 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
15856 break;
15857 case OPC_SHRLV_QH:
15858 check_dspr2(ctx);
15859 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
15860 break;
15861 default: /* Invalid */
15862 MIPS_INVAL("MASK SHLL.OB");
15863 generate_exception_end(ctx, EXCP_RI);
15864 break;
15866 break;
15867 #endif
15870 tcg_temp_free(t0);
15871 tcg_temp_free(v1_t);
15872 tcg_temp_free(v2_t);
15875 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
15876 int ret, int v1, int v2, int check_ret)
15878 TCGv_i32 t0;
15879 TCGv v1_t;
15880 TCGv v2_t;
15882 if ((ret == 0) && (check_ret == 1)) {
15883 /* Treat as NOP. */
15884 return;
15887 t0 = tcg_temp_new_i32();
15888 v1_t = tcg_temp_new();
15889 v2_t = tcg_temp_new();
15891 tcg_gen_movi_i32(t0, ret);
15892 gen_load_gpr(v1_t, v1);
15893 gen_load_gpr(v2_t, v2);
15895 switch (op1) {
15896 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
15897 * the same mask and op1. */
15898 case OPC_MULT_G_2E:
15899 check_dspr2(ctx);
15900 switch (op2) {
15901 case OPC_MUL_PH:
15902 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15903 break;
15904 case OPC_MUL_S_PH:
15905 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15906 break;
15907 case OPC_MULQ_S_W:
15908 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15909 break;
15910 case OPC_MULQ_RS_W:
15911 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15912 break;
15914 break;
15915 case OPC_DPA_W_PH_DSP:
15916 switch (op2) {
15917 case OPC_DPAU_H_QBL:
15918 check_dsp(ctx);
15919 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
15920 break;
15921 case OPC_DPAU_H_QBR:
15922 check_dsp(ctx);
15923 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
15924 break;
15925 case OPC_DPSU_H_QBL:
15926 check_dsp(ctx);
15927 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
15928 break;
15929 case OPC_DPSU_H_QBR:
15930 check_dsp(ctx);
15931 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
15932 break;
15933 case OPC_DPA_W_PH:
15934 check_dspr2(ctx);
15935 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
15936 break;
15937 case OPC_DPAX_W_PH:
15938 check_dspr2(ctx);
15939 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
15940 break;
15941 case OPC_DPAQ_S_W_PH:
15942 check_dsp(ctx);
15943 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15944 break;
15945 case OPC_DPAQX_S_W_PH:
15946 check_dspr2(ctx);
15947 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
15948 break;
15949 case OPC_DPAQX_SA_W_PH:
15950 check_dspr2(ctx);
15951 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
15952 break;
15953 case OPC_DPS_W_PH:
15954 check_dspr2(ctx);
15955 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
15956 break;
15957 case OPC_DPSX_W_PH:
15958 check_dspr2(ctx);
15959 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
15960 break;
15961 case OPC_DPSQ_S_W_PH:
15962 check_dsp(ctx);
15963 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15964 break;
15965 case OPC_DPSQX_S_W_PH:
15966 check_dspr2(ctx);
15967 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
15968 break;
15969 case OPC_DPSQX_SA_W_PH:
15970 check_dspr2(ctx);
15971 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
15972 break;
15973 case OPC_MULSAQ_S_W_PH:
15974 check_dsp(ctx);
15975 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15976 break;
15977 case OPC_DPAQ_SA_L_W:
15978 check_dsp(ctx);
15979 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
15980 break;
15981 case OPC_DPSQ_SA_L_W:
15982 check_dsp(ctx);
15983 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
15984 break;
15985 case OPC_MAQ_S_W_PHL:
15986 check_dsp(ctx);
15987 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
15988 break;
15989 case OPC_MAQ_S_W_PHR:
15990 check_dsp(ctx);
15991 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
15992 break;
15993 case OPC_MAQ_SA_W_PHL:
15994 check_dsp(ctx);
15995 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
15996 break;
15997 case OPC_MAQ_SA_W_PHR:
15998 check_dsp(ctx);
15999 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
16000 break;
16001 case OPC_MULSA_W_PH:
16002 check_dspr2(ctx);
16003 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
16004 break;
16006 break;
16007 #ifdef TARGET_MIPS64
16008 case OPC_DPAQ_W_QH_DSP:
16010 int ac = ret & 0x03;
16011 tcg_gen_movi_i32(t0, ac);
16013 switch (op2) {
16014 case OPC_DMADD:
16015 check_dsp(ctx);
16016 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
16017 break;
16018 case OPC_DMADDU:
16019 check_dsp(ctx);
16020 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
16021 break;
16022 case OPC_DMSUB:
16023 check_dsp(ctx);
16024 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
16025 break;
16026 case OPC_DMSUBU:
16027 check_dsp(ctx);
16028 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
16029 break;
16030 case OPC_DPA_W_QH:
16031 check_dspr2(ctx);
16032 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
16033 break;
16034 case OPC_DPAQ_S_W_QH:
16035 check_dsp(ctx);
16036 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16037 break;
16038 case OPC_DPAQ_SA_L_PW:
16039 check_dsp(ctx);
16040 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16041 break;
16042 case OPC_DPAU_H_OBL:
16043 check_dsp(ctx);
16044 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
16045 break;
16046 case OPC_DPAU_H_OBR:
16047 check_dsp(ctx);
16048 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
16049 break;
16050 case OPC_DPS_W_QH:
16051 check_dspr2(ctx);
16052 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
16053 break;
16054 case OPC_DPSQ_S_W_QH:
16055 check_dsp(ctx);
16056 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16057 break;
16058 case OPC_DPSQ_SA_L_PW:
16059 check_dsp(ctx);
16060 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16061 break;
16062 case OPC_DPSU_H_OBL:
16063 check_dsp(ctx);
16064 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
16065 break;
16066 case OPC_DPSU_H_OBR:
16067 check_dsp(ctx);
16068 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
16069 break;
16070 case OPC_MAQ_S_L_PWL:
16071 check_dsp(ctx);
16072 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
16073 break;
16074 case OPC_MAQ_S_L_PWR:
16075 check_dsp(ctx);
16076 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
16077 break;
16078 case OPC_MAQ_S_W_QHLL:
16079 check_dsp(ctx);
16080 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
16081 break;
16082 case OPC_MAQ_SA_W_QHLL:
16083 check_dsp(ctx);
16084 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
16085 break;
16086 case OPC_MAQ_S_W_QHLR:
16087 check_dsp(ctx);
16088 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
16089 break;
16090 case OPC_MAQ_SA_W_QHLR:
16091 check_dsp(ctx);
16092 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
16093 break;
16094 case OPC_MAQ_S_W_QHRL:
16095 check_dsp(ctx);
16096 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
16097 break;
16098 case OPC_MAQ_SA_W_QHRL:
16099 check_dsp(ctx);
16100 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
16101 break;
16102 case OPC_MAQ_S_W_QHRR:
16103 check_dsp(ctx);
16104 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
16105 break;
16106 case OPC_MAQ_SA_W_QHRR:
16107 check_dsp(ctx);
16108 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
16109 break;
16110 case OPC_MULSAQ_S_L_PW:
16111 check_dsp(ctx);
16112 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
16113 break;
16114 case OPC_MULSAQ_S_W_QH:
16115 check_dsp(ctx);
16116 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16117 break;
16120 break;
16121 #endif
16122 case OPC_ADDU_QB_DSP:
16123 switch (op2) {
16124 case OPC_MULEU_S_PH_QBL:
16125 check_dsp(ctx);
16126 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16127 break;
16128 case OPC_MULEU_S_PH_QBR:
16129 check_dsp(ctx);
16130 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16131 break;
16132 case OPC_MULQ_RS_PH:
16133 check_dsp(ctx);
16134 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16135 break;
16136 case OPC_MULEQ_S_W_PHL:
16137 check_dsp(ctx);
16138 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16139 break;
16140 case OPC_MULEQ_S_W_PHR:
16141 check_dsp(ctx);
16142 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16143 break;
16144 case OPC_MULQ_S_PH:
16145 check_dspr2(ctx);
16146 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16147 break;
16149 break;
16150 #ifdef TARGET_MIPS64
16151 case OPC_ADDU_OB_DSP:
16152 switch (op2) {
16153 case OPC_MULEQ_S_PW_QHL:
16154 check_dsp(ctx);
16155 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16156 break;
16157 case OPC_MULEQ_S_PW_QHR:
16158 check_dsp(ctx);
16159 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16160 break;
16161 case OPC_MULEU_S_QH_OBL:
16162 check_dsp(ctx);
16163 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16164 break;
16165 case OPC_MULEU_S_QH_OBR:
16166 check_dsp(ctx);
16167 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16168 break;
16169 case OPC_MULQ_RS_QH:
16170 check_dsp(ctx);
16171 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16172 break;
16174 break;
16175 #endif
16178 tcg_temp_free_i32(t0);
16179 tcg_temp_free(v1_t);
16180 tcg_temp_free(v2_t);
16183 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16184 int ret, int val)
16186 int16_t imm;
16187 TCGv t0;
16188 TCGv val_t;
16190 if (ret == 0) {
16191 /* Treat as NOP. */
16192 return;
16195 t0 = tcg_temp_new();
16196 val_t = tcg_temp_new();
16197 gen_load_gpr(val_t, val);
16199 switch (op1) {
16200 case OPC_ABSQ_S_PH_DSP:
16201 switch (op2) {
16202 case OPC_BITREV:
16203 check_dsp(ctx);
16204 gen_helper_bitrev(cpu_gpr[ret], val_t);
16205 break;
16206 case OPC_REPL_QB:
16207 check_dsp(ctx);
16209 target_long result;
16210 imm = (ctx->opcode >> 16) & 0xFF;
16211 result = (uint32_t)imm << 24 |
16212 (uint32_t)imm << 16 |
16213 (uint32_t)imm << 8 |
16214 (uint32_t)imm;
16215 result = (int32_t)result;
16216 tcg_gen_movi_tl(cpu_gpr[ret], result);
16218 break;
16219 case OPC_REPLV_QB:
16220 check_dsp(ctx);
16221 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16222 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16223 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16224 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16225 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16226 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16227 break;
16228 case OPC_REPL_PH:
16229 check_dsp(ctx);
16231 imm = (ctx->opcode >> 16) & 0x03FF;
16232 imm = (int16_t)(imm << 6) >> 6;
16233 tcg_gen_movi_tl(cpu_gpr[ret], \
16234 (target_long)((int32_t)imm << 16 | \
16235 (uint16_t)imm));
16237 break;
16238 case OPC_REPLV_PH:
16239 check_dsp(ctx);
16240 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16241 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16242 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16243 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16244 break;
16246 break;
16247 #ifdef TARGET_MIPS64
16248 case OPC_ABSQ_S_QH_DSP:
16249 switch (op2) {
16250 case OPC_REPL_OB:
16251 check_dsp(ctx);
16253 target_long temp;
16255 imm = (ctx->opcode >> 16) & 0xFF;
16256 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
16257 temp = (temp << 16) | temp;
16258 temp = (temp << 32) | temp;
16259 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16260 break;
16262 case OPC_REPL_PW:
16263 check_dsp(ctx);
16265 target_long temp;
16267 imm = (ctx->opcode >> 16) & 0x03FF;
16268 imm = (int16_t)(imm << 6) >> 6;
16269 temp = ((target_long)imm << 32) \
16270 | ((target_long)imm & 0xFFFFFFFF);
16271 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16272 break;
16274 case OPC_REPL_QH:
16275 check_dsp(ctx);
16277 target_long temp;
16279 imm = (ctx->opcode >> 16) & 0x03FF;
16280 imm = (int16_t)(imm << 6) >> 6;
16282 temp = ((uint64_t)(uint16_t)imm << 48) |
16283 ((uint64_t)(uint16_t)imm << 32) |
16284 ((uint64_t)(uint16_t)imm << 16) |
16285 (uint64_t)(uint16_t)imm;
16286 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16287 break;
16289 case OPC_REPLV_OB:
16290 check_dsp(ctx);
16291 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16292 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16293 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16294 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16295 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16296 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16297 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16298 break;
16299 case OPC_REPLV_PW:
16300 check_dsp(ctx);
16301 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
16302 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16303 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16304 break;
16305 case OPC_REPLV_QH:
16306 check_dsp(ctx);
16307 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16308 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16309 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16310 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16311 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16312 break;
16314 break;
16315 #endif
16317 tcg_temp_free(t0);
16318 tcg_temp_free(val_t);
16321 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
16322 uint32_t op1, uint32_t op2,
16323 int ret, int v1, int v2, int check_ret)
16325 TCGv t1;
16326 TCGv v1_t;
16327 TCGv v2_t;
16329 if ((ret == 0) && (check_ret == 1)) {
16330 /* Treat as NOP. */
16331 return;
16334 t1 = tcg_temp_new();
16335 v1_t = tcg_temp_new();
16336 v2_t = tcg_temp_new();
16338 gen_load_gpr(v1_t, v1);
16339 gen_load_gpr(v2_t, v2);
16341 switch (op1) {
16342 case OPC_CMPU_EQ_QB_DSP:
16343 switch (op2) {
16344 case OPC_CMPU_EQ_QB:
16345 check_dsp(ctx);
16346 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
16347 break;
16348 case OPC_CMPU_LT_QB:
16349 check_dsp(ctx);
16350 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
16351 break;
16352 case OPC_CMPU_LE_QB:
16353 check_dsp(ctx);
16354 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
16355 break;
16356 case OPC_CMPGU_EQ_QB:
16357 check_dsp(ctx);
16358 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
16359 break;
16360 case OPC_CMPGU_LT_QB:
16361 check_dsp(ctx);
16362 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
16363 break;
16364 case OPC_CMPGU_LE_QB:
16365 check_dsp(ctx);
16366 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
16367 break;
16368 case OPC_CMPGDU_EQ_QB:
16369 check_dspr2(ctx);
16370 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
16371 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16372 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16373 tcg_gen_shli_tl(t1, t1, 24);
16374 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16375 break;
16376 case OPC_CMPGDU_LT_QB:
16377 check_dspr2(ctx);
16378 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
16379 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16380 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16381 tcg_gen_shli_tl(t1, t1, 24);
16382 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16383 break;
16384 case OPC_CMPGDU_LE_QB:
16385 check_dspr2(ctx);
16386 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
16387 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16388 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16389 tcg_gen_shli_tl(t1, t1, 24);
16390 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16391 break;
16392 case OPC_CMP_EQ_PH:
16393 check_dsp(ctx);
16394 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
16395 break;
16396 case OPC_CMP_LT_PH:
16397 check_dsp(ctx);
16398 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
16399 break;
16400 case OPC_CMP_LE_PH:
16401 check_dsp(ctx);
16402 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
16403 break;
16404 case OPC_PICK_QB:
16405 check_dsp(ctx);
16406 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16407 break;
16408 case OPC_PICK_PH:
16409 check_dsp(ctx);
16410 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16411 break;
16412 case OPC_PACKRL_PH:
16413 check_dsp(ctx);
16414 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
16415 break;
16417 break;
16418 #ifdef TARGET_MIPS64
16419 case OPC_CMPU_EQ_OB_DSP:
16420 switch (op2) {
16421 case OPC_CMP_EQ_PW:
16422 check_dsp(ctx);
16423 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
16424 break;
16425 case OPC_CMP_LT_PW:
16426 check_dsp(ctx);
16427 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
16428 break;
16429 case OPC_CMP_LE_PW:
16430 check_dsp(ctx);
16431 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
16432 break;
16433 case OPC_CMP_EQ_QH:
16434 check_dsp(ctx);
16435 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
16436 break;
16437 case OPC_CMP_LT_QH:
16438 check_dsp(ctx);
16439 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
16440 break;
16441 case OPC_CMP_LE_QH:
16442 check_dsp(ctx);
16443 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
16444 break;
16445 case OPC_CMPGDU_EQ_OB:
16446 check_dspr2(ctx);
16447 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16448 break;
16449 case OPC_CMPGDU_LT_OB:
16450 check_dspr2(ctx);
16451 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16452 break;
16453 case OPC_CMPGDU_LE_OB:
16454 check_dspr2(ctx);
16455 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16456 break;
16457 case OPC_CMPGU_EQ_OB:
16458 check_dsp(ctx);
16459 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
16460 break;
16461 case OPC_CMPGU_LT_OB:
16462 check_dsp(ctx);
16463 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
16464 break;
16465 case OPC_CMPGU_LE_OB:
16466 check_dsp(ctx);
16467 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
16468 break;
16469 case OPC_CMPU_EQ_OB:
16470 check_dsp(ctx);
16471 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
16472 break;
16473 case OPC_CMPU_LT_OB:
16474 check_dsp(ctx);
16475 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
16476 break;
16477 case OPC_CMPU_LE_OB:
16478 check_dsp(ctx);
16479 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
16480 break;
16481 case OPC_PACKRL_PW:
16482 check_dsp(ctx);
16483 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
16484 break;
16485 case OPC_PICK_OB:
16486 check_dsp(ctx);
16487 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16488 break;
16489 case OPC_PICK_PW:
16490 check_dsp(ctx);
16491 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16492 break;
16493 case OPC_PICK_QH:
16494 check_dsp(ctx);
16495 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16496 break;
16498 break;
16499 #endif
16502 tcg_temp_free(t1);
16503 tcg_temp_free(v1_t);
16504 tcg_temp_free(v2_t);
16507 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
16508 uint32_t op1, int rt, int rs, int sa)
16510 TCGv t0;
16512 check_dspr2(ctx);
16514 if (rt == 0) {
16515 /* Treat as NOP. */
16516 return;
16519 t0 = tcg_temp_new();
16520 gen_load_gpr(t0, rs);
16522 switch (op1) {
16523 case OPC_APPEND_DSP:
16524 switch (MASK_APPEND(ctx->opcode)) {
16525 case OPC_APPEND:
16526 if (sa != 0) {
16527 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
16529 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16530 break;
16531 case OPC_PREPEND:
16532 if (sa != 0) {
16533 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
16534 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16535 tcg_gen_shli_tl(t0, t0, 32 - sa);
16536 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16538 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16539 break;
16540 case OPC_BALIGN:
16541 sa &= 3;
16542 if (sa != 0 && sa != 2) {
16543 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16544 tcg_gen_ext32u_tl(t0, t0);
16545 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
16546 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16548 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16549 break;
16550 default: /* Invalid */
16551 MIPS_INVAL("MASK APPEND");
16552 generate_exception_end(ctx, EXCP_RI);
16553 break;
16555 break;
16556 #ifdef TARGET_MIPS64
16557 case OPC_DAPPEND_DSP:
16558 switch (MASK_DAPPEND(ctx->opcode)) {
16559 case OPC_DAPPEND:
16560 if (sa != 0) {
16561 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
16563 break;
16564 case OPC_PREPENDD:
16565 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
16566 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
16567 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
16568 break;
16569 case OPC_PREPENDW:
16570 if (sa != 0) {
16571 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16572 tcg_gen_shli_tl(t0, t0, 64 - sa);
16573 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16575 break;
16576 case OPC_DBALIGN:
16577 sa &= 7;
16578 if (sa != 0 && sa != 2 && sa != 4) {
16579 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16580 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
16581 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16583 break;
16584 default: /* Invalid */
16585 MIPS_INVAL("MASK DAPPEND");
16586 generate_exception_end(ctx, EXCP_RI);
16587 break;
16589 break;
16590 #endif
16592 tcg_temp_free(t0);
16595 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16596 int ret, int v1, int v2, int check_ret)
16599 TCGv t0;
16600 TCGv t1;
16601 TCGv v1_t;
16602 TCGv v2_t;
16603 int16_t imm;
16605 if ((ret == 0) && (check_ret == 1)) {
16606 /* Treat as NOP. */
16607 return;
16610 t0 = tcg_temp_new();
16611 t1 = tcg_temp_new();
16612 v1_t = tcg_temp_new();
16613 v2_t = tcg_temp_new();
16615 gen_load_gpr(v1_t, v1);
16616 gen_load_gpr(v2_t, v2);
16618 switch (op1) {
16619 case OPC_EXTR_W_DSP:
16620 check_dsp(ctx);
16621 switch (op2) {
16622 case OPC_EXTR_W:
16623 tcg_gen_movi_tl(t0, v2);
16624 tcg_gen_movi_tl(t1, v1);
16625 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
16626 break;
16627 case OPC_EXTR_R_W:
16628 tcg_gen_movi_tl(t0, v2);
16629 tcg_gen_movi_tl(t1, v1);
16630 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16631 break;
16632 case OPC_EXTR_RS_W:
16633 tcg_gen_movi_tl(t0, v2);
16634 tcg_gen_movi_tl(t1, v1);
16635 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16636 break;
16637 case OPC_EXTR_S_H:
16638 tcg_gen_movi_tl(t0, v2);
16639 tcg_gen_movi_tl(t1, v1);
16640 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16641 break;
16642 case OPC_EXTRV_S_H:
16643 tcg_gen_movi_tl(t0, v2);
16644 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
16645 break;
16646 case OPC_EXTRV_W:
16647 tcg_gen_movi_tl(t0, v2);
16648 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16649 break;
16650 case OPC_EXTRV_R_W:
16651 tcg_gen_movi_tl(t0, v2);
16652 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16653 break;
16654 case OPC_EXTRV_RS_W:
16655 tcg_gen_movi_tl(t0, v2);
16656 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16657 break;
16658 case OPC_EXTP:
16659 tcg_gen_movi_tl(t0, v2);
16660 tcg_gen_movi_tl(t1, v1);
16661 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
16662 break;
16663 case OPC_EXTPV:
16664 tcg_gen_movi_tl(t0, v2);
16665 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
16666 break;
16667 case OPC_EXTPDP:
16668 tcg_gen_movi_tl(t0, v2);
16669 tcg_gen_movi_tl(t1, v1);
16670 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
16671 break;
16672 case OPC_EXTPDPV:
16673 tcg_gen_movi_tl(t0, v2);
16674 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16675 break;
16676 case OPC_SHILO:
16677 imm = (ctx->opcode >> 20) & 0x3F;
16678 tcg_gen_movi_tl(t0, ret);
16679 tcg_gen_movi_tl(t1, imm);
16680 gen_helper_shilo(t0, t1, cpu_env);
16681 break;
16682 case OPC_SHILOV:
16683 tcg_gen_movi_tl(t0, ret);
16684 gen_helper_shilo(t0, v1_t, cpu_env);
16685 break;
16686 case OPC_MTHLIP:
16687 tcg_gen_movi_tl(t0, ret);
16688 gen_helper_mthlip(t0, v1_t, cpu_env);
16689 break;
16690 case OPC_WRDSP:
16691 imm = (ctx->opcode >> 11) & 0x3FF;
16692 tcg_gen_movi_tl(t0, imm);
16693 gen_helper_wrdsp(v1_t, t0, cpu_env);
16694 break;
16695 case OPC_RDDSP:
16696 imm = (ctx->opcode >> 16) & 0x03FF;
16697 tcg_gen_movi_tl(t0, imm);
16698 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
16699 break;
16701 break;
16702 #ifdef TARGET_MIPS64
16703 case OPC_DEXTR_W_DSP:
16704 check_dsp(ctx);
16705 switch (op2) {
16706 case OPC_DMTHLIP:
16707 tcg_gen_movi_tl(t0, ret);
16708 gen_helper_dmthlip(v1_t, t0, cpu_env);
16709 break;
16710 case OPC_DSHILO:
16712 int shift = (ctx->opcode >> 19) & 0x7F;
16713 int ac = (ctx->opcode >> 11) & 0x03;
16714 tcg_gen_movi_tl(t0, shift);
16715 tcg_gen_movi_tl(t1, ac);
16716 gen_helper_dshilo(t0, t1, cpu_env);
16717 break;
16719 case OPC_DSHILOV:
16721 int ac = (ctx->opcode >> 11) & 0x03;
16722 tcg_gen_movi_tl(t0, ac);
16723 gen_helper_dshilo(v1_t, t0, cpu_env);
16724 break;
16726 case OPC_DEXTP:
16727 tcg_gen_movi_tl(t0, v2);
16728 tcg_gen_movi_tl(t1, v1);
16730 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
16731 break;
16732 case OPC_DEXTPV:
16733 tcg_gen_movi_tl(t0, v2);
16734 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
16735 break;
16736 case OPC_DEXTPDP:
16737 tcg_gen_movi_tl(t0, v2);
16738 tcg_gen_movi_tl(t1, v1);
16739 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
16740 break;
16741 case OPC_DEXTPDPV:
16742 tcg_gen_movi_tl(t0, v2);
16743 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16744 break;
16745 case OPC_DEXTR_L:
16746 tcg_gen_movi_tl(t0, v2);
16747 tcg_gen_movi_tl(t1, v1);
16748 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
16749 break;
16750 case OPC_DEXTR_R_L:
16751 tcg_gen_movi_tl(t0, v2);
16752 tcg_gen_movi_tl(t1, v1);
16753 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
16754 break;
16755 case OPC_DEXTR_RS_L:
16756 tcg_gen_movi_tl(t0, v2);
16757 tcg_gen_movi_tl(t1, v1);
16758 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
16759 break;
16760 case OPC_DEXTR_W:
16761 tcg_gen_movi_tl(t0, v2);
16762 tcg_gen_movi_tl(t1, v1);
16763 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
16764 break;
16765 case OPC_DEXTR_R_W:
16766 tcg_gen_movi_tl(t0, v2);
16767 tcg_gen_movi_tl(t1, v1);
16768 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16769 break;
16770 case OPC_DEXTR_RS_W:
16771 tcg_gen_movi_tl(t0, v2);
16772 tcg_gen_movi_tl(t1, v1);
16773 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16774 break;
16775 case OPC_DEXTR_S_H:
16776 tcg_gen_movi_tl(t0, v2);
16777 tcg_gen_movi_tl(t1, v1);
16778 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16779 break;
16780 case OPC_DEXTRV_S_H:
16781 tcg_gen_movi_tl(t0, v2);
16782 tcg_gen_movi_tl(t1, v1);
16783 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16784 break;
16785 case OPC_DEXTRV_L:
16786 tcg_gen_movi_tl(t0, v2);
16787 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16788 break;
16789 case OPC_DEXTRV_R_L:
16790 tcg_gen_movi_tl(t0, v2);
16791 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16792 break;
16793 case OPC_DEXTRV_RS_L:
16794 tcg_gen_movi_tl(t0, v2);
16795 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16796 break;
16797 case OPC_DEXTRV_W:
16798 tcg_gen_movi_tl(t0, v2);
16799 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16800 break;
16801 case OPC_DEXTRV_R_W:
16802 tcg_gen_movi_tl(t0, v2);
16803 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16804 break;
16805 case OPC_DEXTRV_RS_W:
16806 tcg_gen_movi_tl(t0, v2);
16807 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16808 break;
16810 break;
16811 #endif
16814 tcg_temp_free(t0);
16815 tcg_temp_free(t1);
16816 tcg_temp_free(v1_t);
16817 tcg_temp_free(v2_t);
16820 /* End MIPSDSP functions. */
16822 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
16824 int rs, rt, rd, sa;
16825 uint32_t op1, op2;
16827 rs = (ctx->opcode >> 21) & 0x1f;
16828 rt = (ctx->opcode >> 16) & 0x1f;
16829 rd = (ctx->opcode >> 11) & 0x1f;
16830 sa = (ctx->opcode >> 6) & 0x1f;
16832 op1 = MASK_SPECIAL(ctx->opcode);
16833 switch (op1) {
16834 case OPC_LSA:
16835 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
16836 break;
16837 case OPC_MULT ... OPC_DIVU:
16838 op2 = MASK_R6_MULDIV(ctx->opcode);
16839 switch (op2) {
16840 case R6_OPC_MUL:
16841 case R6_OPC_MUH:
16842 case R6_OPC_MULU:
16843 case R6_OPC_MUHU:
16844 case R6_OPC_DIV:
16845 case R6_OPC_MOD:
16846 case R6_OPC_DIVU:
16847 case R6_OPC_MODU:
16848 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16849 break;
16850 default:
16851 MIPS_INVAL("special_r6 muldiv");
16852 generate_exception_end(ctx, EXCP_RI);
16853 break;
16855 break;
16856 case OPC_SELEQZ:
16857 case OPC_SELNEZ:
16858 gen_cond_move(ctx, op1, rd, rs, rt);
16859 break;
16860 case R6_OPC_CLO:
16861 case R6_OPC_CLZ:
16862 if (rt == 0 && sa == 1) {
16863 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16864 We need additionally to check other fields */
16865 gen_cl(ctx, op1, rd, rs);
16866 } else {
16867 generate_exception_end(ctx, EXCP_RI);
16869 break;
16870 case R6_OPC_SDBBP:
16871 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
16872 gen_helper_do_semihosting(cpu_env);
16873 } else {
16874 if (ctx->hflags & MIPS_HFLAG_SBRI) {
16875 generate_exception_end(ctx, EXCP_RI);
16876 } else {
16877 generate_exception_end(ctx, EXCP_DBp);
16880 break;
16881 #if defined(TARGET_MIPS64)
16882 case OPC_DLSA:
16883 check_mips_64(ctx);
16884 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
16885 break;
16886 case R6_OPC_DCLO:
16887 case R6_OPC_DCLZ:
16888 if (rt == 0 && sa == 1) {
16889 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16890 We need additionally to check other fields */
16891 check_mips_64(ctx);
16892 gen_cl(ctx, op1, rd, rs);
16893 } else {
16894 generate_exception_end(ctx, EXCP_RI);
16896 break;
16897 case OPC_DMULT ... OPC_DDIVU:
16898 op2 = MASK_R6_MULDIV(ctx->opcode);
16899 switch (op2) {
16900 case R6_OPC_DMUL:
16901 case R6_OPC_DMUH:
16902 case R6_OPC_DMULU:
16903 case R6_OPC_DMUHU:
16904 case R6_OPC_DDIV:
16905 case R6_OPC_DMOD:
16906 case R6_OPC_DDIVU:
16907 case R6_OPC_DMODU:
16908 check_mips_64(ctx);
16909 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16910 break;
16911 default:
16912 MIPS_INVAL("special_r6 muldiv");
16913 generate_exception_end(ctx, EXCP_RI);
16914 break;
16916 break;
16917 #endif
16918 default: /* Invalid */
16919 MIPS_INVAL("special_r6");
16920 generate_exception_end(ctx, EXCP_RI);
16921 break;
16925 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
16927 int rs, rt, rd, sa;
16928 uint32_t op1;
16930 rs = (ctx->opcode >> 21) & 0x1f;
16931 rt = (ctx->opcode >> 16) & 0x1f;
16932 rd = (ctx->opcode >> 11) & 0x1f;
16933 sa = (ctx->opcode >> 6) & 0x1f;
16935 op1 = MASK_SPECIAL(ctx->opcode);
16936 switch (op1) {
16937 case OPC_MOVN: /* Conditional move */
16938 case OPC_MOVZ:
16939 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
16940 INSN_LOONGSON2E | INSN_LOONGSON2F);
16941 gen_cond_move(ctx, op1, rd, rs, rt);
16942 break;
16943 case OPC_MFHI: /* Move from HI/LO */
16944 case OPC_MFLO:
16945 gen_HILO(ctx, op1, rs & 3, rd);
16946 break;
16947 case OPC_MTHI:
16948 case OPC_MTLO: /* Move to HI/LO */
16949 gen_HILO(ctx, op1, rd & 3, rs);
16950 break;
16951 case OPC_MOVCI:
16952 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
16953 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16954 check_cp1_enabled(ctx);
16955 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
16956 (ctx->opcode >> 16) & 1);
16957 } else {
16958 generate_exception_err(ctx, EXCP_CpU, 1);
16960 break;
16961 case OPC_MULT:
16962 case OPC_MULTU:
16963 if (sa) {
16964 check_insn(ctx, INSN_VR54XX);
16965 op1 = MASK_MUL_VR54XX(ctx->opcode);
16966 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
16967 } else {
16968 gen_muldiv(ctx, op1, rd & 3, rs, rt);
16970 break;
16971 case OPC_DIV:
16972 case OPC_DIVU:
16973 gen_muldiv(ctx, op1, 0, rs, rt);
16974 break;
16975 #if defined(TARGET_MIPS64)
16976 case OPC_DMULT ... OPC_DDIVU:
16977 check_insn(ctx, ISA_MIPS3);
16978 check_mips_64(ctx);
16979 gen_muldiv(ctx, op1, 0, rs, rt);
16980 break;
16981 #endif
16982 case OPC_JR:
16983 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
16984 break;
16985 case OPC_SPIM:
16986 #ifdef MIPS_STRICT_STANDARD
16987 MIPS_INVAL("SPIM");
16988 generate_exception_end(ctx, EXCP_RI);
16989 #else
16990 /* Implemented as RI exception for now. */
16991 MIPS_INVAL("spim (unofficial)");
16992 generate_exception_end(ctx, EXCP_RI);
16993 #endif
16994 break;
16995 default: /* Invalid */
16996 MIPS_INVAL("special_legacy");
16997 generate_exception_end(ctx, EXCP_RI);
16998 break;
17002 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
17004 int rs, rt, rd, sa;
17005 uint32_t op1;
17007 rs = (ctx->opcode >> 21) & 0x1f;
17008 rt = (ctx->opcode >> 16) & 0x1f;
17009 rd = (ctx->opcode >> 11) & 0x1f;
17010 sa = (ctx->opcode >> 6) & 0x1f;
17012 op1 = MASK_SPECIAL(ctx->opcode);
17013 switch (op1) {
17014 case OPC_SLL: /* Shift with immediate */
17015 if (sa == 5 && rd == 0 &&
17016 rs == 0 && rt == 0) { /* PAUSE */
17017 if ((ctx->insn_flags & ISA_MIPS32R6) &&
17018 (ctx->hflags & MIPS_HFLAG_BMASK)) {
17019 generate_exception_end(ctx, EXCP_RI);
17020 break;
17023 /* Fallthrough */
17024 case OPC_SRA:
17025 gen_shift_imm(ctx, op1, rd, rt, sa);
17026 break;
17027 case OPC_SRL:
17028 switch ((ctx->opcode >> 21) & 0x1f) {
17029 case 1:
17030 /* rotr is decoded as srl on non-R2 CPUs */
17031 if (ctx->insn_flags & ISA_MIPS32R2) {
17032 op1 = OPC_ROTR;
17034 /* Fallthrough */
17035 case 0:
17036 gen_shift_imm(ctx, op1, rd, rt, sa);
17037 break;
17038 default:
17039 generate_exception_end(ctx, EXCP_RI);
17040 break;
17042 break;
17043 case OPC_ADD ... OPC_SUBU:
17044 gen_arith(ctx, op1, rd, rs, rt);
17045 break;
17046 case OPC_SLLV: /* Shifts */
17047 case OPC_SRAV:
17048 gen_shift(ctx, op1, rd, rs, rt);
17049 break;
17050 case OPC_SRLV:
17051 switch ((ctx->opcode >> 6) & 0x1f) {
17052 case 1:
17053 /* rotrv is decoded as srlv on non-R2 CPUs */
17054 if (ctx->insn_flags & ISA_MIPS32R2) {
17055 op1 = OPC_ROTRV;
17057 /* Fallthrough */
17058 case 0:
17059 gen_shift(ctx, op1, rd, rs, rt);
17060 break;
17061 default:
17062 generate_exception_end(ctx, EXCP_RI);
17063 break;
17065 break;
17066 case OPC_SLT: /* Set on less than */
17067 case OPC_SLTU:
17068 gen_slt(ctx, op1, rd, rs, rt);
17069 break;
17070 case OPC_AND: /* Logic*/
17071 case OPC_OR:
17072 case OPC_NOR:
17073 case OPC_XOR:
17074 gen_logic(ctx, op1, rd, rs, rt);
17075 break;
17076 case OPC_JALR:
17077 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17078 break;
17079 case OPC_TGE ... OPC_TEQ: /* Traps */
17080 case OPC_TNE:
17081 check_insn(ctx, ISA_MIPS2);
17082 gen_trap(ctx, op1, rs, rt, -1);
17083 break;
17084 case OPC_LSA: /* OPC_PMON */
17085 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17086 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17087 decode_opc_special_r6(env, ctx);
17088 } else {
17089 /* Pmon entry point, also R4010 selsl */
17090 #ifdef MIPS_STRICT_STANDARD
17091 MIPS_INVAL("PMON / selsl");
17092 generate_exception_end(ctx, EXCP_RI);
17093 #else
17094 gen_helper_0e0i(pmon, sa);
17095 #endif
17097 break;
17098 case OPC_SYSCALL:
17099 generate_exception_end(ctx, EXCP_SYSCALL);
17100 break;
17101 case OPC_BREAK:
17102 generate_exception_end(ctx, EXCP_BREAK);
17103 break;
17104 case OPC_SYNC:
17105 check_insn(ctx, ISA_MIPS2);
17106 /* Treat as NOP. */
17107 break;
17109 #if defined(TARGET_MIPS64)
17110 /* MIPS64 specific opcodes */
17111 case OPC_DSLL:
17112 case OPC_DSRA:
17113 case OPC_DSLL32:
17114 case OPC_DSRA32:
17115 check_insn(ctx, ISA_MIPS3);
17116 check_mips_64(ctx);
17117 gen_shift_imm(ctx, op1, rd, rt, sa);
17118 break;
17119 case OPC_DSRL:
17120 switch ((ctx->opcode >> 21) & 0x1f) {
17121 case 1:
17122 /* drotr is decoded as dsrl on non-R2 CPUs */
17123 if (ctx->insn_flags & ISA_MIPS32R2) {
17124 op1 = OPC_DROTR;
17126 /* Fallthrough */
17127 case 0:
17128 check_insn(ctx, ISA_MIPS3);
17129 check_mips_64(ctx);
17130 gen_shift_imm(ctx, op1, rd, rt, sa);
17131 break;
17132 default:
17133 generate_exception_end(ctx, EXCP_RI);
17134 break;
17136 break;
17137 case OPC_DSRL32:
17138 switch ((ctx->opcode >> 21) & 0x1f) {
17139 case 1:
17140 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
17141 if (ctx->insn_flags & ISA_MIPS32R2) {
17142 op1 = OPC_DROTR32;
17144 /* Fallthrough */
17145 case 0:
17146 check_insn(ctx, ISA_MIPS3);
17147 check_mips_64(ctx);
17148 gen_shift_imm(ctx, op1, rd, rt, sa);
17149 break;
17150 default:
17151 generate_exception_end(ctx, EXCP_RI);
17152 break;
17154 break;
17155 case OPC_DADD ... OPC_DSUBU:
17156 check_insn(ctx, ISA_MIPS3);
17157 check_mips_64(ctx);
17158 gen_arith(ctx, op1, rd, rs, rt);
17159 break;
17160 case OPC_DSLLV:
17161 case OPC_DSRAV:
17162 check_insn(ctx, ISA_MIPS3);
17163 check_mips_64(ctx);
17164 gen_shift(ctx, op1, rd, rs, rt);
17165 break;
17166 case OPC_DSRLV:
17167 switch ((ctx->opcode >> 6) & 0x1f) {
17168 case 1:
17169 /* drotrv is decoded as dsrlv on non-R2 CPUs */
17170 if (ctx->insn_flags & ISA_MIPS32R2) {
17171 op1 = OPC_DROTRV;
17173 /* Fallthrough */
17174 case 0:
17175 check_insn(ctx, ISA_MIPS3);
17176 check_mips_64(ctx);
17177 gen_shift(ctx, op1, rd, rs, rt);
17178 break;
17179 default:
17180 generate_exception_end(ctx, EXCP_RI);
17181 break;
17183 break;
17184 case OPC_DLSA:
17185 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17186 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17187 decode_opc_special_r6(env, ctx);
17189 break;
17190 #endif
17191 default:
17192 if (ctx->insn_flags & ISA_MIPS32R6) {
17193 decode_opc_special_r6(env, ctx);
17194 } else {
17195 decode_opc_special_legacy(env, ctx);
17200 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
17202 int rs, rt, rd;
17203 uint32_t op1;
17205 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17207 rs = (ctx->opcode >> 21) & 0x1f;
17208 rt = (ctx->opcode >> 16) & 0x1f;
17209 rd = (ctx->opcode >> 11) & 0x1f;
17211 op1 = MASK_SPECIAL2(ctx->opcode);
17212 switch (op1) {
17213 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
17214 case OPC_MSUB ... OPC_MSUBU:
17215 check_insn(ctx, ISA_MIPS32);
17216 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17217 break;
17218 case OPC_MUL:
17219 gen_arith(ctx, op1, rd, rs, rt);
17220 break;
17221 case OPC_DIV_G_2F:
17222 case OPC_DIVU_G_2F:
17223 case OPC_MULT_G_2F:
17224 case OPC_MULTU_G_2F:
17225 case OPC_MOD_G_2F:
17226 case OPC_MODU_G_2F:
17227 check_insn(ctx, INSN_LOONGSON2F);
17228 gen_loongson_integer(ctx, op1, rd, rs, rt);
17229 break;
17230 case OPC_CLO:
17231 case OPC_CLZ:
17232 check_insn(ctx, ISA_MIPS32);
17233 gen_cl(ctx, op1, rd, rs);
17234 break;
17235 case OPC_SDBBP:
17236 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17237 gen_helper_do_semihosting(cpu_env);
17238 } else {
17239 /* XXX: not clear which exception should be raised
17240 * when in debug mode...
17242 check_insn(ctx, ISA_MIPS32);
17243 generate_exception_end(ctx, EXCP_DBp);
17245 break;
17246 #if defined(TARGET_MIPS64)
17247 case OPC_DCLO:
17248 case OPC_DCLZ:
17249 check_insn(ctx, ISA_MIPS64);
17250 check_mips_64(ctx);
17251 gen_cl(ctx, op1, rd, rs);
17252 break;
17253 case OPC_DMULT_G_2F:
17254 case OPC_DMULTU_G_2F:
17255 case OPC_DDIV_G_2F:
17256 case OPC_DDIVU_G_2F:
17257 case OPC_DMOD_G_2F:
17258 case OPC_DMODU_G_2F:
17259 check_insn(ctx, INSN_LOONGSON2F);
17260 gen_loongson_integer(ctx, op1, rd, rs, rt);
17261 break;
17262 #endif
17263 default: /* Invalid */
17264 MIPS_INVAL("special2_legacy");
17265 generate_exception_end(ctx, EXCP_RI);
17266 break;
17270 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
17272 int rs, rt, rd, sa;
17273 uint32_t op1, op2;
17274 int16_t imm;
17276 rs = (ctx->opcode >> 21) & 0x1f;
17277 rt = (ctx->opcode >> 16) & 0x1f;
17278 rd = (ctx->opcode >> 11) & 0x1f;
17279 sa = (ctx->opcode >> 6) & 0x1f;
17280 imm = (int16_t)ctx->opcode >> 7;
17282 op1 = MASK_SPECIAL3(ctx->opcode);
17283 switch (op1) {
17284 case R6_OPC_PREF:
17285 if (rt >= 24) {
17286 /* hint codes 24-31 are reserved and signal RI */
17287 generate_exception_end(ctx, EXCP_RI);
17289 /* Treat as NOP. */
17290 break;
17291 case R6_OPC_CACHE:
17292 check_cp0_enabled(ctx);
17293 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17294 gen_cache_operation(ctx, rt, rs, imm);
17296 break;
17297 case R6_OPC_SC:
17298 gen_st_cond(ctx, op1, rt, rs, imm);
17299 break;
17300 case R6_OPC_LL:
17301 gen_ld(ctx, op1, rt, rs, imm);
17302 break;
17303 case OPC_BSHFL:
17305 if (rd == 0) {
17306 /* Treat as NOP. */
17307 break;
17309 op2 = MASK_BSHFL(ctx->opcode);
17310 switch (op2) {
17311 case OPC_ALIGN ... OPC_ALIGN_END:
17312 gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3);
17313 break;
17314 case OPC_BITSWAP:
17315 gen_bitswap(ctx, op2, rd, rt);
17316 break;
17319 break;
17320 #if defined(TARGET_MIPS64)
17321 case R6_OPC_SCD:
17322 gen_st_cond(ctx, op1, rt, rs, imm);
17323 break;
17324 case R6_OPC_LLD:
17325 gen_ld(ctx, op1, rt, rs, imm);
17326 break;
17327 case OPC_DBSHFL:
17328 check_mips_64(ctx);
17330 if (rd == 0) {
17331 /* Treat as NOP. */
17332 break;
17334 op2 = MASK_DBSHFL(ctx->opcode);
17335 switch (op2) {
17336 case OPC_DALIGN ... OPC_DALIGN_END:
17337 gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7);
17338 break;
17339 case OPC_DBITSWAP:
17340 gen_bitswap(ctx, op2, rd, rt);
17341 break;
17345 break;
17346 #endif
17347 default: /* Invalid */
17348 MIPS_INVAL("special3_r6");
17349 generate_exception_end(ctx, EXCP_RI);
17350 break;
17354 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
17356 int rs, rt, rd;
17357 uint32_t op1, op2;
17359 rs = (ctx->opcode >> 21) & 0x1f;
17360 rt = (ctx->opcode >> 16) & 0x1f;
17361 rd = (ctx->opcode >> 11) & 0x1f;
17363 op1 = MASK_SPECIAL3(ctx->opcode);
17364 switch (op1) {
17365 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
17366 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
17367 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
17368 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
17369 * the same mask and op1. */
17370 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
17371 op2 = MASK_ADDUH_QB(ctx->opcode);
17372 switch (op2) {
17373 case OPC_ADDUH_QB:
17374 case OPC_ADDUH_R_QB:
17375 case OPC_ADDQH_PH:
17376 case OPC_ADDQH_R_PH:
17377 case OPC_ADDQH_W:
17378 case OPC_ADDQH_R_W:
17379 case OPC_SUBUH_QB:
17380 case OPC_SUBUH_R_QB:
17381 case OPC_SUBQH_PH:
17382 case OPC_SUBQH_R_PH:
17383 case OPC_SUBQH_W:
17384 case OPC_SUBQH_R_W:
17385 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17386 break;
17387 case OPC_MUL_PH:
17388 case OPC_MUL_S_PH:
17389 case OPC_MULQ_S_W:
17390 case OPC_MULQ_RS_W:
17391 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17392 break;
17393 default:
17394 MIPS_INVAL("MASK ADDUH.QB");
17395 generate_exception_end(ctx, EXCP_RI);
17396 break;
17398 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
17399 gen_loongson_integer(ctx, op1, rd, rs, rt);
17400 } else {
17401 generate_exception_end(ctx, EXCP_RI);
17403 break;
17404 case OPC_LX_DSP:
17405 op2 = MASK_LX(ctx->opcode);
17406 switch (op2) {
17407 #if defined(TARGET_MIPS64)
17408 case OPC_LDX:
17409 #endif
17410 case OPC_LBUX:
17411 case OPC_LHX:
17412 case OPC_LWX:
17413 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
17414 break;
17415 default: /* Invalid */
17416 MIPS_INVAL("MASK LX");
17417 generate_exception_end(ctx, EXCP_RI);
17418 break;
17420 break;
17421 case OPC_ABSQ_S_PH_DSP:
17422 op2 = MASK_ABSQ_S_PH(ctx->opcode);
17423 switch (op2) {
17424 case OPC_ABSQ_S_QB:
17425 case OPC_ABSQ_S_PH:
17426 case OPC_ABSQ_S_W:
17427 case OPC_PRECEQ_W_PHL:
17428 case OPC_PRECEQ_W_PHR:
17429 case OPC_PRECEQU_PH_QBL:
17430 case OPC_PRECEQU_PH_QBR:
17431 case OPC_PRECEQU_PH_QBLA:
17432 case OPC_PRECEQU_PH_QBRA:
17433 case OPC_PRECEU_PH_QBL:
17434 case OPC_PRECEU_PH_QBR:
17435 case OPC_PRECEU_PH_QBLA:
17436 case OPC_PRECEU_PH_QBRA:
17437 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17438 break;
17439 case OPC_BITREV:
17440 case OPC_REPL_QB:
17441 case OPC_REPLV_QB:
17442 case OPC_REPL_PH:
17443 case OPC_REPLV_PH:
17444 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17445 break;
17446 default:
17447 MIPS_INVAL("MASK ABSQ_S.PH");
17448 generate_exception_end(ctx, EXCP_RI);
17449 break;
17451 break;
17452 case OPC_ADDU_QB_DSP:
17453 op2 = MASK_ADDU_QB(ctx->opcode);
17454 switch (op2) {
17455 case OPC_ADDQ_PH:
17456 case OPC_ADDQ_S_PH:
17457 case OPC_ADDQ_S_W:
17458 case OPC_ADDU_QB:
17459 case OPC_ADDU_S_QB:
17460 case OPC_ADDU_PH:
17461 case OPC_ADDU_S_PH:
17462 case OPC_SUBQ_PH:
17463 case OPC_SUBQ_S_PH:
17464 case OPC_SUBQ_S_W:
17465 case OPC_SUBU_QB:
17466 case OPC_SUBU_S_QB:
17467 case OPC_SUBU_PH:
17468 case OPC_SUBU_S_PH:
17469 case OPC_ADDSC:
17470 case OPC_ADDWC:
17471 case OPC_MODSUB:
17472 case OPC_RADDU_W_QB:
17473 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17474 break;
17475 case OPC_MULEU_S_PH_QBL:
17476 case OPC_MULEU_S_PH_QBR:
17477 case OPC_MULQ_RS_PH:
17478 case OPC_MULEQ_S_W_PHL:
17479 case OPC_MULEQ_S_W_PHR:
17480 case OPC_MULQ_S_PH:
17481 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17482 break;
17483 default: /* Invalid */
17484 MIPS_INVAL("MASK ADDU.QB");
17485 generate_exception_end(ctx, EXCP_RI);
17486 break;
17489 break;
17490 case OPC_CMPU_EQ_QB_DSP:
17491 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
17492 switch (op2) {
17493 case OPC_PRECR_SRA_PH_W:
17494 case OPC_PRECR_SRA_R_PH_W:
17495 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17496 break;
17497 case OPC_PRECR_QB_PH:
17498 case OPC_PRECRQ_QB_PH:
17499 case OPC_PRECRQ_PH_W:
17500 case OPC_PRECRQ_RS_PH_W:
17501 case OPC_PRECRQU_S_QB_PH:
17502 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17503 break;
17504 case OPC_CMPU_EQ_QB:
17505 case OPC_CMPU_LT_QB:
17506 case OPC_CMPU_LE_QB:
17507 case OPC_CMP_EQ_PH:
17508 case OPC_CMP_LT_PH:
17509 case OPC_CMP_LE_PH:
17510 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17511 break;
17512 case OPC_CMPGU_EQ_QB:
17513 case OPC_CMPGU_LT_QB:
17514 case OPC_CMPGU_LE_QB:
17515 case OPC_CMPGDU_EQ_QB:
17516 case OPC_CMPGDU_LT_QB:
17517 case OPC_CMPGDU_LE_QB:
17518 case OPC_PICK_QB:
17519 case OPC_PICK_PH:
17520 case OPC_PACKRL_PH:
17521 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17522 break;
17523 default: /* Invalid */
17524 MIPS_INVAL("MASK CMPU.EQ.QB");
17525 generate_exception_end(ctx, EXCP_RI);
17526 break;
17528 break;
17529 case OPC_SHLL_QB_DSP:
17530 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17531 break;
17532 case OPC_DPA_W_PH_DSP:
17533 op2 = MASK_DPA_W_PH(ctx->opcode);
17534 switch (op2) {
17535 case OPC_DPAU_H_QBL:
17536 case OPC_DPAU_H_QBR:
17537 case OPC_DPSU_H_QBL:
17538 case OPC_DPSU_H_QBR:
17539 case OPC_DPA_W_PH:
17540 case OPC_DPAX_W_PH:
17541 case OPC_DPAQ_S_W_PH:
17542 case OPC_DPAQX_S_W_PH:
17543 case OPC_DPAQX_SA_W_PH:
17544 case OPC_DPS_W_PH:
17545 case OPC_DPSX_W_PH:
17546 case OPC_DPSQ_S_W_PH:
17547 case OPC_DPSQX_S_W_PH:
17548 case OPC_DPSQX_SA_W_PH:
17549 case OPC_MULSAQ_S_W_PH:
17550 case OPC_DPAQ_SA_L_W:
17551 case OPC_DPSQ_SA_L_W:
17552 case OPC_MAQ_S_W_PHL:
17553 case OPC_MAQ_S_W_PHR:
17554 case OPC_MAQ_SA_W_PHL:
17555 case OPC_MAQ_SA_W_PHR:
17556 case OPC_MULSA_W_PH:
17557 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17558 break;
17559 default: /* Invalid */
17560 MIPS_INVAL("MASK DPAW.PH");
17561 generate_exception_end(ctx, EXCP_RI);
17562 break;
17564 break;
17565 case OPC_INSV_DSP:
17566 op2 = MASK_INSV(ctx->opcode);
17567 switch (op2) {
17568 case OPC_INSV:
17569 check_dsp(ctx);
17571 TCGv t0, t1;
17573 if (rt == 0) {
17574 break;
17577 t0 = tcg_temp_new();
17578 t1 = tcg_temp_new();
17580 gen_load_gpr(t0, rt);
17581 gen_load_gpr(t1, rs);
17583 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
17585 tcg_temp_free(t0);
17586 tcg_temp_free(t1);
17587 break;
17589 default: /* Invalid */
17590 MIPS_INVAL("MASK INSV");
17591 generate_exception_end(ctx, EXCP_RI);
17592 break;
17594 break;
17595 case OPC_APPEND_DSP:
17596 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17597 break;
17598 case OPC_EXTR_W_DSP:
17599 op2 = MASK_EXTR_W(ctx->opcode);
17600 switch (op2) {
17601 case OPC_EXTR_W:
17602 case OPC_EXTR_R_W:
17603 case OPC_EXTR_RS_W:
17604 case OPC_EXTR_S_H:
17605 case OPC_EXTRV_S_H:
17606 case OPC_EXTRV_W:
17607 case OPC_EXTRV_R_W:
17608 case OPC_EXTRV_RS_W:
17609 case OPC_EXTP:
17610 case OPC_EXTPV:
17611 case OPC_EXTPDP:
17612 case OPC_EXTPDPV:
17613 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17614 break;
17615 case OPC_RDDSP:
17616 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
17617 break;
17618 case OPC_SHILO:
17619 case OPC_SHILOV:
17620 case OPC_MTHLIP:
17621 case OPC_WRDSP:
17622 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17623 break;
17624 default: /* Invalid */
17625 MIPS_INVAL("MASK EXTR.W");
17626 generate_exception_end(ctx, EXCP_RI);
17627 break;
17629 break;
17630 #if defined(TARGET_MIPS64)
17631 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
17632 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
17633 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
17634 check_insn(ctx, INSN_LOONGSON2E);
17635 gen_loongson_integer(ctx, op1, rd, rs, rt);
17636 break;
17637 case OPC_ABSQ_S_QH_DSP:
17638 op2 = MASK_ABSQ_S_QH(ctx->opcode);
17639 switch (op2) {
17640 case OPC_PRECEQ_L_PWL:
17641 case OPC_PRECEQ_L_PWR:
17642 case OPC_PRECEQ_PW_QHL:
17643 case OPC_PRECEQ_PW_QHR:
17644 case OPC_PRECEQ_PW_QHLA:
17645 case OPC_PRECEQ_PW_QHRA:
17646 case OPC_PRECEQU_QH_OBL:
17647 case OPC_PRECEQU_QH_OBR:
17648 case OPC_PRECEQU_QH_OBLA:
17649 case OPC_PRECEQU_QH_OBRA:
17650 case OPC_PRECEU_QH_OBL:
17651 case OPC_PRECEU_QH_OBR:
17652 case OPC_PRECEU_QH_OBLA:
17653 case OPC_PRECEU_QH_OBRA:
17654 case OPC_ABSQ_S_OB:
17655 case OPC_ABSQ_S_PW:
17656 case OPC_ABSQ_S_QH:
17657 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17658 break;
17659 case OPC_REPL_OB:
17660 case OPC_REPL_PW:
17661 case OPC_REPL_QH:
17662 case OPC_REPLV_OB:
17663 case OPC_REPLV_PW:
17664 case OPC_REPLV_QH:
17665 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17666 break;
17667 default: /* Invalid */
17668 MIPS_INVAL("MASK ABSQ_S.QH");
17669 generate_exception_end(ctx, EXCP_RI);
17670 break;
17672 break;
17673 case OPC_ADDU_OB_DSP:
17674 op2 = MASK_ADDU_OB(ctx->opcode);
17675 switch (op2) {
17676 case OPC_RADDU_L_OB:
17677 case OPC_SUBQ_PW:
17678 case OPC_SUBQ_S_PW:
17679 case OPC_SUBQ_QH:
17680 case OPC_SUBQ_S_QH:
17681 case OPC_SUBU_OB:
17682 case OPC_SUBU_S_OB:
17683 case OPC_SUBU_QH:
17684 case OPC_SUBU_S_QH:
17685 case OPC_SUBUH_OB:
17686 case OPC_SUBUH_R_OB:
17687 case OPC_ADDQ_PW:
17688 case OPC_ADDQ_S_PW:
17689 case OPC_ADDQ_QH:
17690 case OPC_ADDQ_S_QH:
17691 case OPC_ADDU_OB:
17692 case OPC_ADDU_S_OB:
17693 case OPC_ADDU_QH:
17694 case OPC_ADDU_S_QH:
17695 case OPC_ADDUH_OB:
17696 case OPC_ADDUH_R_OB:
17697 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17698 break;
17699 case OPC_MULEQ_S_PW_QHL:
17700 case OPC_MULEQ_S_PW_QHR:
17701 case OPC_MULEU_S_QH_OBL:
17702 case OPC_MULEU_S_QH_OBR:
17703 case OPC_MULQ_RS_QH:
17704 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17705 break;
17706 default: /* Invalid */
17707 MIPS_INVAL("MASK ADDU.OB");
17708 generate_exception_end(ctx, EXCP_RI);
17709 break;
17711 break;
17712 case OPC_CMPU_EQ_OB_DSP:
17713 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
17714 switch (op2) {
17715 case OPC_PRECR_SRA_QH_PW:
17716 case OPC_PRECR_SRA_R_QH_PW:
17717 /* Return value is rt. */
17718 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17719 break;
17720 case OPC_PRECR_OB_QH:
17721 case OPC_PRECRQ_OB_QH:
17722 case OPC_PRECRQ_PW_L:
17723 case OPC_PRECRQ_QH_PW:
17724 case OPC_PRECRQ_RS_QH_PW:
17725 case OPC_PRECRQU_S_OB_QH:
17726 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17727 break;
17728 case OPC_CMPU_EQ_OB:
17729 case OPC_CMPU_LT_OB:
17730 case OPC_CMPU_LE_OB:
17731 case OPC_CMP_EQ_QH:
17732 case OPC_CMP_LT_QH:
17733 case OPC_CMP_LE_QH:
17734 case OPC_CMP_EQ_PW:
17735 case OPC_CMP_LT_PW:
17736 case OPC_CMP_LE_PW:
17737 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17738 break;
17739 case OPC_CMPGDU_EQ_OB:
17740 case OPC_CMPGDU_LT_OB:
17741 case OPC_CMPGDU_LE_OB:
17742 case OPC_CMPGU_EQ_OB:
17743 case OPC_CMPGU_LT_OB:
17744 case OPC_CMPGU_LE_OB:
17745 case OPC_PACKRL_PW:
17746 case OPC_PICK_OB:
17747 case OPC_PICK_PW:
17748 case OPC_PICK_QH:
17749 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17750 break;
17751 default: /* Invalid */
17752 MIPS_INVAL("MASK CMPU_EQ.OB");
17753 generate_exception_end(ctx, EXCP_RI);
17754 break;
17756 break;
17757 case OPC_DAPPEND_DSP:
17758 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17759 break;
17760 case OPC_DEXTR_W_DSP:
17761 op2 = MASK_DEXTR_W(ctx->opcode);
17762 switch (op2) {
17763 case OPC_DEXTP:
17764 case OPC_DEXTPDP:
17765 case OPC_DEXTPDPV:
17766 case OPC_DEXTPV:
17767 case OPC_DEXTR_L:
17768 case OPC_DEXTR_R_L:
17769 case OPC_DEXTR_RS_L:
17770 case OPC_DEXTR_W:
17771 case OPC_DEXTR_R_W:
17772 case OPC_DEXTR_RS_W:
17773 case OPC_DEXTR_S_H:
17774 case OPC_DEXTRV_L:
17775 case OPC_DEXTRV_R_L:
17776 case OPC_DEXTRV_RS_L:
17777 case OPC_DEXTRV_S_H:
17778 case OPC_DEXTRV_W:
17779 case OPC_DEXTRV_R_W:
17780 case OPC_DEXTRV_RS_W:
17781 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17782 break;
17783 case OPC_DMTHLIP:
17784 case OPC_DSHILO:
17785 case OPC_DSHILOV:
17786 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17787 break;
17788 default: /* Invalid */
17789 MIPS_INVAL("MASK EXTR.W");
17790 generate_exception_end(ctx, EXCP_RI);
17791 break;
17793 break;
17794 case OPC_DPAQ_W_QH_DSP:
17795 op2 = MASK_DPAQ_W_QH(ctx->opcode);
17796 switch (op2) {
17797 case OPC_DPAU_H_OBL:
17798 case OPC_DPAU_H_OBR:
17799 case OPC_DPSU_H_OBL:
17800 case OPC_DPSU_H_OBR:
17801 case OPC_DPA_W_QH:
17802 case OPC_DPAQ_S_W_QH:
17803 case OPC_DPS_W_QH:
17804 case OPC_DPSQ_S_W_QH:
17805 case OPC_MULSAQ_S_W_QH:
17806 case OPC_DPAQ_SA_L_PW:
17807 case OPC_DPSQ_SA_L_PW:
17808 case OPC_MULSAQ_S_L_PW:
17809 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17810 break;
17811 case OPC_MAQ_S_W_QHLL:
17812 case OPC_MAQ_S_W_QHLR:
17813 case OPC_MAQ_S_W_QHRL:
17814 case OPC_MAQ_S_W_QHRR:
17815 case OPC_MAQ_SA_W_QHLL:
17816 case OPC_MAQ_SA_W_QHLR:
17817 case OPC_MAQ_SA_W_QHRL:
17818 case OPC_MAQ_SA_W_QHRR:
17819 case OPC_MAQ_S_L_PWL:
17820 case OPC_MAQ_S_L_PWR:
17821 case OPC_DMADD:
17822 case OPC_DMADDU:
17823 case OPC_DMSUB:
17824 case OPC_DMSUBU:
17825 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17826 break;
17827 default: /* Invalid */
17828 MIPS_INVAL("MASK DPAQ.W.QH");
17829 generate_exception_end(ctx, EXCP_RI);
17830 break;
17832 break;
17833 case OPC_DINSV_DSP:
17834 op2 = MASK_INSV(ctx->opcode);
17835 switch (op2) {
17836 case OPC_DINSV:
17838 TCGv t0, t1;
17840 if (rt == 0) {
17841 break;
17843 check_dsp(ctx);
17845 t0 = tcg_temp_new();
17846 t1 = tcg_temp_new();
17848 gen_load_gpr(t0, rt);
17849 gen_load_gpr(t1, rs);
17851 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
17853 tcg_temp_free(t0);
17854 tcg_temp_free(t1);
17855 break;
17857 default: /* Invalid */
17858 MIPS_INVAL("MASK DINSV");
17859 generate_exception_end(ctx, EXCP_RI);
17860 break;
17862 break;
17863 case OPC_SHLL_OB_DSP:
17864 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17865 break;
17866 #endif
17867 default: /* Invalid */
17868 MIPS_INVAL("special3_legacy");
17869 generate_exception_end(ctx, EXCP_RI);
17870 break;
17874 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
17876 int rs, rt, rd, sa;
17877 uint32_t op1, op2;
17879 rs = (ctx->opcode >> 21) & 0x1f;
17880 rt = (ctx->opcode >> 16) & 0x1f;
17881 rd = (ctx->opcode >> 11) & 0x1f;
17882 sa = (ctx->opcode >> 6) & 0x1f;
17884 op1 = MASK_SPECIAL3(ctx->opcode);
17885 switch (op1) {
17886 case OPC_EXT:
17887 case OPC_INS:
17888 check_insn(ctx, ISA_MIPS32R2);
17889 gen_bitops(ctx, op1, rt, rs, sa, rd);
17890 break;
17891 case OPC_BSHFL:
17892 op2 = MASK_BSHFL(ctx->opcode);
17893 switch (op2) {
17894 case OPC_ALIGN ... OPC_ALIGN_END:
17895 case OPC_BITSWAP:
17896 check_insn(ctx, ISA_MIPS32R6);
17897 decode_opc_special3_r6(env, ctx);
17898 break;
17899 default:
17900 check_insn(ctx, ISA_MIPS32R2);
17901 gen_bshfl(ctx, op2, rt, rd);
17902 break;
17904 break;
17905 #if defined(TARGET_MIPS64)
17906 case OPC_DEXTM ... OPC_DEXT:
17907 case OPC_DINSM ... OPC_DINS:
17908 check_insn(ctx, ISA_MIPS64R2);
17909 check_mips_64(ctx);
17910 gen_bitops(ctx, op1, rt, rs, sa, rd);
17911 break;
17912 case OPC_DBSHFL:
17913 op2 = MASK_DBSHFL(ctx->opcode);
17914 switch (op2) {
17915 case OPC_DALIGN ... OPC_DALIGN_END:
17916 case OPC_DBITSWAP:
17917 check_insn(ctx, ISA_MIPS32R6);
17918 decode_opc_special3_r6(env, ctx);
17919 break;
17920 default:
17921 check_insn(ctx, ISA_MIPS64R2);
17922 check_mips_64(ctx);
17923 op2 = MASK_DBSHFL(ctx->opcode);
17924 gen_bshfl(ctx, op2, rt, rd);
17925 break;
17927 break;
17928 #endif
17929 case OPC_RDHWR:
17930 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
17931 break;
17932 case OPC_FORK:
17933 check_insn(ctx, ASE_MT);
17935 TCGv t0 = tcg_temp_new();
17936 TCGv t1 = tcg_temp_new();
17938 gen_load_gpr(t0, rt);
17939 gen_load_gpr(t1, rs);
17940 gen_helper_fork(t0, t1);
17941 tcg_temp_free(t0);
17942 tcg_temp_free(t1);
17944 break;
17945 case OPC_YIELD:
17946 check_insn(ctx, ASE_MT);
17948 TCGv t0 = tcg_temp_new();
17950 gen_load_gpr(t0, rs);
17951 gen_helper_yield(t0, cpu_env, t0);
17952 gen_store_gpr(t0, rd);
17953 tcg_temp_free(t0);
17955 break;
17956 default:
17957 if (ctx->insn_flags & ISA_MIPS32R6) {
17958 decode_opc_special3_r6(env, ctx);
17959 } else {
17960 decode_opc_special3_legacy(env, ctx);
17965 /* MIPS SIMD Architecture (MSA) */
17966 static inline int check_msa_access(DisasContext *ctx)
17968 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
17969 !(ctx->hflags & MIPS_HFLAG_F64))) {
17970 generate_exception_end(ctx, EXCP_RI);
17971 return 0;
17974 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
17975 if (ctx->insn_flags & ASE_MSA) {
17976 generate_exception_end(ctx, EXCP_MSADIS);
17977 return 0;
17978 } else {
17979 generate_exception_end(ctx, EXCP_RI);
17980 return 0;
17983 return 1;
17986 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
17988 /* generates tcg ops to check if any element is 0 */
17989 /* Note this function only works with MSA_WRLEN = 128 */
17990 uint64_t eval_zero_or_big = 0;
17991 uint64_t eval_big = 0;
17992 TCGv_i64 t0 = tcg_temp_new_i64();
17993 TCGv_i64 t1 = tcg_temp_new_i64();
17994 switch (df) {
17995 case DF_BYTE:
17996 eval_zero_or_big = 0x0101010101010101ULL;
17997 eval_big = 0x8080808080808080ULL;
17998 break;
17999 case DF_HALF:
18000 eval_zero_or_big = 0x0001000100010001ULL;
18001 eval_big = 0x8000800080008000ULL;
18002 break;
18003 case DF_WORD:
18004 eval_zero_or_big = 0x0000000100000001ULL;
18005 eval_big = 0x8000000080000000ULL;
18006 break;
18007 case DF_DOUBLE:
18008 eval_zero_or_big = 0x0000000000000001ULL;
18009 eval_big = 0x8000000000000000ULL;
18010 break;
18012 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
18013 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
18014 tcg_gen_andi_i64(t0, t0, eval_big);
18015 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
18016 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
18017 tcg_gen_andi_i64(t1, t1, eval_big);
18018 tcg_gen_or_i64(t0, t0, t1);
18019 /* if all bits are zero then all elements are not zero */
18020 /* if some bit is non-zero then some element is zero */
18021 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
18022 tcg_gen_trunc_i64_tl(tresult, t0);
18023 tcg_temp_free_i64(t0);
18024 tcg_temp_free_i64(t1);
18027 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
18029 uint8_t df = (ctx->opcode >> 21) & 0x3;
18030 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18031 int64_t s16 = (int16_t)ctx->opcode;
18033 check_msa_access(ctx);
18035 if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
18036 generate_exception_end(ctx, EXCP_RI);
18037 return;
18039 switch (op1) {
18040 case OPC_BZ_V:
18041 case OPC_BNZ_V:
18043 TCGv_i64 t0 = tcg_temp_new_i64();
18044 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
18045 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
18046 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
18047 tcg_gen_trunc_i64_tl(bcond, t0);
18048 tcg_temp_free_i64(t0);
18050 break;
18051 case OPC_BZ_B:
18052 case OPC_BZ_H:
18053 case OPC_BZ_W:
18054 case OPC_BZ_D:
18055 gen_check_zero_element(bcond, df, wt);
18056 break;
18057 case OPC_BNZ_B:
18058 case OPC_BNZ_H:
18059 case OPC_BNZ_W:
18060 case OPC_BNZ_D:
18061 gen_check_zero_element(bcond, df, wt);
18062 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
18063 break;
18066 ctx->btarget = ctx->pc + (s16 << 2) + 4;
18068 ctx->hflags |= MIPS_HFLAG_BC;
18069 ctx->hflags |= MIPS_HFLAG_BDS32;
18072 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
18074 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
18075 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
18076 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18077 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18079 TCGv_i32 twd = tcg_const_i32(wd);
18080 TCGv_i32 tws = tcg_const_i32(ws);
18081 TCGv_i32 ti8 = tcg_const_i32(i8);
18083 switch (MASK_MSA_I8(ctx->opcode)) {
18084 case OPC_ANDI_B:
18085 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
18086 break;
18087 case OPC_ORI_B:
18088 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
18089 break;
18090 case OPC_NORI_B:
18091 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
18092 break;
18093 case OPC_XORI_B:
18094 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
18095 break;
18096 case OPC_BMNZI_B:
18097 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
18098 break;
18099 case OPC_BMZI_B:
18100 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
18101 break;
18102 case OPC_BSELI_B:
18103 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
18104 break;
18105 case OPC_SHF_B:
18106 case OPC_SHF_H:
18107 case OPC_SHF_W:
18109 uint8_t df = (ctx->opcode >> 24) & 0x3;
18110 if (df == DF_DOUBLE) {
18111 generate_exception_end(ctx, EXCP_RI);
18112 } else {
18113 TCGv_i32 tdf = tcg_const_i32(df);
18114 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
18115 tcg_temp_free_i32(tdf);
18118 break;
18119 default:
18120 MIPS_INVAL("MSA instruction");
18121 generate_exception_end(ctx, EXCP_RI);
18122 break;
18125 tcg_temp_free_i32(twd);
18126 tcg_temp_free_i32(tws);
18127 tcg_temp_free_i32(ti8);
18130 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
18132 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18133 uint8_t df = (ctx->opcode >> 21) & 0x3;
18134 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
18135 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
18136 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18137 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18139 TCGv_i32 tdf = tcg_const_i32(df);
18140 TCGv_i32 twd = tcg_const_i32(wd);
18141 TCGv_i32 tws = tcg_const_i32(ws);
18142 TCGv_i32 timm = tcg_temp_new_i32();
18143 tcg_gen_movi_i32(timm, u5);
18145 switch (MASK_MSA_I5(ctx->opcode)) {
18146 case OPC_ADDVI_df:
18147 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
18148 break;
18149 case OPC_SUBVI_df:
18150 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
18151 break;
18152 case OPC_MAXI_S_df:
18153 tcg_gen_movi_i32(timm, s5);
18154 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
18155 break;
18156 case OPC_MAXI_U_df:
18157 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
18158 break;
18159 case OPC_MINI_S_df:
18160 tcg_gen_movi_i32(timm, s5);
18161 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
18162 break;
18163 case OPC_MINI_U_df:
18164 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
18165 break;
18166 case OPC_CEQI_df:
18167 tcg_gen_movi_i32(timm, s5);
18168 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
18169 break;
18170 case OPC_CLTI_S_df:
18171 tcg_gen_movi_i32(timm, s5);
18172 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
18173 break;
18174 case OPC_CLTI_U_df:
18175 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
18176 break;
18177 case OPC_CLEI_S_df:
18178 tcg_gen_movi_i32(timm, s5);
18179 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
18180 break;
18181 case OPC_CLEI_U_df:
18182 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
18183 break;
18184 case OPC_LDI_df:
18186 int32_t s10 = sextract32(ctx->opcode, 11, 10);
18187 tcg_gen_movi_i32(timm, s10);
18188 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
18190 break;
18191 default:
18192 MIPS_INVAL("MSA instruction");
18193 generate_exception_end(ctx, EXCP_RI);
18194 break;
18197 tcg_temp_free_i32(tdf);
18198 tcg_temp_free_i32(twd);
18199 tcg_temp_free_i32(tws);
18200 tcg_temp_free_i32(timm);
18203 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
18205 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18206 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
18207 uint32_t df = 0, m = 0;
18208 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18209 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18211 TCGv_i32 tdf;
18212 TCGv_i32 tm;
18213 TCGv_i32 twd;
18214 TCGv_i32 tws;
18216 if ((dfm & 0x40) == 0x00) {
18217 m = dfm & 0x3f;
18218 df = DF_DOUBLE;
18219 } else if ((dfm & 0x60) == 0x40) {
18220 m = dfm & 0x1f;
18221 df = DF_WORD;
18222 } else if ((dfm & 0x70) == 0x60) {
18223 m = dfm & 0x0f;
18224 df = DF_HALF;
18225 } else if ((dfm & 0x78) == 0x70) {
18226 m = dfm & 0x7;
18227 df = DF_BYTE;
18228 } else {
18229 generate_exception_end(ctx, EXCP_RI);
18230 return;
18233 tdf = tcg_const_i32(df);
18234 tm = tcg_const_i32(m);
18235 twd = tcg_const_i32(wd);
18236 tws = tcg_const_i32(ws);
18238 switch (MASK_MSA_BIT(ctx->opcode)) {
18239 case OPC_SLLI_df:
18240 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
18241 break;
18242 case OPC_SRAI_df:
18243 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
18244 break;
18245 case OPC_SRLI_df:
18246 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
18247 break;
18248 case OPC_BCLRI_df:
18249 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
18250 break;
18251 case OPC_BSETI_df:
18252 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
18253 break;
18254 case OPC_BNEGI_df:
18255 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
18256 break;
18257 case OPC_BINSLI_df:
18258 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
18259 break;
18260 case OPC_BINSRI_df:
18261 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
18262 break;
18263 case OPC_SAT_S_df:
18264 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
18265 break;
18266 case OPC_SAT_U_df:
18267 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
18268 break;
18269 case OPC_SRARI_df:
18270 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
18271 break;
18272 case OPC_SRLRI_df:
18273 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
18274 break;
18275 default:
18276 MIPS_INVAL("MSA instruction");
18277 generate_exception_end(ctx, EXCP_RI);
18278 break;
18281 tcg_temp_free_i32(tdf);
18282 tcg_temp_free_i32(tm);
18283 tcg_temp_free_i32(twd);
18284 tcg_temp_free_i32(tws);
18287 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
18289 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18290 uint8_t df = (ctx->opcode >> 21) & 0x3;
18291 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18292 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18293 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18295 TCGv_i32 tdf = tcg_const_i32(df);
18296 TCGv_i32 twd = tcg_const_i32(wd);
18297 TCGv_i32 tws = tcg_const_i32(ws);
18298 TCGv_i32 twt = tcg_const_i32(wt);
18300 switch (MASK_MSA_3R(ctx->opcode)) {
18301 case OPC_SLL_df:
18302 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
18303 break;
18304 case OPC_ADDV_df:
18305 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
18306 break;
18307 case OPC_CEQ_df:
18308 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
18309 break;
18310 case OPC_ADD_A_df:
18311 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
18312 break;
18313 case OPC_SUBS_S_df:
18314 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
18315 break;
18316 case OPC_MULV_df:
18317 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
18318 break;
18319 case OPC_SLD_df:
18320 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
18321 break;
18322 case OPC_VSHF_df:
18323 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
18324 break;
18325 case OPC_SRA_df:
18326 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
18327 break;
18328 case OPC_SUBV_df:
18329 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
18330 break;
18331 case OPC_ADDS_A_df:
18332 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
18333 break;
18334 case OPC_SUBS_U_df:
18335 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
18336 break;
18337 case OPC_MADDV_df:
18338 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
18339 break;
18340 case OPC_SPLAT_df:
18341 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
18342 break;
18343 case OPC_SRAR_df:
18344 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
18345 break;
18346 case OPC_SRL_df:
18347 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
18348 break;
18349 case OPC_MAX_S_df:
18350 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
18351 break;
18352 case OPC_CLT_S_df:
18353 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
18354 break;
18355 case OPC_ADDS_S_df:
18356 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
18357 break;
18358 case OPC_SUBSUS_U_df:
18359 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
18360 break;
18361 case OPC_MSUBV_df:
18362 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
18363 break;
18364 case OPC_PCKEV_df:
18365 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
18366 break;
18367 case OPC_SRLR_df:
18368 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
18369 break;
18370 case OPC_BCLR_df:
18371 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
18372 break;
18373 case OPC_MAX_U_df:
18374 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
18375 break;
18376 case OPC_CLT_U_df:
18377 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
18378 break;
18379 case OPC_ADDS_U_df:
18380 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
18381 break;
18382 case OPC_SUBSUU_S_df:
18383 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
18384 break;
18385 case OPC_PCKOD_df:
18386 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
18387 break;
18388 case OPC_BSET_df:
18389 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
18390 break;
18391 case OPC_MIN_S_df:
18392 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
18393 break;
18394 case OPC_CLE_S_df:
18395 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
18396 break;
18397 case OPC_AVE_S_df:
18398 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
18399 break;
18400 case OPC_ASUB_S_df:
18401 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
18402 break;
18403 case OPC_DIV_S_df:
18404 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
18405 break;
18406 case OPC_ILVL_df:
18407 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
18408 break;
18409 case OPC_BNEG_df:
18410 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
18411 break;
18412 case OPC_MIN_U_df:
18413 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
18414 break;
18415 case OPC_CLE_U_df:
18416 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
18417 break;
18418 case OPC_AVE_U_df:
18419 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
18420 break;
18421 case OPC_ASUB_U_df:
18422 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
18423 break;
18424 case OPC_DIV_U_df:
18425 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
18426 break;
18427 case OPC_ILVR_df:
18428 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
18429 break;
18430 case OPC_BINSL_df:
18431 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
18432 break;
18433 case OPC_MAX_A_df:
18434 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
18435 break;
18436 case OPC_AVER_S_df:
18437 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
18438 break;
18439 case OPC_MOD_S_df:
18440 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
18441 break;
18442 case OPC_ILVEV_df:
18443 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
18444 break;
18445 case OPC_BINSR_df:
18446 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
18447 break;
18448 case OPC_MIN_A_df:
18449 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
18450 break;
18451 case OPC_AVER_U_df:
18452 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
18453 break;
18454 case OPC_MOD_U_df:
18455 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
18456 break;
18457 case OPC_ILVOD_df:
18458 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
18459 break;
18461 case OPC_DOTP_S_df:
18462 case OPC_DOTP_U_df:
18463 case OPC_DPADD_S_df:
18464 case OPC_DPADD_U_df:
18465 case OPC_DPSUB_S_df:
18466 case OPC_HADD_S_df:
18467 case OPC_DPSUB_U_df:
18468 case OPC_HADD_U_df:
18469 case OPC_HSUB_S_df:
18470 case OPC_HSUB_U_df:
18471 if (df == DF_BYTE) {
18472 generate_exception_end(ctx, EXCP_RI);
18473 break;
18475 switch (MASK_MSA_3R(ctx->opcode)) {
18476 case OPC_DOTP_S_df:
18477 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
18478 break;
18479 case OPC_DOTP_U_df:
18480 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
18481 break;
18482 case OPC_DPADD_S_df:
18483 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
18484 break;
18485 case OPC_DPADD_U_df:
18486 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
18487 break;
18488 case OPC_DPSUB_S_df:
18489 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
18490 break;
18491 case OPC_HADD_S_df:
18492 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
18493 break;
18494 case OPC_DPSUB_U_df:
18495 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
18496 break;
18497 case OPC_HADD_U_df:
18498 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
18499 break;
18500 case OPC_HSUB_S_df:
18501 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
18502 break;
18503 case OPC_HSUB_U_df:
18504 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
18505 break;
18507 break;
18508 default:
18509 MIPS_INVAL("MSA instruction");
18510 generate_exception_end(ctx, EXCP_RI);
18511 break;
18513 tcg_temp_free_i32(twd);
18514 tcg_temp_free_i32(tws);
18515 tcg_temp_free_i32(twt);
18516 tcg_temp_free_i32(tdf);
18519 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
18521 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
18522 uint8_t source = (ctx->opcode >> 11) & 0x1f;
18523 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
18524 TCGv telm = tcg_temp_new();
18525 TCGv_i32 tsr = tcg_const_i32(source);
18526 TCGv_i32 tdt = tcg_const_i32(dest);
18528 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
18529 case OPC_CTCMSA:
18530 gen_load_gpr(telm, source);
18531 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
18532 break;
18533 case OPC_CFCMSA:
18534 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
18535 gen_store_gpr(telm, dest);
18536 break;
18537 case OPC_MOVE_V:
18538 gen_helper_msa_move_v(cpu_env, tdt, tsr);
18539 break;
18540 default:
18541 MIPS_INVAL("MSA instruction");
18542 generate_exception_end(ctx, EXCP_RI);
18543 break;
18546 tcg_temp_free(telm);
18547 tcg_temp_free_i32(tdt);
18548 tcg_temp_free_i32(tsr);
18551 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
18552 uint32_t n)
18554 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18555 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18556 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18558 TCGv_i32 tws = tcg_const_i32(ws);
18559 TCGv_i32 twd = tcg_const_i32(wd);
18560 TCGv_i32 tn = tcg_const_i32(n);
18561 TCGv_i32 tdf = tcg_const_i32(df);
18563 switch (MASK_MSA_ELM(ctx->opcode)) {
18564 case OPC_SLDI_df:
18565 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
18566 break;
18567 case OPC_SPLATI_df:
18568 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
18569 break;
18570 case OPC_INSVE_df:
18571 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
18572 break;
18573 case OPC_COPY_S_df:
18574 case OPC_COPY_U_df:
18575 case OPC_INSERT_df:
18576 #if !defined(TARGET_MIPS64)
18577 /* Double format valid only for MIPS64 */
18578 if (df == DF_DOUBLE) {
18579 generate_exception_end(ctx, EXCP_RI);
18580 break;
18582 #endif
18583 switch (MASK_MSA_ELM(ctx->opcode)) {
18584 case OPC_COPY_S_df:
18585 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
18586 break;
18587 case OPC_COPY_U_df:
18588 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
18589 break;
18590 case OPC_INSERT_df:
18591 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
18592 break;
18594 break;
18595 default:
18596 MIPS_INVAL("MSA instruction");
18597 generate_exception_end(ctx, EXCP_RI);
18599 tcg_temp_free_i32(twd);
18600 tcg_temp_free_i32(tws);
18601 tcg_temp_free_i32(tn);
18602 tcg_temp_free_i32(tdf);
18605 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
18607 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
18608 uint32_t df = 0, n = 0;
18610 if ((dfn & 0x30) == 0x00) {
18611 n = dfn & 0x0f;
18612 df = DF_BYTE;
18613 } else if ((dfn & 0x38) == 0x20) {
18614 n = dfn & 0x07;
18615 df = DF_HALF;
18616 } else if ((dfn & 0x3c) == 0x30) {
18617 n = dfn & 0x03;
18618 df = DF_WORD;
18619 } else if ((dfn & 0x3e) == 0x38) {
18620 n = dfn & 0x01;
18621 df = DF_DOUBLE;
18622 } else if (dfn == 0x3E) {
18623 /* CTCMSA, CFCMSA, MOVE.V */
18624 gen_msa_elm_3e(env, ctx);
18625 return;
18626 } else {
18627 generate_exception_end(ctx, EXCP_RI);
18628 return;
18631 gen_msa_elm_df(env, ctx, df, n);
18634 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
18636 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18637 uint8_t df = (ctx->opcode >> 21) & 0x1;
18638 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18639 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18640 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18642 TCGv_i32 twd = tcg_const_i32(wd);
18643 TCGv_i32 tws = tcg_const_i32(ws);
18644 TCGv_i32 twt = tcg_const_i32(wt);
18645 TCGv_i32 tdf = tcg_temp_new_i32();
18647 /* adjust df value for floating-point instruction */
18648 tcg_gen_movi_i32(tdf, df + 2);
18650 switch (MASK_MSA_3RF(ctx->opcode)) {
18651 case OPC_FCAF_df:
18652 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
18653 break;
18654 case OPC_FADD_df:
18655 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
18656 break;
18657 case OPC_FCUN_df:
18658 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
18659 break;
18660 case OPC_FSUB_df:
18661 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
18662 break;
18663 case OPC_FCOR_df:
18664 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
18665 break;
18666 case OPC_FCEQ_df:
18667 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
18668 break;
18669 case OPC_FMUL_df:
18670 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
18671 break;
18672 case OPC_FCUNE_df:
18673 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
18674 break;
18675 case OPC_FCUEQ_df:
18676 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
18677 break;
18678 case OPC_FDIV_df:
18679 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
18680 break;
18681 case OPC_FCNE_df:
18682 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
18683 break;
18684 case OPC_FCLT_df:
18685 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
18686 break;
18687 case OPC_FMADD_df:
18688 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
18689 break;
18690 case OPC_MUL_Q_df:
18691 tcg_gen_movi_i32(tdf, df + 1);
18692 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
18693 break;
18694 case OPC_FCULT_df:
18695 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
18696 break;
18697 case OPC_FMSUB_df:
18698 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
18699 break;
18700 case OPC_MADD_Q_df:
18701 tcg_gen_movi_i32(tdf, df + 1);
18702 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
18703 break;
18704 case OPC_FCLE_df:
18705 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
18706 break;
18707 case OPC_MSUB_Q_df:
18708 tcg_gen_movi_i32(tdf, df + 1);
18709 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
18710 break;
18711 case OPC_FCULE_df:
18712 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
18713 break;
18714 case OPC_FEXP2_df:
18715 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
18716 break;
18717 case OPC_FSAF_df:
18718 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
18719 break;
18720 case OPC_FEXDO_df:
18721 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
18722 break;
18723 case OPC_FSUN_df:
18724 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
18725 break;
18726 case OPC_FSOR_df:
18727 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
18728 break;
18729 case OPC_FSEQ_df:
18730 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
18731 break;
18732 case OPC_FTQ_df:
18733 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
18734 break;
18735 case OPC_FSUNE_df:
18736 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
18737 break;
18738 case OPC_FSUEQ_df:
18739 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
18740 break;
18741 case OPC_FSNE_df:
18742 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
18743 break;
18744 case OPC_FSLT_df:
18745 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
18746 break;
18747 case OPC_FMIN_df:
18748 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
18749 break;
18750 case OPC_MULR_Q_df:
18751 tcg_gen_movi_i32(tdf, df + 1);
18752 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
18753 break;
18754 case OPC_FSULT_df:
18755 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
18756 break;
18757 case OPC_FMIN_A_df:
18758 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
18759 break;
18760 case OPC_MADDR_Q_df:
18761 tcg_gen_movi_i32(tdf, df + 1);
18762 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
18763 break;
18764 case OPC_FSLE_df:
18765 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
18766 break;
18767 case OPC_FMAX_df:
18768 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
18769 break;
18770 case OPC_MSUBR_Q_df:
18771 tcg_gen_movi_i32(tdf, df + 1);
18772 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
18773 break;
18774 case OPC_FSULE_df:
18775 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
18776 break;
18777 case OPC_FMAX_A_df:
18778 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
18779 break;
18780 default:
18781 MIPS_INVAL("MSA instruction");
18782 generate_exception_end(ctx, EXCP_RI);
18783 break;
18786 tcg_temp_free_i32(twd);
18787 tcg_temp_free_i32(tws);
18788 tcg_temp_free_i32(twt);
18789 tcg_temp_free_i32(tdf);
18792 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
18794 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18795 (op & (0x7 << 18)))
18796 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18797 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18798 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18799 uint8_t df = (ctx->opcode >> 16) & 0x3;
18800 TCGv_i32 twd = tcg_const_i32(wd);
18801 TCGv_i32 tws = tcg_const_i32(ws);
18802 TCGv_i32 twt = tcg_const_i32(wt);
18803 TCGv_i32 tdf = tcg_const_i32(df);
18805 switch (MASK_MSA_2R(ctx->opcode)) {
18806 case OPC_FILL_df:
18807 #if !defined(TARGET_MIPS64)
18808 /* Double format valid only for MIPS64 */
18809 if (df == DF_DOUBLE) {
18810 generate_exception_end(ctx, EXCP_RI);
18811 break;
18813 #endif
18814 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
18815 break;
18816 case OPC_PCNT_df:
18817 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
18818 break;
18819 case OPC_NLOC_df:
18820 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
18821 break;
18822 case OPC_NLZC_df:
18823 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
18824 break;
18825 default:
18826 MIPS_INVAL("MSA instruction");
18827 generate_exception_end(ctx, EXCP_RI);
18828 break;
18831 tcg_temp_free_i32(twd);
18832 tcg_temp_free_i32(tws);
18833 tcg_temp_free_i32(twt);
18834 tcg_temp_free_i32(tdf);
18837 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
18839 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18840 (op & (0xf << 17)))
18841 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18842 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18843 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18844 uint8_t df = (ctx->opcode >> 16) & 0x1;
18845 TCGv_i32 twd = tcg_const_i32(wd);
18846 TCGv_i32 tws = tcg_const_i32(ws);
18847 TCGv_i32 twt = tcg_const_i32(wt);
18848 /* adjust df value for floating-point instruction */
18849 TCGv_i32 tdf = tcg_const_i32(df + 2);
18851 switch (MASK_MSA_2RF(ctx->opcode)) {
18852 case OPC_FCLASS_df:
18853 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
18854 break;
18855 case OPC_FTRUNC_S_df:
18856 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
18857 break;
18858 case OPC_FTRUNC_U_df:
18859 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
18860 break;
18861 case OPC_FSQRT_df:
18862 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
18863 break;
18864 case OPC_FRSQRT_df:
18865 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
18866 break;
18867 case OPC_FRCP_df:
18868 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
18869 break;
18870 case OPC_FRINT_df:
18871 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
18872 break;
18873 case OPC_FLOG2_df:
18874 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
18875 break;
18876 case OPC_FEXUPL_df:
18877 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
18878 break;
18879 case OPC_FEXUPR_df:
18880 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
18881 break;
18882 case OPC_FFQL_df:
18883 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
18884 break;
18885 case OPC_FFQR_df:
18886 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
18887 break;
18888 case OPC_FTINT_S_df:
18889 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
18890 break;
18891 case OPC_FTINT_U_df:
18892 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
18893 break;
18894 case OPC_FFINT_S_df:
18895 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
18896 break;
18897 case OPC_FFINT_U_df:
18898 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
18899 break;
18902 tcg_temp_free_i32(twd);
18903 tcg_temp_free_i32(tws);
18904 tcg_temp_free_i32(twt);
18905 tcg_temp_free_i32(tdf);
18908 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
18910 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
18911 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18912 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18913 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18914 TCGv_i32 twd = tcg_const_i32(wd);
18915 TCGv_i32 tws = tcg_const_i32(ws);
18916 TCGv_i32 twt = tcg_const_i32(wt);
18918 switch (MASK_MSA_VEC(ctx->opcode)) {
18919 case OPC_AND_V:
18920 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
18921 break;
18922 case OPC_OR_V:
18923 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
18924 break;
18925 case OPC_NOR_V:
18926 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
18927 break;
18928 case OPC_XOR_V:
18929 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
18930 break;
18931 case OPC_BMNZ_V:
18932 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
18933 break;
18934 case OPC_BMZ_V:
18935 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
18936 break;
18937 case OPC_BSEL_V:
18938 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
18939 break;
18940 default:
18941 MIPS_INVAL("MSA instruction");
18942 generate_exception_end(ctx, EXCP_RI);
18943 break;
18946 tcg_temp_free_i32(twd);
18947 tcg_temp_free_i32(tws);
18948 tcg_temp_free_i32(twt);
18951 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
18953 switch (MASK_MSA_VEC(ctx->opcode)) {
18954 case OPC_AND_V:
18955 case OPC_OR_V:
18956 case OPC_NOR_V:
18957 case OPC_XOR_V:
18958 case OPC_BMNZ_V:
18959 case OPC_BMZ_V:
18960 case OPC_BSEL_V:
18961 gen_msa_vec_v(env, ctx);
18962 break;
18963 case OPC_MSA_2R:
18964 gen_msa_2r(env, ctx);
18965 break;
18966 case OPC_MSA_2RF:
18967 gen_msa_2rf(env, ctx);
18968 break;
18969 default:
18970 MIPS_INVAL("MSA instruction");
18971 generate_exception_end(ctx, EXCP_RI);
18972 break;
18976 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
18978 uint32_t opcode = ctx->opcode;
18979 check_insn(ctx, ASE_MSA);
18980 check_msa_access(ctx);
18982 switch (MASK_MSA_MINOR(opcode)) {
18983 case OPC_MSA_I8_00:
18984 case OPC_MSA_I8_01:
18985 case OPC_MSA_I8_02:
18986 gen_msa_i8(env, ctx);
18987 break;
18988 case OPC_MSA_I5_06:
18989 case OPC_MSA_I5_07:
18990 gen_msa_i5(env, ctx);
18991 break;
18992 case OPC_MSA_BIT_09:
18993 case OPC_MSA_BIT_0A:
18994 gen_msa_bit(env, ctx);
18995 break;
18996 case OPC_MSA_3R_0D:
18997 case OPC_MSA_3R_0E:
18998 case OPC_MSA_3R_0F:
18999 case OPC_MSA_3R_10:
19000 case OPC_MSA_3R_11:
19001 case OPC_MSA_3R_12:
19002 case OPC_MSA_3R_13:
19003 case OPC_MSA_3R_14:
19004 case OPC_MSA_3R_15:
19005 gen_msa_3r(env, ctx);
19006 break;
19007 case OPC_MSA_ELM:
19008 gen_msa_elm(env, ctx);
19009 break;
19010 case OPC_MSA_3RF_1A:
19011 case OPC_MSA_3RF_1B:
19012 case OPC_MSA_3RF_1C:
19013 gen_msa_3rf(env, ctx);
19014 break;
19015 case OPC_MSA_VEC:
19016 gen_msa_vec(env, ctx);
19017 break;
19018 case OPC_LD_B:
19019 case OPC_LD_H:
19020 case OPC_LD_W:
19021 case OPC_LD_D:
19022 case OPC_ST_B:
19023 case OPC_ST_H:
19024 case OPC_ST_W:
19025 case OPC_ST_D:
19027 int32_t s10 = sextract32(ctx->opcode, 16, 10);
19028 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
19029 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19030 uint8_t df = (ctx->opcode >> 0) & 0x3;
19032 TCGv_i32 twd = tcg_const_i32(wd);
19033 TCGv taddr = tcg_temp_new();
19034 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
19036 switch (MASK_MSA_MINOR(opcode)) {
19037 case OPC_LD_B:
19038 gen_helper_msa_ld_b(cpu_env, twd, taddr);
19039 break;
19040 case OPC_LD_H:
19041 gen_helper_msa_ld_h(cpu_env, twd, taddr);
19042 break;
19043 case OPC_LD_W:
19044 gen_helper_msa_ld_w(cpu_env, twd, taddr);
19045 break;
19046 case OPC_LD_D:
19047 gen_helper_msa_ld_d(cpu_env, twd, taddr);
19048 break;
19049 case OPC_ST_B:
19050 gen_helper_msa_st_b(cpu_env, twd, taddr);
19051 break;
19052 case OPC_ST_H:
19053 gen_helper_msa_st_h(cpu_env, twd, taddr);
19054 break;
19055 case OPC_ST_W:
19056 gen_helper_msa_st_w(cpu_env, twd, taddr);
19057 break;
19058 case OPC_ST_D:
19059 gen_helper_msa_st_d(cpu_env, twd, taddr);
19060 break;
19063 tcg_temp_free_i32(twd);
19064 tcg_temp_free(taddr);
19066 break;
19067 default:
19068 MIPS_INVAL("MSA instruction");
19069 generate_exception_end(ctx, EXCP_RI);
19070 break;
19075 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
19077 int32_t offset;
19078 int rs, rt, rd, sa;
19079 uint32_t op, op1;
19080 int16_t imm;
19082 /* make sure instructions are on a word boundary */
19083 if (ctx->pc & 0x3) {
19084 env->CP0_BadVAddr = ctx->pc;
19085 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
19086 return;
19089 /* Handle blikely not taken case */
19090 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
19091 TCGLabel *l1 = gen_new_label();
19093 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
19094 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
19095 gen_goto_tb(ctx, 1, ctx->pc + 4);
19096 gen_set_label(l1);
19099 op = MASK_OP_MAJOR(ctx->opcode);
19100 rs = (ctx->opcode >> 21) & 0x1f;
19101 rt = (ctx->opcode >> 16) & 0x1f;
19102 rd = (ctx->opcode >> 11) & 0x1f;
19103 sa = (ctx->opcode >> 6) & 0x1f;
19104 imm = (int16_t)ctx->opcode;
19105 switch (op) {
19106 case OPC_SPECIAL:
19107 decode_opc_special(env, ctx);
19108 break;
19109 case OPC_SPECIAL2:
19110 decode_opc_special2_legacy(env, ctx);
19111 break;
19112 case OPC_SPECIAL3:
19113 decode_opc_special3(env, ctx);
19114 break;
19115 case OPC_REGIMM:
19116 op1 = MASK_REGIMM(ctx->opcode);
19117 switch (op1) {
19118 case OPC_BLTZL: /* REGIMM branches */
19119 case OPC_BGEZL:
19120 case OPC_BLTZALL:
19121 case OPC_BGEZALL:
19122 check_insn(ctx, ISA_MIPS2);
19123 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19124 /* Fallthrough */
19125 case OPC_BLTZ:
19126 case OPC_BGEZ:
19127 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19128 break;
19129 case OPC_BLTZAL:
19130 case OPC_BGEZAL:
19131 if (ctx->insn_flags & ISA_MIPS32R6) {
19132 if (rs == 0) {
19133 /* OPC_NAL, OPC_BAL */
19134 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
19135 } else {
19136 generate_exception_end(ctx, EXCP_RI);
19138 } else {
19139 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19141 break;
19142 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
19143 case OPC_TNEI:
19144 check_insn(ctx, ISA_MIPS2);
19145 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19146 gen_trap(ctx, op1, rs, -1, imm);
19147 break;
19148 case OPC_SIGRIE:
19149 check_insn(ctx, ISA_MIPS32R6);
19150 generate_exception_end(ctx, EXCP_RI);
19151 break;
19152 case OPC_SYNCI:
19153 check_insn(ctx, ISA_MIPS32R2);
19154 /* Break the TB to be able to sync copied instructions
19155 immediately */
19156 ctx->bstate = BS_STOP;
19157 break;
19158 case OPC_BPOSGE32: /* MIPS DSP branch */
19159 #if defined(TARGET_MIPS64)
19160 case OPC_BPOSGE64:
19161 #endif
19162 check_dsp(ctx);
19163 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
19164 break;
19165 #if defined(TARGET_MIPS64)
19166 case OPC_DAHI:
19167 check_insn(ctx, ISA_MIPS32R6);
19168 check_mips_64(ctx);
19169 if (rs != 0) {
19170 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
19172 break;
19173 case OPC_DATI:
19174 check_insn(ctx, ISA_MIPS32R6);
19175 check_mips_64(ctx);
19176 if (rs != 0) {
19177 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
19179 break;
19180 #endif
19181 default: /* Invalid */
19182 MIPS_INVAL("regimm");
19183 generate_exception_end(ctx, EXCP_RI);
19184 break;
19186 break;
19187 case OPC_CP0:
19188 check_cp0_enabled(ctx);
19189 op1 = MASK_CP0(ctx->opcode);
19190 switch (op1) {
19191 case OPC_MFC0:
19192 case OPC_MTC0:
19193 case OPC_MFTR:
19194 case OPC_MTTR:
19195 case OPC_MFHC0:
19196 case OPC_MTHC0:
19197 #if defined(TARGET_MIPS64)
19198 case OPC_DMFC0:
19199 case OPC_DMTC0:
19200 #endif
19201 #ifndef CONFIG_USER_ONLY
19202 gen_cp0(env, ctx, op1, rt, rd);
19203 #endif /* !CONFIG_USER_ONLY */
19204 break;
19205 case OPC_C0_FIRST ... OPC_C0_LAST:
19206 #ifndef CONFIG_USER_ONLY
19207 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
19208 #endif /* !CONFIG_USER_ONLY */
19209 break;
19210 case OPC_MFMC0:
19211 #ifndef CONFIG_USER_ONLY
19213 uint32_t op2;
19214 TCGv t0 = tcg_temp_new();
19216 op2 = MASK_MFMC0(ctx->opcode);
19217 switch (op2) {
19218 case OPC_DMT:
19219 check_insn(ctx, ASE_MT);
19220 gen_helper_dmt(t0);
19221 gen_store_gpr(t0, rt);
19222 break;
19223 case OPC_EMT:
19224 check_insn(ctx, ASE_MT);
19225 gen_helper_emt(t0);
19226 gen_store_gpr(t0, rt);
19227 break;
19228 case OPC_DVPE:
19229 check_insn(ctx, ASE_MT);
19230 gen_helper_dvpe(t0, cpu_env);
19231 gen_store_gpr(t0, rt);
19232 break;
19233 case OPC_EVPE:
19234 check_insn(ctx, ASE_MT);
19235 gen_helper_evpe(t0, cpu_env);
19236 gen_store_gpr(t0, rt);
19237 break;
19238 case OPC_DVP:
19239 check_insn(ctx, ISA_MIPS32R6);
19240 if (ctx->vp) {
19241 gen_helper_dvp(t0, cpu_env);
19242 gen_store_gpr(t0, rt);
19244 break;
19245 case OPC_EVP:
19246 check_insn(ctx, ISA_MIPS32R6);
19247 if (ctx->vp) {
19248 gen_helper_evp(t0, cpu_env);
19249 gen_store_gpr(t0, rt);
19251 break;
19252 case OPC_DI:
19253 check_insn(ctx, ISA_MIPS32R2);
19254 save_cpu_state(ctx, 1);
19255 gen_helper_di(t0, cpu_env);
19256 gen_store_gpr(t0, rt);
19257 /* Stop translation as we may have switched
19258 the execution mode. */
19259 ctx->bstate = BS_STOP;
19260 break;
19261 case OPC_EI:
19262 check_insn(ctx, ISA_MIPS32R2);
19263 save_cpu_state(ctx, 1);
19264 gen_helper_ei(t0, cpu_env);
19265 gen_store_gpr(t0, rt);
19266 /* Stop translation as we may have switched
19267 the execution mode. */
19268 ctx->bstate = BS_STOP;
19269 break;
19270 default: /* Invalid */
19271 MIPS_INVAL("mfmc0");
19272 generate_exception_end(ctx, EXCP_RI);
19273 break;
19275 tcg_temp_free(t0);
19277 #endif /* !CONFIG_USER_ONLY */
19278 break;
19279 case OPC_RDPGPR:
19280 check_insn(ctx, ISA_MIPS32R2);
19281 gen_load_srsgpr(rt, rd);
19282 break;
19283 case OPC_WRPGPR:
19284 check_insn(ctx, ISA_MIPS32R2);
19285 gen_store_srsgpr(rt, rd);
19286 break;
19287 default:
19288 MIPS_INVAL("cp0");
19289 generate_exception_end(ctx, EXCP_RI);
19290 break;
19292 break;
19293 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
19294 if (ctx->insn_flags & ISA_MIPS32R6) {
19295 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
19296 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19297 } else {
19298 /* OPC_ADDI */
19299 /* Arithmetic with immediate opcode */
19300 gen_arith_imm(ctx, op, rt, rs, imm);
19302 break;
19303 case OPC_ADDIU:
19304 gen_arith_imm(ctx, op, rt, rs, imm);
19305 break;
19306 case OPC_SLTI: /* Set on less than with immediate opcode */
19307 case OPC_SLTIU:
19308 gen_slt_imm(ctx, op, rt, rs, imm);
19309 break;
19310 case OPC_ANDI: /* Arithmetic with immediate opcode */
19311 case OPC_LUI: /* OPC_AUI */
19312 case OPC_ORI:
19313 case OPC_XORI:
19314 gen_logic_imm(ctx, op, rt, rs, imm);
19315 break;
19316 case OPC_J ... OPC_JAL: /* Jump */
19317 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19318 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19319 break;
19320 /* Branch */
19321 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
19322 if (ctx->insn_flags & ISA_MIPS32R6) {
19323 if (rt == 0) {
19324 generate_exception_end(ctx, EXCP_RI);
19325 break;
19327 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
19328 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19329 } else {
19330 /* OPC_BLEZL */
19331 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19333 break;
19334 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
19335 if (ctx->insn_flags & ISA_MIPS32R6) {
19336 if (rt == 0) {
19337 generate_exception_end(ctx, EXCP_RI);
19338 break;
19340 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
19341 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19342 } else {
19343 /* OPC_BGTZL */
19344 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19346 break;
19347 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
19348 if (rt == 0) {
19349 /* OPC_BLEZ */
19350 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19351 } else {
19352 check_insn(ctx, ISA_MIPS32R6);
19353 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
19354 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19356 break;
19357 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
19358 if (rt == 0) {
19359 /* OPC_BGTZ */
19360 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19361 } else {
19362 check_insn(ctx, ISA_MIPS32R6);
19363 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
19364 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19366 break;
19367 case OPC_BEQL:
19368 case OPC_BNEL:
19369 check_insn(ctx, ISA_MIPS2);
19370 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19371 /* Fallthrough */
19372 case OPC_BEQ:
19373 case OPC_BNE:
19374 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19375 break;
19376 case OPC_LL: /* Load and stores */
19377 check_insn(ctx, ISA_MIPS2);
19378 /* Fallthrough */
19379 case OPC_LWL:
19380 case OPC_LWR:
19381 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19382 /* Fallthrough */
19383 case OPC_LB ... OPC_LH:
19384 case OPC_LW ... OPC_LHU:
19385 gen_ld(ctx, op, rt, rs, imm);
19386 break;
19387 case OPC_SWL:
19388 case OPC_SWR:
19389 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19390 /* fall through */
19391 case OPC_SB ... OPC_SH:
19392 case OPC_SW:
19393 gen_st(ctx, op, rt, rs, imm);
19394 break;
19395 case OPC_SC:
19396 check_insn(ctx, ISA_MIPS2);
19397 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19398 gen_st_cond(ctx, op, rt, rs, imm);
19399 break;
19400 case OPC_CACHE:
19401 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19402 check_cp0_enabled(ctx);
19403 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
19404 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
19405 gen_cache_operation(ctx, rt, rs, imm);
19407 /* Treat as NOP. */
19408 break;
19409 case OPC_PREF:
19410 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19411 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
19412 /* Treat as NOP. */
19413 break;
19415 /* Floating point (COP1). */
19416 case OPC_LWC1:
19417 case OPC_LDC1:
19418 case OPC_SWC1:
19419 case OPC_SDC1:
19420 gen_cop1_ldst(ctx, op, rt, rs, imm);
19421 break;
19423 case OPC_CP1:
19424 op1 = MASK_CP1(ctx->opcode);
19426 switch (op1) {
19427 case OPC_MFHC1:
19428 case OPC_MTHC1:
19429 check_cp1_enabled(ctx);
19430 check_insn(ctx, ISA_MIPS32R2);
19431 case OPC_MFC1:
19432 case OPC_CFC1:
19433 case OPC_MTC1:
19434 case OPC_CTC1:
19435 check_cp1_enabled(ctx);
19436 gen_cp1(ctx, op1, rt, rd);
19437 break;
19438 #if defined(TARGET_MIPS64)
19439 case OPC_DMFC1:
19440 case OPC_DMTC1:
19441 check_cp1_enabled(ctx);
19442 check_insn(ctx, ISA_MIPS3);
19443 check_mips_64(ctx);
19444 gen_cp1(ctx, op1, rt, rd);
19445 break;
19446 #endif
19447 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
19448 check_cp1_enabled(ctx);
19449 if (ctx->insn_flags & ISA_MIPS32R6) {
19450 /* OPC_BC1EQZ */
19451 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19452 rt, imm << 2, 4);
19453 } else {
19454 /* OPC_BC1ANY2 */
19455 check_cop1x(ctx);
19456 check_insn(ctx, ASE_MIPS3D);
19457 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19458 (rt >> 2) & 0x7, imm << 2);
19460 break;
19461 case OPC_BC1NEZ:
19462 check_cp1_enabled(ctx);
19463 check_insn(ctx, ISA_MIPS32R6);
19464 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19465 rt, imm << 2, 4);
19466 break;
19467 case OPC_BC1ANY4:
19468 check_cp1_enabled(ctx);
19469 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19470 check_cop1x(ctx);
19471 check_insn(ctx, ASE_MIPS3D);
19472 /* fall through */
19473 case OPC_BC1:
19474 check_cp1_enabled(ctx);
19475 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19476 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19477 (rt >> 2) & 0x7, imm << 2);
19478 break;
19479 case OPC_PS_FMT:
19480 check_ps(ctx);
19481 /* fall through */
19482 case OPC_S_FMT:
19483 case OPC_D_FMT:
19484 check_cp1_enabled(ctx);
19485 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19486 (imm >> 8) & 0x7);
19487 break;
19488 case OPC_W_FMT:
19489 case OPC_L_FMT:
19491 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
19492 check_cp1_enabled(ctx);
19493 if (ctx->insn_flags & ISA_MIPS32R6) {
19494 switch (r6_op) {
19495 case R6_OPC_CMP_AF_S:
19496 case R6_OPC_CMP_UN_S:
19497 case R6_OPC_CMP_EQ_S:
19498 case R6_OPC_CMP_UEQ_S:
19499 case R6_OPC_CMP_LT_S:
19500 case R6_OPC_CMP_ULT_S:
19501 case R6_OPC_CMP_LE_S:
19502 case R6_OPC_CMP_ULE_S:
19503 case R6_OPC_CMP_SAF_S:
19504 case R6_OPC_CMP_SUN_S:
19505 case R6_OPC_CMP_SEQ_S:
19506 case R6_OPC_CMP_SEUQ_S:
19507 case R6_OPC_CMP_SLT_S:
19508 case R6_OPC_CMP_SULT_S:
19509 case R6_OPC_CMP_SLE_S:
19510 case R6_OPC_CMP_SULE_S:
19511 case R6_OPC_CMP_OR_S:
19512 case R6_OPC_CMP_UNE_S:
19513 case R6_OPC_CMP_NE_S:
19514 case R6_OPC_CMP_SOR_S:
19515 case R6_OPC_CMP_SUNE_S:
19516 case R6_OPC_CMP_SNE_S:
19517 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19518 break;
19519 case R6_OPC_CMP_AF_D:
19520 case R6_OPC_CMP_UN_D:
19521 case R6_OPC_CMP_EQ_D:
19522 case R6_OPC_CMP_UEQ_D:
19523 case R6_OPC_CMP_LT_D:
19524 case R6_OPC_CMP_ULT_D:
19525 case R6_OPC_CMP_LE_D:
19526 case R6_OPC_CMP_ULE_D:
19527 case R6_OPC_CMP_SAF_D:
19528 case R6_OPC_CMP_SUN_D:
19529 case R6_OPC_CMP_SEQ_D:
19530 case R6_OPC_CMP_SEUQ_D:
19531 case R6_OPC_CMP_SLT_D:
19532 case R6_OPC_CMP_SULT_D:
19533 case R6_OPC_CMP_SLE_D:
19534 case R6_OPC_CMP_SULE_D:
19535 case R6_OPC_CMP_OR_D:
19536 case R6_OPC_CMP_UNE_D:
19537 case R6_OPC_CMP_NE_D:
19538 case R6_OPC_CMP_SOR_D:
19539 case R6_OPC_CMP_SUNE_D:
19540 case R6_OPC_CMP_SNE_D:
19541 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19542 break;
19543 default:
19544 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
19545 rt, rd, sa, (imm >> 8) & 0x7);
19547 break;
19549 } else {
19550 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19551 (imm >> 8) & 0x7);
19553 break;
19555 case OPC_BZ_V:
19556 case OPC_BNZ_V:
19557 case OPC_BZ_B:
19558 case OPC_BZ_H:
19559 case OPC_BZ_W:
19560 case OPC_BZ_D:
19561 case OPC_BNZ_B:
19562 case OPC_BNZ_H:
19563 case OPC_BNZ_W:
19564 case OPC_BNZ_D:
19565 check_insn(ctx, ASE_MSA);
19566 gen_msa_branch(env, ctx, op1);
19567 break;
19568 default:
19569 MIPS_INVAL("cp1");
19570 generate_exception_end(ctx, EXCP_RI);
19571 break;
19573 break;
19575 /* Compact branches [R6] and COP2 [non-R6] */
19576 case OPC_BC: /* OPC_LWC2 */
19577 case OPC_BALC: /* OPC_SWC2 */
19578 if (ctx->insn_flags & ISA_MIPS32R6) {
19579 /* OPC_BC, OPC_BALC */
19580 gen_compute_compact_branch(ctx, op, 0, 0,
19581 sextract32(ctx->opcode << 2, 0, 28));
19582 } else {
19583 /* OPC_LWC2, OPC_SWC2 */
19584 /* COP2: Not implemented. */
19585 generate_exception_err(ctx, EXCP_CpU, 2);
19587 break;
19588 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
19589 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
19590 if (ctx->insn_flags & ISA_MIPS32R6) {
19591 if (rs != 0) {
19592 /* OPC_BEQZC, OPC_BNEZC */
19593 gen_compute_compact_branch(ctx, op, rs, 0,
19594 sextract32(ctx->opcode << 2, 0, 23));
19595 } else {
19596 /* OPC_JIC, OPC_JIALC */
19597 gen_compute_compact_branch(ctx, op, 0, rt, imm);
19599 } else {
19600 /* OPC_LWC2, OPC_SWC2 */
19601 /* COP2: Not implemented. */
19602 generate_exception_err(ctx, EXCP_CpU, 2);
19604 break;
19605 case OPC_CP2:
19606 check_insn(ctx, INSN_LOONGSON2F);
19607 /* Note that these instructions use different fields. */
19608 gen_loongson_multimedia(ctx, sa, rd, rt);
19609 break;
19611 case OPC_CP3:
19612 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19613 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19614 check_cp1_enabled(ctx);
19615 op1 = MASK_CP3(ctx->opcode);
19616 switch (op1) {
19617 case OPC_LUXC1:
19618 case OPC_SUXC1:
19619 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19620 /* Fallthrough */
19621 case OPC_LWXC1:
19622 case OPC_LDXC1:
19623 case OPC_SWXC1:
19624 case OPC_SDXC1:
19625 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19626 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
19627 break;
19628 case OPC_PREFX:
19629 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19630 /* Treat as NOP. */
19631 break;
19632 case OPC_ALNV_PS:
19633 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19634 /* Fallthrough */
19635 case OPC_MADD_S:
19636 case OPC_MADD_D:
19637 case OPC_MADD_PS:
19638 case OPC_MSUB_S:
19639 case OPC_MSUB_D:
19640 case OPC_MSUB_PS:
19641 case OPC_NMADD_S:
19642 case OPC_NMADD_D:
19643 case OPC_NMADD_PS:
19644 case OPC_NMSUB_S:
19645 case OPC_NMSUB_D:
19646 case OPC_NMSUB_PS:
19647 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19648 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
19649 break;
19650 default:
19651 MIPS_INVAL("cp3");
19652 generate_exception_end(ctx, EXCP_RI);
19653 break;
19655 } else {
19656 generate_exception_err(ctx, EXCP_CpU, 1);
19658 break;
19660 #if defined(TARGET_MIPS64)
19661 /* MIPS64 opcodes */
19662 case OPC_LDL ... OPC_LDR:
19663 case OPC_LLD:
19664 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19665 /* fall through */
19666 case OPC_LWU:
19667 case OPC_LD:
19668 check_insn(ctx, ISA_MIPS3);
19669 check_mips_64(ctx);
19670 gen_ld(ctx, op, rt, rs, imm);
19671 break;
19672 case OPC_SDL ... OPC_SDR:
19673 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19674 /* fall through */
19675 case OPC_SD:
19676 check_insn(ctx, ISA_MIPS3);
19677 check_mips_64(ctx);
19678 gen_st(ctx, op, rt, rs, imm);
19679 break;
19680 case OPC_SCD:
19681 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19682 check_insn(ctx, ISA_MIPS3);
19683 check_mips_64(ctx);
19684 gen_st_cond(ctx, op, rt, rs, imm);
19685 break;
19686 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
19687 if (ctx->insn_flags & ISA_MIPS32R6) {
19688 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
19689 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19690 } else {
19691 /* OPC_DADDI */
19692 check_insn(ctx, ISA_MIPS3);
19693 check_mips_64(ctx);
19694 gen_arith_imm(ctx, op, rt, rs, imm);
19696 break;
19697 case OPC_DADDIU:
19698 check_insn(ctx, ISA_MIPS3);
19699 check_mips_64(ctx);
19700 gen_arith_imm(ctx, op, rt, rs, imm);
19701 break;
19702 #else
19703 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
19704 if (ctx->insn_flags & ISA_MIPS32R6) {
19705 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19706 } else {
19707 MIPS_INVAL("major opcode");
19708 generate_exception_end(ctx, EXCP_RI);
19710 break;
19711 #endif
19712 case OPC_DAUI: /* OPC_JALX */
19713 if (ctx->insn_flags & ISA_MIPS32R6) {
19714 #if defined(TARGET_MIPS64)
19715 /* OPC_DAUI */
19716 check_mips_64(ctx);
19717 if (rs == 0) {
19718 generate_exception(ctx, EXCP_RI);
19719 } else if (rt != 0) {
19720 TCGv t0 = tcg_temp_new();
19721 gen_load_gpr(t0, rs);
19722 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
19723 tcg_temp_free(t0);
19725 #else
19726 generate_exception_end(ctx, EXCP_RI);
19727 MIPS_INVAL("major opcode");
19728 #endif
19729 } else {
19730 /* OPC_JALX */
19731 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
19732 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19733 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19735 break;
19736 case OPC_MSA: /* OPC_MDMX */
19737 /* MDMX: Not implemented. */
19738 gen_msa(env, ctx);
19739 break;
19740 case OPC_PCREL:
19741 check_insn(ctx, ISA_MIPS32R6);
19742 gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
19743 break;
19744 default: /* Invalid */
19745 MIPS_INVAL("major opcode");
19746 generate_exception_end(ctx, EXCP_RI);
19747 break;
19751 void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
19753 MIPSCPU *cpu = mips_env_get_cpu(env);
19754 CPUState *cs = CPU(cpu);
19755 DisasContext ctx;
19756 target_ulong pc_start;
19757 target_ulong next_page_start;
19758 int num_insns;
19759 int max_insns;
19760 int insn_bytes;
19761 int is_slot;
19763 pc_start = tb->pc;
19764 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
19765 ctx.pc = pc_start;
19766 ctx.saved_pc = -1;
19767 ctx.singlestep_enabled = cs->singlestep_enabled;
19768 ctx.insn_flags = env->insn_flags;
19769 ctx.CP0_Config1 = env->CP0_Config1;
19770 ctx.tb = tb;
19771 ctx.bstate = BS_NONE;
19772 ctx.btarget = 0;
19773 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
19774 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
19775 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
19776 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
19777 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
19778 ctx.PAMask = env->PAMask;
19779 ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
19780 ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
19781 ctx.cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
19782 /* Restore delay slot state from the tb context. */
19783 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
19784 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
19785 ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
19786 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
19787 ctx.vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
19788 ctx.mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
19789 restore_cpu_state(env, &ctx);
19790 #ifdef CONFIG_USER_ONLY
19791 ctx.mem_idx = MIPS_HFLAG_UM;
19792 #else
19793 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
19794 #endif
19795 ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
19796 MO_UNALN : MO_ALIGN;
19797 num_insns = 0;
19798 max_insns = tb->cflags & CF_COUNT_MASK;
19799 if (max_insns == 0) {
19800 max_insns = CF_COUNT_MASK;
19802 if (max_insns > TCG_MAX_INSNS) {
19803 max_insns = TCG_MAX_INSNS;
19806 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
19807 gen_tb_start(tb);
19808 while (ctx.bstate == BS_NONE) {
19809 tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
19810 num_insns++;
19812 if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
19813 save_cpu_state(&ctx, 1);
19814 ctx.bstate = BS_BRANCH;
19815 gen_helper_raise_exception_debug(cpu_env);
19816 /* The address covered by the breakpoint must be included in
19817 [tb->pc, tb->pc + tb->size) in order to for it to be
19818 properly cleared -- thus we increment the PC here so that
19819 the logic setting tb->size below does the right thing. */
19820 ctx.pc += 4;
19821 goto done_generating;
19824 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
19825 gen_io_start();
19828 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
19829 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
19830 ctx.opcode = cpu_ldl_code(env, ctx.pc);
19831 insn_bytes = 4;
19832 decode_opc(env, &ctx);
19833 } else if (ctx.insn_flags & ASE_MICROMIPS) {
19834 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19835 insn_bytes = decode_micromips_opc(env, &ctx);
19836 } else if (ctx.insn_flags & ASE_MIPS16) {
19837 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19838 insn_bytes = decode_mips16_opc(env, &ctx);
19839 } else {
19840 generate_exception_end(&ctx, EXCP_RI);
19841 break;
19844 if (ctx.hflags & MIPS_HFLAG_BMASK) {
19845 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
19846 MIPS_HFLAG_FBNSLOT))) {
19847 /* force to generate branch as there is neither delay nor
19848 forbidden slot */
19849 is_slot = 1;
19851 if ((ctx.hflags & MIPS_HFLAG_M16) &&
19852 (ctx.hflags & MIPS_HFLAG_FBNSLOT)) {
19853 /* Force to generate branch as microMIPS R6 doesn't restrict
19854 branches in the forbidden slot. */
19855 is_slot = 1;
19858 if (is_slot) {
19859 gen_branch(&ctx, insn_bytes);
19861 ctx.pc += insn_bytes;
19863 /* Execute a branch and its delay slot as a single instruction.
19864 This is what GDB expects and is consistent with what the
19865 hardware does (e.g. if a delay slot instruction faults, the
19866 reported PC is the PC of the branch). */
19867 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
19868 break;
19871 if (ctx.pc >= next_page_start) {
19872 break;
19875 if (tcg_op_buf_full()) {
19876 break;
19879 if (num_insns >= max_insns)
19880 break;
19882 if (singlestep)
19883 break;
19885 if (tb->cflags & CF_LAST_IO) {
19886 gen_io_end();
19888 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
19889 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
19890 gen_helper_raise_exception_debug(cpu_env);
19891 } else {
19892 switch (ctx.bstate) {
19893 case BS_STOP:
19894 gen_goto_tb(&ctx, 0, ctx.pc);
19895 break;
19896 case BS_NONE:
19897 save_cpu_state(&ctx, 0);
19898 gen_goto_tb(&ctx, 0, ctx.pc);
19899 break;
19900 case BS_EXCP:
19901 tcg_gen_exit_tb(0);
19902 break;
19903 case BS_BRANCH:
19904 default:
19905 break;
19908 done_generating:
19909 gen_tb_end(tb, num_insns);
19911 tb->size = ctx.pc - pc_start;
19912 tb->icount = num_insns;
19914 #ifdef DEBUG_DISAS
19915 LOG_DISAS("\n");
19916 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
19917 && qemu_log_in_addr_range(pc_start)) {
19918 qemu_log("IN: %s\n", lookup_symbol(pc_start));
19919 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
19920 qemu_log("\n");
19922 #endif
19925 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
19926 int flags)
19928 int i;
19929 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
19931 #define printfpr(fp) \
19932 do { \
19933 if (is_fpu64) \
19934 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19935 " fd:%13g fs:%13g psu: %13g\n", \
19936 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
19937 (double)(fp)->fd, \
19938 (double)(fp)->fs[FP_ENDIAN_IDX], \
19939 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
19940 else { \
19941 fpr_t tmp; \
19942 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
19943 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
19944 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19945 " fd:%13g fs:%13g psu:%13g\n", \
19946 tmp.w[FP_ENDIAN_IDX], tmp.d, \
19947 (double)tmp.fd, \
19948 (double)tmp.fs[FP_ENDIAN_IDX], \
19949 (double)tmp.fs[!FP_ENDIAN_IDX]); \
19951 } while(0)
19954 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
19955 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
19956 get_float_exception_flags(&env->active_fpu.fp_status));
19957 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
19958 fpu_fprintf(f, "%3s: ", fregnames[i]);
19959 printfpr(&env->active_fpu.fpr[i]);
19962 #undef printfpr
19965 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
19966 int flags)
19968 MIPSCPU *cpu = MIPS_CPU(cs);
19969 CPUMIPSState *env = &cpu->env;
19970 int i;
19972 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
19973 " LO=0x" TARGET_FMT_lx " ds %04x "
19974 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
19975 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
19976 env->hflags, env->btarget, env->bcond);
19977 for (i = 0; i < 32; i++) {
19978 if ((i & 3) == 0)
19979 cpu_fprintf(f, "GPR%02d:", i);
19980 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
19981 if ((i & 3) == 3)
19982 cpu_fprintf(f, "\n");
19985 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
19986 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
19987 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
19988 PRIx64 "\n",
19989 env->CP0_Config0, env->CP0_Config1, env->lladdr);
19990 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
19991 env->CP0_Config2, env->CP0_Config3);
19992 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
19993 env->CP0_Config4, env->CP0_Config5);
19994 if (env->hflags & MIPS_HFLAG_FPU)
19995 fpu_dump_state(env, f, cpu_fprintf, flags);
19998 void mips_tcg_init(void)
20000 int i;
20001 static int inited;
20003 /* Initialize various static tables. */
20004 if (inited)
20005 return;
20007 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
20009 TCGV_UNUSED(cpu_gpr[0]);
20010 for (i = 1; i < 32; i++)
20011 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
20012 offsetof(CPUMIPSState, active_tc.gpr[i]),
20013 regnames[i]);
20015 for (i = 0; i < 32; i++) {
20016 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
20017 msa_wr_d[i * 2] =
20018 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
20019 /* The scalar floating-point unit (FPU) registers are mapped on
20020 * the MSA vector registers. */
20021 fpu_f64[i] = msa_wr_d[i * 2];
20022 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
20023 msa_wr_d[i * 2 + 1] =
20024 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
20027 cpu_PC = tcg_global_mem_new(cpu_env,
20028 offsetof(CPUMIPSState, active_tc.PC), "PC");
20029 for (i = 0; i < MIPS_DSP_ACC; i++) {
20030 cpu_HI[i] = tcg_global_mem_new(cpu_env,
20031 offsetof(CPUMIPSState, active_tc.HI[i]),
20032 regnames_HI[i]);
20033 cpu_LO[i] = tcg_global_mem_new(cpu_env,
20034 offsetof(CPUMIPSState, active_tc.LO[i]),
20035 regnames_LO[i]);
20037 cpu_dspctrl = tcg_global_mem_new(cpu_env,
20038 offsetof(CPUMIPSState, active_tc.DSPControl),
20039 "DSPControl");
20040 bcond = tcg_global_mem_new(cpu_env,
20041 offsetof(CPUMIPSState, bcond), "bcond");
20042 btarget = tcg_global_mem_new(cpu_env,
20043 offsetof(CPUMIPSState, btarget), "btarget");
20044 hflags = tcg_global_mem_new_i32(cpu_env,
20045 offsetof(CPUMIPSState, hflags), "hflags");
20047 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
20048 offsetof(CPUMIPSState, active_fpu.fcr0),
20049 "fcr0");
20050 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
20051 offsetof(CPUMIPSState, active_fpu.fcr31),
20052 "fcr31");
20054 inited = 1;
20057 #include "translate_init.c"
20059 MIPSCPU *cpu_mips_init(const char *cpu_model)
20061 MIPSCPU *cpu;
20062 CPUMIPSState *env;
20063 const mips_def_t *def;
20065 def = cpu_mips_find_by_name(cpu_model);
20066 if (!def)
20067 return NULL;
20068 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
20069 env = &cpu->env;
20070 env->cpu_model = def;
20072 #ifndef CONFIG_USER_ONLY
20073 mmu_init(env, def);
20074 #endif
20075 fpu_init(env, def);
20076 mvp_init(env, def);
20078 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
20080 return cpu;
20083 bool cpu_supports_cps_smp(const char *cpu_model)
20085 const mips_def_t *def = cpu_mips_find_by_name(cpu_model);
20086 if (!def) {
20087 return false;
20090 return (def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
20093 void cpu_state_reset(CPUMIPSState *env)
20095 MIPSCPU *cpu = mips_env_get_cpu(env);
20096 CPUState *cs = CPU(cpu);
20098 /* Reset registers to their default values */
20099 env->CP0_PRid = env->cpu_model->CP0_PRid;
20100 env->CP0_Config0 = env->cpu_model->CP0_Config0;
20101 #ifdef TARGET_WORDS_BIGENDIAN
20102 env->CP0_Config0 |= (1 << CP0C0_BE);
20103 #endif
20104 env->CP0_Config1 = env->cpu_model->CP0_Config1;
20105 env->CP0_Config2 = env->cpu_model->CP0_Config2;
20106 env->CP0_Config3 = env->cpu_model->CP0_Config3;
20107 env->CP0_Config4 = env->cpu_model->CP0_Config4;
20108 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
20109 env->CP0_Config5 = env->cpu_model->CP0_Config5;
20110 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
20111 env->CP0_Config6 = env->cpu_model->CP0_Config6;
20112 env->CP0_Config7 = env->cpu_model->CP0_Config7;
20113 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
20114 << env->cpu_model->CP0_LLAddr_shift;
20115 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
20116 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
20117 env->CCRes = env->cpu_model->CCRes;
20118 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
20119 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
20120 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
20121 env->current_tc = 0;
20122 env->SEGBITS = env->cpu_model->SEGBITS;
20123 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
20124 #if defined(TARGET_MIPS64)
20125 if (env->cpu_model->insn_flags & ISA_MIPS3) {
20126 env->SEGMask |= 3ULL << 62;
20128 #endif
20129 env->PABITS = env->cpu_model->PABITS;
20130 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
20131 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
20132 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
20133 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
20134 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
20135 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
20136 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
20137 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
20138 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
20139 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
20140 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
20141 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
20142 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
20143 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
20144 env->msair = env->cpu_model->MSAIR;
20145 env->insn_flags = env->cpu_model->insn_flags;
20147 #if defined(CONFIG_USER_ONLY)
20148 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
20149 # ifdef TARGET_MIPS64
20150 /* Enable 64-bit register mode. */
20151 env->CP0_Status |= (1 << CP0St_PX);
20152 # endif
20153 # ifdef TARGET_ABI_MIPSN64
20154 /* Enable 64-bit address mode. */
20155 env->CP0_Status |= (1 << CP0St_UX);
20156 # endif
20157 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
20158 hardware registers. */
20159 env->CP0_HWREna |= 0x0000000F;
20160 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
20161 env->CP0_Status |= (1 << CP0St_CU1);
20163 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
20164 env->CP0_Status |= (1 << CP0St_MX);
20166 # if defined(TARGET_MIPS64)
20167 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
20168 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
20169 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
20170 env->CP0_Status |= (1 << CP0St_FR);
20172 # endif
20173 #else
20174 if (env->hflags & MIPS_HFLAG_BMASK) {
20175 /* If the exception was raised from a delay slot,
20176 come back to the jump. */
20177 env->CP0_ErrorEPC = (env->active_tc.PC
20178 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
20179 } else {
20180 env->CP0_ErrorEPC = env->active_tc.PC;
20182 env->active_tc.PC = (int32_t)0xBFC00000;
20183 env->CP0_Random = env->tlb->nb_tlb - 1;
20184 env->tlb->tlb_in_use = env->tlb->nb_tlb;
20185 env->CP0_Wired = 0;
20186 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
20187 env->CP0_EBase = (cs->cpu_index & 0x3FF);
20188 if (kvm_enabled()) {
20189 env->CP0_EBase |= 0x40000000;
20190 } else {
20191 env->CP0_EBase |= 0x80000000;
20193 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
20194 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
20196 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
20197 /* vectored interrupts not implemented, timer on int 7,
20198 no performance counters. */
20199 env->CP0_IntCtl = 0xe0000000;
20201 int i;
20203 for (i = 0; i < 7; i++) {
20204 env->CP0_WatchLo[i] = 0;
20205 env->CP0_WatchHi[i] = 0x80000000;
20207 env->CP0_WatchLo[7] = 0;
20208 env->CP0_WatchHi[7] = 0;
20210 /* Count register increments in debug mode, EJTAG version 1 */
20211 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
20213 cpu_mips_store_count(env, 1);
20215 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
20216 int i;
20218 /* Only TC0 on VPE 0 starts as active. */
20219 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
20220 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
20221 env->tcs[i].CP0_TCHalt = 1;
20223 env->active_tc.CP0_TCHalt = 1;
20224 cs->halted = 1;
20226 if (cs->cpu_index == 0) {
20227 /* VPE0 starts up enabled. */
20228 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
20229 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
20231 /* TC0 starts up unhalted. */
20232 cs->halted = 0;
20233 env->active_tc.CP0_TCHalt = 0;
20234 env->tcs[0].CP0_TCHalt = 0;
20235 /* With thread 0 active. */
20236 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
20237 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
20240 #endif
20241 if ((env->insn_flags & ISA_MIPS32R6) &&
20242 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
20243 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
20244 env->CP0_Status |= (1 << CP0St_FR);
20247 /* MSA */
20248 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
20249 msa_reset(env);
20252 compute_hflags(env);
20253 restore_rounding_mode(env);
20254 restore_flush_mode(env);
20255 restore_pamask(env);
20256 cs->exception_index = EXCP_NONE;
20258 if (semihosting_get_argc()) {
20259 /* UHI interface can be used to obtain argc and argv */
20260 env->active_tc.gpr[4] = -1;
20264 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
20265 target_ulong *data)
20267 env->active_tc.PC = data[0];
20268 env->hflags &= ~MIPS_HFLAG_BMASK;
20269 env->hflags |= data[1];
20270 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
20271 case MIPS_HFLAG_BR:
20272 break;
20273 case MIPS_HFLAG_BC:
20274 case MIPS_HFLAG_BL:
20275 case MIPS_HFLAG_B:
20276 env->btarget = data[2];
20277 break;