block: Remove cache.writeback from blockdev-add
[qemu/ar7.git] / target-mips / translate.c
blob0f43bf4758c37a9128ca2e7ede550ead370f31e9
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "disas/disas.h"
27 #include "tcg-op.h"
28 #include "exec/cpu_ldst.h"
30 #include "exec/helper-proto.h"
31 #include "exec/helper-gen.h"
32 #include "sysemu/kvm.h"
33 #include "exec/semihost.h"
35 #include "trace-tcg.h"
36 #include "exec/log.h"
38 #define MIPS_DEBUG_DISAS 0
40 /* MIPS major opcodes */
41 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
43 enum {
44 /* indirect opcode tables */
45 OPC_SPECIAL = (0x00 << 26),
46 OPC_REGIMM = (0x01 << 26),
47 OPC_CP0 = (0x10 << 26),
48 OPC_CP1 = (0x11 << 26),
49 OPC_CP2 = (0x12 << 26),
50 OPC_CP3 = (0x13 << 26),
51 OPC_SPECIAL2 = (0x1C << 26),
52 OPC_SPECIAL3 = (0x1F << 26),
53 /* arithmetic with immediate */
54 OPC_ADDI = (0x08 << 26),
55 OPC_ADDIU = (0x09 << 26),
56 OPC_SLTI = (0x0A << 26),
57 OPC_SLTIU = (0x0B << 26),
58 /* logic with immediate */
59 OPC_ANDI = (0x0C << 26),
60 OPC_ORI = (0x0D << 26),
61 OPC_XORI = (0x0E << 26),
62 OPC_LUI = (0x0F << 26),
63 /* arithmetic with immediate */
64 OPC_DADDI = (0x18 << 26),
65 OPC_DADDIU = (0x19 << 26),
66 /* Jump and branches */
67 OPC_J = (0x02 << 26),
68 OPC_JAL = (0x03 << 26),
69 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
70 OPC_BEQL = (0x14 << 26),
71 OPC_BNE = (0x05 << 26),
72 OPC_BNEL = (0x15 << 26),
73 OPC_BLEZ = (0x06 << 26),
74 OPC_BLEZL = (0x16 << 26),
75 OPC_BGTZ = (0x07 << 26),
76 OPC_BGTZL = (0x17 << 26),
77 OPC_JALX = (0x1D << 26),
78 OPC_DAUI = (0x1D << 26),
79 /* Load and stores */
80 OPC_LDL = (0x1A << 26),
81 OPC_LDR = (0x1B << 26),
82 OPC_LB = (0x20 << 26),
83 OPC_LH = (0x21 << 26),
84 OPC_LWL = (0x22 << 26),
85 OPC_LW = (0x23 << 26),
86 OPC_LWPC = OPC_LW | 0x5,
87 OPC_LBU = (0x24 << 26),
88 OPC_LHU = (0x25 << 26),
89 OPC_LWR = (0x26 << 26),
90 OPC_LWU = (0x27 << 26),
91 OPC_SB = (0x28 << 26),
92 OPC_SH = (0x29 << 26),
93 OPC_SWL = (0x2A << 26),
94 OPC_SW = (0x2B << 26),
95 OPC_SDL = (0x2C << 26),
96 OPC_SDR = (0x2D << 26),
97 OPC_SWR = (0x2E << 26),
98 OPC_LL = (0x30 << 26),
99 OPC_LLD = (0x34 << 26),
100 OPC_LD = (0x37 << 26),
101 OPC_LDPC = OPC_LD | 0x5,
102 OPC_SC = (0x38 << 26),
103 OPC_SCD = (0x3C << 26),
104 OPC_SD = (0x3F << 26),
105 /* Floating point load/store */
106 OPC_LWC1 = (0x31 << 26),
107 OPC_LWC2 = (0x32 << 26),
108 OPC_LDC1 = (0x35 << 26),
109 OPC_LDC2 = (0x36 << 26),
110 OPC_SWC1 = (0x39 << 26),
111 OPC_SWC2 = (0x3A << 26),
112 OPC_SDC1 = (0x3D << 26),
113 OPC_SDC2 = (0x3E << 26),
114 /* Compact Branches */
115 OPC_BLEZALC = (0x06 << 26),
116 OPC_BGEZALC = (0x06 << 26),
117 OPC_BGEUC = (0x06 << 26),
118 OPC_BGTZALC = (0x07 << 26),
119 OPC_BLTZALC = (0x07 << 26),
120 OPC_BLTUC = (0x07 << 26),
121 OPC_BOVC = (0x08 << 26),
122 OPC_BEQZALC = (0x08 << 26),
123 OPC_BEQC = (0x08 << 26),
124 OPC_BLEZC = (0x16 << 26),
125 OPC_BGEZC = (0x16 << 26),
126 OPC_BGEC = (0x16 << 26),
127 OPC_BGTZC = (0x17 << 26),
128 OPC_BLTZC = (0x17 << 26),
129 OPC_BLTC = (0x17 << 26),
130 OPC_BNVC = (0x18 << 26),
131 OPC_BNEZALC = (0x18 << 26),
132 OPC_BNEC = (0x18 << 26),
133 OPC_BC = (0x32 << 26),
134 OPC_BEQZC = (0x36 << 26),
135 OPC_JIC = (0x36 << 26),
136 OPC_BALC = (0x3A << 26),
137 OPC_BNEZC = (0x3E << 26),
138 OPC_JIALC = (0x3E << 26),
139 /* MDMX ASE specific */
140 OPC_MDMX = (0x1E << 26),
141 /* MSA ASE, same as MDMX */
142 OPC_MSA = OPC_MDMX,
143 /* Cache and prefetch */
144 OPC_CACHE = (0x2F << 26),
145 OPC_PREF = (0x33 << 26),
146 /* PC-relative address computation / loads */
147 OPC_PCREL = (0x3B << 26),
150 /* PC-relative address computation / loads */
151 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
152 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
153 enum {
154 /* Instructions determined by bits 19 and 20 */
155 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
156 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
157 OPC_LWUPC = OPC_PCREL | (2 << 19),
159 /* Instructions determined by bits 16 ... 20 */
160 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
161 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
163 /* Other */
164 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
167 /* MIPS special opcodes */
168 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
170 enum {
171 /* Shifts */
172 OPC_SLL = 0x00 | OPC_SPECIAL,
173 /* NOP is SLL r0, r0, 0 */
174 /* SSNOP is SLL r0, r0, 1 */
175 /* EHB is SLL r0, r0, 3 */
176 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
177 OPC_ROTR = OPC_SRL | (1 << 21),
178 OPC_SRA = 0x03 | OPC_SPECIAL,
179 OPC_SLLV = 0x04 | OPC_SPECIAL,
180 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
181 OPC_ROTRV = OPC_SRLV | (1 << 6),
182 OPC_SRAV = 0x07 | OPC_SPECIAL,
183 OPC_DSLLV = 0x14 | OPC_SPECIAL,
184 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
185 OPC_DROTRV = OPC_DSRLV | (1 << 6),
186 OPC_DSRAV = 0x17 | OPC_SPECIAL,
187 OPC_DSLL = 0x38 | OPC_SPECIAL,
188 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
189 OPC_DROTR = OPC_DSRL | (1 << 21),
190 OPC_DSRA = 0x3B | OPC_SPECIAL,
191 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
192 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
193 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
194 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
195 /* Multiplication / division */
196 OPC_MULT = 0x18 | OPC_SPECIAL,
197 OPC_MULTU = 0x19 | OPC_SPECIAL,
198 OPC_DIV = 0x1A | OPC_SPECIAL,
199 OPC_DIVU = 0x1B | OPC_SPECIAL,
200 OPC_DMULT = 0x1C | OPC_SPECIAL,
201 OPC_DMULTU = 0x1D | OPC_SPECIAL,
202 OPC_DDIV = 0x1E | OPC_SPECIAL,
203 OPC_DDIVU = 0x1F | OPC_SPECIAL,
205 /* 2 registers arithmetic / logic */
206 OPC_ADD = 0x20 | OPC_SPECIAL,
207 OPC_ADDU = 0x21 | OPC_SPECIAL,
208 OPC_SUB = 0x22 | OPC_SPECIAL,
209 OPC_SUBU = 0x23 | OPC_SPECIAL,
210 OPC_AND = 0x24 | OPC_SPECIAL,
211 OPC_OR = 0x25 | OPC_SPECIAL,
212 OPC_XOR = 0x26 | OPC_SPECIAL,
213 OPC_NOR = 0x27 | OPC_SPECIAL,
214 OPC_SLT = 0x2A | OPC_SPECIAL,
215 OPC_SLTU = 0x2B | OPC_SPECIAL,
216 OPC_DADD = 0x2C | OPC_SPECIAL,
217 OPC_DADDU = 0x2D | OPC_SPECIAL,
218 OPC_DSUB = 0x2E | OPC_SPECIAL,
219 OPC_DSUBU = 0x2F | OPC_SPECIAL,
220 /* Jumps */
221 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
222 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
223 /* Traps */
224 OPC_TGE = 0x30 | OPC_SPECIAL,
225 OPC_TGEU = 0x31 | OPC_SPECIAL,
226 OPC_TLT = 0x32 | OPC_SPECIAL,
227 OPC_TLTU = 0x33 | OPC_SPECIAL,
228 OPC_TEQ = 0x34 | OPC_SPECIAL,
229 OPC_TNE = 0x36 | OPC_SPECIAL,
230 /* HI / LO registers load & stores */
231 OPC_MFHI = 0x10 | OPC_SPECIAL,
232 OPC_MTHI = 0x11 | OPC_SPECIAL,
233 OPC_MFLO = 0x12 | OPC_SPECIAL,
234 OPC_MTLO = 0x13 | OPC_SPECIAL,
235 /* Conditional moves */
236 OPC_MOVZ = 0x0A | OPC_SPECIAL,
237 OPC_MOVN = 0x0B | OPC_SPECIAL,
239 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
240 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
242 OPC_MOVCI = 0x01 | OPC_SPECIAL,
244 /* Special */
245 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
246 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
247 OPC_BREAK = 0x0D | OPC_SPECIAL,
248 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
249 OPC_SYNC = 0x0F | OPC_SPECIAL,
251 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
252 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
253 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
254 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
257 /* R6 Multiply and Divide instructions have the same Opcode
258 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
259 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
261 enum {
262 R6_OPC_MUL = OPC_MULT | (2 << 6),
263 R6_OPC_MUH = OPC_MULT | (3 << 6),
264 R6_OPC_MULU = OPC_MULTU | (2 << 6),
265 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
266 R6_OPC_DIV = OPC_DIV | (2 << 6),
267 R6_OPC_MOD = OPC_DIV | (3 << 6),
268 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
269 R6_OPC_MODU = OPC_DIVU | (3 << 6),
271 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
272 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
273 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
274 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
275 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
276 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
277 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
278 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
280 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
281 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
282 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
283 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
284 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
286 OPC_LSA = 0x05 | OPC_SPECIAL,
287 OPC_DLSA = 0x15 | OPC_SPECIAL,
290 /* Multiplication variants of the vr54xx. */
291 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
293 enum {
294 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
295 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
296 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
297 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
298 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
299 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
300 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
301 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
302 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
303 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
304 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
305 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
306 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
307 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
310 /* REGIMM (rt field) opcodes */
311 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
313 enum {
314 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
315 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
316 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
317 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
318 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
319 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
320 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
321 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
322 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
323 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
324 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
325 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
326 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
327 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
328 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
329 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
331 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
332 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
335 /* Special2 opcodes */
336 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
338 enum {
339 /* Multiply & xxx operations */
340 OPC_MADD = 0x00 | OPC_SPECIAL2,
341 OPC_MADDU = 0x01 | OPC_SPECIAL2,
342 OPC_MUL = 0x02 | OPC_SPECIAL2,
343 OPC_MSUB = 0x04 | OPC_SPECIAL2,
344 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
345 /* Loongson 2F */
346 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
347 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
348 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
349 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
350 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
351 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
352 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
353 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
354 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
355 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
356 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
357 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
358 /* Misc */
359 OPC_CLZ = 0x20 | OPC_SPECIAL2,
360 OPC_CLO = 0x21 | OPC_SPECIAL2,
361 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
362 OPC_DCLO = 0x25 | OPC_SPECIAL2,
363 /* Special */
364 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
367 /* Special3 opcodes */
368 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
370 enum {
371 OPC_EXT = 0x00 | OPC_SPECIAL3,
372 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
373 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
374 OPC_DEXT = 0x03 | OPC_SPECIAL3,
375 OPC_INS = 0x04 | OPC_SPECIAL3,
376 OPC_DINSM = 0x05 | OPC_SPECIAL3,
377 OPC_DINSU = 0x06 | OPC_SPECIAL3,
378 OPC_DINS = 0x07 | OPC_SPECIAL3,
379 OPC_FORK = 0x08 | OPC_SPECIAL3,
380 OPC_YIELD = 0x09 | OPC_SPECIAL3,
381 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
382 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
383 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
385 /* Loongson 2E */
386 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
387 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
388 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
389 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
390 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
391 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
392 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
393 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
394 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
395 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
396 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
397 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
399 /* MIPS DSP Load */
400 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
401 /* MIPS DSP Arithmetic */
402 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
403 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
404 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
405 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
406 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
407 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
408 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
409 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
410 /* MIPS DSP GPR-Based Shift Sub-class */
411 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
412 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
413 /* MIPS DSP Multiply Sub-class insns */
414 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
415 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
416 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
417 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
418 /* DSP Bit/Manipulation Sub-class */
419 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
420 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
421 /* MIPS DSP Append Sub-class */
422 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
423 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
424 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
425 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
426 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
428 /* R6 */
429 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
430 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
431 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
432 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
433 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
434 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
437 /* BSHFL opcodes */
438 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
440 enum {
441 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
442 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
443 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
444 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
445 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
446 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
449 /* DBSHFL opcodes */
450 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
452 enum {
453 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
454 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
455 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
456 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
457 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
460 /* MIPS DSP REGIMM opcodes */
461 enum {
462 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
463 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
466 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
467 /* MIPS DSP Load */
468 enum {
469 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
470 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
471 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
472 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
475 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
476 enum {
477 /* MIPS DSP Arithmetic Sub-class */
478 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
479 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
480 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
481 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
482 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
483 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
484 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
485 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
486 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
487 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
488 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
489 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
490 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
491 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
492 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
493 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
494 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
495 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
496 /* MIPS DSP Multiply Sub-class insns */
497 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
498 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
499 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
500 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
501 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
502 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
505 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
506 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
507 enum {
508 /* MIPS DSP Arithmetic Sub-class */
509 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
510 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
511 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
512 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
513 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
514 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
515 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
516 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
517 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
518 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
519 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
520 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
521 /* MIPS DSP Multiply Sub-class insns */
522 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
523 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
524 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
525 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
528 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
529 enum {
530 /* MIPS DSP Arithmetic Sub-class */
531 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
532 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
533 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
534 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
535 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
536 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
537 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
538 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
539 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
540 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
541 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
542 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
543 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
544 /* DSP Bit/Manipulation Sub-class */
545 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
546 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
547 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
548 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
549 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
552 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
553 enum {
554 /* MIPS DSP Arithmetic Sub-class */
555 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
556 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
557 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
558 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
559 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
560 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
561 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
562 /* DSP Compare-Pick Sub-class */
563 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
564 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
565 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
566 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
567 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
568 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
569 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
570 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
571 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
572 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
573 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
574 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
575 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
576 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
577 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
580 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
581 enum {
582 /* MIPS DSP GPR-Based Shift Sub-class */
583 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
584 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
585 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
586 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
587 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
588 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
589 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
590 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
591 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
592 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
593 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
594 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
595 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
596 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
597 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
598 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
599 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
600 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
601 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
602 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
603 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
604 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
607 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
608 enum {
609 /* MIPS DSP Multiply Sub-class insns */
610 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
611 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
612 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
613 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
614 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
615 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
616 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
617 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
618 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
619 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
620 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
621 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
622 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
623 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
624 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
625 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
626 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
627 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
628 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
629 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
630 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
631 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
634 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
635 enum {
636 /* DSP Bit/Manipulation Sub-class */
637 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
640 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
641 enum {
642 /* MIPS DSP Append Sub-class */
643 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
644 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
645 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
648 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
649 enum {
650 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
651 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
652 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
653 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
654 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
655 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
656 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
657 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
658 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
659 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
660 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
661 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
662 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
663 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
664 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
665 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
666 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
667 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
670 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Arithmetic Sub-class */
673 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
674 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
675 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
676 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
677 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
678 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
679 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
680 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
681 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
682 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
683 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
684 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
685 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
686 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
687 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
688 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
689 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
690 /* DSP Bit/Manipulation Sub-class */
691 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
692 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
693 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
694 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
695 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
699 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
700 enum {
701 /* MIPS DSP Multiply Sub-class insns */
702 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
703 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
704 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
705 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
706 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
707 /* MIPS DSP Arithmetic Sub-class */
708 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
709 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
710 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
711 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
712 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
713 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
714 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
715 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
716 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
717 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
718 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
719 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
720 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
721 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
722 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
723 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
724 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
725 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
726 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
727 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
728 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
731 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
732 enum {
733 /* DSP Compare-Pick Sub-class */
734 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
735 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
736 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
737 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
738 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
739 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
740 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
741 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
742 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
743 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
744 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
745 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
746 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
747 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
748 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
749 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
750 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
751 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
752 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
753 /* MIPS DSP Arithmetic Sub-class */
754 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
755 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
756 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
764 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
765 enum {
766 /* DSP Append Sub-class */
767 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
768 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
769 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
770 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
773 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
774 enum {
775 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
776 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
777 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
778 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
779 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
780 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
781 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
782 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
783 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
784 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
785 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
786 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
787 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
788 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
789 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
790 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
791 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
792 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
793 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
794 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
795 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
796 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
799 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
800 enum {
801 /* DSP Bit/Manipulation Sub-class */
802 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
805 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
806 enum {
807 /* MIPS DSP Multiply Sub-class insns */
808 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
809 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
810 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
811 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
812 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
813 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
814 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
815 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
816 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
817 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
818 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
819 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
820 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
821 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
822 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
823 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
824 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
825 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
826 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
827 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
828 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
829 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
830 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
836 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
837 enum {
838 /* MIPS DSP GPR-Based Shift Sub-class */
839 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
840 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
841 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
842 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
843 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
844 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
845 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
846 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
847 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
848 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
849 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
850 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
851 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
852 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
853 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
854 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
855 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
856 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
857 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
858 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
859 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
860 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
861 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
867 /* Coprocessor 0 (rs field) */
868 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
870 enum {
871 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
872 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
873 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
874 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
875 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
876 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
877 OPC_MFTR = (0x08 << 21) | OPC_CP0,
878 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
879 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
880 OPC_MTTR = (0x0C << 21) | OPC_CP0,
881 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
882 OPC_C0 = (0x10 << 21) | OPC_CP0,
883 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
884 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
887 /* MFMC0 opcodes */
888 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
890 enum {
891 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
892 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
893 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
894 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
895 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
896 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
897 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
898 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
901 /* Coprocessor 0 (with rs == C0) */
902 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
904 enum {
905 OPC_TLBR = 0x01 | OPC_C0,
906 OPC_TLBWI = 0x02 | OPC_C0,
907 OPC_TLBINV = 0x03 | OPC_C0,
908 OPC_TLBINVF = 0x04 | OPC_C0,
909 OPC_TLBWR = 0x06 | OPC_C0,
910 OPC_TLBP = 0x08 | OPC_C0,
911 OPC_RFE = 0x10 | OPC_C0,
912 OPC_ERET = 0x18 | OPC_C0,
913 OPC_DERET = 0x1F | OPC_C0,
914 OPC_WAIT = 0x20 | OPC_C0,
917 /* Coprocessor 1 (rs field) */
918 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
920 /* Values for the fmt field in FP instructions */
921 enum {
922 /* 0 - 15 are reserved */
923 FMT_S = 16, /* single fp */
924 FMT_D = 17, /* double fp */
925 FMT_E = 18, /* extended fp */
926 FMT_Q = 19, /* quad fp */
927 FMT_W = 20, /* 32-bit fixed */
928 FMT_L = 21, /* 64-bit fixed */
929 FMT_PS = 22, /* paired single fp */
930 /* 23 - 31 are reserved */
933 enum {
934 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
935 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
936 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
937 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
938 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
939 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
940 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
941 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
942 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
943 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
944 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
945 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
946 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
947 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
948 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
949 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
950 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
951 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
952 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
953 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
954 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
955 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
956 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
957 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
958 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
959 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
960 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
961 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
962 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
963 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
966 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
967 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
969 enum {
970 OPC_BC1F = (0x00 << 16) | OPC_BC1,
971 OPC_BC1T = (0x01 << 16) | OPC_BC1,
972 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
973 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
976 enum {
977 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
978 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
981 enum {
982 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
983 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
986 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
988 enum {
989 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
990 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
991 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
992 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
993 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
994 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
995 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
996 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
997 OPC_BC2 = (0x08 << 21) | OPC_CP2,
998 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
999 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1002 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1004 enum {
1005 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1006 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1007 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1008 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1009 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1010 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1011 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1012 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1014 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1015 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1016 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1018 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1019 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1020 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1021 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1023 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1024 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1025 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1026 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1027 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1028 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1029 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1030 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1032 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1033 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1034 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1035 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1036 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1037 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1038 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1039 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1041 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1042 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1043 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1044 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1045 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1046 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1048 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1049 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1050 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1051 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1052 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1053 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1055 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1056 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1057 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1058 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1059 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1060 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1062 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1063 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1064 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1065 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1066 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1067 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1069 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1070 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1071 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1072 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1073 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1074 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1076 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1077 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1078 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1079 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1080 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1081 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1083 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1084 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1085 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1086 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1087 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1088 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1090 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1091 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1092 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1093 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1094 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1095 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1099 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1101 enum {
1102 OPC_LWXC1 = 0x00 | OPC_CP3,
1103 OPC_LDXC1 = 0x01 | OPC_CP3,
1104 OPC_LUXC1 = 0x05 | OPC_CP3,
1105 OPC_SWXC1 = 0x08 | OPC_CP3,
1106 OPC_SDXC1 = 0x09 | OPC_CP3,
1107 OPC_SUXC1 = 0x0D | OPC_CP3,
1108 OPC_PREFX = 0x0F | OPC_CP3,
1109 OPC_ALNV_PS = 0x1E | OPC_CP3,
1110 OPC_MADD_S = 0x20 | OPC_CP3,
1111 OPC_MADD_D = 0x21 | OPC_CP3,
1112 OPC_MADD_PS = 0x26 | OPC_CP3,
1113 OPC_MSUB_S = 0x28 | OPC_CP3,
1114 OPC_MSUB_D = 0x29 | OPC_CP3,
1115 OPC_MSUB_PS = 0x2E | OPC_CP3,
1116 OPC_NMADD_S = 0x30 | OPC_CP3,
1117 OPC_NMADD_D = 0x31 | OPC_CP3,
1118 OPC_NMADD_PS= 0x36 | OPC_CP3,
1119 OPC_NMSUB_S = 0x38 | OPC_CP3,
1120 OPC_NMSUB_D = 0x39 | OPC_CP3,
1121 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1124 /* MSA Opcodes */
1125 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1126 enum {
1127 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1128 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1129 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1130 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1131 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1132 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1133 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1134 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1135 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1136 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1137 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1138 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1139 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1140 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1141 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1142 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1143 OPC_MSA_ELM = 0x19 | OPC_MSA,
1144 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1145 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1146 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1147 OPC_MSA_VEC = 0x1E | OPC_MSA,
1149 /* MI10 instruction */
1150 OPC_LD_B = (0x20) | OPC_MSA,
1151 OPC_LD_H = (0x21) | OPC_MSA,
1152 OPC_LD_W = (0x22) | OPC_MSA,
1153 OPC_LD_D = (0x23) | OPC_MSA,
1154 OPC_ST_B = (0x24) | OPC_MSA,
1155 OPC_ST_H = (0x25) | OPC_MSA,
1156 OPC_ST_W = (0x26) | OPC_MSA,
1157 OPC_ST_D = (0x27) | OPC_MSA,
1160 enum {
1161 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1162 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1163 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1164 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1165 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1166 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1167 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1168 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1169 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1170 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1171 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1172 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1173 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1175 /* I8 instruction */
1176 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1177 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1178 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1179 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1180 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1181 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1182 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1183 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1184 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1185 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1187 /* VEC/2R/2RF instruction */
1188 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1189 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1190 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1191 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1192 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1193 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1194 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1196 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1197 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1199 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1200 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1201 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1202 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1203 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1205 /* 2RF instruction df(bit 16) = _w, _d */
1206 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1207 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1208 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1209 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1210 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1211 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1212 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1213 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1214 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1215 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1216 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1217 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1218 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1219 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1220 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1221 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1223 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1224 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1225 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1226 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1227 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1228 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1229 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1230 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1231 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1232 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1233 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1234 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1235 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1236 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1237 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1238 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1239 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1240 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1241 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1242 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1243 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1244 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1245 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1246 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1247 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1248 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1249 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1250 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1251 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1252 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1253 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1254 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1255 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1256 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1257 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1258 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1259 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1260 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1261 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1262 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1263 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1264 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1265 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1266 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1267 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1268 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1269 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1270 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1271 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1272 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1273 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1274 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1275 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1276 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1277 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1278 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1279 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1280 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1281 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1282 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1283 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1284 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1285 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1286 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1288 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1289 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1290 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1291 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1292 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1293 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1294 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1295 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1296 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1297 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1299 /* 3RF instruction _df(bit 21) = _w, _d */
1300 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1301 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1302 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1303 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1304 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1305 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1306 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1307 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1308 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1309 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1310 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1311 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1312 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1313 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1314 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1315 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1316 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1317 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1318 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1319 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1320 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1321 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1322 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1323 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1324 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1325 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1326 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1327 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1328 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1329 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1330 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1331 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1332 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1333 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1334 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1335 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1336 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1337 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1338 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1339 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1340 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1342 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1343 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1344 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1345 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1346 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1347 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1348 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1349 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1350 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1351 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1352 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1353 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1354 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1357 /* global register indices */
1358 static TCGv_env cpu_env;
1359 static TCGv cpu_gpr[32], cpu_PC;
1360 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1361 static TCGv cpu_dspctrl, btarget, bcond;
1362 static TCGv_i32 hflags;
1363 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1364 static TCGv_i64 fpu_f64[32];
1365 static TCGv_i64 msa_wr_d[64];
1367 #include "exec/gen-icount.h"
1369 #define gen_helper_0e0i(name, arg) do { \
1370 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1371 gen_helper_##name(cpu_env, helper_tmp); \
1372 tcg_temp_free_i32(helper_tmp); \
1373 } while(0)
1375 #define gen_helper_0e1i(name, arg1, arg2) do { \
1376 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1377 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1378 tcg_temp_free_i32(helper_tmp); \
1379 } while(0)
1381 #define gen_helper_1e0i(name, ret, arg1) do { \
1382 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1383 gen_helper_##name(ret, cpu_env, helper_tmp); \
1384 tcg_temp_free_i32(helper_tmp); \
1385 } while(0)
1387 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1388 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1389 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1390 tcg_temp_free_i32(helper_tmp); \
1391 } while(0)
1393 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1394 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1395 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1396 tcg_temp_free_i32(helper_tmp); \
1397 } while(0)
1399 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1400 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1401 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1402 tcg_temp_free_i32(helper_tmp); \
1403 } while(0)
1405 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1406 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1407 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1408 tcg_temp_free_i32(helper_tmp); \
1409 } while(0)
1411 typedef struct DisasContext {
1412 struct TranslationBlock *tb;
1413 target_ulong pc, saved_pc;
1414 uint32_t opcode;
1415 int singlestep_enabled;
1416 int insn_flags;
1417 int32_t CP0_Config1;
1418 /* Routine used to access memory */
1419 int mem_idx;
1420 TCGMemOp default_tcg_memop_mask;
1421 uint32_t hflags, saved_hflags;
1422 int bstate;
1423 target_ulong btarget;
1424 bool ulri;
1425 int kscrexist;
1426 bool rxi;
1427 int ie;
1428 bool bi;
1429 bool bp;
1430 uint64_t PAMask;
1431 bool mvh;
1432 int CP0_LLAddr_shift;
1433 bool ps;
1434 bool vp;
1435 } DisasContext;
1437 enum {
1438 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1439 * exception condition */
1440 BS_STOP = 1, /* We want to stop translation for any reason */
1441 BS_BRANCH = 2, /* We reached a branch condition */
1442 BS_EXCP = 3, /* We reached an exception condition */
1445 static const char * const regnames[] = {
1446 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1447 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1448 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1449 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1452 static const char * const regnames_HI[] = {
1453 "HI0", "HI1", "HI2", "HI3",
1456 static const char * const regnames_LO[] = {
1457 "LO0", "LO1", "LO2", "LO3",
1460 static const char * const fregnames[] = {
1461 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1462 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1463 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1464 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1467 static const char * const msaregnames[] = {
1468 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1469 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1470 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1471 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1472 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1473 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1474 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1475 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1476 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1477 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1478 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1479 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1480 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1481 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1482 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1483 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1486 #define LOG_DISAS(...) \
1487 do { \
1488 if (MIPS_DEBUG_DISAS) { \
1489 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1491 } while (0)
1493 #define MIPS_INVAL(op) \
1494 do { \
1495 if (MIPS_DEBUG_DISAS) { \
1496 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1497 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
1498 ctx->pc, ctx->opcode, op, ctx->opcode >> 26, \
1499 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
1501 } while (0)
1503 /* General purpose registers moves. */
1504 static inline void gen_load_gpr (TCGv t, int reg)
1506 if (reg == 0)
1507 tcg_gen_movi_tl(t, 0);
1508 else
1509 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1512 static inline void gen_store_gpr (TCGv t, int reg)
1514 if (reg != 0)
1515 tcg_gen_mov_tl(cpu_gpr[reg], t);
1518 /* Moves to/from shadow registers. */
1519 static inline void gen_load_srsgpr (int from, int to)
1521 TCGv t0 = tcg_temp_new();
1523 if (from == 0)
1524 tcg_gen_movi_tl(t0, 0);
1525 else {
1526 TCGv_i32 t2 = tcg_temp_new_i32();
1527 TCGv_ptr addr = tcg_temp_new_ptr();
1529 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1530 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1531 tcg_gen_andi_i32(t2, t2, 0xf);
1532 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1533 tcg_gen_ext_i32_ptr(addr, t2);
1534 tcg_gen_add_ptr(addr, cpu_env, addr);
1536 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1537 tcg_temp_free_ptr(addr);
1538 tcg_temp_free_i32(t2);
1540 gen_store_gpr(t0, to);
1541 tcg_temp_free(t0);
1544 static inline void gen_store_srsgpr (int from, int to)
1546 if (to != 0) {
1547 TCGv t0 = tcg_temp_new();
1548 TCGv_i32 t2 = tcg_temp_new_i32();
1549 TCGv_ptr addr = tcg_temp_new_ptr();
1551 gen_load_gpr(t0, from);
1552 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1553 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1554 tcg_gen_andi_i32(t2, t2, 0xf);
1555 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1556 tcg_gen_ext_i32_ptr(addr, t2);
1557 tcg_gen_add_ptr(addr, cpu_env, addr);
1559 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1560 tcg_temp_free_ptr(addr);
1561 tcg_temp_free_i32(t2);
1562 tcg_temp_free(t0);
1566 /* Tests */
1567 static inline void gen_save_pc(target_ulong pc)
1569 tcg_gen_movi_tl(cpu_PC, pc);
1572 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1574 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1575 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1576 gen_save_pc(ctx->pc);
1577 ctx->saved_pc = ctx->pc;
1579 if (ctx->hflags != ctx->saved_hflags) {
1580 tcg_gen_movi_i32(hflags, ctx->hflags);
1581 ctx->saved_hflags = ctx->hflags;
1582 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1583 case MIPS_HFLAG_BR:
1584 break;
1585 case MIPS_HFLAG_BC:
1586 case MIPS_HFLAG_BL:
1587 case MIPS_HFLAG_B:
1588 tcg_gen_movi_tl(btarget, ctx->btarget);
1589 break;
1594 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1596 ctx->saved_hflags = ctx->hflags;
1597 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1598 case MIPS_HFLAG_BR:
1599 break;
1600 case MIPS_HFLAG_BC:
1601 case MIPS_HFLAG_BL:
1602 case MIPS_HFLAG_B:
1603 ctx->btarget = env->btarget;
1604 break;
1608 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1610 TCGv_i32 texcp = tcg_const_i32(excp);
1611 TCGv_i32 terr = tcg_const_i32(err);
1612 save_cpu_state(ctx, 1);
1613 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1614 tcg_temp_free_i32(terr);
1615 tcg_temp_free_i32(texcp);
1616 ctx->bstate = BS_EXCP;
1619 static inline void generate_exception(DisasContext *ctx, int excp)
1621 gen_helper_0e0i(raise_exception, excp);
1624 static inline void generate_exception_end(DisasContext *ctx, int excp)
1626 generate_exception_err(ctx, excp, 0);
1629 /* Floating point register moves. */
1630 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1632 if (ctx->hflags & MIPS_HFLAG_FRE) {
1633 generate_exception(ctx, EXCP_RI);
1635 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1638 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1640 TCGv_i64 t64;
1641 if (ctx->hflags & MIPS_HFLAG_FRE) {
1642 generate_exception(ctx, EXCP_RI);
1644 t64 = tcg_temp_new_i64();
1645 tcg_gen_extu_i32_i64(t64, t);
1646 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1647 tcg_temp_free_i64(t64);
1650 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1652 if (ctx->hflags & MIPS_HFLAG_F64) {
1653 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1654 } else {
1655 gen_load_fpr32(ctx, t, reg | 1);
1659 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1661 if (ctx->hflags & MIPS_HFLAG_F64) {
1662 TCGv_i64 t64 = tcg_temp_new_i64();
1663 tcg_gen_extu_i32_i64(t64, t);
1664 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1665 tcg_temp_free_i64(t64);
1666 } else {
1667 gen_store_fpr32(ctx, t, reg | 1);
1671 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1673 if (ctx->hflags & MIPS_HFLAG_F64) {
1674 tcg_gen_mov_i64(t, fpu_f64[reg]);
1675 } else {
1676 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1680 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1682 if (ctx->hflags & MIPS_HFLAG_F64) {
1683 tcg_gen_mov_i64(fpu_f64[reg], t);
1684 } else {
1685 TCGv_i64 t0;
1686 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1687 t0 = tcg_temp_new_i64();
1688 tcg_gen_shri_i64(t0, t, 32);
1689 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1690 tcg_temp_free_i64(t0);
1694 static inline int get_fp_bit (int cc)
1696 if (cc)
1697 return 24 + cc;
1698 else
1699 return 23;
1702 /* Addresses computation */
1703 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1705 tcg_gen_add_tl(ret, arg0, arg1);
1707 #if defined(TARGET_MIPS64)
1708 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1709 tcg_gen_ext32s_i64(ret, ret);
1711 #endif
1714 /* Addresses computation (translation time) */
1715 static target_long addr_add(DisasContext *ctx, target_long base,
1716 target_long offset)
1718 target_long sum = base + offset;
1720 #if defined(TARGET_MIPS64)
1721 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1722 sum = (int32_t)sum;
1724 #endif
1725 return sum;
1728 /* Sign-extract the low 32-bits to a target_long. */
1729 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
1731 #if defined(TARGET_MIPS64)
1732 tcg_gen_ext32s_i64(ret, arg);
1733 #else
1734 tcg_gen_extrl_i64_i32(ret, arg);
1735 #endif
1738 /* Sign-extract the high 32-bits to a target_long. */
1739 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
1741 #if defined(TARGET_MIPS64)
1742 tcg_gen_sari_i64(ret, arg, 32);
1743 #else
1744 tcg_gen_extrh_i64_i32(ret, arg);
1745 #endif
1748 static inline void check_cp0_enabled(DisasContext *ctx)
1750 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1751 generate_exception_err(ctx, EXCP_CpU, 0);
1754 static inline void check_cp1_enabled(DisasContext *ctx)
1756 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1757 generate_exception_err(ctx, EXCP_CpU, 1);
1760 /* Verify that the processor is running with COP1X instructions enabled.
1761 This is associated with the nabla symbol in the MIPS32 and MIPS64
1762 opcode tables. */
1764 static inline void check_cop1x(DisasContext *ctx)
1766 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1767 generate_exception_end(ctx, EXCP_RI);
1770 /* Verify that the processor is running with 64-bit floating-point
1771 operations enabled. */
1773 static inline void check_cp1_64bitmode(DisasContext *ctx)
1775 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1776 generate_exception_end(ctx, EXCP_RI);
1780 * Verify if floating point register is valid; an operation is not defined
1781 * if bit 0 of any register specification is set and the FR bit in the
1782 * Status register equals zero, since the register numbers specify an
1783 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1784 * in the Status register equals one, both even and odd register numbers
1785 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1787 * Multiple 64 bit wide registers can be checked by calling
1788 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1790 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1792 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1793 generate_exception_end(ctx, EXCP_RI);
1796 /* Verify that the processor is running with DSP instructions enabled.
1797 This is enabled by CP0 Status register MX(24) bit.
1800 static inline void check_dsp(DisasContext *ctx)
1802 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1803 if (ctx->insn_flags & ASE_DSP) {
1804 generate_exception_end(ctx, EXCP_DSPDIS);
1805 } else {
1806 generate_exception_end(ctx, EXCP_RI);
1811 static inline void check_dspr2(DisasContext *ctx)
1813 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1814 if (ctx->insn_flags & ASE_DSP) {
1815 generate_exception_end(ctx, EXCP_DSPDIS);
1816 } else {
1817 generate_exception_end(ctx, EXCP_RI);
1822 /* This code generates a "reserved instruction" exception if the
1823 CPU does not support the instruction set corresponding to flags. */
1824 static inline void check_insn(DisasContext *ctx, int flags)
1826 if (unlikely(!(ctx->insn_flags & flags))) {
1827 generate_exception_end(ctx, EXCP_RI);
1831 /* This code generates a "reserved instruction" exception if the
1832 CPU has corresponding flag set which indicates that the instruction
1833 has been removed. */
1834 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1836 if (unlikely(ctx->insn_flags & flags)) {
1837 generate_exception_end(ctx, EXCP_RI);
1841 /* This code generates a "reserved instruction" exception if the
1842 CPU does not support 64-bit paired-single (PS) floating point data type */
1843 static inline void check_ps(DisasContext *ctx)
1845 if (unlikely(!ctx->ps)) {
1846 generate_exception(ctx, EXCP_RI);
1848 check_cp1_64bitmode(ctx);
1851 #ifdef TARGET_MIPS64
1852 /* This code generates a "reserved instruction" exception if 64-bit
1853 instructions are not enabled. */
1854 static inline void check_mips_64(DisasContext *ctx)
1856 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1857 generate_exception_end(ctx, EXCP_RI);
1859 #endif
1861 #ifndef CONFIG_USER_ONLY
1862 static inline void check_mvh(DisasContext *ctx)
1864 if (unlikely(!ctx->mvh)) {
1865 generate_exception(ctx, EXCP_RI);
1868 #endif
1870 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1871 calling interface for 32 and 64-bit FPRs. No sense in changing
1872 all callers for gen_load_fpr32 when we need the CTX parameter for
1873 this one use. */
1874 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1875 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1876 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1877 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1878 int ft, int fs, int cc) \
1880 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1881 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1882 switch (ifmt) { \
1883 case FMT_PS: \
1884 check_ps(ctx); \
1885 break; \
1886 case FMT_D: \
1887 if (abs) { \
1888 check_cop1x(ctx); \
1890 check_cp1_registers(ctx, fs | ft); \
1891 break; \
1892 case FMT_S: \
1893 if (abs) { \
1894 check_cop1x(ctx); \
1896 break; \
1898 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1899 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1900 switch (n) { \
1901 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1902 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1903 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1904 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1905 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1906 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1907 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1908 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1909 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1910 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1911 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1912 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1913 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1914 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1915 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1916 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1917 default: abort(); \
1919 tcg_temp_free_i##bits (fp0); \
1920 tcg_temp_free_i##bits (fp1); \
1923 FOP_CONDS(, 0, d, FMT_D, 64)
1924 FOP_CONDS(abs, 1, d, FMT_D, 64)
1925 FOP_CONDS(, 0, s, FMT_S, 32)
1926 FOP_CONDS(abs, 1, s, FMT_S, 32)
1927 FOP_CONDS(, 0, ps, FMT_PS, 64)
1928 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1929 #undef FOP_CONDS
1931 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1932 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1933 int ft, int fs, int fd) \
1935 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1936 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1937 if (ifmt == FMT_D) { \
1938 check_cp1_registers(ctx, fs | ft | fd); \
1940 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1941 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1942 switch (n) { \
1943 case 0: \
1944 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1945 break; \
1946 case 1: \
1947 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1948 break; \
1949 case 2: \
1950 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1951 break; \
1952 case 3: \
1953 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1954 break; \
1955 case 4: \
1956 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1957 break; \
1958 case 5: \
1959 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1960 break; \
1961 case 6: \
1962 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1963 break; \
1964 case 7: \
1965 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1966 break; \
1967 case 8: \
1968 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1969 break; \
1970 case 9: \
1971 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1972 break; \
1973 case 10: \
1974 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1975 break; \
1976 case 11: \
1977 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1978 break; \
1979 case 12: \
1980 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1981 break; \
1982 case 13: \
1983 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1984 break; \
1985 case 14: \
1986 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1987 break; \
1988 case 15: \
1989 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1990 break; \
1991 case 17: \
1992 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1993 break; \
1994 case 18: \
1995 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1996 break; \
1997 case 19: \
1998 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1999 break; \
2000 case 25: \
2001 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2002 break; \
2003 case 26: \
2004 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2005 break; \
2006 case 27: \
2007 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2008 break; \
2009 default: \
2010 abort(); \
2012 STORE; \
2013 tcg_temp_free_i ## bits (fp0); \
2014 tcg_temp_free_i ## bits (fp1); \
2017 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2018 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2019 #undef FOP_CONDNS
2020 #undef gen_ldcmp_fpr32
2021 #undef gen_ldcmp_fpr64
2023 /* load/store instructions. */
2024 #ifdef CONFIG_USER_ONLY
2025 #define OP_LD_ATOMIC(insn,fname) \
2026 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2028 TCGv t0 = tcg_temp_new(); \
2029 tcg_gen_mov_tl(t0, arg1); \
2030 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2031 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2032 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2033 tcg_temp_free(t0); \
2035 #else
2036 #define OP_LD_ATOMIC(insn,fname) \
2037 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2039 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
2041 #endif
2042 OP_LD_ATOMIC(ll,ld32s);
2043 #if defined(TARGET_MIPS64)
2044 OP_LD_ATOMIC(lld,ld64);
2045 #endif
2046 #undef OP_LD_ATOMIC
2048 #ifdef CONFIG_USER_ONLY
2049 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2050 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2052 TCGv t0 = tcg_temp_new(); \
2053 TCGLabel *l1 = gen_new_label(); \
2054 TCGLabel *l2 = gen_new_label(); \
2056 tcg_gen_andi_tl(t0, arg2, almask); \
2057 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2058 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2059 generate_exception(ctx, EXCP_AdES); \
2060 gen_set_label(l1); \
2061 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2062 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2063 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2064 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2065 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2066 generate_exception_end(ctx, EXCP_SC); \
2067 gen_set_label(l2); \
2068 tcg_gen_movi_tl(t0, 0); \
2069 gen_store_gpr(t0, rt); \
2070 tcg_temp_free(t0); \
2072 #else
2073 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2074 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2076 TCGv t0 = tcg_temp_new(); \
2077 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
2078 gen_store_gpr(t0, rt); \
2079 tcg_temp_free(t0); \
2081 #endif
2082 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2083 #if defined(TARGET_MIPS64)
2084 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2085 #endif
2086 #undef OP_ST_ATOMIC
2088 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2089 int base, int16_t offset)
2091 if (base == 0) {
2092 tcg_gen_movi_tl(addr, offset);
2093 } else if (offset == 0) {
2094 gen_load_gpr(addr, base);
2095 } else {
2096 tcg_gen_movi_tl(addr, offset);
2097 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2101 static target_ulong pc_relative_pc (DisasContext *ctx)
2103 target_ulong pc = ctx->pc;
2105 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2106 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2108 pc -= branch_bytes;
2111 pc &= ~(target_ulong)3;
2112 return pc;
2115 /* Load */
2116 static void gen_ld(DisasContext *ctx, uint32_t opc,
2117 int rt, int base, int16_t offset)
2119 TCGv t0, t1, t2;
2121 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2122 /* Loongson CPU uses a load to zero register for prefetch.
2123 We emulate it as a NOP. On other CPU we must perform the
2124 actual memory access. */
2125 return;
2128 t0 = tcg_temp_new();
2129 gen_base_offset_addr(ctx, t0, base, offset);
2131 switch (opc) {
2132 #if defined(TARGET_MIPS64)
2133 case OPC_LWU:
2134 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL |
2135 ctx->default_tcg_memop_mask);
2136 gen_store_gpr(t0, rt);
2137 break;
2138 case OPC_LD:
2139 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
2140 ctx->default_tcg_memop_mask);
2141 gen_store_gpr(t0, rt);
2142 break;
2143 case OPC_LLD:
2144 case R6_OPC_LLD:
2145 op_ld_lld(t0, t0, ctx);
2146 gen_store_gpr(t0, rt);
2147 break;
2148 case OPC_LDL:
2149 t1 = tcg_temp_new();
2150 /* Do a byte access to possibly trigger a page
2151 fault with the unaligned address. */
2152 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2153 tcg_gen_andi_tl(t1, t0, 7);
2154 #ifndef TARGET_WORDS_BIGENDIAN
2155 tcg_gen_xori_tl(t1, t1, 7);
2156 #endif
2157 tcg_gen_shli_tl(t1, t1, 3);
2158 tcg_gen_andi_tl(t0, t0, ~7);
2159 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2160 tcg_gen_shl_tl(t0, t0, t1);
2161 t2 = tcg_const_tl(-1);
2162 tcg_gen_shl_tl(t2, t2, t1);
2163 gen_load_gpr(t1, rt);
2164 tcg_gen_andc_tl(t1, t1, t2);
2165 tcg_temp_free(t2);
2166 tcg_gen_or_tl(t0, t0, t1);
2167 tcg_temp_free(t1);
2168 gen_store_gpr(t0, rt);
2169 break;
2170 case OPC_LDR:
2171 t1 = tcg_temp_new();
2172 /* Do a byte access to possibly trigger a page
2173 fault with the unaligned address. */
2174 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2175 tcg_gen_andi_tl(t1, t0, 7);
2176 #ifdef TARGET_WORDS_BIGENDIAN
2177 tcg_gen_xori_tl(t1, t1, 7);
2178 #endif
2179 tcg_gen_shli_tl(t1, t1, 3);
2180 tcg_gen_andi_tl(t0, t0, ~7);
2181 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2182 tcg_gen_shr_tl(t0, t0, t1);
2183 tcg_gen_xori_tl(t1, t1, 63);
2184 t2 = tcg_const_tl(0xfffffffffffffffeull);
2185 tcg_gen_shl_tl(t2, t2, t1);
2186 gen_load_gpr(t1, rt);
2187 tcg_gen_and_tl(t1, t1, t2);
2188 tcg_temp_free(t2);
2189 tcg_gen_or_tl(t0, t0, t1);
2190 tcg_temp_free(t1);
2191 gen_store_gpr(t0, rt);
2192 break;
2193 case OPC_LDPC:
2194 t1 = tcg_const_tl(pc_relative_pc(ctx));
2195 gen_op_addr_add(ctx, t0, t0, t1);
2196 tcg_temp_free(t1);
2197 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2198 gen_store_gpr(t0, rt);
2199 break;
2200 #endif
2201 case OPC_LWPC:
2202 t1 = tcg_const_tl(pc_relative_pc(ctx));
2203 gen_op_addr_add(ctx, t0, t0, t1);
2204 tcg_temp_free(t1);
2205 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2206 gen_store_gpr(t0, rt);
2207 break;
2208 case OPC_LW:
2209 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
2210 ctx->default_tcg_memop_mask);
2211 gen_store_gpr(t0, rt);
2212 break;
2213 case OPC_LH:
2214 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
2215 ctx->default_tcg_memop_mask);
2216 gen_store_gpr(t0, rt);
2217 break;
2218 case OPC_LHU:
2219 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW |
2220 ctx->default_tcg_memop_mask);
2221 gen_store_gpr(t0, rt);
2222 break;
2223 case OPC_LB:
2224 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
2225 gen_store_gpr(t0, rt);
2226 break;
2227 case OPC_LBU:
2228 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
2229 gen_store_gpr(t0, rt);
2230 break;
2231 case OPC_LWL:
2232 t1 = tcg_temp_new();
2233 /* Do a byte access to possibly trigger a page
2234 fault with the unaligned address. */
2235 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2236 tcg_gen_andi_tl(t1, t0, 3);
2237 #ifndef TARGET_WORDS_BIGENDIAN
2238 tcg_gen_xori_tl(t1, t1, 3);
2239 #endif
2240 tcg_gen_shli_tl(t1, t1, 3);
2241 tcg_gen_andi_tl(t0, t0, ~3);
2242 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2243 tcg_gen_shl_tl(t0, t0, t1);
2244 t2 = tcg_const_tl(-1);
2245 tcg_gen_shl_tl(t2, t2, t1);
2246 gen_load_gpr(t1, rt);
2247 tcg_gen_andc_tl(t1, t1, t2);
2248 tcg_temp_free(t2);
2249 tcg_gen_or_tl(t0, t0, t1);
2250 tcg_temp_free(t1);
2251 tcg_gen_ext32s_tl(t0, t0);
2252 gen_store_gpr(t0, rt);
2253 break;
2254 case OPC_LWR:
2255 t1 = tcg_temp_new();
2256 /* Do a byte access to possibly trigger a page
2257 fault with the unaligned address. */
2258 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2259 tcg_gen_andi_tl(t1, t0, 3);
2260 #ifdef TARGET_WORDS_BIGENDIAN
2261 tcg_gen_xori_tl(t1, t1, 3);
2262 #endif
2263 tcg_gen_shli_tl(t1, t1, 3);
2264 tcg_gen_andi_tl(t0, t0, ~3);
2265 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2266 tcg_gen_shr_tl(t0, t0, t1);
2267 tcg_gen_xori_tl(t1, t1, 31);
2268 t2 = tcg_const_tl(0xfffffffeull);
2269 tcg_gen_shl_tl(t2, t2, t1);
2270 gen_load_gpr(t1, rt);
2271 tcg_gen_and_tl(t1, t1, t2);
2272 tcg_temp_free(t2);
2273 tcg_gen_or_tl(t0, t0, t1);
2274 tcg_temp_free(t1);
2275 tcg_gen_ext32s_tl(t0, t0);
2276 gen_store_gpr(t0, rt);
2277 break;
2278 case OPC_LL:
2279 case R6_OPC_LL:
2280 op_ld_ll(t0, t0, ctx);
2281 gen_store_gpr(t0, rt);
2282 break;
2284 tcg_temp_free(t0);
2287 /* Store */
2288 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2289 int base, int16_t offset)
2291 TCGv t0 = tcg_temp_new();
2292 TCGv t1 = tcg_temp_new();
2294 gen_base_offset_addr(ctx, t0, base, offset);
2295 gen_load_gpr(t1, rt);
2296 switch (opc) {
2297 #if defined(TARGET_MIPS64)
2298 case OPC_SD:
2299 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
2300 ctx->default_tcg_memop_mask);
2301 break;
2302 case OPC_SDL:
2303 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
2304 break;
2305 case OPC_SDR:
2306 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2307 break;
2308 #endif
2309 case OPC_SW:
2310 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
2311 ctx->default_tcg_memop_mask);
2312 break;
2313 case OPC_SH:
2314 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
2315 ctx->default_tcg_memop_mask);
2316 break;
2317 case OPC_SB:
2318 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2319 break;
2320 case OPC_SWL:
2321 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2322 break;
2323 case OPC_SWR:
2324 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2325 break;
2327 tcg_temp_free(t0);
2328 tcg_temp_free(t1);
2332 /* Store conditional */
2333 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2334 int base, int16_t offset)
2336 TCGv t0, t1;
2338 #ifdef CONFIG_USER_ONLY
2339 t0 = tcg_temp_local_new();
2340 t1 = tcg_temp_local_new();
2341 #else
2342 t0 = tcg_temp_new();
2343 t1 = tcg_temp_new();
2344 #endif
2345 gen_base_offset_addr(ctx, t0, base, offset);
2346 gen_load_gpr(t1, rt);
2347 switch (opc) {
2348 #if defined(TARGET_MIPS64)
2349 case OPC_SCD:
2350 case R6_OPC_SCD:
2351 op_st_scd(t1, t0, rt, ctx);
2352 break;
2353 #endif
2354 case OPC_SC:
2355 case R6_OPC_SC:
2356 op_st_sc(t1, t0, rt, ctx);
2357 break;
2359 tcg_temp_free(t1);
2360 tcg_temp_free(t0);
2363 /* Load and store */
2364 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2365 int base, int16_t offset)
2367 TCGv t0 = tcg_temp_new();
2369 gen_base_offset_addr(ctx, t0, base, offset);
2370 /* Don't do NOP if destination is zero: we must perform the actual
2371 memory access. */
2372 switch (opc) {
2373 case OPC_LWC1:
2375 TCGv_i32 fp0 = tcg_temp_new_i32();
2376 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2377 ctx->default_tcg_memop_mask);
2378 gen_store_fpr32(ctx, fp0, ft);
2379 tcg_temp_free_i32(fp0);
2381 break;
2382 case OPC_SWC1:
2384 TCGv_i32 fp0 = tcg_temp_new_i32();
2385 gen_load_fpr32(ctx, fp0, ft);
2386 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2387 ctx->default_tcg_memop_mask);
2388 tcg_temp_free_i32(fp0);
2390 break;
2391 case OPC_LDC1:
2393 TCGv_i64 fp0 = tcg_temp_new_i64();
2394 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2395 ctx->default_tcg_memop_mask);
2396 gen_store_fpr64(ctx, fp0, ft);
2397 tcg_temp_free_i64(fp0);
2399 break;
2400 case OPC_SDC1:
2402 TCGv_i64 fp0 = tcg_temp_new_i64();
2403 gen_load_fpr64(ctx, fp0, ft);
2404 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2405 ctx->default_tcg_memop_mask);
2406 tcg_temp_free_i64(fp0);
2408 break;
2409 default:
2410 MIPS_INVAL("flt_ldst");
2411 generate_exception_end(ctx, EXCP_RI);
2412 goto out;
2414 out:
2415 tcg_temp_free(t0);
2418 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2419 int rs, int16_t imm)
2421 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2422 check_cp1_enabled(ctx);
2423 switch (op) {
2424 case OPC_LDC1:
2425 case OPC_SDC1:
2426 check_insn(ctx, ISA_MIPS2);
2427 /* Fallthrough */
2428 default:
2429 gen_flt_ldst(ctx, op, rt, rs, imm);
2431 } else {
2432 generate_exception_err(ctx, EXCP_CpU, 1);
2436 /* Arithmetic with immediate operand */
2437 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2438 int rt, int rs, int16_t imm)
2440 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2442 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2443 /* If no destination, treat it as a NOP.
2444 For addi, we must generate the overflow exception when needed. */
2445 return;
2447 switch (opc) {
2448 case OPC_ADDI:
2450 TCGv t0 = tcg_temp_local_new();
2451 TCGv t1 = tcg_temp_new();
2452 TCGv t2 = tcg_temp_new();
2453 TCGLabel *l1 = gen_new_label();
2455 gen_load_gpr(t1, rs);
2456 tcg_gen_addi_tl(t0, t1, uimm);
2457 tcg_gen_ext32s_tl(t0, t0);
2459 tcg_gen_xori_tl(t1, t1, ~uimm);
2460 tcg_gen_xori_tl(t2, t0, uimm);
2461 tcg_gen_and_tl(t1, t1, t2);
2462 tcg_temp_free(t2);
2463 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2464 tcg_temp_free(t1);
2465 /* operands of same sign, result different sign */
2466 generate_exception(ctx, EXCP_OVERFLOW);
2467 gen_set_label(l1);
2468 tcg_gen_ext32s_tl(t0, t0);
2469 gen_store_gpr(t0, rt);
2470 tcg_temp_free(t0);
2472 break;
2473 case OPC_ADDIU:
2474 if (rs != 0) {
2475 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2476 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2477 } else {
2478 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2480 break;
2481 #if defined(TARGET_MIPS64)
2482 case OPC_DADDI:
2484 TCGv t0 = tcg_temp_local_new();
2485 TCGv t1 = tcg_temp_new();
2486 TCGv t2 = tcg_temp_new();
2487 TCGLabel *l1 = gen_new_label();
2489 gen_load_gpr(t1, rs);
2490 tcg_gen_addi_tl(t0, t1, uimm);
2492 tcg_gen_xori_tl(t1, t1, ~uimm);
2493 tcg_gen_xori_tl(t2, t0, uimm);
2494 tcg_gen_and_tl(t1, t1, t2);
2495 tcg_temp_free(t2);
2496 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2497 tcg_temp_free(t1);
2498 /* operands of same sign, result different sign */
2499 generate_exception(ctx, EXCP_OVERFLOW);
2500 gen_set_label(l1);
2501 gen_store_gpr(t0, rt);
2502 tcg_temp_free(t0);
2504 break;
2505 case OPC_DADDIU:
2506 if (rs != 0) {
2507 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2508 } else {
2509 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2511 break;
2512 #endif
2516 /* Logic with immediate operand */
2517 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2518 int rt, int rs, int16_t imm)
2520 target_ulong uimm;
2522 if (rt == 0) {
2523 /* If no destination, treat it as a NOP. */
2524 return;
2526 uimm = (uint16_t)imm;
2527 switch (opc) {
2528 case OPC_ANDI:
2529 if (likely(rs != 0))
2530 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2531 else
2532 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2533 break;
2534 case OPC_ORI:
2535 if (rs != 0)
2536 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2537 else
2538 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2539 break;
2540 case OPC_XORI:
2541 if (likely(rs != 0))
2542 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2543 else
2544 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2545 break;
2546 case OPC_LUI:
2547 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2548 /* OPC_AUI */
2549 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2550 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2551 } else {
2552 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2554 break;
2556 default:
2557 break;
2561 /* Set on less than with immediate operand */
2562 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2563 int rt, int rs, int16_t imm)
2565 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2566 TCGv t0;
2568 if (rt == 0) {
2569 /* If no destination, treat it as a NOP. */
2570 return;
2572 t0 = tcg_temp_new();
2573 gen_load_gpr(t0, rs);
2574 switch (opc) {
2575 case OPC_SLTI:
2576 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2577 break;
2578 case OPC_SLTIU:
2579 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2580 break;
2582 tcg_temp_free(t0);
2585 /* Shifts with immediate operand */
2586 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2587 int rt, int rs, int16_t imm)
2589 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2590 TCGv t0;
2592 if (rt == 0) {
2593 /* If no destination, treat it as a NOP. */
2594 return;
2597 t0 = tcg_temp_new();
2598 gen_load_gpr(t0, rs);
2599 switch (opc) {
2600 case OPC_SLL:
2601 tcg_gen_shli_tl(t0, t0, uimm);
2602 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2603 break;
2604 case OPC_SRA:
2605 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2606 break;
2607 case OPC_SRL:
2608 if (uimm != 0) {
2609 tcg_gen_ext32u_tl(t0, t0);
2610 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2611 } else {
2612 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2614 break;
2615 case OPC_ROTR:
2616 if (uimm != 0) {
2617 TCGv_i32 t1 = tcg_temp_new_i32();
2619 tcg_gen_trunc_tl_i32(t1, t0);
2620 tcg_gen_rotri_i32(t1, t1, uimm);
2621 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2622 tcg_temp_free_i32(t1);
2623 } else {
2624 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2626 break;
2627 #if defined(TARGET_MIPS64)
2628 case OPC_DSLL:
2629 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2630 break;
2631 case OPC_DSRA:
2632 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2633 break;
2634 case OPC_DSRL:
2635 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2636 break;
2637 case OPC_DROTR:
2638 if (uimm != 0) {
2639 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2640 } else {
2641 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2643 break;
2644 case OPC_DSLL32:
2645 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2646 break;
2647 case OPC_DSRA32:
2648 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2649 break;
2650 case OPC_DSRL32:
2651 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2652 break;
2653 case OPC_DROTR32:
2654 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2655 break;
2656 #endif
2658 tcg_temp_free(t0);
2661 /* Arithmetic */
2662 static void gen_arith(DisasContext *ctx, uint32_t opc,
2663 int rd, int rs, int rt)
2665 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2666 && opc != OPC_DADD && opc != OPC_DSUB) {
2667 /* If no destination, treat it as a NOP.
2668 For add & sub, we must generate the overflow exception when needed. */
2669 return;
2672 switch (opc) {
2673 case OPC_ADD:
2675 TCGv t0 = tcg_temp_local_new();
2676 TCGv t1 = tcg_temp_new();
2677 TCGv t2 = tcg_temp_new();
2678 TCGLabel *l1 = gen_new_label();
2680 gen_load_gpr(t1, rs);
2681 gen_load_gpr(t2, rt);
2682 tcg_gen_add_tl(t0, t1, t2);
2683 tcg_gen_ext32s_tl(t0, t0);
2684 tcg_gen_xor_tl(t1, t1, t2);
2685 tcg_gen_xor_tl(t2, t0, t2);
2686 tcg_gen_andc_tl(t1, t2, t1);
2687 tcg_temp_free(t2);
2688 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2689 tcg_temp_free(t1);
2690 /* operands of same sign, result different sign */
2691 generate_exception(ctx, EXCP_OVERFLOW);
2692 gen_set_label(l1);
2693 gen_store_gpr(t0, rd);
2694 tcg_temp_free(t0);
2696 break;
2697 case OPC_ADDU:
2698 if (rs != 0 && rt != 0) {
2699 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2700 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2701 } else if (rs == 0 && rt != 0) {
2702 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2703 } else if (rs != 0 && rt == 0) {
2704 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2705 } else {
2706 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2708 break;
2709 case OPC_SUB:
2711 TCGv t0 = tcg_temp_local_new();
2712 TCGv t1 = tcg_temp_new();
2713 TCGv t2 = tcg_temp_new();
2714 TCGLabel *l1 = gen_new_label();
2716 gen_load_gpr(t1, rs);
2717 gen_load_gpr(t2, rt);
2718 tcg_gen_sub_tl(t0, t1, t2);
2719 tcg_gen_ext32s_tl(t0, t0);
2720 tcg_gen_xor_tl(t2, t1, t2);
2721 tcg_gen_xor_tl(t1, t0, t1);
2722 tcg_gen_and_tl(t1, t1, t2);
2723 tcg_temp_free(t2);
2724 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2725 tcg_temp_free(t1);
2726 /* operands of different sign, first operand and result different sign */
2727 generate_exception(ctx, EXCP_OVERFLOW);
2728 gen_set_label(l1);
2729 gen_store_gpr(t0, rd);
2730 tcg_temp_free(t0);
2732 break;
2733 case OPC_SUBU:
2734 if (rs != 0 && rt != 0) {
2735 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2736 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2737 } else if (rs == 0 && rt != 0) {
2738 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2739 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2740 } else if (rs != 0 && rt == 0) {
2741 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2742 } else {
2743 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2745 break;
2746 #if defined(TARGET_MIPS64)
2747 case OPC_DADD:
2749 TCGv t0 = tcg_temp_local_new();
2750 TCGv t1 = tcg_temp_new();
2751 TCGv t2 = tcg_temp_new();
2752 TCGLabel *l1 = gen_new_label();
2754 gen_load_gpr(t1, rs);
2755 gen_load_gpr(t2, rt);
2756 tcg_gen_add_tl(t0, t1, t2);
2757 tcg_gen_xor_tl(t1, t1, t2);
2758 tcg_gen_xor_tl(t2, t0, t2);
2759 tcg_gen_andc_tl(t1, t2, t1);
2760 tcg_temp_free(t2);
2761 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2762 tcg_temp_free(t1);
2763 /* operands of same sign, result different sign */
2764 generate_exception(ctx, EXCP_OVERFLOW);
2765 gen_set_label(l1);
2766 gen_store_gpr(t0, rd);
2767 tcg_temp_free(t0);
2769 break;
2770 case OPC_DADDU:
2771 if (rs != 0 && rt != 0) {
2772 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2773 } else if (rs == 0 && rt != 0) {
2774 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2775 } else if (rs != 0 && rt == 0) {
2776 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2777 } else {
2778 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2780 break;
2781 case OPC_DSUB:
2783 TCGv t0 = tcg_temp_local_new();
2784 TCGv t1 = tcg_temp_new();
2785 TCGv t2 = tcg_temp_new();
2786 TCGLabel *l1 = gen_new_label();
2788 gen_load_gpr(t1, rs);
2789 gen_load_gpr(t2, rt);
2790 tcg_gen_sub_tl(t0, t1, t2);
2791 tcg_gen_xor_tl(t2, t1, t2);
2792 tcg_gen_xor_tl(t1, t0, t1);
2793 tcg_gen_and_tl(t1, t1, t2);
2794 tcg_temp_free(t2);
2795 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2796 tcg_temp_free(t1);
2797 /* operands of different sign, first operand and result different sign */
2798 generate_exception(ctx, EXCP_OVERFLOW);
2799 gen_set_label(l1);
2800 gen_store_gpr(t0, rd);
2801 tcg_temp_free(t0);
2803 break;
2804 case OPC_DSUBU:
2805 if (rs != 0 && rt != 0) {
2806 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2807 } else if (rs == 0 && rt != 0) {
2808 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2809 } else if (rs != 0 && rt == 0) {
2810 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2811 } else {
2812 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2814 break;
2815 #endif
2816 case OPC_MUL:
2817 if (likely(rs != 0 && rt != 0)) {
2818 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2819 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2820 } else {
2821 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2823 break;
2827 /* Conditional move */
2828 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2829 int rd, int rs, int rt)
2831 TCGv t0, t1, t2;
2833 if (rd == 0) {
2834 /* If no destination, treat it as a NOP. */
2835 return;
2838 t0 = tcg_temp_new();
2839 gen_load_gpr(t0, rt);
2840 t1 = tcg_const_tl(0);
2841 t2 = tcg_temp_new();
2842 gen_load_gpr(t2, rs);
2843 switch (opc) {
2844 case OPC_MOVN:
2845 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2846 break;
2847 case OPC_MOVZ:
2848 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2849 break;
2850 case OPC_SELNEZ:
2851 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2852 break;
2853 case OPC_SELEQZ:
2854 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2855 break;
2857 tcg_temp_free(t2);
2858 tcg_temp_free(t1);
2859 tcg_temp_free(t0);
2862 /* Logic */
2863 static void gen_logic(DisasContext *ctx, uint32_t opc,
2864 int rd, int rs, int rt)
2866 if (rd == 0) {
2867 /* If no destination, treat it as a NOP. */
2868 return;
2871 switch (opc) {
2872 case OPC_AND:
2873 if (likely(rs != 0 && rt != 0)) {
2874 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2875 } else {
2876 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2878 break;
2879 case OPC_NOR:
2880 if (rs != 0 && rt != 0) {
2881 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2882 } else if (rs == 0 && rt != 0) {
2883 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2884 } else if (rs != 0 && rt == 0) {
2885 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2886 } else {
2887 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2889 break;
2890 case OPC_OR:
2891 if (likely(rs != 0 && rt != 0)) {
2892 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2893 } else if (rs == 0 && rt != 0) {
2894 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2895 } else if (rs != 0 && rt == 0) {
2896 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2897 } else {
2898 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2900 break;
2901 case OPC_XOR:
2902 if (likely(rs != 0 && rt != 0)) {
2903 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2904 } else if (rs == 0 && rt != 0) {
2905 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2906 } else if (rs != 0 && rt == 0) {
2907 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2908 } else {
2909 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2911 break;
2915 /* Set on lower than */
2916 static void gen_slt(DisasContext *ctx, uint32_t opc,
2917 int rd, int rs, int rt)
2919 TCGv t0, t1;
2921 if (rd == 0) {
2922 /* If no destination, treat it as a NOP. */
2923 return;
2926 t0 = tcg_temp_new();
2927 t1 = tcg_temp_new();
2928 gen_load_gpr(t0, rs);
2929 gen_load_gpr(t1, rt);
2930 switch (opc) {
2931 case OPC_SLT:
2932 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2933 break;
2934 case OPC_SLTU:
2935 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2936 break;
2938 tcg_temp_free(t0);
2939 tcg_temp_free(t1);
2942 /* Shifts */
2943 static void gen_shift(DisasContext *ctx, uint32_t opc,
2944 int rd, int rs, int rt)
2946 TCGv t0, t1;
2948 if (rd == 0) {
2949 /* If no destination, treat it as a NOP.
2950 For add & sub, we must generate the overflow exception when needed. */
2951 return;
2954 t0 = tcg_temp_new();
2955 t1 = tcg_temp_new();
2956 gen_load_gpr(t0, rs);
2957 gen_load_gpr(t1, rt);
2958 switch (opc) {
2959 case OPC_SLLV:
2960 tcg_gen_andi_tl(t0, t0, 0x1f);
2961 tcg_gen_shl_tl(t0, t1, t0);
2962 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2963 break;
2964 case OPC_SRAV:
2965 tcg_gen_andi_tl(t0, t0, 0x1f);
2966 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2967 break;
2968 case OPC_SRLV:
2969 tcg_gen_ext32u_tl(t1, t1);
2970 tcg_gen_andi_tl(t0, t0, 0x1f);
2971 tcg_gen_shr_tl(t0, t1, t0);
2972 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2973 break;
2974 case OPC_ROTRV:
2976 TCGv_i32 t2 = tcg_temp_new_i32();
2977 TCGv_i32 t3 = tcg_temp_new_i32();
2979 tcg_gen_trunc_tl_i32(t2, t0);
2980 tcg_gen_trunc_tl_i32(t3, t1);
2981 tcg_gen_andi_i32(t2, t2, 0x1f);
2982 tcg_gen_rotr_i32(t2, t3, t2);
2983 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2984 tcg_temp_free_i32(t2);
2985 tcg_temp_free_i32(t3);
2987 break;
2988 #if defined(TARGET_MIPS64)
2989 case OPC_DSLLV:
2990 tcg_gen_andi_tl(t0, t0, 0x3f);
2991 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2992 break;
2993 case OPC_DSRAV:
2994 tcg_gen_andi_tl(t0, t0, 0x3f);
2995 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2996 break;
2997 case OPC_DSRLV:
2998 tcg_gen_andi_tl(t0, t0, 0x3f);
2999 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3000 break;
3001 case OPC_DROTRV:
3002 tcg_gen_andi_tl(t0, t0, 0x3f);
3003 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3004 break;
3005 #endif
3007 tcg_temp_free(t0);
3008 tcg_temp_free(t1);
3011 /* Arithmetic on HI/LO registers */
3012 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3014 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3015 /* Treat as NOP. */
3016 return;
3019 if (acc != 0) {
3020 check_dsp(ctx);
3023 switch (opc) {
3024 case OPC_MFHI:
3025 #if defined(TARGET_MIPS64)
3026 if (acc != 0) {
3027 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3028 } else
3029 #endif
3031 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3033 break;
3034 case OPC_MFLO:
3035 #if defined(TARGET_MIPS64)
3036 if (acc != 0) {
3037 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3038 } else
3039 #endif
3041 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3043 break;
3044 case OPC_MTHI:
3045 if (reg != 0) {
3046 #if defined(TARGET_MIPS64)
3047 if (acc != 0) {
3048 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3049 } else
3050 #endif
3052 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3054 } else {
3055 tcg_gen_movi_tl(cpu_HI[acc], 0);
3057 break;
3058 case OPC_MTLO:
3059 if (reg != 0) {
3060 #if defined(TARGET_MIPS64)
3061 if (acc != 0) {
3062 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3063 } else
3064 #endif
3066 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3068 } else {
3069 tcg_gen_movi_tl(cpu_LO[acc], 0);
3071 break;
3075 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3076 TCGMemOp memop)
3078 TCGv t0 = tcg_const_tl(addr);
3079 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3080 gen_store_gpr(t0, reg);
3081 tcg_temp_free(t0);
3084 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3085 int rs)
3087 target_long offset;
3088 target_long addr;
3090 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3091 case OPC_ADDIUPC:
3092 if (rs != 0) {
3093 offset = sextract32(ctx->opcode << 2, 0, 21);
3094 addr = addr_add(ctx, pc, offset);
3095 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3097 break;
3098 case R6_OPC_LWPC:
3099 offset = sextract32(ctx->opcode << 2, 0, 21);
3100 addr = addr_add(ctx, pc, offset);
3101 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3102 break;
3103 #if defined(TARGET_MIPS64)
3104 case OPC_LWUPC:
3105 check_mips_64(ctx);
3106 offset = sextract32(ctx->opcode << 2, 0, 21);
3107 addr = addr_add(ctx, pc, offset);
3108 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3109 break;
3110 #endif
3111 default:
3112 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3113 case OPC_AUIPC:
3114 if (rs != 0) {
3115 offset = sextract32(ctx->opcode, 0, 16) << 16;
3116 addr = addr_add(ctx, pc, offset);
3117 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3119 break;
3120 case OPC_ALUIPC:
3121 if (rs != 0) {
3122 offset = sextract32(ctx->opcode, 0, 16) << 16;
3123 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3124 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3126 break;
3127 #if defined(TARGET_MIPS64)
3128 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3129 case R6_OPC_LDPC + (1 << 16):
3130 case R6_OPC_LDPC + (2 << 16):
3131 case R6_OPC_LDPC + (3 << 16):
3132 check_mips_64(ctx);
3133 offset = sextract32(ctx->opcode << 3, 0, 21);
3134 addr = addr_add(ctx, (pc & ~0x7), offset);
3135 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3136 break;
3137 #endif
3138 default:
3139 MIPS_INVAL("OPC_PCREL");
3140 generate_exception_end(ctx, EXCP_RI);
3141 break;
3143 break;
3147 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3149 TCGv t0, t1;
3151 if (rd == 0) {
3152 /* Treat as NOP. */
3153 return;
3156 t0 = tcg_temp_new();
3157 t1 = tcg_temp_new();
3159 gen_load_gpr(t0, rs);
3160 gen_load_gpr(t1, rt);
3162 switch (opc) {
3163 case R6_OPC_DIV:
3165 TCGv t2 = tcg_temp_new();
3166 TCGv t3 = tcg_temp_new();
3167 tcg_gen_ext32s_tl(t0, t0);
3168 tcg_gen_ext32s_tl(t1, t1);
3169 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3170 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3171 tcg_gen_and_tl(t2, t2, t3);
3172 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3173 tcg_gen_or_tl(t2, t2, t3);
3174 tcg_gen_movi_tl(t3, 0);
3175 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3176 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3177 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3178 tcg_temp_free(t3);
3179 tcg_temp_free(t2);
3181 break;
3182 case R6_OPC_MOD:
3184 TCGv t2 = tcg_temp_new();
3185 TCGv t3 = tcg_temp_new();
3186 tcg_gen_ext32s_tl(t0, t0);
3187 tcg_gen_ext32s_tl(t1, t1);
3188 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3189 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3190 tcg_gen_and_tl(t2, t2, t3);
3191 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3192 tcg_gen_or_tl(t2, t2, t3);
3193 tcg_gen_movi_tl(t3, 0);
3194 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3195 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3196 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3197 tcg_temp_free(t3);
3198 tcg_temp_free(t2);
3200 break;
3201 case R6_OPC_DIVU:
3203 TCGv t2 = tcg_const_tl(0);
3204 TCGv t3 = tcg_const_tl(1);
3205 tcg_gen_ext32u_tl(t0, t0);
3206 tcg_gen_ext32u_tl(t1, t1);
3207 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3208 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3209 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3210 tcg_temp_free(t3);
3211 tcg_temp_free(t2);
3213 break;
3214 case R6_OPC_MODU:
3216 TCGv t2 = tcg_const_tl(0);
3217 TCGv t3 = tcg_const_tl(1);
3218 tcg_gen_ext32u_tl(t0, t0);
3219 tcg_gen_ext32u_tl(t1, t1);
3220 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3221 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3222 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3223 tcg_temp_free(t3);
3224 tcg_temp_free(t2);
3226 break;
3227 case R6_OPC_MUL:
3229 TCGv_i32 t2 = tcg_temp_new_i32();
3230 TCGv_i32 t3 = tcg_temp_new_i32();
3231 tcg_gen_trunc_tl_i32(t2, t0);
3232 tcg_gen_trunc_tl_i32(t3, t1);
3233 tcg_gen_mul_i32(t2, t2, t3);
3234 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3235 tcg_temp_free_i32(t2);
3236 tcg_temp_free_i32(t3);
3238 break;
3239 case R6_OPC_MUH:
3241 TCGv_i32 t2 = tcg_temp_new_i32();
3242 TCGv_i32 t3 = tcg_temp_new_i32();
3243 tcg_gen_trunc_tl_i32(t2, t0);
3244 tcg_gen_trunc_tl_i32(t3, t1);
3245 tcg_gen_muls2_i32(t2, t3, t2, t3);
3246 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3247 tcg_temp_free_i32(t2);
3248 tcg_temp_free_i32(t3);
3250 break;
3251 case R6_OPC_MULU:
3253 TCGv_i32 t2 = tcg_temp_new_i32();
3254 TCGv_i32 t3 = tcg_temp_new_i32();
3255 tcg_gen_trunc_tl_i32(t2, t0);
3256 tcg_gen_trunc_tl_i32(t3, t1);
3257 tcg_gen_mul_i32(t2, t2, t3);
3258 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3259 tcg_temp_free_i32(t2);
3260 tcg_temp_free_i32(t3);
3262 break;
3263 case R6_OPC_MUHU:
3265 TCGv_i32 t2 = tcg_temp_new_i32();
3266 TCGv_i32 t3 = tcg_temp_new_i32();
3267 tcg_gen_trunc_tl_i32(t2, t0);
3268 tcg_gen_trunc_tl_i32(t3, t1);
3269 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3270 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3271 tcg_temp_free_i32(t2);
3272 tcg_temp_free_i32(t3);
3274 break;
3275 #if defined(TARGET_MIPS64)
3276 case R6_OPC_DDIV:
3278 TCGv t2 = tcg_temp_new();
3279 TCGv t3 = tcg_temp_new();
3280 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3281 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3282 tcg_gen_and_tl(t2, t2, t3);
3283 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3284 tcg_gen_or_tl(t2, t2, t3);
3285 tcg_gen_movi_tl(t3, 0);
3286 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3287 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3288 tcg_temp_free(t3);
3289 tcg_temp_free(t2);
3291 break;
3292 case R6_OPC_DMOD:
3294 TCGv t2 = tcg_temp_new();
3295 TCGv t3 = tcg_temp_new();
3296 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3297 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3298 tcg_gen_and_tl(t2, t2, t3);
3299 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3300 tcg_gen_or_tl(t2, t2, t3);
3301 tcg_gen_movi_tl(t3, 0);
3302 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3303 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3304 tcg_temp_free(t3);
3305 tcg_temp_free(t2);
3307 break;
3308 case R6_OPC_DDIVU:
3310 TCGv t2 = tcg_const_tl(0);
3311 TCGv t3 = tcg_const_tl(1);
3312 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3313 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3314 tcg_temp_free(t3);
3315 tcg_temp_free(t2);
3317 break;
3318 case R6_OPC_DMODU:
3320 TCGv t2 = tcg_const_tl(0);
3321 TCGv t3 = tcg_const_tl(1);
3322 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3323 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3324 tcg_temp_free(t3);
3325 tcg_temp_free(t2);
3327 break;
3328 case R6_OPC_DMUL:
3329 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3330 break;
3331 case R6_OPC_DMUH:
3333 TCGv t2 = tcg_temp_new();
3334 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3335 tcg_temp_free(t2);
3337 break;
3338 case R6_OPC_DMULU:
3339 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3340 break;
3341 case R6_OPC_DMUHU:
3343 TCGv t2 = tcg_temp_new();
3344 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3345 tcg_temp_free(t2);
3347 break;
3348 #endif
3349 default:
3350 MIPS_INVAL("r6 mul/div");
3351 generate_exception_end(ctx, EXCP_RI);
3352 goto out;
3354 out:
3355 tcg_temp_free(t0);
3356 tcg_temp_free(t1);
3359 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3360 int acc, int rs, int rt)
3362 TCGv t0, t1;
3364 t0 = tcg_temp_new();
3365 t1 = tcg_temp_new();
3367 gen_load_gpr(t0, rs);
3368 gen_load_gpr(t1, rt);
3370 if (acc != 0) {
3371 check_dsp(ctx);
3374 switch (opc) {
3375 case OPC_DIV:
3377 TCGv t2 = tcg_temp_new();
3378 TCGv t3 = tcg_temp_new();
3379 tcg_gen_ext32s_tl(t0, t0);
3380 tcg_gen_ext32s_tl(t1, t1);
3381 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3382 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3383 tcg_gen_and_tl(t2, t2, t3);
3384 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3385 tcg_gen_or_tl(t2, t2, t3);
3386 tcg_gen_movi_tl(t3, 0);
3387 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3388 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3389 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3390 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3391 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3392 tcg_temp_free(t3);
3393 tcg_temp_free(t2);
3395 break;
3396 case OPC_DIVU:
3398 TCGv t2 = tcg_const_tl(0);
3399 TCGv t3 = tcg_const_tl(1);
3400 tcg_gen_ext32u_tl(t0, t0);
3401 tcg_gen_ext32u_tl(t1, t1);
3402 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3403 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3404 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3405 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3406 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3407 tcg_temp_free(t3);
3408 tcg_temp_free(t2);
3410 break;
3411 case OPC_MULT:
3413 TCGv_i32 t2 = tcg_temp_new_i32();
3414 TCGv_i32 t3 = tcg_temp_new_i32();
3415 tcg_gen_trunc_tl_i32(t2, t0);
3416 tcg_gen_trunc_tl_i32(t3, t1);
3417 tcg_gen_muls2_i32(t2, t3, t2, t3);
3418 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3419 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3420 tcg_temp_free_i32(t2);
3421 tcg_temp_free_i32(t3);
3423 break;
3424 case OPC_MULTU:
3426 TCGv_i32 t2 = tcg_temp_new_i32();
3427 TCGv_i32 t3 = tcg_temp_new_i32();
3428 tcg_gen_trunc_tl_i32(t2, t0);
3429 tcg_gen_trunc_tl_i32(t3, t1);
3430 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3431 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3432 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3433 tcg_temp_free_i32(t2);
3434 tcg_temp_free_i32(t3);
3436 break;
3437 #if defined(TARGET_MIPS64)
3438 case OPC_DDIV:
3440 TCGv t2 = tcg_temp_new();
3441 TCGv t3 = tcg_temp_new();
3442 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3443 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3444 tcg_gen_and_tl(t2, t2, t3);
3445 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3446 tcg_gen_or_tl(t2, t2, t3);
3447 tcg_gen_movi_tl(t3, 0);
3448 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3449 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3450 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3451 tcg_temp_free(t3);
3452 tcg_temp_free(t2);
3454 break;
3455 case OPC_DDIVU:
3457 TCGv t2 = tcg_const_tl(0);
3458 TCGv t3 = tcg_const_tl(1);
3459 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3460 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3461 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3462 tcg_temp_free(t3);
3463 tcg_temp_free(t2);
3465 break;
3466 case OPC_DMULT:
3467 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3468 break;
3469 case OPC_DMULTU:
3470 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3471 break;
3472 #endif
3473 case OPC_MADD:
3475 TCGv_i64 t2 = tcg_temp_new_i64();
3476 TCGv_i64 t3 = tcg_temp_new_i64();
3478 tcg_gen_ext_tl_i64(t2, t0);
3479 tcg_gen_ext_tl_i64(t3, t1);
3480 tcg_gen_mul_i64(t2, t2, t3);
3481 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3482 tcg_gen_add_i64(t2, t2, t3);
3483 tcg_temp_free_i64(t3);
3484 gen_move_low32(cpu_LO[acc], t2);
3485 gen_move_high32(cpu_HI[acc], t2);
3486 tcg_temp_free_i64(t2);
3488 break;
3489 case OPC_MADDU:
3491 TCGv_i64 t2 = tcg_temp_new_i64();
3492 TCGv_i64 t3 = tcg_temp_new_i64();
3494 tcg_gen_ext32u_tl(t0, t0);
3495 tcg_gen_ext32u_tl(t1, t1);
3496 tcg_gen_extu_tl_i64(t2, t0);
3497 tcg_gen_extu_tl_i64(t3, t1);
3498 tcg_gen_mul_i64(t2, t2, t3);
3499 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3500 tcg_gen_add_i64(t2, t2, t3);
3501 tcg_temp_free_i64(t3);
3502 gen_move_low32(cpu_LO[acc], t2);
3503 gen_move_high32(cpu_HI[acc], t2);
3504 tcg_temp_free_i64(t2);
3506 break;
3507 case OPC_MSUB:
3509 TCGv_i64 t2 = tcg_temp_new_i64();
3510 TCGv_i64 t3 = tcg_temp_new_i64();
3512 tcg_gen_ext_tl_i64(t2, t0);
3513 tcg_gen_ext_tl_i64(t3, t1);
3514 tcg_gen_mul_i64(t2, t2, t3);
3515 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3516 tcg_gen_sub_i64(t2, t3, t2);
3517 tcg_temp_free_i64(t3);
3518 gen_move_low32(cpu_LO[acc], t2);
3519 gen_move_high32(cpu_HI[acc], t2);
3520 tcg_temp_free_i64(t2);
3522 break;
3523 case OPC_MSUBU:
3525 TCGv_i64 t2 = tcg_temp_new_i64();
3526 TCGv_i64 t3 = tcg_temp_new_i64();
3528 tcg_gen_ext32u_tl(t0, t0);
3529 tcg_gen_ext32u_tl(t1, t1);
3530 tcg_gen_extu_tl_i64(t2, t0);
3531 tcg_gen_extu_tl_i64(t3, t1);
3532 tcg_gen_mul_i64(t2, t2, t3);
3533 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3534 tcg_gen_sub_i64(t2, t3, t2);
3535 tcg_temp_free_i64(t3);
3536 gen_move_low32(cpu_LO[acc], t2);
3537 gen_move_high32(cpu_HI[acc], t2);
3538 tcg_temp_free_i64(t2);
3540 break;
3541 default:
3542 MIPS_INVAL("mul/div");
3543 generate_exception_end(ctx, EXCP_RI);
3544 goto out;
3546 out:
3547 tcg_temp_free(t0);
3548 tcg_temp_free(t1);
3551 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3552 int rd, int rs, int rt)
3554 TCGv t0 = tcg_temp_new();
3555 TCGv t1 = tcg_temp_new();
3557 gen_load_gpr(t0, rs);
3558 gen_load_gpr(t1, rt);
3560 switch (opc) {
3561 case OPC_VR54XX_MULS:
3562 gen_helper_muls(t0, cpu_env, t0, t1);
3563 break;
3564 case OPC_VR54XX_MULSU:
3565 gen_helper_mulsu(t0, cpu_env, t0, t1);
3566 break;
3567 case OPC_VR54XX_MACC:
3568 gen_helper_macc(t0, cpu_env, t0, t1);
3569 break;
3570 case OPC_VR54XX_MACCU:
3571 gen_helper_maccu(t0, cpu_env, t0, t1);
3572 break;
3573 case OPC_VR54XX_MSAC:
3574 gen_helper_msac(t0, cpu_env, t0, t1);
3575 break;
3576 case OPC_VR54XX_MSACU:
3577 gen_helper_msacu(t0, cpu_env, t0, t1);
3578 break;
3579 case OPC_VR54XX_MULHI:
3580 gen_helper_mulhi(t0, cpu_env, t0, t1);
3581 break;
3582 case OPC_VR54XX_MULHIU:
3583 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3584 break;
3585 case OPC_VR54XX_MULSHI:
3586 gen_helper_mulshi(t0, cpu_env, t0, t1);
3587 break;
3588 case OPC_VR54XX_MULSHIU:
3589 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3590 break;
3591 case OPC_VR54XX_MACCHI:
3592 gen_helper_macchi(t0, cpu_env, t0, t1);
3593 break;
3594 case OPC_VR54XX_MACCHIU:
3595 gen_helper_macchiu(t0, cpu_env, t0, t1);
3596 break;
3597 case OPC_VR54XX_MSACHI:
3598 gen_helper_msachi(t0, cpu_env, t0, t1);
3599 break;
3600 case OPC_VR54XX_MSACHIU:
3601 gen_helper_msachiu(t0, cpu_env, t0, t1);
3602 break;
3603 default:
3604 MIPS_INVAL("mul vr54xx");
3605 generate_exception_end(ctx, EXCP_RI);
3606 goto out;
3608 gen_store_gpr(t0, rd);
3610 out:
3611 tcg_temp_free(t0);
3612 tcg_temp_free(t1);
3615 static void gen_cl (DisasContext *ctx, uint32_t opc,
3616 int rd, int rs)
3618 TCGv t0;
3620 if (rd == 0) {
3621 /* Treat as NOP. */
3622 return;
3624 t0 = tcg_temp_new();
3625 gen_load_gpr(t0, rs);
3626 switch (opc) {
3627 case OPC_CLO:
3628 case R6_OPC_CLO:
3629 gen_helper_clo(cpu_gpr[rd], t0);
3630 break;
3631 case OPC_CLZ:
3632 case R6_OPC_CLZ:
3633 gen_helper_clz(cpu_gpr[rd], t0);
3634 break;
3635 #if defined(TARGET_MIPS64)
3636 case OPC_DCLO:
3637 case R6_OPC_DCLO:
3638 gen_helper_dclo(cpu_gpr[rd], t0);
3639 break;
3640 case OPC_DCLZ:
3641 case R6_OPC_DCLZ:
3642 gen_helper_dclz(cpu_gpr[rd], t0);
3643 break;
3644 #endif
3646 tcg_temp_free(t0);
3649 /* Godson integer instructions */
3650 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3651 int rd, int rs, int rt)
3653 TCGv t0, t1;
3655 if (rd == 0) {
3656 /* Treat as NOP. */
3657 return;
3660 switch (opc) {
3661 case OPC_MULT_G_2E:
3662 case OPC_MULT_G_2F:
3663 case OPC_MULTU_G_2E:
3664 case OPC_MULTU_G_2F:
3665 #if defined(TARGET_MIPS64)
3666 case OPC_DMULT_G_2E:
3667 case OPC_DMULT_G_2F:
3668 case OPC_DMULTU_G_2E:
3669 case OPC_DMULTU_G_2F:
3670 #endif
3671 t0 = tcg_temp_new();
3672 t1 = tcg_temp_new();
3673 break;
3674 default:
3675 t0 = tcg_temp_local_new();
3676 t1 = tcg_temp_local_new();
3677 break;
3680 gen_load_gpr(t0, rs);
3681 gen_load_gpr(t1, rt);
3683 switch (opc) {
3684 case OPC_MULT_G_2E:
3685 case OPC_MULT_G_2F:
3686 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3687 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3688 break;
3689 case OPC_MULTU_G_2E:
3690 case OPC_MULTU_G_2F:
3691 tcg_gen_ext32u_tl(t0, t0);
3692 tcg_gen_ext32u_tl(t1, t1);
3693 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3694 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3695 break;
3696 case OPC_DIV_G_2E:
3697 case OPC_DIV_G_2F:
3699 TCGLabel *l1 = gen_new_label();
3700 TCGLabel *l2 = gen_new_label();
3701 TCGLabel *l3 = gen_new_label();
3702 tcg_gen_ext32s_tl(t0, t0);
3703 tcg_gen_ext32s_tl(t1, t1);
3704 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3705 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3706 tcg_gen_br(l3);
3707 gen_set_label(l1);
3708 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3709 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3710 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3711 tcg_gen_br(l3);
3712 gen_set_label(l2);
3713 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3714 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3715 gen_set_label(l3);
3717 break;
3718 case OPC_DIVU_G_2E:
3719 case OPC_DIVU_G_2F:
3721 TCGLabel *l1 = gen_new_label();
3722 TCGLabel *l2 = gen_new_label();
3723 tcg_gen_ext32u_tl(t0, t0);
3724 tcg_gen_ext32u_tl(t1, t1);
3725 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3726 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3727 tcg_gen_br(l2);
3728 gen_set_label(l1);
3729 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3730 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3731 gen_set_label(l2);
3733 break;
3734 case OPC_MOD_G_2E:
3735 case OPC_MOD_G_2F:
3737 TCGLabel *l1 = gen_new_label();
3738 TCGLabel *l2 = gen_new_label();
3739 TCGLabel *l3 = gen_new_label();
3740 tcg_gen_ext32u_tl(t0, t0);
3741 tcg_gen_ext32u_tl(t1, t1);
3742 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3743 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3744 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3745 gen_set_label(l1);
3746 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3747 tcg_gen_br(l3);
3748 gen_set_label(l2);
3749 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3750 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3751 gen_set_label(l3);
3753 break;
3754 case OPC_MODU_G_2E:
3755 case OPC_MODU_G_2F:
3757 TCGLabel *l1 = gen_new_label();
3758 TCGLabel *l2 = gen_new_label();
3759 tcg_gen_ext32u_tl(t0, t0);
3760 tcg_gen_ext32u_tl(t1, t1);
3761 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3762 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3763 tcg_gen_br(l2);
3764 gen_set_label(l1);
3765 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3766 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3767 gen_set_label(l2);
3769 break;
3770 #if defined(TARGET_MIPS64)
3771 case OPC_DMULT_G_2E:
3772 case OPC_DMULT_G_2F:
3773 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3774 break;
3775 case OPC_DMULTU_G_2E:
3776 case OPC_DMULTU_G_2F:
3777 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3778 break;
3779 case OPC_DDIV_G_2E:
3780 case OPC_DDIV_G_2F:
3782 TCGLabel *l1 = gen_new_label();
3783 TCGLabel *l2 = gen_new_label();
3784 TCGLabel *l3 = gen_new_label();
3785 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3786 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3787 tcg_gen_br(l3);
3788 gen_set_label(l1);
3789 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3790 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3791 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3792 tcg_gen_br(l3);
3793 gen_set_label(l2);
3794 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3795 gen_set_label(l3);
3797 break;
3798 case OPC_DDIVU_G_2E:
3799 case OPC_DDIVU_G_2F:
3801 TCGLabel *l1 = gen_new_label();
3802 TCGLabel *l2 = gen_new_label();
3803 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3804 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3805 tcg_gen_br(l2);
3806 gen_set_label(l1);
3807 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3808 gen_set_label(l2);
3810 break;
3811 case OPC_DMOD_G_2E:
3812 case OPC_DMOD_G_2F:
3814 TCGLabel *l1 = gen_new_label();
3815 TCGLabel *l2 = gen_new_label();
3816 TCGLabel *l3 = gen_new_label();
3817 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3818 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3819 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3820 gen_set_label(l1);
3821 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3822 tcg_gen_br(l3);
3823 gen_set_label(l2);
3824 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3825 gen_set_label(l3);
3827 break;
3828 case OPC_DMODU_G_2E:
3829 case OPC_DMODU_G_2F:
3831 TCGLabel *l1 = gen_new_label();
3832 TCGLabel *l2 = gen_new_label();
3833 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3834 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3835 tcg_gen_br(l2);
3836 gen_set_label(l1);
3837 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3838 gen_set_label(l2);
3840 break;
3841 #endif
3844 tcg_temp_free(t0);
3845 tcg_temp_free(t1);
3848 /* Loongson multimedia instructions */
3849 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3851 uint32_t opc, shift_max;
3852 TCGv_i64 t0, t1;
3854 opc = MASK_LMI(ctx->opcode);
3855 switch (opc) {
3856 case OPC_ADD_CP2:
3857 case OPC_SUB_CP2:
3858 case OPC_DADD_CP2:
3859 case OPC_DSUB_CP2:
3860 t0 = tcg_temp_local_new_i64();
3861 t1 = tcg_temp_local_new_i64();
3862 break;
3863 default:
3864 t0 = tcg_temp_new_i64();
3865 t1 = tcg_temp_new_i64();
3866 break;
3869 gen_load_fpr64(ctx, t0, rs);
3870 gen_load_fpr64(ctx, t1, rt);
3872 #define LMI_HELPER(UP, LO) \
3873 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
3874 #define LMI_HELPER_1(UP, LO) \
3875 case OPC_##UP: gen_helper_##LO(t0, t0); break
3876 #define LMI_DIRECT(UP, LO, OP) \
3877 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
3879 switch (opc) {
3880 LMI_HELPER(PADDSH, paddsh);
3881 LMI_HELPER(PADDUSH, paddush);
3882 LMI_HELPER(PADDH, paddh);
3883 LMI_HELPER(PADDW, paddw);
3884 LMI_HELPER(PADDSB, paddsb);
3885 LMI_HELPER(PADDUSB, paddusb);
3886 LMI_HELPER(PADDB, paddb);
3888 LMI_HELPER(PSUBSH, psubsh);
3889 LMI_HELPER(PSUBUSH, psubush);
3890 LMI_HELPER(PSUBH, psubh);
3891 LMI_HELPER(PSUBW, psubw);
3892 LMI_HELPER(PSUBSB, psubsb);
3893 LMI_HELPER(PSUBUSB, psubusb);
3894 LMI_HELPER(PSUBB, psubb);
3896 LMI_HELPER(PSHUFH, pshufh);
3897 LMI_HELPER(PACKSSWH, packsswh);
3898 LMI_HELPER(PACKSSHB, packsshb);
3899 LMI_HELPER(PACKUSHB, packushb);
3901 LMI_HELPER(PUNPCKLHW, punpcklhw);
3902 LMI_HELPER(PUNPCKHHW, punpckhhw);
3903 LMI_HELPER(PUNPCKLBH, punpcklbh);
3904 LMI_HELPER(PUNPCKHBH, punpckhbh);
3905 LMI_HELPER(PUNPCKLWD, punpcklwd);
3906 LMI_HELPER(PUNPCKHWD, punpckhwd);
3908 LMI_HELPER(PAVGH, pavgh);
3909 LMI_HELPER(PAVGB, pavgb);
3910 LMI_HELPER(PMAXSH, pmaxsh);
3911 LMI_HELPER(PMINSH, pminsh);
3912 LMI_HELPER(PMAXUB, pmaxub);
3913 LMI_HELPER(PMINUB, pminub);
3915 LMI_HELPER(PCMPEQW, pcmpeqw);
3916 LMI_HELPER(PCMPGTW, pcmpgtw);
3917 LMI_HELPER(PCMPEQH, pcmpeqh);
3918 LMI_HELPER(PCMPGTH, pcmpgth);
3919 LMI_HELPER(PCMPEQB, pcmpeqb);
3920 LMI_HELPER(PCMPGTB, pcmpgtb);
3922 LMI_HELPER(PSLLW, psllw);
3923 LMI_HELPER(PSLLH, psllh);
3924 LMI_HELPER(PSRLW, psrlw);
3925 LMI_HELPER(PSRLH, psrlh);
3926 LMI_HELPER(PSRAW, psraw);
3927 LMI_HELPER(PSRAH, psrah);
3929 LMI_HELPER(PMULLH, pmullh);
3930 LMI_HELPER(PMULHH, pmulhh);
3931 LMI_HELPER(PMULHUH, pmulhuh);
3932 LMI_HELPER(PMADDHW, pmaddhw);
3934 LMI_HELPER(PASUBUB, pasubub);
3935 LMI_HELPER_1(BIADD, biadd);
3936 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3938 LMI_DIRECT(PADDD, paddd, add);
3939 LMI_DIRECT(PSUBD, psubd, sub);
3940 LMI_DIRECT(XOR_CP2, xor, xor);
3941 LMI_DIRECT(NOR_CP2, nor, nor);
3942 LMI_DIRECT(AND_CP2, and, and);
3943 LMI_DIRECT(PANDN, pandn, andc);
3944 LMI_DIRECT(OR, or, or);
3946 case OPC_PINSRH_0:
3947 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3948 break;
3949 case OPC_PINSRH_1:
3950 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3951 break;
3952 case OPC_PINSRH_2:
3953 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3954 break;
3955 case OPC_PINSRH_3:
3956 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3957 break;
3959 case OPC_PEXTRH:
3960 tcg_gen_andi_i64(t1, t1, 3);
3961 tcg_gen_shli_i64(t1, t1, 4);
3962 tcg_gen_shr_i64(t0, t0, t1);
3963 tcg_gen_ext16u_i64(t0, t0);
3964 break;
3966 case OPC_ADDU_CP2:
3967 tcg_gen_add_i64(t0, t0, t1);
3968 tcg_gen_ext32s_i64(t0, t0);
3969 break;
3970 case OPC_SUBU_CP2:
3971 tcg_gen_sub_i64(t0, t0, t1);
3972 tcg_gen_ext32s_i64(t0, t0);
3973 break;
3975 case OPC_SLL_CP2:
3976 shift_max = 32;
3977 goto do_shift;
3978 case OPC_SRL_CP2:
3979 shift_max = 32;
3980 goto do_shift;
3981 case OPC_SRA_CP2:
3982 shift_max = 32;
3983 goto do_shift;
3984 case OPC_DSLL_CP2:
3985 shift_max = 64;
3986 goto do_shift;
3987 case OPC_DSRL_CP2:
3988 shift_max = 64;
3989 goto do_shift;
3990 case OPC_DSRA_CP2:
3991 shift_max = 64;
3992 goto do_shift;
3993 do_shift:
3994 /* Make sure shift count isn't TCG undefined behaviour. */
3995 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3997 switch (opc) {
3998 case OPC_SLL_CP2:
3999 case OPC_DSLL_CP2:
4000 tcg_gen_shl_i64(t0, t0, t1);
4001 break;
4002 case OPC_SRA_CP2:
4003 case OPC_DSRA_CP2:
4004 /* Since SRA is UndefinedResult without sign-extended inputs,
4005 we can treat SRA and DSRA the same. */
4006 tcg_gen_sar_i64(t0, t0, t1);
4007 break;
4008 case OPC_SRL_CP2:
4009 /* We want to shift in zeros for SRL; zero-extend first. */
4010 tcg_gen_ext32u_i64(t0, t0);
4011 /* FALLTHRU */
4012 case OPC_DSRL_CP2:
4013 tcg_gen_shr_i64(t0, t0, t1);
4014 break;
4017 if (shift_max == 32) {
4018 tcg_gen_ext32s_i64(t0, t0);
4021 /* Shifts larger than MAX produce zero. */
4022 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4023 tcg_gen_neg_i64(t1, t1);
4024 tcg_gen_and_i64(t0, t0, t1);
4025 break;
4027 case OPC_ADD_CP2:
4028 case OPC_DADD_CP2:
4030 TCGv_i64 t2 = tcg_temp_new_i64();
4031 TCGLabel *lab = gen_new_label();
4033 tcg_gen_mov_i64(t2, t0);
4034 tcg_gen_add_i64(t0, t1, t2);
4035 if (opc == OPC_ADD_CP2) {
4036 tcg_gen_ext32s_i64(t0, t0);
4038 tcg_gen_xor_i64(t1, t1, t2);
4039 tcg_gen_xor_i64(t2, t2, t0);
4040 tcg_gen_andc_i64(t1, t2, t1);
4041 tcg_temp_free_i64(t2);
4042 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4043 generate_exception(ctx, EXCP_OVERFLOW);
4044 gen_set_label(lab);
4045 break;
4048 case OPC_SUB_CP2:
4049 case OPC_DSUB_CP2:
4051 TCGv_i64 t2 = tcg_temp_new_i64();
4052 TCGLabel *lab = gen_new_label();
4054 tcg_gen_mov_i64(t2, t0);
4055 tcg_gen_sub_i64(t0, t1, t2);
4056 if (opc == OPC_SUB_CP2) {
4057 tcg_gen_ext32s_i64(t0, t0);
4059 tcg_gen_xor_i64(t1, t1, t2);
4060 tcg_gen_xor_i64(t2, t2, t0);
4061 tcg_gen_and_i64(t1, t1, t2);
4062 tcg_temp_free_i64(t2);
4063 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4064 generate_exception(ctx, EXCP_OVERFLOW);
4065 gen_set_label(lab);
4066 break;
4069 case OPC_PMULUW:
4070 tcg_gen_ext32u_i64(t0, t0);
4071 tcg_gen_ext32u_i64(t1, t1);
4072 tcg_gen_mul_i64(t0, t0, t1);
4073 break;
4075 case OPC_SEQU_CP2:
4076 case OPC_SEQ_CP2:
4077 case OPC_SLTU_CP2:
4078 case OPC_SLT_CP2:
4079 case OPC_SLEU_CP2:
4080 case OPC_SLE_CP2:
4081 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4082 FD field is the CC field? */
4083 default:
4084 MIPS_INVAL("loongson_cp2");
4085 generate_exception_end(ctx, EXCP_RI);
4086 return;
4089 #undef LMI_HELPER
4090 #undef LMI_DIRECT
4092 gen_store_fpr64(ctx, t0, rd);
4094 tcg_temp_free_i64(t0);
4095 tcg_temp_free_i64(t1);
4098 /* Traps */
4099 static void gen_trap (DisasContext *ctx, uint32_t opc,
4100 int rs, int rt, int16_t imm)
4102 int cond;
4103 TCGv t0 = tcg_temp_new();
4104 TCGv t1 = tcg_temp_new();
4106 cond = 0;
4107 /* Load needed operands */
4108 switch (opc) {
4109 case OPC_TEQ:
4110 case OPC_TGE:
4111 case OPC_TGEU:
4112 case OPC_TLT:
4113 case OPC_TLTU:
4114 case OPC_TNE:
4115 /* Compare two registers */
4116 if (rs != rt) {
4117 gen_load_gpr(t0, rs);
4118 gen_load_gpr(t1, rt);
4119 cond = 1;
4121 break;
4122 case OPC_TEQI:
4123 case OPC_TGEI:
4124 case OPC_TGEIU:
4125 case OPC_TLTI:
4126 case OPC_TLTIU:
4127 case OPC_TNEI:
4128 /* Compare register to immediate */
4129 if (rs != 0 || imm != 0) {
4130 gen_load_gpr(t0, rs);
4131 tcg_gen_movi_tl(t1, (int32_t)imm);
4132 cond = 1;
4134 break;
4136 if (cond == 0) {
4137 switch (opc) {
4138 case OPC_TEQ: /* rs == rs */
4139 case OPC_TEQI: /* r0 == 0 */
4140 case OPC_TGE: /* rs >= rs */
4141 case OPC_TGEI: /* r0 >= 0 */
4142 case OPC_TGEU: /* rs >= rs unsigned */
4143 case OPC_TGEIU: /* r0 >= 0 unsigned */
4144 /* Always trap */
4145 generate_exception_end(ctx, EXCP_TRAP);
4146 break;
4147 case OPC_TLT: /* rs < rs */
4148 case OPC_TLTI: /* r0 < 0 */
4149 case OPC_TLTU: /* rs < rs unsigned */
4150 case OPC_TLTIU: /* r0 < 0 unsigned */
4151 case OPC_TNE: /* rs != rs */
4152 case OPC_TNEI: /* r0 != 0 */
4153 /* Never trap: treat as NOP. */
4154 break;
4156 } else {
4157 TCGLabel *l1 = gen_new_label();
4159 switch (opc) {
4160 case OPC_TEQ:
4161 case OPC_TEQI:
4162 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4163 break;
4164 case OPC_TGE:
4165 case OPC_TGEI:
4166 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4167 break;
4168 case OPC_TGEU:
4169 case OPC_TGEIU:
4170 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4171 break;
4172 case OPC_TLT:
4173 case OPC_TLTI:
4174 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4175 break;
4176 case OPC_TLTU:
4177 case OPC_TLTIU:
4178 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4179 break;
4180 case OPC_TNE:
4181 case OPC_TNEI:
4182 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4183 break;
4185 generate_exception(ctx, EXCP_TRAP);
4186 gen_set_label(l1);
4188 tcg_temp_free(t0);
4189 tcg_temp_free(t1);
4192 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4194 TranslationBlock *tb;
4195 tb = ctx->tb;
4196 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
4197 likely(!ctx->singlestep_enabled)) {
4198 tcg_gen_goto_tb(n);
4199 gen_save_pc(dest);
4200 tcg_gen_exit_tb((uintptr_t)tb + n);
4201 } else {
4202 gen_save_pc(dest);
4203 if (ctx->singlestep_enabled) {
4204 save_cpu_state(ctx, 0);
4205 gen_helper_raise_exception_debug(cpu_env);
4207 tcg_gen_exit_tb(0);
4211 /* Branches (before delay slot) */
4212 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4213 int insn_bytes,
4214 int rs, int rt, int32_t offset,
4215 int delayslot_size)
4217 target_ulong btgt = -1;
4218 int blink = 0;
4219 int bcond_compute = 0;
4220 TCGv t0 = tcg_temp_new();
4221 TCGv t1 = tcg_temp_new();
4223 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4224 #ifdef MIPS_DEBUG_DISAS
4225 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4226 TARGET_FMT_lx "\n", ctx->pc);
4227 #endif
4228 generate_exception_end(ctx, EXCP_RI);
4229 goto out;
4232 /* Load needed operands */
4233 switch (opc) {
4234 case OPC_BEQ:
4235 case OPC_BEQL:
4236 case OPC_BNE:
4237 case OPC_BNEL:
4238 /* Compare two registers */
4239 if (rs != rt) {
4240 gen_load_gpr(t0, rs);
4241 gen_load_gpr(t1, rt);
4242 bcond_compute = 1;
4244 btgt = ctx->pc + insn_bytes + offset;
4245 break;
4246 case OPC_BGEZ:
4247 case OPC_BGEZAL:
4248 case OPC_BGEZALL:
4249 case OPC_BGEZL:
4250 case OPC_BGTZ:
4251 case OPC_BGTZL:
4252 case OPC_BLEZ:
4253 case OPC_BLEZL:
4254 case OPC_BLTZ:
4255 case OPC_BLTZAL:
4256 case OPC_BLTZALL:
4257 case OPC_BLTZL:
4258 /* Compare to zero */
4259 if (rs != 0) {
4260 gen_load_gpr(t0, rs);
4261 bcond_compute = 1;
4263 btgt = ctx->pc + insn_bytes + offset;
4264 break;
4265 case OPC_BPOSGE32:
4266 #if defined(TARGET_MIPS64)
4267 case OPC_BPOSGE64:
4268 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4269 #else
4270 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4271 #endif
4272 bcond_compute = 1;
4273 btgt = ctx->pc + insn_bytes + offset;
4274 break;
4275 case OPC_J:
4276 case OPC_JAL:
4277 case OPC_JALX:
4278 /* Jump to immediate */
4279 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4280 break;
4281 case OPC_JR:
4282 case OPC_JALR:
4283 /* Jump to register */
4284 if (offset != 0 && offset != 16) {
4285 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4286 others are reserved. */
4287 MIPS_INVAL("jump hint");
4288 generate_exception_end(ctx, EXCP_RI);
4289 goto out;
4291 gen_load_gpr(btarget, rs);
4292 break;
4293 default:
4294 MIPS_INVAL("branch/jump");
4295 generate_exception_end(ctx, EXCP_RI);
4296 goto out;
4298 if (bcond_compute == 0) {
4299 /* No condition to be computed */
4300 switch (opc) {
4301 case OPC_BEQ: /* rx == rx */
4302 case OPC_BEQL: /* rx == rx likely */
4303 case OPC_BGEZ: /* 0 >= 0 */
4304 case OPC_BGEZL: /* 0 >= 0 likely */
4305 case OPC_BLEZ: /* 0 <= 0 */
4306 case OPC_BLEZL: /* 0 <= 0 likely */
4307 /* Always take */
4308 ctx->hflags |= MIPS_HFLAG_B;
4309 break;
4310 case OPC_BGEZAL: /* 0 >= 0 */
4311 case OPC_BGEZALL: /* 0 >= 0 likely */
4312 /* Always take and link */
4313 blink = 31;
4314 ctx->hflags |= MIPS_HFLAG_B;
4315 break;
4316 case OPC_BNE: /* rx != rx */
4317 case OPC_BGTZ: /* 0 > 0 */
4318 case OPC_BLTZ: /* 0 < 0 */
4319 /* Treat as NOP. */
4320 goto out;
4321 case OPC_BLTZAL: /* 0 < 0 */
4322 /* Handle as an unconditional branch to get correct delay
4323 slot checking. */
4324 blink = 31;
4325 btgt = ctx->pc + insn_bytes + delayslot_size;
4326 ctx->hflags |= MIPS_HFLAG_B;
4327 break;
4328 case OPC_BLTZALL: /* 0 < 0 likely */
4329 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4330 /* Skip the instruction in the delay slot */
4331 ctx->pc += 4;
4332 goto out;
4333 case OPC_BNEL: /* rx != rx likely */
4334 case OPC_BGTZL: /* 0 > 0 likely */
4335 case OPC_BLTZL: /* 0 < 0 likely */
4336 /* Skip the instruction in the delay slot */
4337 ctx->pc += 4;
4338 goto out;
4339 case OPC_J:
4340 ctx->hflags |= MIPS_HFLAG_B;
4341 break;
4342 case OPC_JALX:
4343 ctx->hflags |= MIPS_HFLAG_BX;
4344 /* Fallthrough */
4345 case OPC_JAL:
4346 blink = 31;
4347 ctx->hflags |= MIPS_HFLAG_B;
4348 break;
4349 case OPC_JR:
4350 ctx->hflags |= MIPS_HFLAG_BR;
4351 break;
4352 case OPC_JALR:
4353 blink = rt;
4354 ctx->hflags |= MIPS_HFLAG_BR;
4355 break;
4356 default:
4357 MIPS_INVAL("branch/jump");
4358 generate_exception_end(ctx, EXCP_RI);
4359 goto out;
4361 } else {
4362 switch (opc) {
4363 case OPC_BEQ:
4364 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4365 goto not_likely;
4366 case OPC_BEQL:
4367 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4368 goto likely;
4369 case OPC_BNE:
4370 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4371 goto not_likely;
4372 case OPC_BNEL:
4373 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4374 goto likely;
4375 case OPC_BGEZ:
4376 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4377 goto not_likely;
4378 case OPC_BGEZL:
4379 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4380 goto likely;
4381 case OPC_BGEZAL:
4382 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4383 blink = 31;
4384 goto not_likely;
4385 case OPC_BGEZALL:
4386 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4387 blink = 31;
4388 goto likely;
4389 case OPC_BGTZ:
4390 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4391 goto not_likely;
4392 case OPC_BGTZL:
4393 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4394 goto likely;
4395 case OPC_BLEZ:
4396 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4397 goto not_likely;
4398 case OPC_BLEZL:
4399 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4400 goto likely;
4401 case OPC_BLTZ:
4402 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4403 goto not_likely;
4404 case OPC_BLTZL:
4405 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4406 goto likely;
4407 case OPC_BPOSGE32:
4408 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4409 goto not_likely;
4410 #if defined(TARGET_MIPS64)
4411 case OPC_BPOSGE64:
4412 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4413 goto not_likely;
4414 #endif
4415 case OPC_BLTZAL:
4416 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4417 blink = 31;
4418 not_likely:
4419 ctx->hflags |= MIPS_HFLAG_BC;
4420 break;
4421 case OPC_BLTZALL:
4422 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4423 blink = 31;
4424 likely:
4425 ctx->hflags |= MIPS_HFLAG_BL;
4426 break;
4427 default:
4428 MIPS_INVAL("conditional branch/jump");
4429 generate_exception_end(ctx, EXCP_RI);
4430 goto out;
4434 ctx->btarget = btgt;
4436 switch (delayslot_size) {
4437 case 2:
4438 ctx->hflags |= MIPS_HFLAG_BDS16;
4439 break;
4440 case 4:
4441 ctx->hflags |= MIPS_HFLAG_BDS32;
4442 break;
4445 if (blink > 0) {
4446 int post_delay = insn_bytes + delayslot_size;
4447 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4449 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4452 out:
4453 if (insn_bytes == 2)
4454 ctx->hflags |= MIPS_HFLAG_B16;
4455 tcg_temp_free(t0);
4456 tcg_temp_free(t1);
4459 /* special3 bitfield operations */
4460 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4461 int rs, int lsb, int msb)
4463 TCGv t0 = tcg_temp_new();
4464 TCGv t1 = tcg_temp_new();
4466 gen_load_gpr(t1, rs);
4467 switch (opc) {
4468 case OPC_EXT:
4469 if (lsb + msb > 31) {
4470 goto fail;
4472 tcg_gen_shri_tl(t0, t1, lsb);
4473 if (msb != 31) {
4474 tcg_gen_andi_tl(t0, t0, (1U << (msb + 1)) - 1);
4475 } else {
4476 tcg_gen_ext32s_tl(t0, t0);
4478 break;
4479 #if defined(TARGET_MIPS64)
4480 case OPC_DEXTU:
4481 lsb += 32;
4482 goto do_dext;
4483 case OPC_DEXTM:
4484 msb += 32;
4485 goto do_dext;
4486 case OPC_DEXT:
4487 do_dext:
4488 if (lsb + msb > 63) {
4489 goto fail;
4491 tcg_gen_shri_tl(t0, t1, lsb);
4492 if (msb != 63) {
4493 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4495 break;
4496 #endif
4497 case OPC_INS:
4498 if (lsb > msb) {
4499 goto fail;
4501 gen_load_gpr(t0, rt);
4502 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4503 tcg_gen_ext32s_tl(t0, t0);
4504 break;
4505 #if defined(TARGET_MIPS64)
4506 case OPC_DINSU:
4507 lsb += 32;
4508 /* FALLTHRU */
4509 case OPC_DINSM:
4510 msb += 32;
4511 /* FALLTHRU */
4512 case OPC_DINS:
4513 if (lsb > msb) {
4514 goto fail;
4516 gen_load_gpr(t0, rt);
4517 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4518 break;
4519 #endif
4520 default:
4521 fail:
4522 MIPS_INVAL("bitops");
4523 generate_exception_end(ctx, EXCP_RI);
4524 tcg_temp_free(t0);
4525 tcg_temp_free(t1);
4526 return;
4528 gen_store_gpr(t0, rt);
4529 tcg_temp_free(t0);
4530 tcg_temp_free(t1);
4533 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4535 TCGv t0;
4537 if (rd == 0) {
4538 /* If no destination, treat it as a NOP. */
4539 return;
4542 t0 = tcg_temp_new();
4543 gen_load_gpr(t0, rt);
4544 switch (op2) {
4545 case OPC_WSBH:
4547 TCGv t1 = tcg_temp_new();
4549 tcg_gen_shri_tl(t1, t0, 8);
4550 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4551 tcg_gen_shli_tl(t0, t0, 8);
4552 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4553 tcg_gen_or_tl(t0, t0, t1);
4554 tcg_temp_free(t1);
4555 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4557 break;
4558 case OPC_SEB:
4559 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4560 break;
4561 case OPC_SEH:
4562 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4563 break;
4564 #if defined(TARGET_MIPS64)
4565 case OPC_DSBH:
4567 TCGv t1 = tcg_temp_new();
4569 tcg_gen_shri_tl(t1, t0, 8);
4570 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4571 tcg_gen_shli_tl(t0, t0, 8);
4572 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4573 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4574 tcg_temp_free(t1);
4576 break;
4577 case OPC_DSHD:
4579 TCGv t1 = tcg_temp_new();
4581 tcg_gen_shri_tl(t1, t0, 16);
4582 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4583 tcg_gen_shli_tl(t0, t0, 16);
4584 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4585 tcg_gen_or_tl(t0, t0, t1);
4586 tcg_gen_shri_tl(t1, t0, 32);
4587 tcg_gen_shli_tl(t0, t0, 32);
4588 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4589 tcg_temp_free(t1);
4591 break;
4592 #endif
4593 default:
4594 MIPS_INVAL("bsfhl");
4595 generate_exception_end(ctx, EXCP_RI);
4596 tcg_temp_free(t0);
4597 return;
4599 tcg_temp_free(t0);
4602 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4603 int imm2)
4605 TCGv t0;
4606 TCGv t1;
4607 if (rd == 0) {
4608 /* Treat as NOP. */
4609 return;
4611 t0 = tcg_temp_new();
4612 t1 = tcg_temp_new();
4613 gen_load_gpr(t0, rs);
4614 gen_load_gpr(t1, rt);
4615 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4616 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4617 if (opc == OPC_LSA) {
4618 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4621 tcg_temp_free(t1);
4622 tcg_temp_free(t0);
4624 return;
4627 static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
4628 int bp)
4630 TCGv t0;
4631 if (rd == 0) {
4632 /* Treat as NOP. */
4633 return;
4635 t0 = tcg_temp_new();
4636 gen_load_gpr(t0, rt);
4637 if (bp == 0) {
4638 switch (opc) {
4639 case OPC_ALIGN:
4640 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4641 break;
4642 #if defined(TARGET_MIPS64)
4643 case OPC_DALIGN:
4644 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4645 break;
4646 #endif
4648 } else {
4649 TCGv t1 = tcg_temp_new();
4650 gen_load_gpr(t1, rs);
4651 switch (opc) {
4652 case OPC_ALIGN:
4654 TCGv_i64 t2 = tcg_temp_new_i64();
4655 tcg_gen_concat_tl_i64(t2, t1, t0);
4656 tcg_gen_shri_i64(t2, t2, 8 * (4 - bp));
4657 gen_move_low32(cpu_gpr[rd], t2);
4658 tcg_temp_free_i64(t2);
4660 break;
4661 #if defined(TARGET_MIPS64)
4662 case OPC_DALIGN:
4663 tcg_gen_shli_tl(t0, t0, 8 * bp);
4664 tcg_gen_shri_tl(t1, t1, 8 * (8 - bp));
4665 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4666 break;
4667 #endif
4669 tcg_temp_free(t1);
4672 tcg_temp_free(t0);
4675 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4677 TCGv t0;
4678 if (rd == 0) {
4679 /* Treat as NOP. */
4680 return;
4682 t0 = tcg_temp_new();
4683 gen_load_gpr(t0, rt);
4684 switch (opc) {
4685 case OPC_BITSWAP:
4686 gen_helper_bitswap(cpu_gpr[rd], t0);
4687 break;
4688 #if defined(TARGET_MIPS64)
4689 case OPC_DBITSWAP:
4690 gen_helper_dbitswap(cpu_gpr[rd], t0);
4691 break;
4692 #endif
4694 tcg_temp_free(t0);
4697 #ifndef CONFIG_USER_ONLY
4698 /* CP0 (MMU and control) */
4699 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4701 TCGv_i64 t0 = tcg_temp_new_i64();
4702 TCGv_i64 t1 = tcg_temp_new_i64();
4704 tcg_gen_ext_tl_i64(t0, arg);
4705 tcg_gen_ld_i64(t1, cpu_env, off);
4706 #if defined(TARGET_MIPS64)
4707 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4708 #else
4709 tcg_gen_concat32_i64(t1, t1, t0);
4710 #endif
4711 tcg_gen_st_i64(t1, cpu_env, off);
4712 tcg_temp_free_i64(t1);
4713 tcg_temp_free_i64(t0);
4716 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4718 TCGv_i64 t0 = tcg_temp_new_i64();
4719 TCGv_i64 t1 = tcg_temp_new_i64();
4721 tcg_gen_ext_tl_i64(t0, arg);
4722 tcg_gen_ld_i64(t1, cpu_env, off);
4723 tcg_gen_concat32_i64(t1, t1, t0);
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_mfhc0_entrylo(TCGv arg, target_ulong off)
4731 TCGv_i64 t0 = tcg_temp_new_i64();
4733 tcg_gen_ld_i64(t0, cpu_env, off);
4734 #if defined(TARGET_MIPS64)
4735 tcg_gen_shri_i64(t0, t0, 30);
4736 #else
4737 tcg_gen_shri_i64(t0, t0, 32);
4738 #endif
4739 gen_move_low32(arg, t0);
4740 tcg_temp_free_i64(t0);
4743 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
4745 TCGv_i64 t0 = tcg_temp_new_i64();
4747 tcg_gen_ld_i64(t0, cpu_env, off);
4748 tcg_gen_shri_i64(t0, t0, 32 + shift);
4749 gen_move_low32(arg, t0);
4750 tcg_temp_free_i64(t0);
4753 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4755 TCGv_i32 t0 = tcg_temp_new_i32();
4757 tcg_gen_ld_i32(t0, cpu_env, off);
4758 tcg_gen_ext_i32_tl(arg, t0);
4759 tcg_temp_free_i32(t0);
4762 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4764 tcg_gen_ld_tl(arg, cpu_env, off);
4765 tcg_gen_ext32s_tl(arg, arg);
4768 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4770 TCGv_i32 t0 = tcg_temp_new_i32();
4772 tcg_gen_trunc_tl_i32(t0, arg);
4773 tcg_gen_st_i32(t0, cpu_env, off);
4774 tcg_temp_free_i32(t0);
4777 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4779 const char *rn = "invalid";
4781 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
4782 goto mfhc0_read_zero;
4785 switch (reg) {
4786 case 2:
4787 switch (sel) {
4788 case 0:
4789 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4790 rn = "EntryLo0";
4791 break;
4792 default:
4793 goto mfhc0_read_zero;
4795 break;
4796 case 3:
4797 switch (sel) {
4798 case 0:
4799 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4800 rn = "EntryLo1";
4801 break;
4802 default:
4803 goto mfhc0_read_zero;
4805 break;
4806 case 17:
4807 switch (sel) {
4808 case 0:
4809 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
4810 ctx->CP0_LLAddr_shift);
4811 rn = "LLAddr";
4812 break;
4813 default:
4814 goto mfhc0_read_zero;
4816 break;
4817 case 28:
4818 switch (sel) {
4819 case 0:
4820 case 2:
4821 case 4:
4822 case 6:
4823 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
4824 rn = "TagLo";
4825 break;
4826 default:
4827 goto mfhc0_read_zero;
4829 break;
4830 default:
4831 goto mfhc0_read_zero;
4834 (void)rn; /* avoid a compiler warning */
4835 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4836 return;
4838 mfhc0_read_zero:
4839 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4840 tcg_gen_movi_tl(arg, 0);
4843 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4845 const char *rn = "invalid";
4846 uint64_t mask = ctx->PAMask >> 36;
4848 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
4849 goto mthc0_nop;
4852 switch (reg) {
4853 case 2:
4854 switch (sel) {
4855 case 0:
4856 tcg_gen_andi_tl(arg, arg, mask);
4857 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4858 rn = "EntryLo0";
4859 break;
4860 default:
4861 goto mthc0_nop;
4863 break;
4864 case 3:
4865 switch (sel) {
4866 case 0:
4867 tcg_gen_andi_tl(arg, arg, mask);
4868 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4869 rn = "EntryLo1";
4870 break;
4871 default:
4872 goto mthc0_nop;
4874 break;
4875 case 17:
4876 switch (sel) {
4877 case 0:
4878 /* LLAddr is read-only (the only exception is bit 0 if LLB is
4879 supported); the CP0_LLAddr_rw_bitmask does not seem to be
4880 relevant for modern MIPS cores supporting MTHC0, therefore
4881 treating MTHC0 to LLAddr as NOP. */
4882 rn = "LLAddr";
4883 break;
4884 default:
4885 goto mthc0_nop;
4887 break;
4888 case 28:
4889 switch (sel) {
4890 case 0:
4891 case 2:
4892 case 4:
4893 case 6:
4894 tcg_gen_andi_tl(arg, arg, mask);
4895 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
4896 rn = "TagLo";
4897 break;
4898 default:
4899 goto mthc0_nop;
4901 break;
4902 default:
4903 goto mthc0_nop;
4906 (void)rn; /* avoid a compiler warning */
4907 mthc0_nop:
4908 LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
4911 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
4913 if (ctx->insn_flags & ISA_MIPS32R6) {
4914 tcg_gen_movi_tl(arg, 0);
4915 } else {
4916 tcg_gen_movi_tl(arg, ~0);
4920 #define CP0_CHECK(c) \
4921 do { \
4922 if (!(c)) { \
4923 goto cp0_unimplemented; \
4925 } while (0)
4927 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4929 const char *rn = "invalid";
4931 if (sel != 0)
4932 check_insn(ctx, ISA_MIPS32);
4934 switch (reg) {
4935 case 0:
4936 switch (sel) {
4937 case 0:
4938 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4939 rn = "Index";
4940 break;
4941 case 1:
4942 CP0_CHECK(ctx->insn_flags & ASE_MT);
4943 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4944 rn = "MVPControl";
4945 break;
4946 case 2:
4947 CP0_CHECK(ctx->insn_flags & ASE_MT);
4948 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4949 rn = "MVPConf0";
4950 break;
4951 case 3:
4952 CP0_CHECK(ctx->insn_flags & ASE_MT);
4953 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4954 rn = "MVPConf1";
4955 break;
4956 case 4:
4957 CP0_CHECK(ctx->vp);
4958 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
4959 rn = "VPControl";
4960 break;
4961 default:
4962 goto cp0_unimplemented;
4964 break;
4965 case 1:
4966 switch (sel) {
4967 case 0:
4968 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
4969 gen_helper_mfc0_random(arg, cpu_env);
4970 rn = "Random";
4971 break;
4972 case 1:
4973 CP0_CHECK(ctx->insn_flags & ASE_MT);
4974 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4975 rn = "VPEControl";
4976 break;
4977 case 2:
4978 CP0_CHECK(ctx->insn_flags & ASE_MT);
4979 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
4980 rn = "VPEConf0";
4981 break;
4982 case 3:
4983 CP0_CHECK(ctx->insn_flags & ASE_MT);
4984 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
4985 rn = "VPEConf1";
4986 break;
4987 case 4:
4988 CP0_CHECK(ctx->insn_flags & ASE_MT);
4989 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
4990 rn = "YQMask";
4991 break;
4992 case 5:
4993 CP0_CHECK(ctx->insn_flags & ASE_MT);
4994 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
4995 rn = "VPESchedule";
4996 break;
4997 case 6:
4998 CP0_CHECK(ctx->insn_flags & ASE_MT);
4999 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5000 rn = "VPEScheFBack";
5001 break;
5002 case 7:
5003 CP0_CHECK(ctx->insn_flags & ASE_MT);
5004 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5005 rn = "VPEOpt";
5006 break;
5007 default:
5008 goto cp0_unimplemented;
5010 break;
5011 case 2:
5012 switch (sel) {
5013 case 0:
5015 TCGv_i64 tmp = tcg_temp_new_i64();
5016 tcg_gen_ld_i64(tmp, cpu_env,
5017 offsetof(CPUMIPSState, CP0_EntryLo0));
5018 #if defined(TARGET_MIPS64)
5019 if (ctx->rxi) {
5020 /* Move RI/XI fields to bits 31:30 */
5021 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5022 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5024 #endif
5025 gen_move_low32(arg, tmp);
5026 tcg_temp_free_i64(tmp);
5028 rn = "EntryLo0";
5029 break;
5030 case 1:
5031 CP0_CHECK(ctx->insn_flags & ASE_MT);
5032 gen_helper_mfc0_tcstatus(arg, cpu_env);
5033 rn = "TCStatus";
5034 break;
5035 case 2:
5036 CP0_CHECK(ctx->insn_flags & ASE_MT);
5037 gen_helper_mfc0_tcbind(arg, cpu_env);
5038 rn = "TCBind";
5039 break;
5040 case 3:
5041 CP0_CHECK(ctx->insn_flags & ASE_MT);
5042 gen_helper_mfc0_tcrestart(arg, cpu_env);
5043 rn = "TCRestart";
5044 break;
5045 case 4:
5046 CP0_CHECK(ctx->insn_flags & ASE_MT);
5047 gen_helper_mfc0_tchalt(arg, cpu_env);
5048 rn = "TCHalt";
5049 break;
5050 case 5:
5051 CP0_CHECK(ctx->insn_flags & ASE_MT);
5052 gen_helper_mfc0_tccontext(arg, cpu_env);
5053 rn = "TCContext";
5054 break;
5055 case 6:
5056 CP0_CHECK(ctx->insn_flags & ASE_MT);
5057 gen_helper_mfc0_tcschedule(arg, cpu_env);
5058 rn = "TCSchedule";
5059 break;
5060 case 7:
5061 CP0_CHECK(ctx->insn_flags & ASE_MT);
5062 gen_helper_mfc0_tcschefback(arg, cpu_env);
5063 rn = "TCScheFBack";
5064 break;
5065 default:
5066 goto cp0_unimplemented;
5068 break;
5069 case 3:
5070 switch (sel) {
5071 case 0:
5073 TCGv_i64 tmp = tcg_temp_new_i64();
5074 tcg_gen_ld_i64(tmp, cpu_env,
5075 offsetof(CPUMIPSState, CP0_EntryLo1));
5076 #if defined(TARGET_MIPS64)
5077 if (ctx->rxi) {
5078 /* Move RI/XI fields to bits 31:30 */
5079 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5080 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5082 #endif
5083 gen_move_low32(arg, tmp);
5084 tcg_temp_free_i64(tmp);
5086 rn = "EntryLo1";
5087 break;
5088 case 1:
5089 CP0_CHECK(ctx->vp);
5090 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5091 rn = "GlobalNumber";
5092 break;
5093 default:
5094 goto cp0_unimplemented;
5096 break;
5097 case 4:
5098 switch (sel) {
5099 case 0:
5100 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5101 tcg_gen_ext32s_tl(arg, arg);
5102 rn = "Context";
5103 break;
5104 case 1:
5105 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5106 rn = "ContextConfig";
5107 goto cp0_unimplemented;
5108 // break;
5109 case 2:
5110 CP0_CHECK(ctx->ulri);
5111 tcg_gen_ld32s_tl(arg, cpu_env,
5112 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5113 rn = "UserLocal";
5114 break;
5115 default:
5116 goto cp0_unimplemented;
5118 break;
5119 case 5:
5120 switch (sel) {
5121 case 0:
5122 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5123 rn = "PageMask";
5124 break;
5125 case 1:
5126 check_insn(ctx, ISA_MIPS32R2);
5127 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5128 rn = "PageGrain";
5129 break;
5130 default:
5131 goto cp0_unimplemented;
5133 break;
5134 case 6:
5135 switch (sel) {
5136 case 0:
5137 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5138 rn = "Wired";
5139 break;
5140 case 1:
5141 check_insn(ctx, ISA_MIPS32R2);
5142 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5143 rn = "SRSConf0";
5144 break;
5145 case 2:
5146 check_insn(ctx, ISA_MIPS32R2);
5147 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5148 rn = "SRSConf1";
5149 break;
5150 case 3:
5151 check_insn(ctx, ISA_MIPS32R2);
5152 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5153 rn = "SRSConf2";
5154 break;
5155 case 4:
5156 check_insn(ctx, ISA_MIPS32R2);
5157 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5158 rn = "SRSConf3";
5159 break;
5160 case 5:
5161 check_insn(ctx, ISA_MIPS32R2);
5162 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5163 rn = "SRSConf4";
5164 break;
5165 default:
5166 goto cp0_unimplemented;
5168 break;
5169 case 7:
5170 switch (sel) {
5171 case 0:
5172 check_insn(ctx, ISA_MIPS32R2);
5173 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5174 rn = "HWREna";
5175 break;
5176 default:
5177 goto cp0_unimplemented;
5179 break;
5180 case 8:
5181 switch (sel) {
5182 case 0:
5183 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5184 tcg_gen_ext32s_tl(arg, arg);
5185 rn = "BadVAddr";
5186 break;
5187 case 1:
5188 CP0_CHECK(ctx->bi);
5189 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5190 rn = "BadInstr";
5191 break;
5192 case 2:
5193 CP0_CHECK(ctx->bp);
5194 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5195 rn = "BadInstrP";
5196 break;
5197 default:
5198 goto cp0_unimplemented;
5200 break;
5201 case 9:
5202 switch (sel) {
5203 case 0:
5204 /* Mark as an IO operation because we read the time. */
5205 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5206 gen_io_start();
5208 gen_helper_mfc0_count(arg, cpu_env);
5209 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5210 gen_io_end();
5212 /* Break the TB to be able to take timer interrupts immediately
5213 after reading count. */
5214 ctx->bstate = BS_STOP;
5215 rn = "Count";
5216 break;
5217 /* 6,7 are implementation dependent */
5218 default:
5219 goto cp0_unimplemented;
5221 break;
5222 case 10:
5223 switch (sel) {
5224 case 0:
5225 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5226 tcg_gen_ext32s_tl(arg, arg);
5227 rn = "EntryHi";
5228 break;
5229 default:
5230 goto cp0_unimplemented;
5232 break;
5233 case 11:
5234 switch (sel) {
5235 case 0:
5236 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5237 rn = "Compare";
5238 break;
5239 /* 6,7 are implementation dependent */
5240 default:
5241 goto cp0_unimplemented;
5243 break;
5244 case 12:
5245 switch (sel) {
5246 case 0:
5247 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5248 rn = "Status";
5249 break;
5250 case 1:
5251 check_insn(ctx, ISA_MIPS32R2);
5252 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5253 rn = "IntCtl";
5254 break;
5255 case 2:
5256 check_insn(ctx, ISA_MIPS32R2);
5257 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5258 rn = "SRSCtl";
5259 break;
5260 case 3:
5261 check_insn(ctx, ISA_MIPS32R2);
5262 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5263 rn = "SRSMap";
5264 break;
5265 default:
5266 goto cp0_unimplemented;
5268 break;
5269 case 13:
5270 switch (sel) {
5271 case 0:
5272 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5273 rn = "Cause";
5274 break;
5275 default:
5276 goto cp0_unimplemented;
5278 break;
5279 case 14:
5280 switch (sel) {
5281 case 0:
5282 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5283 tcg_gen_ext32s_tl(arg, arg);
5284 rn = "EPC";
5285 break;
5286 default:
5287 goto cp0_unimplemented;
5289 break;
5290 case 15:
5291 switch (sel) {
5292 case 0:
5293 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5294 rn = "PRid";
5295 break;
5296 case 1:
5297 check_insn(ctx, ISA_MIPS32R2);
5298 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5299 rn = "EBase";
5300 break;
5301 default:
5302 goto cp0_unimplemented;
5304 break;
5305 case 16:
5306 switch (sel) {
5307 case 0:
5308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5309 rn = "Config";
5310 break;
5311 case 1:
5312 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5313 rn = "Config1";
5314 break;
5315 case 2:
5316 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5317 rn = "Config2";
5318 break;
5319 case 3:
5320 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5321 rn = "Config3";
5322 break;
5323 case 4:
5324 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5325 rn = "Config4";
5326 break;
5327 case 5:
5328 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5329 rn = "Config5";
5330 break;
5331 /* 6,7 are implementation dependent */
5332 case 6:
5333 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5334 rn = "Config6";
5335 break;
5336 case 7:
5337 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5338 rn = "Config7";
5339 break;
5340 default:
5341 goto cp0_unimplemented;
5343 break;
5344 case 17:
5345 switch (sel) {
5346 case 0:
5347 gen_helper_mfc0_lladdr(arg, cpu_env);
5348 rn = "LLAddr";
5349 break;
5350 default:
5351 goto cp0_unimplemented;
5353 break;
5354 case 18:
5355 switch (sel) {
5356 case 0 ... 7:
5357 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5358 rn = "WatchLo";
5359 break;
5360 default:
5361 goto cp0_unimplemented;
5363 break;
5364 case 19:
5365 switch (sel) {
5366 case 0 ...7:
5367 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5368 rn = "WatchHi";
5369 break;
5370 default:
5371 goto cp0_unimplemented;
5373 break;
5374 case 20:
5375 switch (sel) {
5376 case 0:
5377 #if defined(TARGET_MIPS64)
5378 check_insn(ctx, ISA_MIPS3);
5379 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5380 tcg_gen_ext32s_tl(arg, arg);
5381 rn = "XContext";
5382 break;
5383 #endif
5384 default:
5385 goto cp0_unimplemented;
5387 break;
5388 case 21:
5389 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5390 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5391 switch (sel) {
5392 case 0:
5393 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5394 rn = "Framemask";
5395 break;
5396 default:
5397 goto cp0_unimplemented;
5399 break;
5400 case 22:
5401 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5402 rn = "'Diagnostic"; /* implementation dependent */
5403 break;
5404 case 23:
5405 switch (sel) {
5406 case 0:
5407 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5408 rn = "Debug";
5409 break;
5410 case 1:
5411 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5412 rn = "TraceControl";
5413 // break;
5414 case 2:
5415 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5416 rn = "TraceControl2";
5417 // break;
5418 case 3:
5419 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5420 rn = "UserTraceData";
5421 // break;
5422 case 4:
5423 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5424 rn = "TraceBPC";
5425 // break;
5426 default:
5427 goto cp0_unimplemented;
5429 break;
5430 case 24:
5431 switch (sel) {
5432 case 0:
5433 /* EJTAG support */
5434 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5435 tcg_gen_ext32s_tl(arg, arg);
5436 rn = "DEPC";
5437 break;
5438 default:
5439 goto cp0_unimplemented;
5441 break;
5442 case 25:
5443 switch (sel) {
5444 case 0:
5445 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5446 rn = "Performance0";
5447 break;
5448 case 1:
5449 // gen_helper_mfc0_performance1(arg);
5450 rn = "Performance1";
5451 // break;
5452 case 2:
5453 // gen_helper_mfc0_performance2(arg);
5454 rn = "Performance2";
5455 // break;
5456 case 3:
5457 // gen_helper_mfc0_performance3(arg);
5458 rn = "Performance3";
5459 // break;
5460 case 4:
5461 // gen_helper_mfc0_performance4(arg);
5462 rn = "Performance4";
5463 // break;
5464 case 5:
5465 // gen_helper_mfc0_performance5(arg);
5466 rn = "Performance5";
5467 // break;
5468 case 6:
5469 // gen_helper_mfc0_performance6(arg);
5470 rn = "Performance6";
5471 // break;
5472 case 7:
5473 // gen_helper_mfc0_performance7(arg);
5474 rn = "Performance7";
5475 // break;
5476 default:
5477 goto cp0_unimplemented;
5479 break;
5480 case 26:
5481 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5482 rn = "ECC";
5483 break;
5484 case 27:
5485 switch (sel) {
5486 case 0 ... 3:
5487 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5488 rn = "CacheErr";
5489 break;
5490 default:
5491 goto cp0_unimplemented;
5493 break;
5494 case 28:
5495 switch (sel) {
5496 case 0:
5497 case 2:
5498 case 4:
5499 case 6:
5501 TCGv_i64 tmp = tcg_temp_new_i64();
5502 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5503 gen_move_low32(arg, tmp);
5504 tcg_temp_free_i64(tmp);
5506 rn = "TagLo";
5507 break;
5508 case 1:
5509 case 3:
5510 case 5:
5511 case 7:
5512 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5513 rn = "DataLo";
5514 break;
5515 default:
5516 goto cp0_unimplemented;
5518 break;
5519 case 29:
5520 switch (sel) {
5521 case 0:
5522 case 2:
5523 case 4:
5524 case 6:
5525 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5526 rn = "TagHi";
5527 break;
5528 case 1:
5529 case 3:
5530 case 5:
5531 case 7:
5532 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5533 rn = "DataHi";
5534 break;
5535 default:
5536 goto cp0_unimplemented;
5538 break;
5539 case 30:
5540 switch (sel) {
5541 case 0:
5542 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5543 tcg_gen_ext32s_tl(arg, arg);
5544 rn = "ErrorEPC";
5545 break;
5546 default:
5547 goto cp0_unimplemented;
5549 break;
5550 case 31:
5551 switch (sel) {
5552 case 0:
5553 /* EJTAG support */
5554 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5555 rn = "DESAVE";
5556 break;
5557 case 2 ... 7:
5558 CP0_CHECK(ctx->kscrexist & (1 << sel));
5559 tcg_gen_ld_tl(arg, cpu_env,
5560 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5561 tcg_gen_ext32s_tl(arg, arg);
5562 rn = "KScratch";
5563 break;
5564 default:
5565 goto cp0_unimplemented;
5567 break;
5568 default:
5569 goto cp0_unimplemented;
5571 (void)rn; /* avoid a compiler warning */
5572 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5573 return;
5575 cp0_unimplemented:
5576 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5577 gen_mfc0_unimplemented(ctx, arg);
5580 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5582 const char *rn = "invalid";
5584 if (sel != 0)
5585 check_insn(ctx, ISA_MIPS32);
5587 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5588 gen_io_start();
5591 switch (reg) {
5592 case 0:
5593 switch (sel) {
5594 case 0:
5595 gen_helper_mtc0_index(cpu_env, arg);
5596 rn = "Index";
5597 break;
5598 case 1:
5599 CP0_CHECK(ctx->insn_flags & ASE_MT);
5600 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5601 rn = "MVPControl";
5602 break;
5603 case 2:
5604 CP0_CHECK(ctx->insn_flags & ASE_MT);
5605 /* ignored */
5606 rn = "MVPConf0";
5607 break;
5608 case 3:
5609 CP0_CHECK(ctx->insn_flags & ASE_MT);
5610 /* ignored */
5611 rn = "MVPConf1";
5612 break;
5613 case 4:
5614 CP0_CHECK(ctx->vp);
5615 /* ignored */
5616 rn = "VPControl";
5617 break;
5618 default:
5619 goto cp0_unimplemented;
5621 break;
5622 case 1:
5623 switch (sel) {
5624 case 0:
5625 /* ignored */
5626 rn = "Random";
5627 break;
5628 case 1:
5629 CP0_CHECK(ctx->insn_flags & ASE_MT);
5630 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5631 rn = "VPEControl";
5632 break;
5633 case 2:
5634 CP0_CHECK(ctx->insn_flags & ASE_MT);
5635 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5636 rn = "VPEConf0";
5637 break;
5638 case 3:
5639 CP0_CHECK(ctx->insn_flags & ASE_MT);
5640 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5641 rn = "VPEConf1";
5642 break;
5643 case 4:
5644 CP0_CHECK(ctx->insn_flags & ASE_MT);
5645 gen_helper_mtc0_yqmask(cpu_env, arg);
5646 rn = "YQMask";
5647 break;
5648 case 5:
5649 CP0_CHECK(ctx->insn_flags & ASE_MT);
5650 tcg_gen_st_tl(arg, cpu_env,
5651 offsetof(CPUMIPSState, CP0_VPESchedule));
5652 rn = "VPESchedule";
5653 break;
5654 case 6:
5655 CP0_CHECK(ctx->insn_flags & ASE_MT);
5656 tcg_gen_st_tl(arg, cpu_env,
5657 offsetof(CPUMIPSState, CP0_VPEScheFBack));
5658 rn = "VPEScheFBack";
5659 break;
5660 case 7:
5661 CP0_CHECK(ctx->insn_flags & ASE_MT);
5662 gen_helper_mtc0_vpeopt(cpu_env, arg);
5663 rn = "VPEOpt";
5664 break;
5665 default:
5666 goto cp0_unimplemented;
5668 break;
5669 case 2:
5670 switch (sel) {
5671 case 0:
5672 gen_helper_mtc0_entrylo0(cpu_env, arg);
5673 rn = "EntryLo0";
5674 break;
5675 case 1:
5676 CP0_CHECK(ctx->insn_flags & ASE_MT);
5677 gen_helper_mtc0_tcstatus(cpu_env, arg);
5678 rn = "TCStatus";
5679 break;
5680 case 2:
5681 CP0_CHECK(ctx->insn_flags & ASE_MT);
5682 gen_helper_mtc0_tcbind(cpu_env, arg);
5683 rn = "TCBind";
5684 break;
5685 case 3:
5686 CP0_CHECK(ctx->insn_flags & ASE_MT);
5687 gen_helper_mtc0_tcrestart(cpu_env, arg);
5688 rn = "TCRestart";
5689 break;
5690 case 4:
5691 CP0_CHECK(ctx->insn_flags & ASE_MT);
5692 gen_helper_mtc0_tchalt(cpu_env, arg);
5693 rn = "TCHalt";
5694 break;
5695 case 5:
5696 CP0_CHECK(ctx->insn_flags & ASE_MT);
5697 gen_helper_mtc0_tccontext(cpu_env, arg);
5698 rn = "TCContext";
5699 break;
5700 case 6:
5701 CP0_CHECK(ctx->insn_flags & ASE_MT);
5702 gen_helper_mtc0_tcschedule(cpu_env, arg);
5703 rn = "TCSchedule";
5704 break;
5705 case 7:
5706 CP0_CHECK(ctx->insn_flags & ASE_MT);
5707 gen_helper_mtc0_tcschefback(cpu_env, arg);
5708 rn = "TCScheFBack";
5709 break;
5710 default:
5711 goto cp0_unimplemented;
5713 break;
5714 case 3:
5715 switch (sel) {
5716 case 0:
5717 gen_helper_mtc0_entrylo1(cpu_env, arg);
5718 rn = "EntryLo1";
5719 break;
5720 case 1:
5721 CP0_CHECK(ctx->vp);
5722 /* ignored */
5723 rn = "GlobalNumber";
5724 break;
5725 default:
5726 goto cp0_unimplemented;
5728 break;
5729 case 4:
5730 switch (sel) {
5731 case 0:
5732 gen_helper_mtc0_context(cpu_env, arg);
5733 rn = "Context";
5734 break;
5735 case 1:
5736 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5737 rn = "ContextConfig";
5738 goto cp0_unimplemented;
5739 // break;
5740 case 2:
5741 CP0_CHECK(ctx->ulri);
5742 tcg_gen_st_tl(arg, cpu_env,
5743 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5744 rn = "UserLocal";
5745 break;
5746 default:
5747 goto cp0_unimplemented;
5749 break;
5750 case 5:
5751 switch (sel) {
5752 case 0:
5753 gen_helper_mtc0_pagemask(cpu_env, arg);
5754 rn = "PageMask";
5755 break;
5756 case 1:
5757 check_insn(ctx, ISA_MIPS32R2);
5758 gen_helper_mtc0_pagegrain(cpu_env, arg);
5759 rn = "PageGrain";
5760 ctx->bstate = BS_STOP;
5761 break;
5762 default:
5763 goto cp0_unimplemented;
5765 break;
5766 case 6:
5767 switch (sel) {
5768 case 0:
5769 gen_helper_mtc0_wired(cpu_env, arg);
5770 rn = "Wired";
5771 break;
5772 case 1:
5773 check_insn(ctx, ISA_MIPS32R2);
5774 gen_helper_mtc0_srsconf0(cpu_env, arg);
5775 rn = "SRSConf0";
5776 break;
5777 case 2:
5778 check_insn(ctx, ISA_MIPS32R2);
5779 gen_helper_mtc0_srsconf1(cpu_env, arg);
5780 rn = "SRSConf1";
5781 break;
5782 case 3:
5783 check_insn(ctx, ISA_MIPS32R2);
5784 gen_helper_mtc0_srsconf2(cpu_env, arg);
5785 rn = "SRSConf2";
5786 break;
5787 case 4:
5788 check_insn(ctx, ISA_MIPS32R2);
5789 gen_helper_mtc0_srsconf3(cpu_env, arg);
5790 rn = "SRSConf3";
5791 break;
5792 case 5:
5793 check_insn(ctx, ISA_MIPS32R2);
5794 gen_helper_mtc0_srsconf4(cpu_env, arg);
5795 rn = "SRSConf4";
5796 break;
5797 default:
5798 goto cp0_unimplemented;
5800 break;
5801 case 7:
5802 switch (sel) {
5803 case 0:
5804 check_insn(ctx, ISA_MIPS32R2);
5805 gen_helper_mtc0_hwrena(cpu_env, arg);
5806 ctx->bstate = BS_STOP;
5807 rn = "HWREna";
5808 break;
5809 default:
5810 goto cp0_unimplemented;
5812 break;
5813 case 8:
5814 switch (sel) {
5815 case 0:
5816 /* ignored */
5817 rn = "BadVAddr";
5818 break;
5819 case 1:
5820 /* ignored */
5821 rn = "BadInstr";
5822 break;
5823 case 2:
5824 /* ignored */
5825 rn = "BadInstrP";
5826 break;
5827 default:
5828 goto cp0_unimplemented;
5830 break;
5831 case 9:
5832 switch (sel) {
5833 case 0:
5834 gen_helper_mtc0_count(cpu_env, arg);
5835 rn = "Count";
5836 break;
5837 /* 6,7 are implementation dependent */
5838 default:
5839 goto cp0_unimplemented;
5841 break;
5842 case 10:
5843 switch (sel) {
5844 case 0:
5845 gen_helper_mtc0_entryhi(cpu_env, arg);
5846 rn = "EntryHi";
5847 break;
5848 default:
5849 goto cp0_unimplemented;
5851 break;
5852 case 11:
5853 switch (sel) {
5854 case 0:
5855 gen_helper_mtc0_compare(cpu_env, arg);
5856 rn = "Compare";
5857 break;
5858 /* 6,7 are implementation dependent */
5859 default:
5860 goto cp0_unimplemented;
5862 break;
5863 case 12:
5864 switch (sel) {
5865 case 0:
5866 save_cpu_state(ctx, 1);
5867 gen_helper_mtc0_status(cpu_env, arg);
5868 /* BS_STOP isn't good enough here, hflags may have changed. */
5869 gen_save_pc(ctx->pc + 4);
5870 ctx->bstate = BS_EXCP;
5871 rn = "Status";
5872 break;
5873 case 1:
5874 check_insn(ctx, ISA_MIPS32R2);
5875 gen_helper_mtc0_intctl(cpu_env, arg);
5876 /* Stop translation as we may have switched the execution mode */
5877 ctx->bstate = BS_STOP;
5878 rn = "IntCtl";
5879 break;
5880 case 2:
5881 check_insn(ctx, ISA_MIPS32R2);
5882 gen_helper_mtc0_srsctl(cpu_env, arg);
5883 /* Stop translation as we may have switched the execution mode */
5884 ctx->bstate = BS_STOP;
5885 rn = "SRSCtl";
5886 break;
5887 case 3:
5888 check_insn(ctx, ISA_MIPS32R2);
5889 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5890 /* Stop translation as we may have switched the execution mode */
5891 ctx->bstate = BS_STOP;
5892 rn = "SRSMap";
5893 break;
5894 default:
5895 goto cp0_unimplemented;
5897 break;
5898 case 13:
5899 switch (sel) {
5900 case 0:
5901 save_cpu_state(ctx, 1);
5902 gen_helper_mtc0_cause(cpu_env, arg);
5903 rn = "Cause";
5904 break;
5905 default:
5906 goto cp0_unimplemented;
5908 break;
5909 case 14:
5910 switch (sel) {
5911 case 0:
5912 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5913 rn = "EPC";
5914 break;
5915 default:
5916 goto cp0_unimplemented;
5918 break;
5919 case 15:
5920 switch (sel) {
5921 case 0:
5922 /* ignored */
5923 rn = "PRid";
5924 break;
5925 case 1:
5926 check_insn(ctx, ISA_MIPS32R2);
5927 gen_helper_mtc0_ebase(cpu_env, arg);
5928 rn = "EBase";
5929 break;
5930 default:
5931 goto cp0_unimplemented;
5933 break;
5934 case 16:
5935 switch (sel) {
5936 case 0:
5937 gen_helper_mtc0_config0(cpu_env, arg);
5938 rn = "Config";
5939 /* Stop translation as we may have switched the execution mode */
5940 ctx->bstate = BS_STOP;
5941 break;
5942 case 1:
5943 /* ignored, read only */
5944 rn = "Config1";
5945 break;
5946 case 2:
5947 gen_helper_mtc0_config2(cpu_env, arg);
5948 rn = "Config2";
5949 /* Stop translation as we may have switched the execution mode */
5950 ctx->bstate = BS_STOP;
5951 break;
5952 case 3:
5953 gen_helper_mtc0_config3(cpu_env, arg);
5954 rn = "Config3";
5955 /* Stop translation as we may have switched the execution mode */
5956 ctx->bstate = BS_STOP;
5957 break;
5958 case 4:
5959 gen_helper_mtc0_config4(cpu_env, arg);
5960 rn = "Config4";
5961 ctx->bstate = BS_STOP;
5962 break;
5963 case 5:
5964 gen_helper_mtc0_config5(cpu_env, arg);
5965 rn = "Config5";
5966 /* Stop translation as we may have switched the execution mode */
5967 ctx->bstate = BS_STOP;
5968 break;
5969 /* 6,7 are implementation dependent */
5970 case 6:
5971 /* ignored */
5972 rn = "Config6";
5973 break;
5974 case 7:
5975 /* ignored */
5976 rn = "Config7";
5977 break;
5978 default:
5979 rn = "Invalid config selector";
5980 goto cp0_unimplemented;
5982 break;
5983 case 17:
5984 switch (sel) {
5985 case 0:
5986 gen_helper_mtc0_lladdr(cpu_env, arg);
5987 rn = "LLAddr";
5988 break;
5989 default:
5990 goto cp0_unimplemented;
5992 break;
5993 case 18:
5994 switch (sel) {
5995 case 0 ... 7:
5996 gen_helper_0e1i(mtc0_watchlo, arg, sel);
5997 rn = "WatchLo";
5998 break;
5999 default:
6000 goto cp0_unimplemented;
6002 break;
6003 case 19:
6004 switch (sel) {
6005 case 0 ... 7:
6006 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6007 rn = "WatchHi";
6008 break;
6009 default:
6010 goto cp0_unimplemented;
6012 break;
6013 case 20:
6014 switch (sel) {
6015 case 0:
6016 #if defined(TARGET_MIPS64)
6017 check_insn(ctx, ISA_MIPS3);
6018 gen_helper_mtc0_xcontext(cpu_env, arg);
6019 rn = "XContext";
6020 break;
6021 #endif
6022 default:
6023 goto cp0_unimplemented;
6025 break;
6026 case 21:
6027 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6028 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6029 switch (sel) {
6030 case 0:
6031 gen_helper_mtc0_framemask(cpu_env, arg);
6032 rn = "Framemask";
6033 break;
6034 default:
6035 goto cp0_unimplemented;
6037 break;
6038 case 22:
6039 /* ignored */
6040 rn = "Diagnostic"; /* implementation dependent */
6041 break;
6042 case 23:
6043 switch (sel) {
6044 case 0:
6045 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6046 /* BS_STOP isn't good enough here, hflags may have changed. */
6047 gen_save_pc(ctx->pc + 4);
6048 ctx->bstate = BS_EXCP;
6049 rn = "Debug";
6050 break;
6051 case 1:
6052 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6053 rn = "TraceControl";
6054 /* Stop translation as we may have switched the execution mode */
6055 ctx->bstate = BS_STOP;
6056 // break;
6057 case 2:
6058 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6059 rn = "TraceControl2";
6060 /* Stop translation as we may have switched the execution mode */
6061 ctx->bstate = BS_STOP;
6062 // break;
6063 case 3:
6064 /* Stop translation as we may have switched the execution mode */
6065 ctx->bstate = BS_STOP;
6066 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6067 rn = "UserTraceData";
6068 /* Stop translation as we may have switched the execution mode */
6069 ctx->bstate = BS_STOP;
6070 // break;
6071 case 4:
6072 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6073 /* Stop translation as we may have switched the execution mode */
6074 ctx->bstate = BS_STOP;
6075 rn = "TraceBPC";
6076 // break;
6077 default:
6078 goto cp0_unimplemented;
6080 break;
6081 case 24:
6082 switch (sel) {
6083 case 0:
6084 /* EJTAG support */
6085 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6086 rn = "DEPC";
6087 break;
6088 default:
6089 goto cp0_unimplemented;
6091 break;
6092 case 25:
6093 switch (sel) {
6094 case 0:
6095 gen_helper_mtc0_performance0(cpu_env, arg);
6096 rn = "Performance0";
6097 break;
6098 case 1:
6099 // gen_helper_mtc0_performance1(arg);
6100 rn = "Performance1";
6101 // break;
6102 case 2:
6103 // gen_helper_mtc0_performance2(arg);
6104 rn = "Performance2";
6105 // break;
6106 case 3:
6107 // gen_helper_mtc0_performance3(arg);
6108 rn = "Performance3";
6109 // break;
6110 case 4:
6111 // gen_helper_mtc0_performance4(arg);
6112 rn = "Performance4";
6113 // break;
6114 case 5:
6115 // gen_helper_mtc0_performance5(arg);
6116 rn = "Performance5";
6117 // break;
6118 case 6:
6119 // gen_helper_mtc0_performance6(arg);
6120 rn = "Performance6";
6121 // break;
6122 case 7:
6123 // gen_helper_mtc0_performance7(arg);
6124 rn = "Performance7";
6125 // break;
6126 default:
6127 goto cp0_unimplemented;
6129 break;
6130 case 26:
6131 /* ignored */
6132 rn = "ECC";
6133 break;
6134 case 27:
6135 switch (sel) {
6136 case 0 ... 3:
6137 /* ignored */
6138 rn = "CacheErr";
6139 break;
6140 default:
6141 goto cp0_unimplemented;
6143 break;
6144 case 28:
6145 switch (sel) {
6146 case 0:
6147 case 2:
6148 case 4:
6149 case 6:
6150 gen_helper_mtc0_taglo(cpu_env, arg);
6151 rn = "TagLo";
6152 break;
6153 case 1:
6154 case 3:
6155 case 5:
6156 case 7:
6157 gen_helper_mtc0_datalo(cpu_env, arg);
6158 rn = "DataLo";
6159 break;
6160 default:
6161 goto cp0_unimplemented;
6163 break;
6164 case 29:
6165 switch (sel) {
6166 case 0:
6167 case 2:
6168 case 4:
6169 case 6:
6170 gen_helper_mtc0_taghi(cpu_env, arg);
6171 rn = "TagHi";
6172 break;
6173 case 1:
6174 case 3:
6175 case 5:
6176 case 7:
6177 gen_helper_mtc0_datahi(cpu_env, arg);
6178 rn = "DataHi";
6179 break;
6180 default:
6181 rn = "invalid sel";
6182 goto cp0_unimplemented;
6184 break;
6185 case 30:
6186 switch (sel) {
6187 case 0:
6188 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6189 rn = "ErrorEPC";
6190 break;
6191 default:
6192 goto cp0_unimplemented;
6194 break;
6195 case 31:
6196 switch (sel) {
6197 case 0:
6198 /* EJTAG support */
6199 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6200 rn = "DESAVE";
6201 break;
6202 case 2 ... 7:
6203 CP0_CHECK(ctx->kscrexist & (1 << sel));
6204 tcg_gen_st_tl(arg, cpu_env,
6205 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6206 rn = "KScratch";
6207 break;
6208 default:
6209 goto cp0_unimplemented;
6211 /* Stop translation as we may have switched the execution mode */
6212 ctx->bstate = BS_STOP;
6213 break;
6214 default:
6215 goto cp0_unimplemented;
6217 (void)rn; /* avoid a compiler warning */
6218 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6219 /* For simplicity assume that all writes can cause interrupts. */
6220 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6221 gen_io_end();
6222 ctx->bstate = BS_STOP;
6224 return;
6226 cp0_unimplemented:
6227 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6230 #if defined(TARGET_MIPS64)
6231 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6233 const char *rn = "invalid";
6235 if (sel != 0)
6236 check_insn(ctx, ISA_MIPS64);
6238 switch (reg) {
6239 case 0:
6240 switch (sel) {
6241 case 0:
6242 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6243 rn = "Index";
6244 break;
6245 case 1:
6246 CP0_CHECK(ctx->insn_flags & ASE_MT);
6247 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6248 rn = "MVPControl";
6249 break;
6250 case 2:
6251 CP0_CHECK(ctx->insn_flags & ASE_MT);
6252 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6253 rn = "MVPConf0";
6254 break;
6255 case 3:
6256 CP0_CHECK(ctx->insn_flags & ASE_MT);
6257 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6258 rn = "MVPConf1";
6259 break;
6260 case 4:
6261 CP0_CHECK(ctx->vp);
6262 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6263 rn = "VPControl";
6264 break;
6265 default:
6266 goto cp0_unimplemented;
6268 break;
6269 case 1:
6270 switch (sel) {
6271 case 0:
6272 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6273 gen_helper_mfc0_random(arg, cpu_env);
6274 rn = "Random";
6275 break;
6276 case 1:
6277 CP0_CHECK(ctx->insn_flags & ASE_MT);
6278 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6279 rn = "VPEControl";
6280 break;
6281 case 2:
6282 CP0_CHECK(ctx->insn_flags & ASE_MT);
6283 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6284 rn = "VPEConf0";
6285 break;
6286 case 3:
6287 CP0_CHECK(ctx->insn_flags & ASE_MT);
6288 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6289 rn = "VPEConf1";
6290 break;
6291 case 4:
6292 CP0_CHECK(ctx->insn_flags & ASE_MT);
6293 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6294 rn = "YQMask";
6295 break;
6296 case 5:
6297 CP0_CHECK(ctx->insn_flags & ASE_MT);
6298 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6299 rn = "VPESchedule";
6300 break;
6301 case 6:
6302 CP0_CHECK(ctx->insn_flags & ASE_MT);
6303 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6304 rn = "VPEScheFBack";
6305 break;
6306 case 7:
6307 CP0_CHECK(ctx->insn_flags & ASE_MT);
6308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6309 rn = "VPEOpt";
6310 break;
6311 default:
6312 goto cp0_unimplemented;
6314 break;
6315 case 2:
6316 switch (sel) {
6317 case 0:
6318 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6319 rn = "EntryLo0";
6320 break;
6321 case 1:
6322 CP0_CHECK(ctx->insn_flags & ASE_MT);
6323 gen_helper_mfc0_tcstatus(arg, cpu_env);
6324 rn = "TCStatus";
6325 break;
6326 case 2:
6327 CP0_CHECK(ctx->insn_flags & ASE_MT);
6328 gen_helper_mfc0_tcbind(arg, cpu_env);
6329 rn = "TCBind";
6330 break;
6331 case 3:
6332 CP0_CHECK(ctx->insn_flags & ASE_MT);
6333 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6334 rn = "TCRestart";
6335 break;
6336 case 4:
6337 CP0_CHECK(ctx->insn_flags & ASE_MT);
6338 gen_helper_dmfc0_tchalt(arg, cpu_env);
6339 rn = "TCHalt";
6340 break;
6341 case 5:
6342 CP0_CHECK(ctx->insn_flags & ASE_MT);
6343 gen_helper_dmfc0_tccontext(arg, cpu_env);
6344 rn = "TCContext";
6345 break;
6346 case 6:
6347 CP0_CHECK(ctx->insn_flags & ASE_MT);
6348 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6349 rn = "TCSchedule";
6350 break;
6351 case 7:
6352 CP0_CHECK(ctx->insn_flags & ASE_MT);
6353 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6354 rn = "TCScheFBack";
6355 break;
6356 default:
6357 goto cp0_unimplemented;
6359 break;
6360 case 3:
6361 switch (sel) {
6362 case 0:
6363 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6364 rn = "EntryLo1";
6365 break;
6366 case 1:
6367 CP0_CHECK(ctx->vp);
6368 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6369 rn = "GlobalNumber";
6370 break;
6371 default:
6372 goto cp0_unimplemented;
6374 break;
6375 case 4:
6376 switch (sel) {
6377 case 0:
6378 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6379 rn = "Context";
6380 break;
6381 case 1:
6382 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6383 rn = "ContextConfig";
6384 goto cp0_unimplemented;
6385 // break;
6386 case 2:
6387 CP0_CHECK(ctx->ulri);
6388 tcg_gen_ld_tl(arg, cpu_env,
6389 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6390 rn = "UserLocal";
6391 break;
6392 default:
6393 goto cp0_unimplemented;
6395 break;
6396 case 5:
6397 switch (sel) {
6398 case 0:
6399 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6400 rn = "PageMask";
6401 break;
6402 case 1:
6403 check_insn(ctx, ISA_MIPS32R2);
6404 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6405 rn = "PageGrain";
6406 break;
6407 default:
6408 goto cp0_unimplemented;
6410 break;
6411 case 6:
6412 switch (sel) {
6413 case 0:
6414 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6415 rn = "Wired";
6416 break;
6417 case 1:
6418 check_insn(ctx, ISA_MIPS32R2);
6419 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6420 rn = "SRSConf0";
6421 break;
6422 case 2:
6423 check_insn(ctx, ISA_MIPS32R2);
6424 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6425 rn = "SRSConf1";
6426 break;
6427 case 3:
6428 check_insn(ctx, ISA_MIPS32R2);
6429 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6430 rn = "SRSConf2";
6431 break;
6432 case 4:
6433 check_insn(ctx, ISA_MIPS32R2);
6434 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6435 rn = "SRSConf3";
6436 break;
6437 case 5:
6438 check_insn(ctx, ISA_MIPS32R2);
6439 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6440 rn = "SRSConf4";
6441 break;
6442 default:
6443 goto cp0_unimplemented;
6445 break;
6446 case 7:
6447 switch (sel) {
6448 case 0:
6449 check_insn(ctx, ISA_MIPS32R2);
6450 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6451 rn = "HWREna";
6452 break;
6453 default:
6454 goto cp0_unimplemented;
6456 break;
6457 case 8:
6458 switch (sel) {
6459 case 0:
6460 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6461 rn = "BadVAddr";
6462 break;
6463 case 1:
6464 CP0_CHECK(ctx->bi);
6465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6466 rn = "BadInstr";
6467 break;
6468 case 2:
6469 CP0_CHECK(ctx->bp);
6470 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6471 rn = "BadInstrP";
6472 break;
6473 default:
6474 goto cp0_unimplemented;
6476 break;
6477 case 9:
6478 switch (sel) {
6479 case 0:
6480 /* Mark as an IO operation because we read the time. */
6481 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6482 gen_io_start();
6484 gen_helper_mfc0_count(arg, cpu_env);
6485 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6486 gen_io_end();
6488 /* Break the TB to be able to take timer interrupts immediately
6489 after reading count. */
6490 ctx->bstate = BS_STOP;
6491 rn = "Count";
6492 break;
6493 /* 6,7 are implementation dependent */
6494 default:
6495 goto cp0_unimplemented;
6497 break;
6498 case 10:
6499 switch (sel) {
6500 case 0:
6501 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6502 rn = "EntryHi";
6503 break;
6504 default:
6505 goto cp0_unimplemented;
6507 break;
6508 case 11:
6509 switch (sel) {
6510 case 0:
6511 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6512 rn = "Compare";
6513 break;
6514 /* 6,7 are implementation dependent */
6515 default:
6516 goto cp0_unimplemented;
6518 break;
6519 case 12:
6520 switch (sel) {
6521 case 0:
6522 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6523 rn = "Status";
6524 break;
6525 case 1:
6526 check_insn(ctx, ISA_MIPS32R2);
6527 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6528 rn = "IntCtl";
6529 break;
6530 case 2:
6531 check_insn(ctx, ISA_MIPS32R2);
6532 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6533 rn = "SRSCtl";
6534 break;
6535 case 3:
6536 check_insn(ctx, ISA_MIPS32R2);
6537 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6538 rn = "SRSMap";
6539 break;
6540 default:
6541 goto cp0_unimplemented;
6543 break;
6544 case 13:
6545 switch (sel) {
6546 case 0:
6547 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6548 rn = "Cause";
6549 break;
6550 default:
6551 goto cp0_unimplemented;
6553 break;
6554 case 14:
6555 switch (sel) {
6556 case 0:
6557 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6558 rn = "EPC";
6559 break;
6560 default:
6561 goto cp0_unimplemented;
6563 break;
6564 case 15:
6565 switch (sel) {
6566 case 0:
6567 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6568 rn = "PRid";
6569 break;
6570 case 1:
6571 check_insn(ctx, ISA_MIPS32R2);
6572 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6573 rn = "EBase";
6574 break;
6575 default:
6576 goto cp0_unimplemented;
6578 break;
6579 case 16:
6580 switch (sel) {
6581 case 0:
6582 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6583 rn = "Config";
6584 break;
6585 case 1:
6586 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6587 rn = "Config1";
6588 break;
6589 case 2:
6590 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6591 rn = "Config2";
6592 break;
6593 case 3:
6594 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6595 rn = "Config3";
6596 break;
6597 case 4:
6598 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6599 rn = "Config4";
6600 break;
6601 case 5:
6602 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6603 rn = "Config5";
6604 break;
6605 /* 6,7 are implementation dependent */
6606 case 6:
6607 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6608 rn = "Config6";
6609 break;
6610 case 7:
6611 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6612 rn = "Config7";
6613 break;
6614 default:
6615 goto cp0_unimplemented;
6617 break;
6618 case 17:
6619 switch (sel) {
6620 case 0:
6621 gen_helper_dmfc0_lladdr(arg, cpu_env);
6622 rn = "LLAddr";
6623 break;
6624 default:
6625 goto cp0_unimplemented;
6627 break;
6628 case 18:
6629 switch (sel) {
6630 case 0 ... 7:
6631 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6632 rn = "WatchLo";
6633 break;
6634 default:
6635 goto cp0_unimplemented;
6637 break;
6638 case 19:
6639 switch (sel) {
6640 case 0 ... 7:
6641 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6642 rn = "WatchHi";
6643 break;
6644 default:
6645 goto cp0_unimplemented;
6647 break;
6648 case 20:
6649 switch (sel) {
6650 case 0:
6651 check_insn(ctx, ISA_MIPS3);
6652 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6653 rn = "XContext";
6654 break;
6655 default:
6656 goto cp0_unimplemented;
6658 break;
6659 case 21:
6660 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6661 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6662 switch (sel) {
6663 case 0:
6664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6665 rn = "Framemask";
6666 break;
6667 default:
6668 goto cp0_unimplemented;
6670 break;
6671 case 22:
6672 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6673 rn = "'Diagnostic"; /* implementation dependent */
6674 break;
6675 case 23:
6676 switch (sel) {
6677 case 0:
6678 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6679 rn = "Debug";
6680 break;
6681 case 1:
6682 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6683 rn = "TraceControl";
6684 // break;
6685 case 2:
6686 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6687 rn = "TraceControl2";
6688 // break;
6689 case 3:
6690 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6691 rn = "UserTraceData";
6692 // break;
6693 case 4:
6694 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6695 rn = "TraceBPC";
6696 // break;
6697 default:
6698 goto cp0_unimplemented;
6700 break;
6701 case 24:
6702 switch (sel) {
6703 case 0:
6704 /* EJTAG support */
6705 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6706 rn = "DEPC";
6707 break;
6708 default:
6709 goto cp0_unimplemented;
6711 break;
6712 case 25:
6713 switch (sel) {
6714 case 0:
6715 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6716 rn = "Performance0";
6717 break;
6718 case 1:
6719 // gen_helper_dmfc0_performance1(arg);
6720 rn = "Performance1";
6721 // break;
6722 case 2:
6723 // gen_helper_dmfc0_performance2(arg);
6724 rn = "Performance2";
6725 // break;
6726 case 3:
6727 // gen_helper_dmfc0_performance3(arg);
6728 rn = "Performance3";
6729 // break;
6730 case 4:
6731 // gen_helper_dmfc0_performance4(arg);
6732 rn = "Performance4";
6733 // break;
6734 case 5:
6735 // gen_helper_dmfc0_performance5(arg);
6736 rn = "Performance5";
6737 // break;
6738 case 6:
6739 // gen_helper_dmfc0_performance6(arg);
6740 rn = "Performance6";
6741 // break;
6742 case 7:
6743 // gen_helper_dmfc0_performance7(arg);
6744 rn = "Performance7";
6745 // break;
6746 default:
6747 goto cp0_unimplemented;
6749 break;
6750 case 26:
6751 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6752 rn = "ECC";
6753 break;
6754 case 27:
6755 switch (sel) {
6756 /* ignored */
6757 case 0 ... 3:
6758 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6759 rn = "CacheErr";
6760 break;
6761 default:
6762 goto cp0_unimplemented;
6764 break;
6765 case 28:
6766 switch (sel) {
6767 case 0:
6768 case 2:
6769 case 4:
6770 case 6:
6771 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
6772 rn = "TagLo";
6773 break;
6774 case 1:
6775 case 3:
6776 case 5:
6777 case 7:
6778 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6779 rn = "DataLo";
6780 break;
6781 default:
6782 goto cp0_unimplemented;
6784 break;
6785 case 29:
6786 switch (sel) {
6787 case 0:
6788 case 2:
6789 case 4:
6790 case 6:
6791 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6792 rn = "TagHi";
6793 break;
6794 case 1:
6795 case 3:
6796 case 5:
6797 case 7:
6798 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6799 rn = "DataHi";
6800 break;
6801 default:
6802 goto cp0_unimplemented;
6804 break;
6805 case 30:
6806 switch (sel) {
6807 case 0:
6808 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6809 rn = "ErrorEPC";
6810 break;
6811 default:
6812 goto cp0_unimplemented;
6814 break;
6815 case 31:
6816 switch (sel) {
6817 case 0:
6818 /* EJTAG support */
6819 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6820 rn = "DESAVE";
6821 break;
6822 case 2 ... 7:
6823 CP0_CHECK(ctx->kscrexist & (1 << sel));
6824 tcg_gen_ld_tl(arg, cpu_env,
6825 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6826 rn = "KScratch";
6827 break;
6828 default:
6829 goto cp0_unimplemented;
6831 break;
6832 default:
6833 goto cp0_unimplemented;
6835 (void)rn; /* avoid a compiler warning */
6836 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6837 return;
6839 cp0_unimplemented:
6840 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6841 gen_mfc0_unimplemented(ctx, arg);
6844 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6846 const char *rn = "invalid";
6848 if (sel != 0)
6849 check_insn(ctx, ISA_MIPS64);
6851 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6852 gen_io_start();
6855 switch (reg) {
6856 case 0:
6857 switch (sel) {
6858 case 0:
6859 gen_helper_mtc0_index(cpu_env, arg);
6860 rn = "Index";
6861 break;
6862 case 1:
6863 CP0_CHECK(ctx->insn_flags & ASE_MT);
6864 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6865 rn = "MVPControl";
6866 break;
6867 case 2:
6868 CP0_CHECK(ctx->insn_flags & ASE_MT);
6869 /* ignored */
6870 rn = "MVPConf0";
6871 break;
6872 case 3:
6873 CP0_CHECK(ctx->insn_flags & ASE_MT);
6874 /* ignored */
6875 rn = "MVPConf1";
6876 break;
6877 case 4:
6878 CP0_CHECK(ctx->vp);
6879 /* ignored */
6880 rn = "VPControl";
6881 break;
6882 default:
6883 goto cp0_unimplemented;
6885 break;
6886 case 1:
6887 switch (sel) {
6888 case 0:
6889 /* ignored */
6890 rn = "Random";
6891 break;
6892 case 1:
6893 CP0_CHECK(ctx->insn_flags & ASE_MT);
6894 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6895 rn = "VPEControl";
6896 break;
6897 case 2:
6898 CP0_CHECK(ctx->insn_flags & ASE_MT);
6899 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6900 rn = "VPEConf0";
6901 break;
6902 case 3:
6903 CP0_CHECK(ctx->insn_flags & ASE_MT);
6904 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6905 rn = "VPEConf1";
6906 break;
6907 case 4:
6908 CP0_CHECK(ctx->insn_flags & ASE_MT);
6909 gen_helper_mtc0_yqmask(cpu_env, arg);
6910 rn = "YQMask";
6911 break;
6912 case 5:
6913 CP0_CHECK(ctx->insn_flags & ASE_MT);
6914 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6915 rn = "VPESchedule";
6916 break;
6917 case 6:
6918 CP0_CHECK(ctx->insn_flags & ASE_MT);
6919 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6920 rn = "VPEScheFBack";
6921 break;
6922 case 7:
6923 CP0_CHECK(ctx->insn_flags & ASE_MT);
6924 gen_helper_mtc0_vpeopt(cpu_env, arg);
6925 rn = "VPEOpt";
6926 break;
6927 default:
6928 goto cp0_unimplemented;
6930 break;
6931 case 2:
6932 switch (sel) {
6933 case 0:
6934 gen_helper_dmtc0_entrylo0(cpu_env, arg);
6935 rn = "EntryLo0";
6936 break;
6937 case 1:
6938 CP0_CHECK(ctx->insn_flags & ASE_MT);
6939 gen_helper_mtc0_tcstatus(cpu_env, arg);
6940 rn = "TCStatus";
6941 break;
6942 case 2:
6943 CP0_CHECK(ctx->insn_flags & ASE_MT);
6944 gen_helper_mtc0_tcbind(cpu_env, arg);
6945 rn = "TCBind";
6946 break;
6947 case 3:
6948 CP0_CHECK(ctx->insn_flags & ASE_MT);
6949 gen_helper_mtc0_tcrestart(cpu_env, arg);
6950 rn = "TCRestart";
6951 break;
6952 case 4:
6953 CP0_CHECK(ctx->insn_flags & ASE_MT);
6954 gen_helper_mtc0_tchalt(cpu_env, arg);
6955 rn = "TCHalt";
6956 break;
6957 case 5:
6958 CP0_CHECK(ctx->insn_flags & ASE_MT);
6959 gen_helper_mtc0_tccontext(cpu_env, arg);
6960 rn = "TCContext";
6961 break;
6962 case 6:
6963 CP0_CHECK(ctx->insn_flags & ASE_MT);
6964 gen_helper_mtc0_tcschedule(cpu_env, arg);
6965 rn = "TCSchedule";
6966 break;
6967 case 7:
6968 CP0_CHECK(ctx->insn_flags & ASE_MT);
6969 gen_helper_mtc0_tcschefback(cpu_env, arg);
6970 rn = "TCScheFBack";
6971 break;
6972 default:
6973 goto cp0_unimplemented;
6975 break;
6976 case 3:
6977 switch (sel) {
6978 case 0:
6979 gen_helper_dmtc0_entrylo1(cpu_env, arg);
6980 rn = "EntryLo1";
6981 break;
6982 case 1:
6983 CP0_CHECK(ctx->vp);
6984 /* ignored */
6985 rn = "GlobalNumber";
6986 break;
6987 default:
6988 goto cp0_unimplemented;
6990 break;
6991 case 4:
6992 switch (sel) {
6993 case 0:
6994 gen_helper_mtc0_context(cpu_env, arg);
6995 rn = "Context";
6996 break;
6997 case 1:
6998 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
6999 rn = "ContextConfig";
7000 goto cp0_unimplemented;
7001 // break;
7002 case 2:
7003 CP0_CHECK(ctx->ulri);
7004 tcg_gen_st_tl(arg, cpu_env,
7005 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7006 rn = "UserLocal";
7007 break;
7008 default:
7009 goto cp0_unimplemented;
7011 break;
7012 case 5:
7013 switch (sel) {
7014 case 0:
7015 gen_helper_mtc0_pagemask(cpu_env, arg);
7016 rn = "PageMask";
7017 break;
7018 case 1:
7019 check_insn(ctx, ISA_MIPS32R2);
7020 gen_helper_mtc0_pagegrain(cpu_env, arg);
7021 rn = "PageGrain";
7022 break;
7023 default:
7024 goto cp0_unimplemented;
7026 break;
7027 case 6:
7028 switch (sel) {
7029 case 0:
7030 gen_helper_mtc0_wired(cpu_env, arg);
7031 rn = "Wired";
7032 break;
7033 case 1:
7034 check_insn(ctx, ISA_MIPS32R2);
7035 gen_helper_mtc0_srsconf0(cpu_env, arg);
7036 rn = "SRSConf0";
7037 break;
7038 case 2:
7039 check_insn(ctx, ISA_MIPS32R2);
7040 gen_helper_mtc0_srsconf1(cpu_env, arg);
7041 rn = "SRSConf1";
7042 break;
7043 case 3:
7044 check_insn(ctx, ISA_MIPS32R2);
7045 gen_helper_mtc0_srsconf2(cpu_env, arg);
7046 rn = "SRSConf2";
7047 break;
7048 case 4:
7049 check_insn(ctx, ISA_MIPS32R2);
7050 gen_helper_mtc0_srsconf3(cpu_env, arg);
7051 rn = "SRSConf3";
7052 break;
7053 case 5:
7054 check_insn(ctx, ISA_MIPS32R2);
7055 gen_helper_mtc0_srsconf4(cpu_env, arg);
7056 rn = "SRSConf4";
7057 break;
7058 default:
7059 goto cp0_unimplemented;
7061 break;
7062 case 7:
7063 switch (sel) {
7064 case 0:
7065 check_insn(ctx, ISA_MIPS32R2);
7066 gen_helper_mtc0_hwrena(cpu_env, arg);
7067 ctx->bstate = BS_STOP;
7068 rn = "HWREna";
7069 break;
7070 default:
7071 goto cp0_unimplemented;
7073 break;
7074 case 8:
7075 switch (sel) {
7076 case 0:
7077 /* ignored */
7078 rn = "BadVAddr";
7079 break;
7080 case 1:
7081 /* ignored */
7082 rn = "BadInstr";
7083 break;
7084 case 2:
7085 /* ignored */
7086 rn = "BadInstrP";
7087 break;
7088 default:
7089 goto cp0_unimplemented;
7091 break;
7092 case 9:
7093 switch (sel) {
7094 case 0:
7095 gen_helper_mtc0_count(cpu_env, arg);
7096 rn = "Count";
7097 break;
7098 /* 6,7 are implementation dependent */
7099 default:
7100 goto cp0_unimplemented;
7102 /* Stop translation as we may have switched the execution mode */
7103 ctx->bstate = BS_STOP;
7104 break;
7105 case 10:
7106 switch (sel) {
7107 case 0:
7108 gen_helper_mtc0_entryhi(cpu_env, arg);
7109 rn = "EntryHi";
7110 break;
7111 default:
7112 goto cp0_unimplemented;
7114 break;
7115 case 11:
7116 switch (sel) {
7117 case 0:
7118 gen_helper_mtc0_compare(cpu_env, arg);
7119 rn = "Compare";
7120 break;
7121 /* 6,7 are implementation dependent */
7122 default:
7123 goto cp0_unimplemented;
7125 /* Stop translation as we may have switched the execution mode */
7126 ctx->bstate = BS_STOP;
7127 break;
7128 case 12:
7129 switch (sel) {
7130 case 0:
7131 save_cpu_state(ctx, 1);
7132 gen_helper_mtc0_status(cpu_env, arg);
7133 /* BS_STOP isn't good enough here, hflags may have changed. */
7134 gen_save_pc(ctx->pc + 4);
7135 ctx->bstate = BS_EXCP;
7136 rn = "Status";
7137 break;
7138 case 1:
7139 check_insn(ctx, ISA_MIPS32R2);
7140 gen_helper_mtc0_intctl(cpu_env, arg);
7141 /* Stop translation as we may have switched the execution mode */
7142 ctx->bstate = BS_STOP;
7143 rn = "IntCtl";
7144 break;
7145 case 2:
7146 check_insn(ctx, ISA_MIPS32R2);
7147 gen_helper_mtc0_srsctl(cpu_env, arg);
7148 /* Stop translation as we may have switched the execution mode */
7149 ctx->bstate = BS_STOP;
7150 rn = "SRSCtl";
7151 break;
7152 case 3:
7153 check_insn(ctx, ISA_MIPS32R2);
7154 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7155 /* Stop translation as we may have switched the execution mode */
7156 ctx->bstate = BS_STOP;
7157 rn = "SRSMap";
7158 break;
7159 default:
7160 goto cp0_unimplemented;
7162 break;
7163 case 13:
7164 switch (sel) {
7165 case 0:
7166 save_cpu_state(ctx, 1);
7167 /* Mark as an IO operation because we may trigger a software
7168 interrupt. */
7169 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7170 gen_io_start();
7172 gen_helper_mtc0_cause(cpu_env, arg);
7173 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7174 gen_io_end();
7176 /* Stop translation as we may have triggered an intetrupt */
7177 ctx->bstate = BS_STOP;
7178 rn = "Cause";
7179 break;
7180 default:
7181 goto cp0_unimplemented;
7183 break;
7184 case 14:
7185 switch (sel) {
7186 case 0:
7187 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7188 rn = "EPC";
7189 break;
7190 default:
7191 goto cp0_unimplemented;
7193 break;
7194 case 15:
7195 switch (sel) {
7196 case 0:
7197 /* ignored */
7198 rn = "PRid";
7199 break;
7200 case 1:
7201 check_insn(ctx, ISA_MIPS32R2);
7202 gen_helper_mtc0_ebase(cpu_env, arg);
7203 rn = "EBase";
7204 break;
7205 default:
7206 goto cp0_unimplemented;
7208 break;
7209 case 16:
7210 switch (sel) {
7211 case 0:
7212 gen_helper_mtc0_config0(cpu_env, arg);
7213 rn = "Config";
7214 /* Stop translation as we may have switched the execution mode */
7215 ctx->bstate = BS_STOP;
7216 break;
7217 case 1:
7218 /* ignored, read only */
7219 rn = "Config1";
7220 break;
7221 case 2:
7222 gen_helper_mtc0_config2(cpu_env, arg);
7223 rn = "Config2";
7224 /* Stop translation as we may have switched the execution mode */
7225 ctx->bstate = BS_STOP;
7226 break;
7227 case 3:
7228 gen_helper_mtc0_config3(cpu_env, arg);
7229 rn = "Config3";
7230 /* Stop translation as we may have switched the execution mode */
7231 ctx->bstate = BS_STOP;
7232 break;
7233 case 4:
7234 /* currently ignored */
7235 rn = "Config4";
7236 break;
7237 case 5:
7238 gen_helper_mtc0_config5(cpu_env, arg);
7239 rn = "Config5";
7240 /* Stop translation as we may have switched the execution mode */
7241 ctx->bstate = BS_STOP;
7242 break;
7243 /* 6,7 are implementation dependent */
7244 default:
7245 rn = "Invalid config selector";
7246 goto cp0_unimplemented;
7248 break;
7249 case 17:
7250 switch (sel) {
7251 case 0:
7252 gen_helper_mtc0_lladdr(cpu_env, arg);
7253 rn = "LLAddr";
7254 break;
7255 default:
7256 goto cp0_unimplemented;
7258 break;
7259 case 18:
7260 switch (sel) {
7261 case 0 ... 7:
7262 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7263 rn = "WatchLo";
7264 break;
7265 default:
7266 goto cp0_unimplemented;
7268 break;
7269 case 19:
7270 switch (sel) {
7271 case 0 ... 7:
7272 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7273 rn = "WatchHi";
7274 break;
7275 default:
7276 goto cp0_unimplemented;
7278 break;
7279 case 20:
7280 switch (sel) {
7281 case 0:
7282 check_insn(ctx, ISA_MIPS3);
7283 gen_helper_mtc0_xcontext(cpu_env, arg);
7284 rn = "XContext";
7285 break;
7286 default:
7287 goto cp0_unimplemented;
7289 break;
7290 case 21:
7291 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7292 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7293 switch (sel) {
7294 case 0:
7295 gen_helper_mtc0_framemask(cpu_env, arg);
7296 rn = "Framemask";
7297 break;
7298 default:
7299 goto cp0_unimplemented;
7301 break;
7302 case 22:
7303 /* ignored */
7304 rn = "Diagnostic"; /* implementation dependent */
7305 break;
7306 case 23:
7307 switch (sel) {
7308 case 0:
7309 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7310 /* BS_STOP isn't good enough here, hflags may have changed. */
7311 gen_save_pc(ctx->pc + 4);
7312 ctx->bstate = BS_EXCP;
7313 rn = "Debug";
7314 break;
7315 case 1:
7316 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7317 /* Stop translation as we may have switched the execution mode */
7318 ctx->bstate = BS_STOP;
7319 rn = "TraceControl";
7320 // break;
7321 case 2:
7322 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7323 /* Stop translation as we may have switched the execution mode */
7324 ctx->bstate = BS_STOP;
7325 rn = "TraceControl2";
7326 // break;
7327 case 3:
7328 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7329 /* Stop translation as we may have switched the execution mode */
7330 ctx->bstate = BS_STOP;
7331 rn = "UserTraceData";
7332 // break;
7333 case 4:
7334 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7335 /* Stop translation as we may have switched the execution mode */
7336 ctx->bstate = BS_STOP;
7337 rn = "TraceBPC";
7338 // break;
7339 default:
7340 goto cp0_unimplemented;
7342 break;
7343 case 24:
7344 switch (sel) {
7345 case 0:
7346 /* EJTAG support */
7347 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7348 rn = "DEPC";
7349 break;
7350 default:
7351 goto cp0_unimplemented;
7353 break;
7354 case 25:
7355 switch (sel) {
7356 case 0:
7357 gen_helper_mtc0_performance0(cpu_env, arg);
7358 rn = "Performance0";
7359 break;
7360 case 1:
7361 // gen_helper_mtc0_performance1(cpu_env, arg);
7362 rn = "Performance1";
7363 // break;
7364 case 2:
7365 // gen_helper_mtc0_performance2(cpu_env, arg);
7366 rn = "Performance2";
7367 // break;
7368 case 3:
7369 // gen_helper_mtc0_performance3(cpu_env, arg);
7370 rn = "Performance3";
7371 // break;
7372 case 4:
7373 // gen_helper_mtc0_performance4(cpu_env, arg);
7374 rn = "Performance4";
7375 // break;
7376 case 5:
7377 // gen_helper_mtc0_performance5(cpu_env, arg);
7378 rn = "Performance5";
7379 // break;
7380 case 6:
7381 // gen_helper_mtc0_performance6(cpu_env, arg);
7382 rn = "Performance6";
7383 // break;
7384 case 7:
7385 // gen_helper_mtc0_performance7(cpu_env, arg);
7386 rn = "Performance7";
7387 // break;
7388 default:
7389 goto cp0_unimplemented;
7391 break;
7392 case 26:
7393 /* ignored */
7394 rn = "ECC";
7395 break;
7396 case 27:
7397 switch (sel) {
7398 case 0 ... 3:
7399 /* ignored */
7400 rn = "CacheErr";
7401 break;
7402 default:
7403 goto cp0_unimplemented;
7405 break;
7406 case 28:
7407 switch (sel) {
7408 case 0:
7409 case 2:
7410 case 4:
7411 case 6:
7412 gen_helper_mtc0_taglo(cpu_env, arg);
7413 rn = "TagLo";
7414 break;
7415 case 1:
7416 case 3:
7417 case 5:
7418 case 7:
7419 gen_helper_mtc0_datalo(cpu_env, arg);
7420 rn = "DataLo";
7421 break;
7422 default:
7423 goto cp0_unimplemented;
7425 break;
7426 case 29:
7427 switch (sel) {
7428 case 0:
7429 case 2:
7430 case 4:
7431 case 6:
7432 gen_helper_mtc0_taghi(cpu_env, arg);
7433 rn = "TagHi";
7434 break;
7435 case 1:
7436 case 3:
7437 case 5:
7438 case 7:
7439 gen_helper_mtc0_datahi(cpu_env, arg);
7440 rn = "DataHi";
7441 break;
7442 default:
7443 rn = "invalid sel";
7444 goto cp0_unimplemented;
7446 break;
7447 case 30:
7448 switch (sel) {
7449 case 0:
7450 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7451 rn = "ErrorEPC";
7452 break;
7453 default:
7454 goto cp0_unimplemented;
7456 break;
7457 case 31:
7458 switch (sel) {
7459 case 0:
7460 /* EJTAG support */
7461 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7462 rn = "DESAVE";
7463 break;
7464 case 2 ... 7:
7465 CP0_CHECK(ctx->kscrexist & (1 << sel));
7466 tcg_gen_st_tl(arg, cpu_env,
7467 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7468 rn = "KScratch";
7469 break;
7470 default:
7471 goto cp0_unimplemented;
7473 /* Stop translation as we may have switched the execution mode */
7474 ctx->bstate = BS_STOP;
7475 break;
7476 default:
7477 goto cp0_unimplemented;
7479 (void)rn; /* avoid a compiler warning */
7480 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7481 /* For simplicity assume that all writes can cause interrupts. */
7482 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7483 gen_io_end();
7484 ctx->bstate = BS_STOP;
7486 return;
7488 cp0_unimplemented:
7489 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7491 #endif /* TARGET_MIPS64 */
7493 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7494 int u, int sel, int h)
7496 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7497 TCGv t0 = tcg_temp_local_new();
7499 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7500 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7501 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7502 tcg_gen_movi_tl(t0, -1);
7503 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7504 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7505 tcg_gen_movi_tl(t0, -1);
7506 else if (u == 0) {
7507 switch (rt) {
7508 case 1:
7509 switch (sel) {
7510 case 1:
7511 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7512 break;
7513 case 2:
7514 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7515 break;
7516 default:
7517 goto die;
7518 break;
7520 break;
7521 case 2:
7522 switch (sel) {
7523 case 1:
7524 gen_helper_mftc0_tcstatus(t0, cpu_env);
7525 break;
7526 case 2:
7527 gen_helper_mftc0_tcbind(t0, cpu_env);
7528 break;
7529 case 3:
7530 gen_helper_mftc0_tcrestart(t0, cpu_env);
7531 break;
7532 case 4:
7533 gen_helper_mftc0_tchalt(t0, cpu_env);
7534 break;
7535 case 5:
7536 gen_helper_mftc0_tccontext(t0, cpu_env);
7537 break;
7538 case 6:
7539 gen_helper_mftc0_tcschedule(t0, cpu_env);
7540 break;
7541 case 7:
7542 gen_helper_mftc0_tcschefback(t0, cpu_env);
7543 break;
7544 default:
7545 gen_mfc0(ctx, t0, rt, sel);
7546 break;
7548 break;
7549 case 10:
7550 switch (sel) {
7551 case 0:
7552 gen_helper_mftc0_entryhi(t0, cpu_env);
7553 break;
7554 default:
7555 gen_mfc0(ctx, t0, rt, sel);
7556 break;
7558 case 12:
7559 switch (sel) {
7560 case 0:
7561 gen_helper_mftc0_status(t0, cpu_env);
7562 break;
7563 default:
7564 gen_mfc0(ctx, t0, rt, sel);
7565 break;
7567 case 13:
7568 switch (sel) {
7569 case 0:
7570 gen_helper_mftc0_cause(t0, cpu_env);
7571 break;
7572 default:
7573 goto die;
7574 break;
7576 break;
7577 case 14:
7578 switch (sel) {
7579 case 0:
7580 gen_helper_mftc0_epc(t0, cpu_env);
7581 break;
7582 default:
7583 goto die;
7584 break;
7586 break;
7587 case 15:
7588 switch (sel) {
7589 case 1:
7590 gen_helper_mftc0_ebase(t0, cpu_env);
7591 break;
7592 default:
7593 goto die;
7594 break;
7596 break;
7597 case 16:
7598 switch (sel) {
7599 case 0 ... 7:
7600 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7601 break;
7602 default:
7603 goto die;
7604 break;
7606 break;
7607 case 23:
7608 switch (sel) {
7609 case 0:
7610 gen_helper_mftc0_debug(t0, cpu_env);
7611 break;
7612 default:
7613 gen_mfc0(ctx, t0, rt, sel);
7614 break;
7616 break;
7617 default:
7618 gen_mfc0(ctx, t0, rt, sel);
7620 } else switch (sel) {
7621 /* GPR registers. */
7622 case 0:
7623 gen_helper_1e0i(mftgpr, t0, rt);
7624 break;
7625 /* Auxiliary CPU registers */
7626 case 1:
7627 switch (rt) {
7628 case 0:
7629 gen_helper_1e0i(mftlo, t0, 0);
7630 break;
7631 case 1:
7632 gen_helper_1e0i(mfthi, t0, 0);
7633 break;
7634 case 2:
7635 gen_helper_1e0i(mftacx, t0, 0);
7636 break;
7637 case 4:
7638 gen_helper_1e0i(mftlo, t0, 1);
7639 break;
7640 case 5:
7641 gen_helper_1e0i(mfthi, t0, 1);
7642 break;
7643 case 6:
7644 gen_helper_1e0i(mftacx, t0, 1);
7645 break;
7646 case 8:
7647 gen_helper_1e0i(mftlo, t0, 2);
7648 break;
7649 case 9:
7650 gen_helper_1e0i(mfthi, t0, 2);
7651 break;
7652 case 10:
7653 gen_helper_1e0i(mftacx, t0, 2);
7654 break;
7655 case 12:
7656 gen_helper_1e0i(mftlo, t0, 3);
7657 break;
7658 case 13:
7659 gen_helper_1e0i(mfthi, t0, 3);
7660 break;
7661 case 14:
7662 gen_helper_1e0i(mftacx, t0, 3);
7663 break;
7664 case 16:
7665 gen_helper_mftdsp(t0, cpu_env);
7666 break;
7667 default:
7668 goto die;
7670 break;
7671 /* Floating point (COP1). */
7672 case 2:
7673 /* XXX: For now we support only a single FPU context. */
7674 if (h == 0) {
7675 TCGv_i32 fp0 = tcg_temp_new_i32();
7677 gen_load_fpr32(ctx, fp0, rt);
7678 tcg_gen_ext_i32_tl(t0, fp0);
7679 tcg_temp_free_i32(fp0);
7680 } else {
7681 TCGv_i32 fp0 = tcg_temp_new_i32();
7683 gen_load_fpr32h(ctx, fp0, rt);
7684 tcg_gen_ext_i32_tl(t0, fp0);
7685 tcg_temp_free_i32(fp0);
7687 break;
7688 case 3:
7689 /* XXX: For now we support only a single FPU context. */
7690 gen_helper_1e0i(cfc1, t0, rt);
7691 break;
7692 /* COP2: Not implemented. */
7693 case 4:
7694 case 5:
7695 /* fall through */
7696 default:
7697 goto die;
7699 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7700 gen_store_gpr(t0, rd);
7701 tcg_temp_free(t0);
7702 return;
7704 die:
7705 tcg_temp_free(t0);
7706 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7707 generate_exception_end(ctx, EXCP_RI);
7710 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7711 int u, int sel, int h)
7713 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7714 TCGv t0 = tcg_temp_local_new();
7716 gen_load_gpr(t0, rt);
7717 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7718 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7719 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7720 /* NOP */ ;
7721 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7722 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7723 /* NOP */ ;
7724 else if (u == 0) {
7725 switch (rd) {
7726 case 1:
7727 switch (sel) {
7728 case 1:
7729 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7730 break;
7731 case 2:
7732 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7733 break;
7734 default:
7735 goto die;
7736 break;
7738 break;
7739 case 2:
7740 switch (sel) {
7741 case 1:
7742 gen_helper_mttc0_tcstatus(cpu_env, t0);
7743 break;
7744 case 2:
7745 gen_helper_mttc0_tcbind(cpu_env, t0);
7746 break;
7747 case 3:
7748 gen_helper_mttc0_tcrestart(cpu_env, t0);
7749 break;
7750 case 4:
7751 gen_helper_mttc0_tchalt(cpu_env, t0);
7752 break;
7753 case 5:
7754 gen_helper_mttc0_tccontext(cpu_env, t0);
7755 break;
7756 case 6:
7757 gen_helper_mttc0_tcschedule(cpu_env, t0);
7758 break;
7759 case 7:
7760 gen_helper_mttc0_tcschefback(cpu_env, t0);
7761 break;
7762 default:
7763 gen_mtc0(ctx, t0, rd, sel);
7764 break;
7766 break;
7767 case 10:
7768 switch (sel) {
7769 case 0:
7770 gen_helper_mttc0_entryhi(cpu_env, t0);
7771 break;
7772 default:
7773 gen_mtc0(ctx, t0, rd, sel);
7774 break;
7776 case 12:
7777 switch (sel) {
7778 case 0:
7779 gen_helper_mttc0_status(cpu_env, t0);
7780 break;
7781 default:
7782 gen_mtc0(ctx, t0, rd, sel);
7783 break;
7785 case 13:
7786 switch (sel) {
7787 case 0:
7788 gen_helper_mttc0_cause(cpu_env, t0);
7789 break;
7790 default:
7791 goto die;
7792 break;
7794 break;
7795 case 15:
7796 switch (sel) {
7797 case 1:
7798 gen_helper_mttc0_ebase(cpu_env, t0);
7799 break;
7800 default:
7801 goto die;
7802 break;
7804 break;
7805 case 23:
7806 switch (sel) {
7807 case 0:
7808 gen_helper_mttc0_debug(cpu_env, t0);
7809 break;
7810 default:
7811 gen_mtc0(ctx, t0, rd, sel);
7812 break;
7814 break;
7815 default:
7816 gen_mtc0(ctx, t0, rd, sel);
7818 } else switch (sel) {
7819 /* GPR registers. */
7820 case 0:
7821 gen_helper_0e1i(mttgpr, t0, rd);
7822 break;
7823 /* Auxiliary CPU registers */
7824 case 1:
7825 switch (rd) {
7826 case 0:
7827 gen_helper_0e1i(mttlo, t0, 0);
7828 break;
7829 case 1:
7830 gen_helper_0e1i(mtthi, t0, 0);
7831 break;
7832 case 2:
7833 gen_helper_0e1i(mttacx, t0, 0);
7834 break;
7835 case 4:
7836 gen_helper_0e1i(mttlo, t0, 1);
7837 break;
7838 case 5:
7839 gen_helper_0e1i(mtthi, t0, 1);
7840 break;
7841 case 6:
7842 gen_helper_0e1i(mttacx, t0, 1);
7843 break;
7844 case 8:
7845 gen_helper_0e1i(mttlo, t0, 2);
7846 break;
7847 case 9:
7848 gen_helper_0e1i(mtthi, t0, 2);
7849 break;
7850 case 10:
7851 gen_helper_0e1i(mttacx, t0, 2);
7852 break;
7853 case 12:
7854 gen_helper_0e1i(mttlo, t0, 3);
7855 break;
7856 case 13:
7857 gen_helper_0e1i(mtthi, t0, 3);
7858 break;
7859 case 14:
7860 gen_helper_0e1i(mttacx, t0, 3);
7861 break;
7862 case 16:
7863 gen_helper_mttdsp(cpu_env, t0);
7864 break;
7865 default:
7866 goto die;
7868 break;
7869 /* Floating point (COP1). */
7870 case 2:
7871 /* XXX: For now we support only a single FPU context. */
7872 if (h == 0) {
7873 TCGv_i32 fp0 = tcg_temp_new_i32();
7875 tcg_gen_trunc_tl_i32(fp0, t0);
7876 gen_store_fpr32(ctx, fp0, rd);
7877 tcg_temp_free_i32(fp0);
7878 } else {
7879 TCGv_i32 fp0 = tcg_temp_new_i32();
7881 tcg_gen_trunc_tl_i32(fp0, t0);
7882 gen_store_fpr32h(ctx, fp0, rd);
7883 tcg_temp_free_i32(fp0);
7885 break;
7886 case 3:
7887 /* XXX: For now we support only a single FPU context. */
7889 TCGv_i32 fs_tmp = tcg_const_i32(rd);
7891 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7892 tcg_temp_free_i32(fs_tmp);
7894 /* Stop translation as we may have changed hflags */
7895 ctx->bstate = BS_STOP;
7896 break;
7897 /* COP2: Not implemented. */
7898 case 4:
7899 case 5:
7900 /* fall through */
7901 default:
7902 goto die;
7904 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7905 tcg_temp_free(t0);
7906 return;
7908 die:
7909 tcg_temp_free(t0);
7910 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7911 generate_exception_end(ctx, EXCP_RI);
7914 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
7916 const char *opn = "ldst";
7918 check_cp0_enabled(ctx);
7919 switch (opc) {
7920 case OPC_MFC0:
7921 if (rt == 0) {
7922 /* Treat as NOP. */
7923 return;
7925 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7926 opn = "mfc0";
7927 break;
7928 case OPC_MTC0:
7930 TCGv t0 = tcg_temp_new();
7932 gen_load_gpr(t0, rt);
7933 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
7934 tcg_temp_free(t0);
7936 opn = "mtc0";
7937 break;
7938 #if defined(TARGET_MIPS64)
7939 case OPC_DMFC0:
7940 check_insn(ctx, ISA_MIPS3);
7941 if (rt == 0) {
7942 /* Treat as NOP. */
7943 return;
7945 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7946 opn = "dmfc0";
7947 break;
7948 case OPC_DMTC0:
7949 check_insn(ctx, ISA_MIPS3);
7951 TCGv t0 = tcg_temp_new();
7953 gen_load_gpr(t0, rt);
7954 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
7955 tcg_temp_free(t0);
7957 opn = "dmtc0";
7958 break;
7959 #endif
7960 case OPC_MFHC0:
7961 check_mvh(ctx);
7962 if (rt == 0) {
7963 /* Treat as NOP. */
7964 return;
7966 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7967 opn = "mfhc0";
7968 break;
7969 case OPC_MTHC0:
7970 check_mvh(ctx);
7972 TCGv t0 = tcg_temp_new();
7973 gen_load_gpr(t0, rt);
7974 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
7975 tcg_temp_free(t0);
7977 opn = "mthc0";
7978 break;
7979 case OPC_MFTR:
7980 check_insn(ctx, ASE_MT);
7981 if (rd == 0) {
7982 /* Treat as NOP. */
7983 return;
7985 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
7986 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
7987 opn = "mftr";
7988 break;
7989 case OPC_MTTR:
7990 check_insn(ctx, ASE_MT);
7991 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
7992 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
7993 opn = "mttr";
7994 break;
7995 case OPC_TLBWI:
7996 opn = "tlbwi";
7997 if (!env->tlb->helper_tlbwi)
7998 goto die;
7999 gen_helper_tlbwi(cpu_env);
8000 break;
8001 case OPC_TLBINV:
8002 opn = "tlbinv";
8003 if (ctx->ie >= 2) {
8004 if (!env->tlb->helper_tlbinv) {
8005 goto die;
8007 gen_helper_tlbinv(cpu_env);
8008 } /* treat as nop if TLBINV not supported */
8009 break;
8010 case OPC_TLBINVF:
8011 opn = "tlbinvf";
8012 if (ctx->ie >= 2) {
8013 if (!env->tlb->helper_tlbinvf) {
8014 goto die;
8016 gen_helper_tlbinvf(cpu_env);
8017 } /* treat as nop if TLBINV not supported */
8018 break;
8019 case OPC_TLBWR:
8020 opn = "tlbwr";
8021 if (!env->tlb->helper_tlbwr)
8022 goto die;
8023 gen_helper_tlbwr(cpu_env);
8024 break;
8025 case OPC_TLBP:
8026 opn = "tlbp";
8027 if (!env->tlb->helper_tlbp)
8028 goto die;
8029 gen_helper_tlbp(cpu_env);
8030 break;
8031 case OPC_TLBR:
8032 opn = "tlbr";
8033 if (!env->tlb->helper_tlbr)
8034 goto die;
8035 gen_helper_tlbr(cpu_env);
8036 break;
8037 case OPC_ERET: /* OPC_ERETNC */
8038 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8039 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8040 goto die;
8041 } else {
8042 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8043 if (ctx->opcode & (1 << bit_shift)) {
8044 /* OPC_ERETNC */
8045 opn = "eretnc";
8046 check_insn(ctx, ISA_MIPS32R5);
8047 gen_helper_eretnc(cpu_env);
8048 } else {
8049 /* OPC_ERET */
8050 opn = "eret";
8051 check_insn(ctx, ISA_MIPS2);
8052 gen_helper_eret(cpu_env);
8054 ctx->bstate = BS_EXCP;
8056 break;
8057 case OPC_DERET:
8058 opn = "deret";
8059 check_insn(ctx, ISA_MIPS32);
8060 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8061 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8062 goto die;
8064 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8065 MIPS_INVAL(opn);
8066 generate_exception_end(ctx, EXCP_RI);
8067 } else {
8068 gen_helper_deret(cpu_env);
8069 ctx->bstate = BS_EXCP;
8071 break;
8072 case OPC_WAIT:
8073 opn = "wait";
8074 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8075 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8076 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8077 goto die;
8079 /* If we get an exception, we want to restart at next instruction */
8080 ctx->pc += 4;
8081 save_cpu_state(ctx, 1);
8082 ctx->pc -= 4;
8083 gen_helper_wait(cpu_env);
8084 ctx->bstate = BS_EXCP;
8085 break;
8086 default:
8087 die:
8088 MIPS_INVAL(opn);
8089 generate_exception_end(ctx, EXCP_RI);
8090 return;
8092 (void)opn; /* avoid a compiler warning */
8094 #endif /* !CONFIG_USER_ONLY */
8096 /* CP1 Branches (before delay slot) */
8097 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8098 int32_t cc, int32_t offset)
8100 target_ulong btarget;
8101 TCGv_i32 t0 = tcg_temp_new_i32();
8103 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8104 generate_exception_end(ctx, EXCP_RI);
8105 goto out;
8108 if (cc != 0)
8109 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8111 btarget = ctx->pc + 4 + offset;
8113 switch (op) {
8114 case OPC_BC1F:
8115 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8116 tcg_gen_not_i32(t0, t0);
8117 tcg_gen_andi_i32(t0, t0, 1);
8118 tcg_gen_extu_i32_tl(bcond, t0);
8119 goto not_likely;
8120 case OPC_BC1FL:
8121 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8122 tcg_gen_not_i32(t0, t0);
8123 tcg_gen_andi_i32(t0, t0, 1);
8124 tcg_gen_extu_i32_tl(bcond, t0);
8125 goto likely;
8126 case OPC_BC1T:
8127 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8128 tcg_gen_andi_i32(t0, t0, 1);
8129 tcg_gen_extu_i32_tl(bcond, t0);
8130 goto not_likely;
8131 case OPC_BC1TL:
8132 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8133 tcg_gen_andi_i32(t0, t0, 1);
8134 tcg_gen_extu_i32_tl(bcond, t0);
8135 likely:
8136 ctx->hflags |= MIPS_HFLAG_BL;
8137 break;
8138 case OPC_BC1FANY2:
8140 TCGv_i32 t1 = tcg_temp_new_i32();
8141 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8142 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8143 tcg_gen_nand_i32(t0, t0, t1);
8144 tcg_temp_free_i32(t1);
8145 tcg_gen_andi_i32(t0, t0, 1);
8146 tcg_gen_extu_i32_tl(bcond, t0);
8148 goto not_likely;
8149 case OPC_BC1TANY2:
8151 TCGv_i32 t1 = tcg_temp_new_i32();
8152 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8153 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8154 tcg_gen_or_i32(t0, t0, t1);
8155 tcg_temp_free_i32(t1);
8156 tcg_gen_andi_i32(t0, t0, 1);
8157 tcg_gen_extu_i32_tl(bcond, t0);
8159 goto not_likely;
8160 case OPC_BC1FANY4:
8162 TCGv_i32 t1 = tcg_temp_new_i32();
8163 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8164 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8165 tcg_gen_and_i32(t0, t0, t1);
8166 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8167 tcg_gen_and_i32(t0, t0, t1);
8168 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8169 tcg_gen_nand_i32(t0, t0, t1);
8170 tcg_temp_free_i32(t1);
8171 tcg_gen_andi_i32(t0, t0, 1);
8172 tcg_gen_extu_i32_tl(bcond, t0);
8174 goto not_likely;
8175 case OPC_BC1TANY4:
8177 TCGv_i32 t1 = tcg_temp_new_i32();
8178 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8179 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8180 tcg_gen_or_i32(t0, t0, t1);
8181 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8182 tcg_gen_or_i32(t0, t0, t1);
8183 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8184 tcg_gen_or_i32(t0, t0, t1);
8185 tcg_temp_free_i32(t1);
8186 tcg_gen_andi_i32(t0, t0, 1);
8187 tcg_gen_extu_i32_tl(bcond, t0);
8189 not_likely:
8190 ctx->hflags |= MIPS_HFLAG_BC;
8191 break;
8192 default:
8193 MIPS_INVAL("cp1 cond branch");
8194 generate_exception_end(ctx, EXCP_RI);
8195 goto out;
8197 ctx->btarget = btarget;
8198 ctx->hflags |= MIPS_HFLAG_BDS32;
8199 out:
8200 tcg_temp_free_i32(t0);
8203 /* R6 CP1 Branches */
8204 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8205 int32_t ft, int32_t offset,
8206 int delayslot_size)
8208 target_ulong btarget;
8209 TCGv_i64 t0 = tcg_temp_new_i64();
8211 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8212 #ifdef MIPS_DEBUG_DISAS
8213 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8214 "\n", ctx->pc);
8215 #endif
8216 generate_exception_end(ctx, EXCP_RI);
8217 goto out;
8220 gen_load_fpr64(ctx, t0, ft);
8221 tcg_gen_andi_i64(t0, t0, 1);
8223 btarget = addr_add(ctx, ctx->pc + 4, offset);
8225 switch (op) {
8226 case OPC_BC1EQZ:
8227 tcg_gen_xori_i64(t0, t0, 1);
8228 ctx->hflags |= MIPS_HFLAG_BC;
8229 break;
8230 case OPC_BC1NEZ:
8231 /* t0 already set */
8232 ctx->hflags |= MIPS_HFLAG_BC;
8233 break;
8234 default:
8235 MIPS_INVAL("cp1 cond branch");
8236 generate_exception_end(ctx, EXCP_RI);
8237 goto out;
8240 tcg_gen_trunc_i64_tl(bcond, t0);
8242 ctx->btarget = btarget;
8244 switch (delayslot_size) {
8245 case 2:
8246 ctx->hflags |= MIPS_HFLAG_BDS16;
8247 break;
8248 case 4:
8249 ctx->hflags |= MIPS_HFLAG_BDS32;
8250 break;
8253 out:
8254 tcg_temp_free_i64(t0);
8257 /* Coprocessor 1 (FPU) */
8259 #define FOP(func, fmt) (((fmt) << 21) | (func))
8261 enum fopcode {
8262 OPC_ADD_S = FOP(0, FMT_S),
8263 OPC_SUB_S = FOP(1, FMT_S),
8264 OPC_MUL_S = FOP(2, FMT_S),
8265 OPC_DIV_S = FOP(3, FMT_S),
8266 OPC_SQRT_S = FOP(4, FMT_S),
8267 OPC_ABS_S = FOP(5, FMT_S),
8268 OPC_MOV_S = FOP(6, FMT_S),
8269 OPC_NEG_S = FOP(7, FMT_S),
8270 OPC_ROUND_L_S = FOP(8, FMT_S),
8271 OPC_TRUNC_L_S = FOP(9, FMT_S),
8272 OPC_CEIL_L_S = FOP(10, FMT_S),
8273 OPC_FLOOR_L_S = FOP(11, FMT_S),
8274 OPC_ROUND_W_S = FOP(12, FMT_S),
8275 OPC_TRUNC_W_S = FOP(13, FMT_S),
8276 OPC_CEIL_W_S = FOP(14, FMT_S),
8277 OPC_FLOOR_W_S = FOP(15, FMT_S),
8278 OPC_SEL_S = FOP(16, FMT_S),
8279 OPC_MOVCF_S = FOP(17, FMT_S),
8280 OPC_MOVZ_S = FOP(18, FMT_S),
8281 OPC_MOVN_S = FOP(19, FMT_S),
8282 OPC_SELEQZ_S = FOP(20, FMT_S),
8283 OPC_RECIP_S = FOP(21, FMT_S),
8284 OPC_RSQRT_S = FOP(22, FMT_S),
8285 OPC_SELNEZ_S = FOP(23, FMT_S),
8286 OPC_MADDF_S = FOP(24, FMT_S),
8287 OPC_MSUBF_S = FOP(25, FMT_S),
8288 OPC_RINT_S = FOP(26, FMT_S),
8289 OPC_CLASS_S = FOP(27, FMT_S),
8290 OPC_MIN_S = FOP(28, FMT_S),
8291 OPC_RECIP2_S = FOP(28, FMT_S),
8292 OPC_MINA_S = FOP(29, FMT_S),
8293 OPC_RECIP1_S = FOP(29, FMT_S),
8294 OPC_MAX_S = FOP(30, FMT_S),
8295 OPC_RSQRT1_S = FOP(30, FMT_S),
8296 OPC_MAXA_S = FOP(31, FMT_S),
8297 OPC_RSQRT2_S = FOP(31, FMT_S),
8298 OPC_CVT_D_S = FOP(33, FMT_S),
8299 OPC_CVT_W_S = FOP(36, FMT_S),
8300 OPC_CVT_L_S = FOP(37, FMT_S),
8301 OPC_CVT_PS_S = FOP(38, FMT_S),
8302 OPC_CMP_F_S = FOP (48, FMT_S),
8303 OPC_CMP_UN_S = FOP (49, FMT_S),
8304 OPC_CMP_EQ_S = FOP (50, FMT_S),
8305 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8306 OPC_CMP_OLT_S = FOP (52, FMT_S),
8307 OPC_CMP_ULT_S = FOP (53, FMT_S),
8308 OPC_CMP_OLE_S = FOP (54, FMT_S),
8309 OPC_CMP_ULE_S = FOP (55, FMT_S),
8310 OPC_CMP_SF_S = FOP (56, FMT_S),
8311 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8312 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8313 OPC_CMP_NGL_S = FOP (59, FMT_S),
8314 OPC_CMP_LT_S = FOP (60, FMT_S),
8315 OPC_CMP_NGE_S = FOP (61, FMT_S),
8316 OPC_CMP_LE_S = FOP (62, FMT_S),
8317 OPC_CMP_NGT_S = FOP (63, FMT_S),
8319 OPC_ADD_D = FOP(0, FMT_D),
8320 OPC_SUB_D = FOP(1, FMT_D),
8321 OPC_MUL_D = FOP(2, FMT_D),
8322 OPC_DIV_D = FOP(3, FMT_D),
8323 OPC_SQRT_D = FOP(4, FMT_D),
8324 OPC_ABS_D = FOP(5, FMT_D),
8325 OPC_MOV_D = FOP(6, FMT_D),
8326 OPC_NEG_D = FOP(7, FMT_D),
8327 OPC_ROUND_L_D = FOP(8, FMT_D),
8328 OPC_TRUNC_L_D = FOP(9, FMT_D),
8329 OPC_CEIL_L_D = FOP(10, FMT_D),
8330 OPC_FLOOR_L_D = FOP(11, FMT_D),
8331 OPC_ROUND_W_D = FOP(12, FMT_D),
8332 OPC_TRUNC_W_D = FOP(13, FMT_D),
8333 OPC_CEIL_W_D = FOP(14, FMT_D),
8334 OPC_FLOOR_W_D = FOP(15, FMT_D),
8335 OPC_SEL_D = FOP(16, FMT_D),
8336 OPC_MOVCF_D = FOP(17, FMT_D),
8337 OPC_MOVZ_D = FOP(18, FMT_D),
8338 OPC_MOVN_D = FOP(19, FMT_D),
8339 OPC_SELEQZ_D = FOP(20, FMT_D),
8340 OPC_RECIP_D = FOP(21, FMT_D),
8341 OPC_RSQRT_D = FOP(22, FMT_D),
8342 OPC_SELNEZ_D = FOP(23, FMT_D),
8343 OPC_MADDF_D = FOP(24, FMT_D),
8344 OPC_MSUBF_D = FOP(25, FMT_D),
8345 OPC_RINT_D = FOP(26, FMT_D),
8346 OPC_CLASS_D = FOP(27, FMT_D),
8347 OPC_MIN_D = FOP(28, FMT_D),
8348 OPC_RECIP2_D = FOP(28, FMT_D),
8349 OPC_MINA_D = FOP(29, FMT_D),
8350 OPC_RECIP1_D = FOP(29, FMT_D),
8351 OPC_MAX_D = FOP(30, FMT_D),
8352 OPC_RSQRT1_D = FOP(30, FMT_D),
8353 OPC_MAXA_D = FOP(31, FMT_D),
8354 OPC_RSQRT2_D = FOP(31, FMT_D),
8355 OPC_CVT_S_D = FOP(32, FMT_D),
8356 OPC_CVT_W_D = FOP(36, FMT_D),
8357 OPC_CVT_L_D = FOP(37, FMT_D),
8358 OPC_CMP_F_D = FOP (48, FMT_D),
8359 OPC_CMP_UN_D = FOP (49, FMT_D),
8360 OPC_CMP_EQ_D = FOP (50, FMT_D),
8361 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8362 OPC_CMP_OLT_D = FOP (52, FMT_D),
8363 OPC_CMP_ULT_D = FOP (53, FMT_D),
8364 OPC_CMP_OLE_D = FOP (54, FMT_D),
8365 OPC_CMP_ULE_D = FOP (55, FMT_D),
8366 OPC_CMP_SF_D = FOP (56, FMT_D),
8367 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8368 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8369 OPC_CMP_NGL_D = FOP (59, FMT_D),
8370 OPC_CMP_LT_D = FOP (60, FMT_D),
8371 OPC_CMP_NGE_D = FOP (61, FMT_D),
8372 OPC_CMP_LE_D = FOP (62, FMT_D),
8373 OPC_CMP_NGT_D = FOP (63, FMT_D),
8375 OPC_CVT_S_W = FOP(32, FMT_W),
8376 OPC_CVT_D_W = FOP(33, FMT_W),
8377 OPC_CVT_S_L = FOP(32, FMT_L),
8378 OPC_CVT_D_L = FOP(33, FMT_L),
8379 OPC_CVT_PS_PW = FOP(38, FMT_W),
8381 OPC_ADD_PS = FOP(0, FMT_PS),
8382 OPC_SUB_PS = FOP(1, FMT_PS),
8383 OPC_MUL_PS = FOP(2, FMT_PS),
8384 OPC_DIV_PS = FOP(3, FMT_PS),
8385 OPC_ABS_PS = FOP(5, FMT_PS),
8386 OPC_MOV_PS = FOP(6, FMT_PS),
8387 OPC_NEG_PS = FOP(7, FMT_PS),
8388 OPC_MOVCF_PS = FOP(17, FMT_PS),
8389 OPC_MOVZ_PS = FOP(18, FMT_PS),
8390 OPC_MOVN_PS = FOP(19, FMT_PS),
8391 OPC_ADDR_PS = FOP(24, FMT_PS),
8392 OPC_MULR_PS = FOP(26, FMT_PS),
8393 OPC_RECIP2_PS = FOP(28, FMT_PS),
8394 OPC_RECIP1_PS = FOP(29, FMT_PS),
8395 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8396 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8398 OPC_CVT_S_PU = FOP(32, FMT_PS),
8399 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8400 OPC_CVT_S_PL = FOP(40, FMT_PS),
8401 OPC_PLL_PS = FOP(44, FMT_PS),
8402 OPC_PLU_PS = FOP(45, FMT_PS),
8403 OPC_PUL_PS = FOP(46, FMT_PS),
8404 OPC_PUU_PS = FOP(47, FMT_PS),
8405 OPC_CMP_F_PS = FOP (48, FMT_PS),
8406 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8407 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8408 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8409 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8410 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8411 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8412 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8413 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8414 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8415 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8416 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8417 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8418 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8419 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8420 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8423 enum r6_f_cmp_op {
8424 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8425 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8426 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8427 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8428 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8429 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8430 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8431 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8432 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8433 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8434 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8435 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8436 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8437 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8438 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8439 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8440 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8441 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8442 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8443 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8444 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8445 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8447 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8448 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8449 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8450 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8451 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8452 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8453 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8454 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8455 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8456 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8457 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8458 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8459 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8460 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8461 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8462 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8463 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8464 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8465 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8466 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8467 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8468 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8470 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8472 TCGv t0 = tcg_temp_new();
8474 switch (opc) {
8475 case OPC_MFC1:
8477 TCGv_i32 fp0 = tcg_temp_new_i32();
8479 gen_load_fpr32(ctx, fp0, fs);
8480 tcg_gen_ext_i32_tl(t0, fp0);
8481 tcg_temp_free_i32(fp0);
8483 gen_store_gpr(t0, rt);
8484 break;
8485 case OPC_MTC1:
8486 gen_load_gpr(t0, rt);
8488 TCGv_i32 fp0 = tcg_temp_new_i32();
8490 tcg_gen_trunc_tl_i32(fp0, t0);
8491 gen_store_fpr32(ctx, fp0, fs);
8492 tcg_temp_free_i32(fp0);
8494 break;
8495 case OPC_CFC1:
8496 gen_helper_1e0i(cfc1, t0, fs);
8497 gen_store_gpr(t0, rt);
8498 break;
8499 case OPC_CTC1:
8500 gen_load_gpr(t0, rt);
8501 save_cpu_state(ctx, 0);
8503 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8505 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8506 tcg_temp_free_i32(fs_tmp);
8508 /* Stop translation as we may have changed hflags */
8509 ctx->bstate = BS_STOP;
8510 break;
8511 #if defined(TARGET_MIPS64)
8512 case OPC_DMFC1:
8513 gen_load_fpr64(ctx, t0, fs);
8514 gen_store_gpr(t0, rt);
8515 break;
8516 case OPC_DMTC1:
8517 gen_load_gpr(t0, rt);
8518 gen_store_fpr64(ctx, t0, fs);
8519 break;
8520 #endif
8521 case OPC_MFHC1:
8523 TCGv_i32 fp0 = tcg_temp_new_i32();
8525 gen_load_fpr32h(ctx, fp0, fs);
8526 tcg_gen_ext_i32_tl(t0, fp0);
8527 tcg_temp_free_i32(fp0);
8529 gen_store_gpr(t0, rt);
8530 break;
8531 case OPC_MTHC1:
8532 gen_load_gpr(t0, rt);
8534 TCGv_i32 fp0 = tcg_temp_new_i32();
8536 tcg_gen_trunc_tl_i32(fp0, t0);
8537 gen_store_fpr32h(ctx, fp0, fs);
8538 tcg_temp_free_i32(fp0);
8540 break;
8541 default:
8542 MIPS_INVAL("cp1 move");
8543 generate_exception_end(ctx, EXCP_RI);
8544 goto out;
8547 out:
8548 tcg_temp_free(t0);
8551 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8553 TCGLabel *l1;
8554 TCGCond cond;
8555 TCGv_i32 t0;
8557 if (rd == 0) {
8558 /* Treat as NOP. */
8559 return;
8562 if (tf)
8563 cond = TCG_COND_EQ;
8564 else
8565 cond = TCG_COND_NE;
8567 l1 = gen_new_label();
8568 t0 = tcg_temp_new_i32();
8569 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8570 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8571 tcg_temp_free_i32(t0);
8572 if (rs == 0) {
8573 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8574 } else {
8575 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8577 gen_set_label(l1);
8580 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
8581 int tf)
8583 int cond;
8584 TCGv_i32 t0 = tcg_temp_new_i32();
8585 TCGLabel *l1 = gen_new_label();
8587 if (tf)
8588 cond = TCG_COND_EQ;
8589 else
8590 cond = TCG_COND_NE;
8592 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8593 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8594 gen_load_fpr32(ctx, t0, fs);
8595 gen_store_fpr32(ctx, t0, fd);
8596 gen_set_label(l1);
8597 tcg_temp_free_i32(t0);
8600 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8602 int cond;
8603 TCGv_i32 t0 = tcg_temp_new_i32();
8604 TCGv_i64 fp0;
8605 TCGLabel *l1 = gen_new_label();
8607 if (tf)
8608 cond = TCG_COND_EQ;
8609 else
8610 cond = TCG_COND_NE;
8612 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8613 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8614 tcg_temp_free_i32(t0);
8615 fp0 = tcg_temp_new_i64();
8616 gen_load_fpr64(ctx, fp0, fs);
8617 gen_store_fpr64(ctx, fp0, fd);
8618 tcg_temp_free_i64(fp0);
8619 gen_set_label(l1);
8622 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8623 int cc, int tf)
8625 int cond;
8626 TCGv_i32 t0 = tcg_temp_new_i32();
8627 TCGLabel *l1 = gen_new_label();
8628 TCGLabel *l2 = gen_new_label();
8630 if (tf)
8631 cond = TCG_COND_EQ;
8632 else
8633 cond = TCG_COND_NE;
8635 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8636 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8637 gen_load_fpr32(ctx, t0, fs);
8638 gen_store_fpr32(ctx, t0, fd);
8639 gen_set_label(l1);
8641 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8642 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8643 gen_load_fpr32h(ctx, t0, fs);
8644 gen_store_fpr32h(ctx, t0, fd);
8645 tcg_temp_free_i32(t0);
8646 gen_set_label(l2);
8649 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8650 int fs)
8652 TCGv_i32 t1 = tcg_const_i32(0);
8653 TCGv_i32 fp0 = tcg_temp_new_i32();
8654 TCGv_i32 fp1 = tcg_temp_new_i32();
8655 TCGv_i32 fp2 = tcg_temp_new_i32();
8656 gen_load_fpr32(ctx, fp0, fd);
8657 gen_load_fpr32(ctx, fp1, ft);
8658 gen_load_fpr32(ctx, fp2, fs);
8660 switch (op1) {
8661 case OPC_SEL_S:
8662 tcg_gen_andi_i32(fp0, fp0, 1);
8663 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8664 break;
8665 case OPC_SELEQZ_S:
8666 tcg_gen_andi_i32(fp1, fp1, 1);
8667 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8668 break;
8669 case OPC_SELNEZ_S:
8670 tcg_gen_andi_i32(fp1, fp1, 1);
8671 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8672 break;
8673 default:
8674 MIPS_INVAL("gen_sel_s");
8675 generate_exception_end(ctx, EXCP_RI);
8676 break;
8679 gen_store_fpr32(ctx, fp0, fd);
8680 tcg_temp_free_i32(fp2);
8681 tcg_temp_free_i32(fp1);
8682 tcg_temp_free_i32(fp0);
8683 tcg_temp_free_i32(t1);
8686 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8687 int fs)
8689 TCGv_i64 t1 = tcg_const_i64(0);
8690 TCGv_i64 fp0 = tcg_temp_new_i64();
8691 TCGv_i64 fp1 = tcg_temp_new_i64();
8692 TCGv_i64 fp2 = tcg_temp_new_i64();
8693 gen_load_fpr64(ctx, fp0, fd);
8694 gen_load_fpr64(ctx, fp1, ft);
8695 gen_load_fpr64(ctx, fp2, fs);
8697 switch (op1) {
8698 case OPC_SEL_D:
8699 tcg_gen_andi_i64(fp0, fp0, 1);
8700 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8701 break;
8702 case OPC_SELEQZ_D:
8703 tcg_gen_andi_i64(fp1, fp1, 1);
8704 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8705 break;
8706 case OPC_SELNEZ_D:
8707 tcg_gen_andi_i64(fp1, fp1, 1);
8708 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8709 break;
8710 default:
8711 MIPS_INVAL("gen_sel_d");
8712 generate_exception_end(ctx, EXCP_RI);
8713 break;
8716 gen_store_fpr64(ctx, fp0, fd);
8717 tcg_temp_free_i64(fp2);
8718 tcg_temp_free_i64(fp1);
8719 tcg_temp_free_i64(fp0);
8720 tcg_temp_free_i64(t1);
8723 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8724 int ft, int fs, int fd, int cc)
8726 uint32_t func = ctx->opcode & 0x3f;
8727 switch (op1) {
8728 case OPC_ADD_S:
8730 TCGv_i32 fp0 = tcg_temp_new_i32();
8731 TCGv_i32 fp1 = tcg_temp_new_i32();
8733 gen_load_fpr32(ctx, fp0, fs);
8734 gen_load_fpr32(ctx, fp1, ft);
8735 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
8736 tcg_temp_free_i32(fp1);
8737 gen_store_fpr32(ctx, fp0, fd);
8738 tcg_temp_free_i32(fp0);
8740 break;
8741 case OPC_SUB_S:
8743 TCGv_i32 fp0 = tcg_temp_new_i32();
8744 TCGv_i32 fp1 = tcg_temp_new_i32();
8746 gen_load_fpr32(ctx, fp0, fs);
8747 gen_load_fpr32(ctx, fp1, ft);
8748 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
8749 tcg_temp_free_i32(fp1);
8750 gen_store_fpr32(ctx, fp0, fd);
8751 tcg_temp_free_i32(fp0);
8753 break;
8754 case OPC_MUL_S:
8756 TCGv_i32 fp0 = tcg_temp_new_i32();
8757 TCGv_i32 fp1 = tcg_temp_new_i32();
8759 gen_load_fpr32(ctx, fp0, fs);
8760 gen_load_fpr32(ctx, fp1, ft);
8761 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
8762 tcg_temp_free_i32(fp1);
8763 gen_store_fpr32(ctx, fp0, fd);
8764 tcg_temp_free_i32(fp0);
8766 break;
8767 case OPC_DIV_S:
8769 TCGv_i32 fp0 = tcg_temp_new_i32();
8770 TCGv_i32 fp1 = tcg_temp_new_i32();
8772 gen_load_fpr32(ctx, fp0, fs);
8773 gen_load_fpr32(ctx, fp1, ft);
8774 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
8775 tcg_temp_free_i32(fp1);
8776 gen_store_fpr32(ctx, fp0, fd);
8777 tcg_temp_free_i32(fp0);
8779 break;
8780 case OPC_SQRT_S:
8782 TCGv_i32 fp0 = tcg_temp_new_i32();
8784 gen_load_fpr32(ctx, fp0, fs);
8785 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
8786 gen_store_fpr32(ctx, fp0, fd);
8787 tcg_temp_free_i32(fp0);
8789 break;
8790 case OPC_ABS_S:
8792 TCGv_i32 fp0 = tcg_temp_new_i32();
8794 gen_load_fpr32(ctx, fp0, fs);
8795 gen_helper_float_abs_s(fp0, fp0);
8796 gen_store_fpr32(ctx, fp0, fd);
8797 tcg_temp_free_i32(fp0);
8799 break;
8800 case OPC_MOV_S:
8802 TCGv_i32 fp0 = tcg_temp_new_i32();
8804 gen_load_fpr32(ctx, fp0, fs);
8805 gen_store_fpr32(ctx, fp0, fd);
8806 tcg_temp_free_i32(fp0);
8808 break;
8809 case OPC_NEG_S:
8811 TCGv_i32 fp0 = tcg_temp_new_i32();
8813 gen_load_fpr32(ctx, fp0, fs);
8814 gen_helper_float_chs_s(fp0, fp0);
8815 gen_store_fpr32(ctx, fp0, fd);
8816 tcg_temp_free_i32(fp0);
8818 break;
8819 case OPC_ROUND_L_S:
8820 check_cp1_64bitmode(ctx);
8822 TCGv_i32 fp32 = tcg_temp_new_i32();
8823 TCGv_i64 fp64 = tcg_temp_new_i64();
8825 gen_load_fpr32(ctx, fp32, fs);
8826 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
8827 tcg_temp_free_i32(fp32);
8828 gen_store_fpr64(ctx, fp64, fd);
8829 tcg_temp_free_i64(fp64);
8831 break;
8832 case OPC_TRUNC_L_S:
8833 check_cp1_64bitmode(ctx);
8835 TCGv_i32 fp32 = tcg_temp_new_i32();
8836 TCGv_i64 fp64 = tcg_temp_new_i64();
8838 gen_load_fpr32(ctx, fp32, fs);
8839 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
8840 tcg_temp_free_i32(fp32);
8841 gen_store_fpr64(ctx, fp64, fd);
8842 tcg_temp_free_i64(fp64);
8844 break;
8845 case OPC_CEIL_L_S:
8846 check_cp1_64bitmode(ctx);
8848 TCGv_i32 fp32 = tcg_temp_new_i32();
8849 TCGv_i64 fp64 = tcg_temp_new_i64();
8851 gen_load_fpr32(ctx, fp32, fs);
8852 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
8853 tcg_temp_free_i32(fp32);
8854 gen_store_fpr64(ctx, fp64, fd);
8855 tcg_temp_free_i64(fp64);
8857 break;
8858 case OPC_FLOOR_L_S:
8859 check_cp1_64bitmode(ctx);
8861 TCGv_i32 fp32 = tcg_temp_new_i32();
8862 TCGv_i64 fp64 = tcg_temp_new_i64();
8864 gen_load_fpr32(ctx, fp32, fs);
8865 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
8866 tcg_temp_free_i32(fp32);
8867 gen_store_fpr64(ctx, fp64, fd);
8868 tcg_temp_free_i64(fp64);
8870 break;
8871 case OPC_ROUND_W_S:
8873 TCGv_i32 fp0 = tcg_temp_new_i32();
8875 gen_load_fpr32(ctx, fp0, fs);
8876 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
8877 gen_store_fpr32(ctx, fp0, fd);
8878 tcg_temp_free_i32(fp0);
8880 break;
8881 case OPC_TRUNC_W_S:
8883 TCGv_i32 fp0 = tcg_temp_new_i32();
8885 gen_load_fpr32(ctx, fp0, fs);
8886 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
8887 gen_store_fpr32(ctx, fp0, fd);
8888 tcg_temp_free_i32(fp0);
8890 break;
8891 case OPC_CEIL_W_S:
8893 TCGv_i32 fp0 = tcg_temp_new_i32();
8895 gen_load_fpr32(ctx, fp0, fs);
8896 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
8897 gen_store_fpr32(ctx, fp0, fd);
8898 tcg_temp_free_i32(fp0);
8900 break;
8901 case OPC_FLOOR_W_S:
8903 TCGv_i32 fp0 = tcg_temp_new_i32();
8905 gen_load_fpr32(ctx, fp0, fs);
8906 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
8907 gen_store_fpr32(ctx, fp0, fd);
8908 tcg_temp_free_i32(fp0);
8910 break;
8911 case OPC_SEL_S:
8912 check_insn(ctx, ISA_MIPS32R6);
8913 gen_sel_s(ctx, op1, fd, ft, fs);
8914 break;
8915 case OPC_SELEQZ_S:
8916 check_insn(ctx, ISA_MIPS32R6);
8917 gen_sel_s(ctx, op1, fd, ft, fs);
8918 break;
8919 case OPC_SELNEZ_S:
8920 check_insn(ctx, ISA_MIPS32R6);
8921 gen_sel_s(ctx, op1, fd, ft, fs);
8922 break;
8923 case OPC_MOVCF_S:
8924 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8925 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
8926 break;
8927 case OPC_MOVZ_S:
8928 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8930 TCGLabel *l1 = gen_new_label();
8931 TCGv_i32 fp0;
8933 if (ft != 0) {
8934 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8936 fp0 = tcg_temp_new_i32();
8937 gen_load_fpr32(ctx, fp0, fs);
8938 gen_store_fpr32(ctx, fp0, fd);
8939 tcg_temp_free_i32(fp0);
8940 gen_set_label(l1);
8942 break;
8943 case OPC_MOVN_S:
8944 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8946 TCGLabel *l1 = gen_new_label();
8947 TCGv_i32 fp0;
8949 if (ft != 0) {
8950 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8951 fp0 = tcg_temp_new_i32();
8952 gen_load_fpr32(ctx, fp0, fs);
8953 gen_store_fpr32(ctx, fp0, fd);
8954 tcg_temp_free_i32(fp0);
8955 gen_set_label(l1);
8958 break;
8959 case OPC_RECIP_S:
8961 TCGv_i32 fp0 = tcg_temp_new_i32();
8963 gen_load_fpr32(ctx, fp0, fs);
8964 gen_helper_float_recip_s(fp0, cpu_env, fp0);
8965 gen_store_fpr32(ctx, fp0, fd);
8966 tcg_temp_free_i32(fp0);
8968 break;
8969 case OPC_RSQRT_S:
8971 TCGv_i32 fp0 = tcg_temp_new_i32();
8973 gen_load_fpr32(ctx, fp0, fs);
8974 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
8975 gen_store_fpr32(ctx, fp0, fd);
8976 tcg_temp_free_i32(fp0);
8978 break;
8979 case OPC_MADDF_S:
8980 check_insn(ctx, ISA_MIPS32R6);
8982 TCGv_i32 fp0 = tcg_temp_new_i32();
8983 TCGv_i32 fp1 = tcg_temp_new_i32();
8984 TCGv_i32 fp2 = tcg_temp_new_i32();
8985 gen_load_fpr32(ctx, fp0, fs);
8986 gen_load_fpr32(ctx, fp1, ft);
8987 gen_load_fpr32(ctx, fp2, fd);
8988 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
8989 gen_store_fpr32(ctx, fp2, fd);
8990 tcg_temp_free_i32(fp2);
8991 tcg_temp_free_i32(fp1);
8992 tcg_temp_free_i32(fp0);
8994 break;
8995 case OPC_MSUBF_S:
8996 check_insn(ctx, ISA_MIPS32R6);
8998 TCGv_i32 fp0 = tcg_temp_new_i32();
8999 TCGv_i32 fp1 = tcg_temp_new_i32();
9000 TCGv_i32 fp2 = tcg_temp_new_i32();
9001 gen_load_fpr32(ctx, fp0, fs);
9002 gen_load_fpr32(ctx, fp1, ft);
9003 gen_load_fpr32(ctx, fp2, fd);
9004 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9005 gen_store_fpr32(ctx, fp2, fd);
9006 tcg_temp_free_i32(fp2);
9007 tcg_temp_free_i32(fp1);
9008 tcg_temp_free_i32(fp0);
9010 break;
9011 case OPC_RINT_S:
9012 check_insn(ctx, ISA_MIPS32R6);
9014 TCGv_i32 fp0 = tcg_temp_new_i32();
9015 gen_load_fpr32(ctx, fp0, fs);
9016 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9017 gen_store_fpr32(ctx, fp0, fd);
9018 tcg_temp_free_i32(fp0);
9020 break;
9021 case OPC_CLASS_S:
9022 check_insn(ctx, ISA_MIPS32R6);
9024 TCGv_i32 fp0 = tcg_temp_new_i32();
9025 gen_load_fpr32(ctx, fp0, fs);
9026 gen_helper_float_class_s(fp0, fp0);
9027 gen_store_fpr32(ctx, fp0, fd);
9028 tcg_temp_free_i32(fp0);
9030 break;
9031 case OPC_MIN_S: /* OPC_RECIP2_S */
9032 if (ctx->insn_flags & ISA_MIPS32R6) {
9033 /* OPC_MIN_S */
9034 TCGv_i32 fp0 = tcg_temp_new_i32();
9035 TCGv_i32 fp1 = tcg_temp_new_i32();
9036 TCGv_i32 fp2 = tcg_temp_new_i32();
9037 gen_load_fpr32(ctx, fp0, fs);
9038 gen_load_fpr32(ctx, fp1, ft);
9039 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9040 gen_store_fpr32(ctx, fp2, fd);
9041 tcg_temp_free_i32(fp2);
9042 tcg_temp_free_i32(fp1);
9043 tcg_temp_free_i32(fp0);
9044 } else {
9045 /* OPC_RECIP2_S */
9046 check_cp1_64bitmode(ctx);
9048 TCGv_i32 fp0 = tcg_temp_new_i32();
9049 TCGv_i32 fp1 = tcg_temp_new_i32();
9051 gen_load_fpr32(ctx, fp0, fs);
9052 gen_load_fpr32(ctx, fp1, ft);
9053 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9054 tcg_temp_free_i32(fp1);
9055 gen_store_fpr32(ctx, fp0, fd);
9056 tcg_temp_free_i32(fp0);
9059 break;
9060 case OPC_MINA_S: /* OPC_RECIP1_S */
9061 if (ctx->insn_flags & ISA_MIPS32R6) {
9062 /* OPC_MINA_S */
9063 TCGv_i32 fp0 = tcg_temp_new_i32();
9064 TCGv_i32 fp1 = tcg_temp_new_i32();
9065 TCGv_i32 fp2 = tcg_temp_new_i32();
9066 gen_load_fpr32(ctx, fp0, fs);
9067 gen_load_fpr32(ctx, fp1, ft);
9068 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9069 gen_store_fpr32(ctx, fp2, fd);
9070 tcg_temp_free_i32(fp2);
9071 tcg_temp_free_i32(fp1);
9072 tcg_temp_free_i32(fp0);
9073 } else {
9074 /* OPC_RECIP1_S */
9075 check_cp1_64bitmode(ctx);
9077 TCGv_i32 fp0 = tcg_temp_new_i32();
9079 gen_load_fpr32(ctx, fp0, fs);
9080 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9081 gen_store_fpr32(ctx, fp0, fd);
9082 tcg_temp_free_i32(fp0);
9085 break;
9086 case OPC_MAX_S: /* OPC_RSQRT1_S */
9087 if (ctx->insn_flags & ISA_MIPS32R6) {
9088 /* OPC_MAX_S */
9089 TCGv_i32 fp0 = tcg_temp_new_i32();
9090 TCGv_i32 fp1 = tcg_temp_new_i32();
9091 gen_load_fpr32(ctx, fp0, fs);
9092 gen_load_fpr32(ctx, fp1, ft);
9093 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9094 gen_store_fpr32(ctx, fp1, fd);
9095 tcg_temp_free_i32(fp1);
9096 tcg_temp_free_i32(fp0);
9097 } else {
9098 /* OPC_RSQRT1_S */
9099 check_cp1_64bitmode(ctx);
9101 TCGv_i32 fp0 = tcg_temp_new_i32();
9103 gen_load_fpr32(ctx, fp0, fs);
9104 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9105 gen_store_fpr32(ctx, fp0, fd);
9106 tcg_temp_free_i32(fp0);
9109 break;
9110 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9111 if (ctx->insn_flags & ISA_MIPS32R6) {
9112 /* OPC_MAXA_S */
9113 TCGv_i32 fp0 = tcg_temp_new_i32();
9114 TCGv_i32 fp1 = tcg_temp_new_i32();
9115 gen_load_fpr32(ctx, fp0, fs);
9116 gen_load_fpr32(ctx, fp1, ft);
9117 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9118 gen_store_fpr32(ctx, fp1, fd);
9119 tcg_temp_free_i32(fp1);
9120 tcg_temp_free_i32(fp0);
9121 } else {
9122 /* OPC_RSQRT2_S */
9123 check_cp1_64bitmode(ctx);
9125 TCGv_i32 fp0 = tcg_temp_new_i32();
9126 TCGv_i32 fp1 = tcg_temp_new_i32();
9128 gen_load_fpr32(ctx, fp0, fs);
9129 gen_load_fpr32(ctx, fp1, ft);
9130 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9131 tcg_temp_free_i32(fp1);
9132 gen_store_fpr32(ctx, fp0, fd);
9133 tcg_temp_free_i32(fp0);
9136 break;
9137 case OPC_CVT_D_S:
9138 check_cp1_registers(ctx, fd);
9140 TCGv_i32 fp32 = tcg_temp_new_i32();
9141 TCGv_i64 fp64 = tcg_temp_new_i64();
9143 gen_load_fpr32(ctx, fp32, fs);
9144 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9145 tcg_temp_free_i32(fp32);
9146 gen_store_fpr64(ctx, fp64, fd);
9147 tcg_temp_free_i64(fp64);
9149 break;
9150 case OPC_CVT_W_S:
9152 TCGv_i32 fp0 = tcg_temp_new_i32();
9154 gen_load_fpr32(ctx, fp0, fs);
9155 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
9156 gen_store_fpr32(ctx, fp0, fd);
9157 tcg_temp_free_i32(fp0);
9159 break;
9160 case OPC_CVT_L_S:
9161 check_cp1_64bitmode(ctx);
9163 TCGv_i32 fp32 = tcg_temp_new_i32();
9164 TCGv_i64 fp64 = tcg_temp_new_i64();
9166 gen_load_fpr32(ctx, fp32, fs);
9167 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
9168 tcg_temp_free_i32(fp32);
9169 gen_store_fpr64(ctx, fp64, fd);
9170 tcg_temp_free_i64(fp64);
9172 break;
9173 case OPC_CVT_PS_S:
9174 check_ps(ctx);
9176 TCGv_i64 fp64 = tcg_temp_new_i64();
9177 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9178 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9180 gen_load_fpr32(ctx, fp32_0, fs);
9181 gen_load_fpr32(ctx, fp32_1, ft);
9182 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9183 tcg_temp_free_i32(fp32_1);
9184 tcg_temp_free_i32(fp32_0);
9185 gen_store_fpr64(ctx, fp64, fd);
9186 tcg_temp_free_i64(fp64);
9188 break;
9189 case OPC_CMP_F_S:
9190 case OPC_CMP_UN_S:
9191 case OPC_CMP_EQ_S:
9192 case OPC_CMP_UEQ_S:
9193 case OPC_CMP_OLT_S:
9194 case OPC_CMP_ULT_S:
9195 case OPC_CMP_OLE_S:
9196 case OPC_CMP_ULE_S:
9197 case OPC_CMP_SF_S:
9198 case OPC_CMP_NGLE_S:
9199 case OPC_CMP_SEQ_S:
9200 case OPC_CMP_NGL_S:
9201 case OPC_CMP_LT_S:
9202 case OPC_CMP_NGE_S:
9203 case OPC_CMP_LE_S:
9204 case OPC_CMP_NGT_S:
9205 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9206 if (ctx->opcode & (1 << 6)) {
9207 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9208 } else {
9209 gen_cmp_s(ctx, func-48, ft, fs, cc);
9211 break;
9212 case OPC_ADD_D:
9213 check_cp1_registers(ctx, fs | ft | fd);
9215 TCGv_i64 fp0 = tcg_temp_new_i64();
9216 TCGv_i64 fp1 = tcg_temp_new_i64();
9218 gen_load_fpr64(ctx, fp0, fs);
9219 gen_load_fpr64(ctx, fp1, ft);
9220 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9221 tcg_temp_free_i64(fp1);
9222 gen_store_fpr64(ctx, fp0, fd);
9223 tcg_temp_free_i64(fp0);
9225 break;
9226 case OPC_SUB_D:
9227 check_cp1_registers(ctx, fs | ft | fd);
9229 TCGv_i64 fp0 = tcg_temp_new_i64();
9230 TCGv_i64 fp1 = tcg_temp_new_i64();
9232 gen_load_fpr64(ctx, fp0, fs);
9233 gen_load_fpr64(ctx, fp1, ft);
9234 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9235 tcg_temp_free_i64(fp1);
9236 gen_store_fpr64(ctx, fp0, fd);
9237 tcg_temp_free_i64(fp0);
9239 break;
9240 case OPC_MUL_D:
9241 check_cp1_registers(ctx, fs | ft | fd);
9243 TCGv_i64 fp0 = tcg_temp_new_i64();
9244 TCGv_i64 fp1 = tcg_temp_new_i64();
9246 gen_load_fpr64(ctx, fp0, fs);
9247 gen_load_fpr64(ctx, fp1, ft);
9248 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9249 tcg_temp_free_i64(fp1);
9250 gen_store_fpr64(ctx, fp0, fd);
9251 tcg_temp_free_i64(fp0);
9253 break;
9254 case OPC_DIV_D:
9255 check_cp1_registers(ctx, fs | ft | fd);
9257 TCGv_i64 fp0 = tcg_temp_new_i64();
9258 TCGv_i64 fp1 = tcg_temp_new_i64();
9260 gen_load_fpr64(ctx, fp0, fs);
9261 gen_load_fpr64(ctx, fp1, ft);
9262 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9263 tcg_temp_free_i64(fp1);
9264 gen_store_fpr64(ctx, fp0, fd);
9265 tcg_temp_free_i64(fp0);
9267 break;
9268 case OPC_SQRT_D:
9269 check_cp1_registers(ctx, fs | fd);
9271 TCGv_i64 fp0 = tcg_temp_new_i64();
9273 gen_load_fpr64(ctx, fp0, fs);
9274 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9275 gen_store_fpr64(ctx, fp0, fd);
9276 tcg_temp_free_i64(fp0);
9278 break;
9279 case OPC_ABS_D:
9280 check_cp1_registers(ctx, fs | fd);
9282 TCGv_i64 fp0 = tcg_temp_new_i64();
9284 gen_load_fpr64(ctx, fp0, fs);
9285 gen_helper_float_abs_d(fp0, fp0);
9286 gen_store_fpr64(ctx, fp0, fd);
9287 tcg_temp_free_i64(fp0);
9289 break;
9290 case OPC_MOV_D:
9291 check_cp1_registers(ctx, fs | fd);
9293 TCGv_i64 fp0 = tcg_temp_new_i64();
9295 gen_load_fpr64(ctx, fp0, fs);
9296 gen_store_fpr64(ctx, fp0, fd);
9297 tcg_temp_free_i64(fp0);
9299 break;
9300 case OPC_NEG_D:
9301 check_cp1_registers(ctx, fs | fd);
9303 TCGv_i64 fp0 = tcg_temp_new_i64();
9305 gen_load_fpr64(ctx, fp0, fs);
9306 gen_helper_float_chs_d(fp0, fp0);
9307 gen_store_fpr64(ctx, fp0, fd);
9308 tcg_temp_free_i64(fp0);
9310 break;
9311 case OPC_ROUND_L_D:
9312 check_cp1_64bitmode(ctx);
9314 TCGv_i64 fp0 = tcg_temp_new_i64();
9316 gen_load_fpr64(ctx, fp0, fs);
9317 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
9318 gen_store_fpr64(ctx, fp0, fd);
9319 tcg_temp_free_i64(fp0);
9321 break;
9322 case OPC_TRUNC_L_D:
9323 check_cp1_64bitmode(ctx);
9325 TCGv_i64 fp0 = tcg_temp_new_i64();
9327 gen_load_fpr64(ctx, fp0, fs);
9328 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
9329 gen_store_fpr64(ctx, fp0, fd);
9330 tcg_temp_free_i64(fp0);
9332 break;
9333 case OPC_CEIL_L_D:
9334 check_cp1_64bitmode(ctx);
9336 TCGv_i64 fp0 = tcg_temp_new_i64();
9338 gen_load_fpr64(ctx, fp0, fs);
9339 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
9340 gen_store_fpr64(ctx, fp0, fd);
9341 tcg_temp_free_i64(fp0);
9343 break;
9344 case OPC_FLOOR_L_D:
9345 check_cp1_64bitmode(ctx);
9347 TCGv_i64 fp0 = tcg_temp_new_i64();
9349 gen_load_fpr64(ctx, fp0, fs);
9350 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
9351 gen_store_fpr64(ctx, fp0, fd);
9352 tcg_temp_free_i64(fp0);
9354 break;
9355 case OPC_ROUND_W_D:
9356 check_cp1_registers(ctx, fs);
9358 TCGv_i32 fp32 = tcg_temp_new_i32();
9359 TCGv_i64 fp64 = tcg_temp_new_i64();
9361 gen_load_fpr64(ctx, fp64, fs);
9362 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
9363 tcg_temp_free_i64(fp64);
9364 gen_store_fpr32(ctx, fp32, fd);
9365 tcg_temp_free_i32(fp32);
9367 break;
9368 case OPC_TRUNC_W_D:
9369 check_cp1_registers(ctx, fs);
9371 TCGv_i32 fp32 = tcg_temp_new_i32();
9372 TCGv_i64 fp64 = tcg_temp_new_i64();
9374 gen_load_fpr64(ctx, fp64, fs);
9375 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
9376 tcg_temp_free_i64(fp64);
9377 gen_store_fpr32(ctx, fp32, fd);
9378 tcg_temp_free_i32(fp32);
9380 break;
9381 case OPC_CEIL_W_D:
9382 check_cp1_registers(ctx, fs);
9384 TCGv_i32 fp32 = tcg_temp_new_i32();
9385 TCGv_i64 fp64 = tcg_temp_new_i64();
9387 gen_load_fpr64(ctx, fp64, fs);
9388 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
9389 tcg_temp_free_i64(fp64);
9390 gen_store_fpr32(ctx, fp32, fd);
9391 tcg_temp_free_i32(fp32);
9393 break;
9394 case OPC_FLOOR_W_D:
9395 check_cp1_registers(ctx, fs);
9397 TCGv_i32 fp32 = tcg_temp_new_i32();
9398 TCGv_i64 fp64 = tcg_temp_new_i64();
9400 gen_load_fpr64(ctx, fp64, fs);
9401 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
9402 tcg_temp_free_i64(fp64);
9403 gen_store_fpr32(ctx, fp32, fd);
9404 tcg_temp_free_i32(fp32);
9406 break;
9407 case OPC_SEL_D:
9408 check_insn(ctx, ISA_MIPS32R6);
9409 gen_sel_d(ctx, op1, fd, ft, fs);
9410 break;
9411 case OPC_SELEQZ_D:
9412 check_insn(ctx, ISA_MIPS32R6);
9413 gen_sel_d(ctx, op1, fd, ft, fs);
9414 break;
9415 case OPC_SELNEZ_D:
9416 check_insn(ctx, ISA_MIPS32R6);
9417 gen_sel_d(ctx, op1, fd, ft, fs);
9418 break;
9419 case OPC_MOVCF_D:
9420 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9421 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9422 break;
9423 case OPC_MOVZ_D:
9424 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9426 TCGLabel *l1 = gen_new_label();
9427 TCGv_i64 fp0;
9429 if (ft != 0) {
9430 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9432 fp0 = tcg_temp_new_i64();
9433 gen_load_fpr64(ctx, fp0, fs);
9434 gen_store_fpr64(ctx, fp0, fd);
9435 tcg_temp_free_i64(fp0);
9436 gen_set_label(l1);
9438 break;
9439 case OPC_MOVN_D:
9440 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9442 TCGLabel *l1 = gen_new_label();
9443 TCGv_i64 fp0;
9445 if (ft != 0) {
9446 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9447 fp0 = tcg_temp_new_i64();
9448 gen_load_fpr64(ctx, fp0, fs);
9449 gen_store_fpr64(ctx, fp0, fd);
9450 tcg_temp_free_i64(fp0);
9451 gen_set_label(l1);
9454 break;
9455 case OPC_RECIP_D:
9456 check_cp1_registers(ctx, fs | fd);
9458 TCGv_i64 fp0 = tcg_temp_new_i64();
9460 gen_load_fpr64(ctx, fp0, fs);
9461 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9462 gen_store_fpr64(ctx, fp0, fd);
9463 tcg_temp_free_i64(fp0);
9465 break;
9466 case OPC_RSQRT_D:
9467 check_cp1_registers(ctx, fs | fd);
9469 TCGv_i64 fp0 = tcg_temp_new_i64();
9471 gen_load_fpr64(ctx, fp0, fs);
9472 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9473 gen_store_fpr64(ctx, fp0, fd);
9474 tcg_temp_free_i64(fp0);
9476 break;
9477 case OPC_MADDF_D:
9478 check_insn(ctx, ISA_MIPS32R6);
9480 TCGv_i64 fp0 = tcg_temp_new_i64();
9481 TCGv_i64 fp1 = tcg_temp_new_i64();
9482 TCGv_i64 fp2 = tcg_temp_new_i64();
9483 gen_load_fpr64(ctx, fp0, fs);
9484 gen_load_fpr64(ctx, fp1, ft);
9485 gen_load_fpr64(ctx, fp2, fd);
9486 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9487 gen_store_fpr64(ctx, fp2, fd);
9488 tcg_temp_free_i64(fp2);
9489 tcg_temp_free_i64(fp1);
9490 tcg_temp_free_i64(fp0);
9492 break;
9493 case OPC_MSUBF_D:
9494 check_insn(ctx, ISA_MIPS32R6);
9496 TCGv_i64 fp0 = tcg_temp_new_i64();
9497 TCGv_i64 fp1 = tcg_temp_new_i64();
9498 TCGv_i64 fp2 = tcg_temp_new_i64();
9499 gen_load_fpr64(ctx, fp0, fs);
9500 gen_load_fpr64(ctx, fp1, ft);
9501 gen_load_fpr64(ctx, fp2, fd);
9502 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9503 gen_store_fpr64(ctx, fp2, fd);
9504 tcg_temp_free_i64(fp2);
9505 tcg_temp_free_i64(fp1);
9506 tcg_temp_free_i64(fp0);
9508 break;
9509 case OPC_RINT_D:
9510 check_insn(ctx, ISA_MIPS32R6);
9512 TCGv_i64 fp0 = tcg_temp_new_i64();
9513 gen_load_fpr64(ctx, fp0, fs);
9514 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9515 gen_store_fpr64(ctx, fp0, fd);
9516 tcg_temp_free_i64(fp0);
9518 break;
9519 case OPC_CLASS_D:
9520 check_insn(ctx, ISA_MIPS32R6);
9522 TCGv_i64 fp0 = tcg_temp_new_i64();
9523 gen_load_fpr64(ctx, fp0, fs);
9524 gen_helper_float_class_d(fp0, fp0);
9525 gen_store_fpr64(ctx, fp0, fd);
9526 tcg_temp_free_i64(fp0);
9528 break;
9529 case OPC_MIN_D: /* OPC_RECIP2_D */
9530 if (ctx->insn_flags & ISA_MIPS32R6) {
9531 /* OPC_MIN_D */
9532 TCGv_i64 fp0 = tcg_temp_new_i64();
9533 TCGv_i64 fp1 = tcg_temp_new_i64();
9534 gen_load_fpr64(ctx, fp0, fs);
9535 gen_load_fpr64(ctx, fp1, ft);
9536 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9537 gen_store_fpr64(ctx, fp1, fd);
9538 tcg_temp_free_i64(fp1);
9539 tcg_temp_free_i64(fp0);
9540 } else {
9541 /* OPC_RECIP2_D */
9542 check_cp1_64bitmode(ctx);
9544 TCGv_i64 fp0 = tcg_temp_new_i64();
9545 TCGv_i64 fp1 = tcg_temp_new_i64();
9547 gen_load_fpr64(ctx, fp0, fs);
9548 gen_load_fpr64(ctx, fp1, ft);
9549 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9550 tcg_temp_free_i64(fp1);
9551 gen_store_fpr64(ctx, fp0, fd);
9552 tcg_temp_free_i64(fp0);
9555 break;
9556 case OPC_MINA_D: /* OPC_RECIP1_D */
9557 if (ctx->insn_flags & ISA_MIPS32R6) {
9558 /* OPC_MINA_D */
9559 TCGv_i64 fp0 = tcg_temp_new_i64();
9560 TCGv_i64 fp1 = tcg_temp_new_i64();
9561 gen_load_fpr64(ctx, fp0, fs);
9562 gen_load_fpr64(ctx, fp1, ft);
9563 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9564 gen_store_fpr64(ctx, fp1, fd);
9565 tcg_temp_free_i64(fp1);
9566 tcg_temp_free_i64(fp0);
9567 } else {
9568 /* OPC_RECIP1_D */
9569 check_cp1_64bitmode(ctx);
9571 TCGv_i64 fp0 = tcg_temp_new_i64();
9573 gen_load_fpr64(ctx, fp0, fs);
9574 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9575 gen_store_fpr64(ctx, fp0, fd);
9576 tcg_temp_free_i64(fp0);
9579 break;
9580 case OPC_MAX_D: /* OPC_RSQRT1_D */
9581 if (ctx->insn_flags & ISA_MIPS32R6) {
9582 /* OPC_MAX_D */
9583 TCGv_i64 fp0 = tcg_temp_new_i64();
9584 TCGv_i64 fp1 = tcg_temp_new_i64();
9585 gen_load_fpr64(ctx, fp0, fs);
9586 gen_load_fpr64(ctx, fp1, ft);
9587 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9588 gen_store_fpr64(ctx, fp1, fd);
9589 tcg_temp_free_i64(fp1);
9590 tcg_temp_free_i64(fp0);
9591 } else {
9592 /* OPC_RSQRT1_D */
9593 check_cp1_64bitmode(ctx);
9595 TCGv_i64 fp0 = tcg_temp_new_i64();
9597 gen_load_fpr64(ctx, fp0, fs);
9598 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9599 gen_store_fpr64(ctx, fp0, fd);
9600 tcg_temp_free_i64(fp0);
9603 break;
9604 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9605 if (ctx->insn_flags & ISA_MIPS32R6) {
9606 /* OPC_MAXA_D */
9607 TCGv_i64 fp0 = tcg_temp_new_i64();
9608 TCGv_i64 fp1 = tcg_temp_new_i64();
9609 gen_load_fpr64(ctx, fp0, fs);
9610 gen_load_fpr64(ctx, fp1, ft);
9611 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9612 gen_store_fpr64(ctx, fp1, fd);
9613 tcg_temp_free_i64(fp1);
9614 tcg_temp_free_i64(fp0);
9615 } else {
9616 /* OPC_RSQRT2_D */
9617 check_cp1_64bitmode(ctx);
9619 TCGv_i64 fp0 = tcg_temp_new_i64();
9620 TCGv_i64 fp1 = tcg_temp_new_i64();
9622 gen_load_fpr64(ctx, fp0, fs);
9623 gen_load_fpr64(ctx, fp1, ft);
9624 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9625 tcg_temp_free_i64(fp1);
9626 gen_store_fpr64(ctx, fp0, fd);
9627 tcg_temp_free_i64(fp0);
9630 break;
9631 case OPC_CMP_F_D:
9632 case OPC_CMP_UN_D:
9633 case OPC_CMP_EQ_D:
9634 case OPC_CMP_UEQ_D:
9635 case OPC_CMP_OLT_D:
9636 case OPC_CMP_ULT_D:
9637 case OPC_CMP_OLE_D:
9638 case OPC_CMP_ULE_D:
9639 case OPC_CMP_SF_D:
9640 case OPC_CMP_NGLE_D:
9641 case OPC_CMP_SEQ_D:
9642 case OPC_CMP_NGL_D:
9643 case OPC_CMP_LT_D:
9644 case OPC_CMP_NGE_D:
9645 case OPC_CMP_LE_D:
9646 case OPC_CMP_NGT_D:
9647 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9648 if (ctx->opcode & (1 << 6)) {
9649 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9650 } else {
9651 gen_cmp_d(ctx, func-48, ft, fs, cc);
9653 break;
9654 case OPC_CVT_S_D:
9655 check_cp1_registers(ctx, fs);
9657 TCGv_i32 fp32 = tcg_temp_new_i32();
9658 TCGv_i64 fp64 = tcg_temp_new_i64();
9660 gen_load_fpr64(ctx, fp64, fs);
9661 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
9662 tcg_temp_free_i64(fp64);
9663 gen_store_fpr32(ctx, fp32, fd);
9664 tcg_temp_free_i32(fp32);
9666 break;
9667 case OPC_CVT_W_D:
9668 check_cp1_registers(ctx, fs);
9670 TCGv_i32 fp32 = tcg_temp_new_i32();
9671 TCGv_i64 fp64 = tcg_temp_new_i64();
9673 gen_load_fpr64(ctx, fp64, fs);
9674 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
9675 tcg_temp_free_i64(fp64);
9676 gen_store_fpr32(ctx, fp32, fd);
9677 tcg_temp_free_i32(fp32);
9679 break;
9680 case OPC_CVT_L_D:
9681 check_cp1_64bitmode(ctx);
9683 TCGv_i64 fp0 = tcg_temp_new_i64();
9685 gen_load_fpr64(ctx, fp0, fs);
9686 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
9687 gen_store_fpr64(ctx, fp0, fd);
9688 tcg_temp_free_i64(fp0);
9690 break;
9691 case OPC_CVT_S_W:
9693 TCGv_i32 fp0 = tcg_temp_new_i32();
9695 gen_load_fpr32(ctx, fp0, fs);
9696 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
9697 gen_store_fpr32(ctx, fp0, fd);
9698 tcg_temp_free_i32(fp0);
9700 break;
9701 case OPC_CVT_D_W:
9702 check_cp1_registers(ctx, fd);
9704 TCGv_i32 fp32 = tcg_temp_new_i32();
9705 TCGv_i64 fp64 = tcg_temp_new_i64();
9707 gen_load_fpr32(ctx, fp32, fs);
9708 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
9709 tcg_temp_free_i32(fp32);
9710 gen_store_fpr64(ctx, fp64, fd);
9711 tcg_temp_free_i64(fp64);
9713 break;
9714 case OPC_CVT_S_L:
9715 check_cp1_64bitmode(ctx);
9717 TCGv_i32 fp32 = tcg_temp_new_i32();
9718 TCGv_i64 fp64 = tcg_temp_new_i64();
9720 gen_load_fpr64(ctx, fp64, fs);
9721 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
9722 tcg_temp_free_i64(fp64);
9723 gen_store_fpr32(ctx, fp32, fd);
9724 tcg_temp_free_i32(fp32);
9726 break;
9727 case OPC_CVT_D_L:
9728 check_cp1_64bitmode(ctx);
9730 TCGv_i64 fp0 = tcg_temp_new_i64();
9732 gen_load_fpr64(ctx, fp0, fs);
9733 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
9734 gen_store_fpr64(ctx, fp0, fd);
9735 tcg_temp_free_i64(fp0);
9737 break;
9738 case OPC_CVT_PS_PW:
9739 check_ps(ctx);
9741 TCGv_i64 fp0 = tcg_temp_new_i64();
9743 gen_load_fpr64(ctx, fp0, fs);
9744 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
9745 gen_store_fpr64(ctx, fp0, fd);
9746 tcg_temp_free_i64(fp0);
9748 break;
9749 case OPC_ADD_PS:
9750 check_ps(ctx);
9752 TCGv_i64 fp0 = tcg_temp_new_i64();
9753 TCGv_i64 fp1 = tcg_temp_new_i64();
9755 gen_load_fpr64(ctx, fp0, fs);
9756 gen_load_fpr64(ctx, fp1, ft);
9757 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
9758 tcg_temp_free_i64(fp1);
9759 gen_store_fpr64(ctx, fp0, fd);
9760 tcg_temp_free_i64(fp0);
9762 break;
9763 case OPC_SUB_PS:
9764 check_ps(ctx);
9766 TCGv_i64 fp0 = tcg_temp_new_i64();
9767 TCGv_i64 fp1 = tcg_temp_new_i64();
9769 gen_load_fpr64(ctx, fp0, fs);
9770 gen_load_fpr64(ctx, fp1, ft);
9771 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
9772 tcg_temp_free_i64(fp1);
9773 gen_store_fpr64(ctx, fp0, fd);
9774 tcg_temp_free_i64(fp0);
9776 break;
9777 case OPC_MUL_PS:
9778 check_ps(ctx);
9780 TCGv_i64 fp0 = tcg_temp_new_i64();
9781 TCGv_i64 fp1 = tcg_temp_new_i64();
9783 gen_load_fpr64(ctx, fp0, fs);
9784 gen_load_fpr64(ctx, fp1, ft);
9785 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
9786 tcg_temp_free_i64(fp1);
9787 gen_store_fpr64(ctx, fp0, fd);
9788 tcg_temp_free_i64(fp0);
9790 break;
9791 case OPC_ABS_PS:
9792 check_ps(ctx);
9794 TCGv_i64 fp0 = tcg_temp_new_i64();
9796 gen_load_fpr64(ctx, fp0, fs);
9797 gen_helper_float_abs_ps(fp0, fp0);
9798 gen_store_fpr64(ctx, fp0, fd);
9799 tcg_temp_free_i64(fp0);
9801 break;
9802 case OPC_MOV_PS:
9803 check_ps(ctx);
9805 TCGv_i64 fp0 = tcg_temp_new_i64();
9807 gen_load_fpr64(ctx, fp0, fs);
9808 gen_store_fpr64(ctx, fp0, fd);
9809 tcg_temp_free_i64(fp0);
9811 break;
9812 case OPC_NEG_PS:
9813 check_ps(ctx);
9815 TCGv_i64 fp0 = tcg_temp_new_i64();
9817 gen_load_fpr64(ctx, fp0, fs);
9818 gen_helper_float_chs_ps(fp0, fp0);
9819 gen_store_fpr64(ctx, fp0, fd);
9820 tcg_temp_free_i64(fp0);
9822 break;
9823 case OPC_MOVCF_PS:
9824 check_ps(ctx);
9825 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9826 break;
9827 case OPC_MOVZ_PS:
9828 check_ps(ctx);
9830 TCGLabel *l1 = gen_new_label();
9831 TCGv_i64 fp0;
9833 if (ft != 0)
9834 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9835 fp0 = tcg_temp_new_i64();
9836 gen_load_fpr64(ctx, fp0, fs);
9837 gen_store_fpr64(ctx, fp0, fd);
9838 tcg_temp_free_i64(fp0);
9839 gen_set_label(l1);
9841 break;
9842 case OPC_MOVN_PS:
9843 check_ps(ctx);
9845 TCGLabel *l1 = gen_new_label();
9846 TCGv_i64 fp0;
9848 if (ft != 0) {
9849 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9850 fp0 = tcg_temp_new_i64();
9851 gen_load_fpr64(ctx, fp0, fs);
9852 gen_store_fpr64(ctx, fp0, fd);
9853 tcg_temp_free_i64(fp0);
9854 gen_set_label(l1);
9857 break;
9858 case OPC_ADDR_PS:
9859 check_ps(ctx);
9861 TCGv_i64 fp0 = tcg_temp_new_i64();
9862 TCGv_i64 fp1 = tcg_temp_new_i64();
9864 gen_load_fpr64(ctx, fp0, ft);
9865 gen_load_fpr64(ctx, fp1, fs);
9866 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
9867 tcg_temp_free_i64(fp1);
9868 gen_store_fpr64(ctx, fp0, fd);
9869 tcg_temp_free_i64(fp0);
9871 break;
9872 case OPC_MULR_PS:
9873 check_ps(ctx);
9875 TCGv_i64 fp0 = tcg_temp_new_i64();
9876 TCGv_i64 fp1 = tcg_temp_new_i64();
9878 gen_load_fpr64(ctx, fp0, ft);
9879 gen_load_fpr64(ctx, fp1, fs);
9880 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
9881 tcg_temp_free_i64(fp1);
9882 gen_store_fpr64(ctx, fp0, fd);
9883 tcg_temp_free_i64(fp0);
9885 break;
9886 case OPC_RECIP2_PS:
9887 check_ps(ctx);
9889 TCGv_i64 fp0 = tcg_temp_new_i64();
9890 TCGv_i64 fp1 = tcg_temp_new_i64();
9892 gen_load_fpr64(ctx, fp0, fs);
9893 gen_load_fpr64(ctx, fp1, ft);
9894 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
9895 tcg_temp_free_i64(fp1);
9896 gen_store_fpr64(ctx, fp0, fd);
9897 tcg_temp_free_i64(fp0);
9899 break;
9900 case OPC_RECIP1_PS:
9901 check_ps(ctx);
9903 TCGv_i64 fp0 = tcg_temp_new_i64();
9905 gen_load_fpr64(ctx, fp0, fs);
9906 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
9907 gen_store_fpr64(ctx, fp0, fd);
9908 tcg_temp_free_i64(fp0);
9910 break;
9911 case OPC_RSQRT1_PS:
9912 check_ps(ctx);
9914 TCGv_i64 fp0 = tcg_temp_new_i64();
9916 gen_load_fpr64(ctx, fp0, fs);
9917 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
9918 gen_store_fpr64(ctx, fp0, fd);
9919 tcg_temp_free_i64(fp0);
9921 break;
9922 case OPC_RSQRT2_PS:
9923 check_ps(ctx);
9925 TCGv_i64 fp0 = tcg_temp_new_i64();
9926 TCGv_i64 fp1 = tcg_temp_new_i64();
9928 gen_load_fpr64(ctx, fp0, fs);
9929 gen_load_fpr64(ctx, fp1, ft);
9930 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
9931 tcg_temp_free_i64(fp1);
9932 gen_store_fpr64(ctx, fp0, fd);
9933 tcg_temp_free_i64(fp0);
9935 break;
9936 case OPC_CVT_S_PU:
9937 check_cp1_64bitmode(ctx);
9939 TCGv_i32 fp0 = tcg_temp_new_i32();
9941 gen_load_fpr32h(ctx, fp0, fs);
9942 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
9943 gen_store_fpr32(ctx, fp0, fd);
9944 tcg_temp_free_i32(fp0);
9946 break;
9947 case OPC_CVT_PW_PS:
9948 check_ps(ctx);
9950 TCGv_i64 fp0 = tcg_temp_new_i64();
9952 gen_load_fpr64(ctx, fp0, fs);
9953 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
9954 gen_store_fpr64(ctx, fp0, fd);
9955 tcg_temp_free_i64(fp0);
9957 break;
9958 case OPC_CVT_S_PL:
9959 check_cp1_64bitmode(ctx);
9961 TCGv_i32 fp0 = tcg_temp_new_i32();
9963 gen_load_fpr32(ctx, fp0, fs);
9964 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
9965 gen_store_fpr32(ctx, fp0, fd);
9966 tcg_temp_free_i32(fp0);
9968 break;
9969 case OPC_PLL_PS:
9970 check_ps(ctx);
9972 TCGv_i32 fp0 = tcg_temp_new_i32();
9973 TCGv_i32 fp1 = tcg_temp_new_i32();
9975 gen_load_fpr32(ctx, fp0, fs);
9976 gen_load_fpr32(ctx, fp1, ft);
9977 gen_store_fpr32h(ctx, fp0, fd);
9978 gen_store_fpr32(ctx, fp1, fd);
9979 tcg_temp_free_i32(fp0);
9980 tcg_temp_free_i32(fp1);
9982 break;
9983 case OPC_PLU_PS:
9984 check_ps(ctx);
9986 TCGv_i32 fp0 = tcg_temp_new_i32();
9987 TCGv_i32 fp1 = tcg_temp_new_i32();
9989 gen_load_fpr32(ctx, fp0, fs);
9990 gen_load_fpr32h(ctx, fp1, ft);
9991 gen_store_fpr32(ctx, fp1, fd);
9992 gen_store_fpr32h(ctx, fp0, fd);
9993 tcg_temp_free_i32(fp0);
9994 tcg_temp_free_i32(fp1);
9996 break;
9997 case OPC_PUL_PS:
9998 check_ps(ctx);
10000 TCGv_i32 fp0 = tcg_temp_new_i32();
10001 TCGv_i32 fp1 = tcg_temp_new_i32();
10003 gen_load_fpr32h(ctx, fp0, fs);
10004 gen_load_fpr32(ctx, fp1, ft);
10005 gen_store_fpr32(ctx, fp1, fd);
10006 gen_store_fpr32h(ctx, fp0, fd);
10007 tcg_temp_free_i32(fp0);
10008 tcg_temp_free_i32(fp1);
10010 break;
10011 case OPC_PUU_PS:
10012 check_ps(ctx);
10014 TCGv_i32 fp0 = tcg_temp_new_i32();
10015 TCGv_i32 fp1 = tcg_temp_new_i32();
10017 gen_load_fpr32h(ctx, fp0, fs);
10018 gen_load_fpr32h(ctx, fp1, ft);
10019 gen_store_fpr32(ctx, fp1, fd);
10020 gen_store_fpr32h(ctx, fp0, fd);
10021 tcg_temp_free_i32(fp0);
10022 tcg_temp_free_i32(fp1);
10024 break;
10025 case OPC_CMP_F_PS:
10026 case OPC_CMP_UN_PS:
10027 case OPC_CMP_EQ_PS:
10028 case OPC_CMP_UEQ_PS:
10029 case OPC_CMP_OLT_PS:
10030 case OPC_CMP_ULT_PS:
10031 case OPC_CMP_OLE_PS:
10032 case OPC_CMP_ULE_PS:
10033 case OPC_CMP_SF_PS:
10034 case OPC_CMP_NGLE_PS:
10035 case OPC_CMP_SEQ_PS:
10036 case OPC_CMP_NGL_PS:
10037 case OPC_CMP_LT_PS:
10038 case OPC_CMP_NGE_PS:
10039 case OPC_CMP_LE_PS:
10040 case OPC_CMP_NGT_PS:
10041 if (ctx->opcode & (1 << 6)) {
10042 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10043 } else {
10044 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10046 break;
10047 default:
10048 MIPS_INVAL("farith");
10049 generate_exception_end(ctx, EXCP_RI);
10050 return;
10054 /* Coprocessor 3 (FPU) */
10055 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10056 int fd, int fs, int base, int index)
10058 TCGv t0 = tcg_temp_new();
10060 if (base == 0) {
10061 gen_load_gpr(t0, index);
10062 } else if (index == 0) {
10063 gen_load_gpr(t0, base);
10064 } else {
10065 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10067 /* Don't do NOP if destination is zero: we must perform the actual
10068 memory access. */
10069 switch (opc) {
10070 case OPC_LWXC1:
10071 check_cop1x(ctx);
10073 TCGv_i32 fp0 = tcg_temp_new_i32();
10075 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10076 tcg_gen_trunc_tl_i32(fp0, t0);
10077 gen_store_fpr32(ctx, fp0, fd);
10078 tcg_temp_free_i32(fp0);
10080 break;
10081 case OPC_LDXC1:
10082 check_cop1x(ctx);
10083 check_cp1_registers(ctx, fd);
10085 TCGv_i64 fp0 = tcg_temp_new_i64();
10086 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10087 gen_store_fpr64(ctx, fp0, fd);
10088 tcg_temp_free_i64(fp0);
10090 break;
10091 case OPC_LUXC1:
10092 check_cp1_64bitmode(ctx);
10093 tcg_gen_andi_tl(t0, t0, ~0x7);
10095 TCGv_i64 fp0 = tcg_temp_new_i64();
10097 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10098 gen_store_fpr64(ctx, fp0, fd);
10099 tcg_temp_free_i64(fp0);
10101 break;
10102 case OPC_SWXC1:
10103 check_cop1x(ctx);
10105 TCGv_i32 fp0 = tcg_temp_new_i32();
10106 gen_load_fpr32(ctx, fp0, fs);
10107 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10108 tcg_temp_free_i32(fp0);
10110 break;
10111 case OPC_SDXC1:
10112 check_cop1x(ctx);
10113 check_cp1_registers(ctx, fs);
10115 TCGv_i64 fp0 = tcg_temp_new_i64();
10116 gen_load_fpr64(ctx, fp0, fs);
10117 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10118 tcg_temp_free_i64(fp0);
10120 break;
10121 case OPC_SUXC1:
10122 check_cp1_64bitmode(ctx);
10123 tcg_gen_andi_tl(t0, t0, ~0x7);
10125 TCGv_i64 fp0 = tcg_temp_new_i64();
10126 gen_load_fpr64(ctx, fp0, fs);
10127 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10128 tcg_temp_free_i64(fp0);
10130 break;
10132 tcg_temp_free(t0);
10135 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10136 int fd, int fr, int fs, int ft)
10138 switch (opc) {
10139 case OPC_ALNV_PS:
10140 check_ps(ctx);
10142 TCGv t0 = tcg_temp_local_new();
10143 TCGv_i32 fp = tcg_temp_new_i32();
10144 TCGv_i32 fph = tcg_temp_new_i32();
10145 TCGLabel *l1 = gen_new_label();
10146 TCGLabel *l2 = gen_new_label();
10148 gen_load_gpr(t0, fr);
10149 tcg_gen_andi_tl(t0, t0, 0x7);
10151 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10152 gen_load_fpr32(ctx, fp, fs);
10153 gen_load_fpr32h(ctx, fph, fs);
10154 gen_store_fpr32(ctx, fp, fd);
10155 gen_store_fpr32h(ctx, fph, fd);
10156 tcg_gen_br(l2);
10157 gen_set_label(l1);
10158 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10159 tcg_temp_free(t0);
10160 #ifdef TARGET_WORDS_BIGENDIAN
10161 gen_load_fpr32(ctx, fp, fs);
10162 gen_load_fpr32h(ctx, fph, ft);
10163 gen_store_fpr32h(ctx, fp, fd);
10164 gen_store_fpr32(ctx, fph, fd);
10165 #else
10166 gen_load_fpr32h(ctx, fph, fs);
10167 gen_load_fpr32(ctx, fp, ft);
10168 gen_store_fpr32(ctx, fph, fd);
10169 gen_store_fpr32h(ctx, fp, fd);
10170 #endif
10171 gen_set_label(l2);
10172 tcg_temp_free_i32(fp);
10173 tcg_temp_free_i32(fph);
10175 break;
10176 case OPC_MADD_S:
10177 check_cop1x(ctx);
10179 TCGv_i32 fp0 = tcg_temp_new_i32();
10180 TCGv_i32 fp1 = tcg_temp_new_i32();
10181 TCGv_i32 fp2 = tcg_temp_new_i32();
10183 gen_load_fpr32(ctx, fp0, fs);
10184 gen_load_fpr32(ctx, fp1, ft);
10185 gen_load_fpr32(ctx, fp2, fr);
10186 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10187 tcg_temp_free_i32(fp0);
10188 tcg_temp_free_i32(fp1);
10189 gen_store_fpr32(ctx, fp2, fd);
10190 tcg_temp_free_i32(fp2);
10192 break;
10193 case OPC_MADD_D:
10194 check_cop1x(ctx);
10195 check_cp1_registers(ctx, fd | fs | ft | fr);
10197 TCGv_i64 fp0 = tcg_temp_new_i64();
10198 TCGv_i64 fp1 = tcg_temp_new_i64();
10199 TCGv_i64 fp2 = tcg_temp_new_i64();
10201 gen_load_fpr64(ctx, fp0, fs);
10202 gen_load_fpr64(ctx, fp1, ft);
10203 gen_load_fpr64(ctx, fp2, fr);
10204 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10205 tcg_temp_free_i64(fp0);
10206 tcg_temp_free_i64(fp1);
10207 gen_store_fpr64(ctx, fp2, fd);
10208 tcg_temp_free_i64(fp2);
10210 break;
10211 case OPC_MADD_PS:
10212 check_ps(ctx);
10214 TCGv_i64 fp0 = tcg_temp_new_i64();
10215 TCGv_i64 fp1 = tcg_temp_new_i64();
10216 TCGv_i64 fp2 = tcg_temp_new_i64();
10218 gen_load_fpr64(ctx, fp0, fs);
10219 gen_load_fpr64(ctx, fp1, ft);
10220 gen_load_fpr64(ctx, fp2, fr);
10221 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10222 tcg_temp_free_i64(fp0);
10223 tcg_temp_free_i64(fp1);
10224 gen_store_fpr64(ctx, fp2, fd);
10225 tcg_temp_free_i64(fp2);
10227 break;
10228 case OPC_MSUB_S:
10229 check_cop1x(ctx);
10231 TCGv_i32 fp0 = tcg_temp_new_i32();
10232 TCGv_i32 fp1 = tcg_temp_new_i32();
10233 TCGv_i32 fp2 = tcg_temp_new_i32();
10235 gen_load_fpr32(ctx, fp0, fs);
10236 gen_load_fpr32(ctx, fp1, ft);
10237 gen_load_fpr32(ctx, fp2, fr);
10238 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10239 tcg_temp_free_i32(fp0);
10240 tcg_temp_free_i32(fp1);
10241 gen_store_fpr32(ctx, fp2, fd);
10242 tcg_temp_free_i32(fp2);
10244 break;
10245 case OPC_MSUB_D:
10246 check_cop1x(ctx);
10247 check_cp1_registers(ctx, fd | fs | ft | fr);
10249 TCGv_i64 fp0 = tcg_temp_new_i64();
10250 TCGv_i64 fp1 = tcg_temp_new_i64();
10251 TCGv_i64 fp2 = tcg_temp_new_i64();
10253 gen_load_fpr64(ctx, fp0, fs);
10254 gen_load_fpr64(ctx, fp1, ft);
10255 gen_load_fpr64(ctx, fp2, fr);
10256 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10257 tcg_temp_free_i64(fp0);
10258 tcg_temp_free_i64(fp1);
10259 gen_store_fpr64(ctx, fp2, fd);
10260 tcg_temp_free_i64(fp2);
10262 break;
10263 case OPC_MSUB_PS:
10264 check_ps(ctx);
10266 TCGv_i64 fp0 = tcg_temp_new_i64();
10267 TCGv_i64 fp1 = tcg_temp_new_i64();
10268 TCGv_i64 fp2 = tcg_temp_new_i64();
10270 gen_load_fpr64(ctx, fp0, fs);
10271 gen_load_fpr64(ctx, fp1, ft);
10272 gen_load_fpr64(ctx, fp2, fr);
10273 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10274 tcg_temp_free_i64(fp0);
10275 tcg_temp_free_i64(fp1);
10276 gen_store_fpr64(ctx, fp2, fd);
10277 tcg_temp_free_i64(fp2);
10279 break;
10280 case OPC_NMADD_S:
10281 check_cop1x(ctx);
10283 TCGv_i32 fp0 = tcg_temp_new_i32();
10284 TCGv_i32 fp1 = tcg_temp_new_i32();
10285 TCGv_i32 fp2 = tcg_temp_new_i32();
10287 gen_load_fpr32(ctx, fp0, fs);
10288 gen_load_fpr32(ctx, fp1, ft);
10289 gen_load_fpr32(ctx, fp2, fr);
10290 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10291 tcg_temp_free_i32(fp0);
10292 tcg_temp_free_i32(fp1);
10293 gen_store_fpr32(ctx, fp2, fd);
10294 tcg_temp_free_i32(fp2);
10296 break;
10297 case OPC_NMADD_D:
10298 check_cop1x(ctx);
10299 check_cp1_registers(ctx, fd | fs | ft | fr);
10301 TCGv_i64 fp0 = tcg_temp_new_i64();
10302 TCGv_i64 fp1 = tcg_temp_new_i64();
10303 TCGv_i64 fp2 = tcg_temp_new_i64();
10305 gen_load_fpr64(ctx, fp0, fs);
10306 gen_load_fpr64(ctx, fp1, ft);
10307 gen_load_fpr64(ctx, fp2, fr);
10308 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10309 tcg_temp_free_i64(fp0);
10310 tcg_temp_free_i64(fp1);
10311 gen_store_fpr64(ctx, fp2, fd);
10312 tcg_temp_free_i64(fp2);
10314 break;
10315 case OPC_NMADD_PS:
10316 check_ps(ctx);
10318 TCGv_i64 fp0 = tcg_temp_new_i64();
10319 TCGv_i64 fp1 = tcg_temp_new_i64();
10320 TCGv_i64 fp2 = tcg_temp_new_i64();
10322 gen_load_fpr64(ctx, fp0, fs);
10323 gen_load_fpr64(ctx, fp1, ft);
10324 gen_load_fpr64(ctx, fp2, fr);
10325 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10326 tcg_temp_free_i64(fp0);
10327 tcg_temp_free_i64(fp1);
10328 gen_store_fpr64(ctx, fp2, fd);
10329 tcg_temp_free_i64(fp2);
10331 break;
10332 case OPC_NMSUB_S:
10333 check_cop1x(ctx);
10335 TCGv_i32 fp0 = tcg_temp_new_i32();
10336 TCGv_i32 fp1 = tcg_temp_new_i32();
10337 TCGv_i32 fp2 = tcg_temp_new_i32();
10339 gen_load_fpr32(ctx, fp0, fs);
10340 gen_load_fpr32(ctx, fp1, ft);
10341 gen_load_fpr32(ctx, fp2, fr);
10342 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10343 tcg_temp_free_i32(fp0);
10344 tcg_temp_free_i32(fp1);
10345 gen_store_fpr32(ctx, fp2, fd);
10346 tcg_temp_free_i32(fp2);
10348 break;
10349 case OPC_NMSUB_D:
10350 check_cop1x(ctx);
10351 check_cp1_registers(ctx, fd | fs | ft | fr);
10353 TCGv_i64 fp0 = tcg_temp_new_i64();
10354 TCGv_i64 fp1 = tcg_temp_new_i64();
10355 TCGv_i64 fp2 = tcg_temp_new_i64();
10357 gen_load_fpr64(ctx, fp0, fs);
10358 gen_load_fpr64(ctx, fp1, ft);
10359 gen_load_fpr64(ctx, fp2, fr);
10360 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10361 tcg_temp_free_i64(fp0);
10362 tcg_temp_free_i64(fp1);
10363 gen_store_fpr64(ctx, fp2, fd);
10364 tcg_temp_free_i64(fp2);
10366 break;
10367 case OPC_NMSUB_PS:
10368 check_ps(ctx);
10370 TCGv_i64 fp0 = tcg_temp_new_i64();
10371 TCGv_i64 fp1 = tcg_temp_new_i64();
10372 TCGv_i64 fp2 = tcg_temp_new_i64();
10374 gen_load_fpr64(ctx, fp0, fs);
10375 gen_load_fpr64(ctx, fp1, ft);
10376 gen_load_fpr64(ctx, fp2, fr);
10377 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10378 tcg_temp_free_i64(fp0);
10379 tcg_temp_free_i64(fp1);
10380 gen_store_fpr64(ctx, fp2, fd);
10381 tcg_temp_free_i64(fp2);
10383 break;
10384 default:
10385 MIPS_INVAL("flt3_arith");
10386 generate_exception_end(ctx, EXCP_RI);
10387 return;
10391 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
10393 TCGv t0;
10395 #if !defined(CONFIG_USER_ONLY)
10396 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10397 Therefore only check the ISA in system mode. */
10398 check_insn(ctx, ISA_MIPS32R2);
10399 #endif
10400 t0 = tcg_temp_new();
10402 switch (rd) {
10403 case 0:
10404 gen_helper_rdhwr_cpunum(t0, cpu_env);
10405 gen_store_gpr(t0, rt);
10406 break;
10407 case 1:
10408 gen_helper_rdhwr_synci_step(t0, cpu_env);
10409 gen_store_gpr(t0, rt);
10410 break;
10411 case 2:
10412 gen_helper_rdhwr_cc(t0, cpu_env);
10413 gen_store_gpr(t0, rt);
10414 break;
10415 case 3:
10416 gen_helper_rdhwr_ccres(t0, cpu_env);
10417 gen_store_gpr(t0, rt);
10418 break;
10419 case 4:
10420 check_insn(ctx, ISA_MIPS32R6);
10421 if (sel != 0) {
10422 /* Performance counter registers are not implemented other than
10423 * control register 0.
10425 generate_exception(ctx, EXCP_RI);
10427 gen_helper_rdhwr_performance(t0, cpu_env);
10428 gen_store_gpr(t0, rt);
10429 break;
10430 case 5:
10431 check_insn(ctx, ISA_MIPS32R6);
10432 gen_helper_rdhwr_xnp(t0, cpu_env);
10433 gen_store_gpr(t0, rt);
10434 break;
10435 case 29:
10436 #if defined(CONFIG_USER_ONLY)
10437 tcg_gen_ld_tl(t0, cpu_env,
10438 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10439 gen_store_gpr(t0, rt);
10440 break;
10441 #else
10442 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10443 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10444 tcg_gen_ld_tl(t0, cpu_env,
10445 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10446 gen_store_gpr(t0, rt);
10447 } else {
10448 generate_exception_end(ctx, EXCP_RI);
10450 break;
10451 #endif
10452 default: /* Invalid */
10453 MIPS_INVAL("rdhwr");
10454 generate_exception_end(ctx, EXCP_RI);
10455 break;
10457 tcg_temp_free(t0);
10460 static inline void clear_branch_hflags(DisasContext *ctx)
10462 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10463 if (ctx->bstate == BS_NONE) {
10464 save_cpu_state(ctx, 0);
10465 } else {
10466 /* it is not safe to save ctx->hflags as hflags may be changed
10467 in execution time by the instruction in delay / forbidden slot. */
10468 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10472 static void gen_branch(DisasContext *ctx, int insn_bytes)
10474 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10475 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10476 /* Branches completion */
10477 clear_branch_hflags(ctx);
10478 ctx->bstate = BS_BRANCH;
10479 /* FIXME: Need to clear can_do_io. */
10480 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10481 case MIPS_HFLAG_FBNSLOT:
10482 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10483 break;
10484 case MIPS_HFLAG_B:
10485 /* unconditional branch */
10486 if (proc_hflags & MIPS_HFLAG_BX) {
10487 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10489 gen_goto_tb(ctx, 0, ctx->btarget);
10490 break;
10491 case MIPS_HFLAG_BL:
10492 /* blikely taken case */
10493 gen_goto_tb(ctx, 0, ctx->btarget);
10494 break;
10495 case MIPS_HFLAG_BC:
10496 /* Conditional branch */
10498 TCGLabel *l1 = gen_new_label();
10500 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10501 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10502 gen_set_label(l1);
10503 gen_goto_tb(ctx, 0, ctx->btarget);
10505 break;
10506 case MIPS_HFLAG_BR:
10507 /* unconditional branch to register */
10508 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10509 TCGv t0 = tcg_temp_new();
10510 TCGv_i32 t1 = tcg_temp_new_i32();
10512 tcg_gen_andi_tl(t0, btarget, 0x1);
10513 tcg_gen_trunc_tl_i32(t1, t0);
10514 tcg_temp_free(t0);
10515 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10516 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10517 tcg_gen_or_i32(hflags, hflags, t1);
10518 tcg_temp_free_i32(t1);
10520 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10521 } else {
10522 tcg_gen_mov_tl(cpu_PC, btarget);
10524 if (ctx->singlestep_enabled) {
10525 save_cpu_state(ctx, 0);
10526 gen_helper_raise_exception_debug(cpu_env);
10528 tcg_gen_exit_tb(0);
10529 break;
10530 default:
10531 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
10532 abort();
10537 /* Compact Branches */
10538 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
10539 int rs, int rt, int32_t offset)
10541 int bcond_compute = 0;
10542 TCGv t0 = tcg_temp_new();
10543 TCGv t1 = tcg_temp_new();
10544 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
10546 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10547 #ifdef MIPS_DEBUG_DISAS
10548 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10549 "\n", ctx->pc);
10550 #endif
10551 generate_exception_end(ctx, EXCP_RI);
10552 goto out;
10555 /* Load needed operands and calculate btarget */
10556 switch (opc) {
10557 /* compact branch */
10558 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10559 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10560 gen_load_gpr(t0, rs);
10561 gen_load_gpr(t1, rt);
10562 bcond_compute = 1;
10563 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10564 if (rs <= rt && rs == 0) {
10565 /* OPC_BEQZALC, OPC_BNEZALC */
10566 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10568 break;
10569 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10570 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10571 gen_load_gpr(t0, rs);
10572 gen_load_gpr(t1, rt);
10573 bcond_compute = 1;
10574 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10575 break;
10576 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10577 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10578 if (rs == 0 || rs == rt) {
10579 /* OPC_BLEZALC, OPC_BGEZALC */
10580 /* OPC_BGTZALC, OPC_BLTZALC */
10581 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10583 gen_load_gpr(t0, rs);
10584 gen_load_gpr(t1, rt);
10585 bcond_compute = 1;
10586 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10587 break;
10588 case OPC_BC:
10589 case OPC_BALC:
10590 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10591 break;
10592 case OPC_BEQZC:
10593 case OPC_BNEZC:
10594 if (rs != 0) {
10595 /* OPC_BEQZC, OPC_BNEZC */
10596 gen_load_gpr(t0, rs);
10597 bcond_compute = 1;
10598 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10599 } else {
10600 /* OPC_JIC, OPC_JIALC */
10601 TCGv tbase = tcg_temp_new();
10602 TCGv toffset = tcg_temp_new();
10604 gen_load_gpr(tbase, rt);
10605 tcg_gen_movi_tl(toffset, offset);
10606 gen_op_addr_add(ctx, btarget, tbase, toffset);
10607 tcg_temp_free(tbase);
10608 tcg_temp_free(toffset);
10610 break;
10611 default:
10612 MIPS_INVAL("Compact branch/jump");
10613 generate_exception_end(ctx, EXCP_RI);
10614 goto out;
10617 if (bcond_compute == 0) {
10618 /* Uncoditional compact branch */
10619 switch (opc) {
10620 case OPC_JIALC:
10621 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10622 /* Fallthrough */
10623 case OPC_JIC:
10624 ctx->hflags |= MIPS_HFLAG_BR;
10625 break;
10626 case OPC_BALC:
10627 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10628 /* Fallthrough */
10629 case OPC_BC:
10630 ctx->hflags |= MIPS_HFLAG_B;
10631 break;
10632 default:
10633 MIPS_INVAL("Compact branch/jump");
10634 generate_exception_end(ctx, EXCP_RI);
10635 goto out;
10638 /* Generating branch here as compact branches don't have delay slot */
10639 gen_branch(ctx, 4);
10640 } else {
10641 /* Conditional compact branch */
10642 TCGLabel *fs = gen_new_label();
10643 save_cpu_state(ctx, 0);
10645 switch (opc) {
10646 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10647 if (rs == 0 && rt != 0) {
10648 /* OPC_BLEZALC */
10649 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10650 } else if (rs != 0 && rt != 0 && rs == rt) {
10651 /* OPC_BGEZALC */
10652 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10653 } else {
10654 /* OPC_BGEUC */
10655 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
10657 break;
10658 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10659 if (rs == 0 && rt != 0) {
10660 /* OPC_BGTZALC */
10661 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10662 } else if (rs != 0 && rt != 0 && rs == rt) {
10663 /* OPC_BLTZALC */
10664 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10665 } else {
10666 /* OPC_BLTUC */
10667 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
10669 break;
10670 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10671 if (rs == 0 && rt != 0) {
10672 /* OPC_BLEZC */
10673 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10674 } else if (rs != 0 && rt != 0 && rs == rt) {
10675 /* OPC_BGEZC */
10676 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10677 } else {
10678 /* OPC_BGEC */
10679 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
10681 break;
10682 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10683 if (rs == 0 && rt != 0) {
10684 /* OPC_BGTZC */
10685 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10686 } else if (rs != 0 && rt != 0 && rs == rt) {
10687 /* OPC_BLTZC */
10688 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10689 } else {
10690 /* OPC_BLTC */
10691 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
10693 break;
10694 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10695 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10696 if (rs >= rt) {
10697 /* OPC_BOVC, OPC_BNVC */
10698 TCGv t2 = tcg_temp_new();
10699 TCGv t3 = tcg_temp_new();
10700 TCGv t4 = tcg_temp_new();
10701 TCGv input_overflow = tcg_temp_new();
10703 gen_load_gpr(t0, rs);
10704 gen_load_gpr(t1, rt);
10705 tcg_gen_ext32s_tl(t2, t0);
10706 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
10707 tcg_gen_ext32s_tl(t3, t1);
10708 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
10709 tcg_gen_or_tl(input_overflow, input_overflow, t4);
10711 tcg_gen_add_tl(t4, t2, t3);
10712 tcg_gen_ext32s_tl(t4, t4);
10713 tcg_gen_xor_tl(t2, t2, t3);
10714 tcg_gen_xor_tl(t3, t4, t3);
10715 tcg_gen_andc_tl(t2, t3, t2);
10716 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
10717 tcg_gen_or_tl(t4, t4, input_overflow);
10718 if (opc == OPC_BOVC) {
10719 /* OPC_BOVC */
10720 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
10721 } else {
10722 /* OPC_BNVC */
10723 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
10725 tcg_temp_free(input_overflow);
10726 tcg_temp_free(t4);
10727 tcg_temp_free(t3);
10728 tcg_temp_free(t2);
10729 } else if (rs < rt && rs == 0) {
10730 /* OPC_BEQZALC, OPC_BNEZALC */
10731 if (opc == OPC_BEQZALC) {
10732 /* OPC_BEQZALC */
10733 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
10734 } else {
10735 /* OPC_BNEZALC */
10736 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
10738 } else {
10739 /* OPC_BEQC, OPC_BNEC */
10740 if (opc == OPC_BEQC) {
10741 /* OPC_BEQC */
10742 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
10743 } else {
10744 /* OPC_BNEC */
10745 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
10748 break;
10749 case OPC_BEQZC:
10750 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
10751 break;
10752 case OPC_BNEZC:
10753 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
10754 break;
10755 default:
10756 MIPS_INVAL("Compact conditional branch/jump");
10757 generate_exception_end(ctx, EXCP_RI);
10758 goto out;
10761 /* Generating branch here as compact branches don't have delay slot */
10762 gen_goto_tb(ctx, 1, ctx->btarget);
10763 gen_set_label(fs);
10765 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
10768 out:
10769 tcg_temp_free(t0);
10770 tcg_temp_free(t1);
10773 /* ISA extensions (ASEs) */
10774 /* MIPS16 extension to MIPS32 */
10776 /* MIPS16 major opcodes */
10777 enum {
10778 M16_OPC_ADDIUSP = 0x00,
10779 M16_OPC_ADDIUPC = 0x01,
10780 M16_OPC_B = 0x02,
10781 M16_OPC_JAL = 0x03,
10782 M16_OPC_BEQZ = 0x04,
10783 M16_OPC_BNEQZ = 0x05,
10784 M16_OPC_SHIFT = 0x06,
10785 M16_OPC_LD = 0x07,
10786 M16_OPC_RRIA = 0x08,
10787 M16_OPC_ADDIU8 = 0x09,
10788 M16_OPC_SLTI = 0x0a,
10789 M16_OPC_SLTIU = 0x0b,
10790 M16_OPC_I8 = 0x0c,
10791 M16_OPC_LI = 0x0d,
10792 M16_OPC_CMPI = 0x0e,
10793 M16_OPC_SD = 0x0f,
10794 M16_OPC_LB = 0x10,
10795 M16_OPC_LH = 0x11,
10796 M16_OPC_LWSP = 0x12,
10797 M16_OPC_LW = 0x13,
10798 M16_OPC_LBU = 0x14,
10799 M16_OPC_LHU = 0x15,
10800 M16_OPC_LWPC = 0x16,
10801 M16_OPC_LWU = 0x17,
10802 M16_OPC_SB = 0x18,
10803 M16_OPC_SH = 0x19,
10804 M16_OPC_SWSP = 0x1a,
10805 M16_OPC_SW = 0x1b,
10806 M16_OPC_RRR = 0x1c,
10807 M16_OPC_RR = 0x1d,
10808 M16_OPC_EXTEND = 0x1e,
10809 M16_OPC_I64 = 0x1f
10812 /* I8 funct field */
10813 enum {
10814 I8_BTEQZ = 0x0,
10815 I8_BTNEZ = 0x1,
10816 I8_SWRASP = 0x2,
10817 I8_ADJSP = 0x3,
10818 I8_SVRS = 0x4,
10819 I8_MOV32R = 0x5,
10820 I8_MOVR32 = 0x7
10823 /* RRR f field */
10824 enum {
10825 RRR_DADDU = 0x0,
10826 RRR_ADDU = 0x1,
10827 RRR_DSUBU = 0x2,
10828 RRR_SUBU = 0x3
10831 /* RR funct field */
10832 enum {
10833 RR_JR = 0x00,
10834 RR_SDBBP = 0x01,
10835 RR_SLT = 0x02,
10836 RR_SLTU = 0x03,
10837 RR_SLLV = 0x04,
10838 RR_BREAK = 0x05,
10839 RR_SRLV = 0x06,
10840 RR_SRAV = 0x07,
10841 RR_DSRL = 0x08,
10842 RR_CMP = 0x0a,
10843 RR_NEG = 0x0b,
10844 RR_AND = 0x0c,
10845 RR_OR = 0x0d,
10846 RR_XOR = 0x0e,
10847 RR_NOT = 0x0f,
10848 RR_MFHI = 0x10,
10849 RR_CNVT = 0x11,
10850 RR_MFLO = 0x12,
10851 RR_DSRA = 0x13,
10852 RR_DSLLV = 0x14,
10853 RR_DSRLV = 0x16,
10854 RR_DSRAV = 0x17,
10855 RR_MULT = 0x18,
10856 RR_MULTU = 0x19,
10857 RR_DIV = 0x1a,
10858 RR_DIVU = 0x1b,
10859 RR_DMULT = 0x1c,
10860 RR_DMULTU = 0x1d,
10861 RR_DDIV = 0x1e,
10862 RR_DDIVU = 0x1f
10865 /* I64 funct field */
10866 enum {
10867 I64_LDSP = 0x0,
10868 I64_SDSP = 0x1,
10869 I64_SDRASP = 0x2,
10870 I64_DADJSP = 0x3,
10871 I64_LDPC = 0x4,
10872 I64_DADDIU5 = 0x5,
10873 I64_DADDIUPC = 0x6,
10874 I64_DADDIUSP = 0x7
10877 /* RR ry field for CNVT */
10878 enum {
10879 RR_RY_CNVT_ZEB = 0x0,
10880 RR_RY_CNVT_ZEH = 0x1,
10881 RR_RY_CNVT_ZEW = 0x2,
10882 RR_RY_CNVT_SEB = 0x4,
10883 RR_RY_CNVT_SEH = 0x5,
10884 RR_RY_CNVT_SEW = 0x6,
10887 static int xlat (int r)
10889 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10891 return map[r];
10894 static void gen_mips16_save (DisasContext *ctx,
10895 int xsregs, int aregs,
10896 int do_ra, int do_s0, int do_s1,
10897 int framesize)
10899 TCGv t0 = tcg_temp_new();
10900 TCGv t1 = tcg_temp_new();
10901 TCGv t2 = tcg_temp_new();
10902 int args, astatic;
10904 switch (aregs) {
10905 case 0:
10906 case 1:
10907 case 2:
10908 case 3:
10909 case 11:
10910 args = 0;
10911 break;
10912 case 4:
10913 case 5:
10914 case 6:
10915 case 7:
10916 args = 1;
10917 break;
10918 case 8:
10919 case 9:
10920 case 10:
10921 args = 2;
10922 break;
10923 case 12:
10924 case 13:
10925 args = 3;
10926 break;
10927 case 14:
10928 args = 4;
10929 break;
10930 default:
10931 generate_exception_end(ctx, EXCP_RI);
10932 return;
10935 switch (args) {
10936 case 4:
10937 gen_base_offset_addr(ctx, t0, 29, 12);
10938 gen_load_gpr(t1, 7);
10939 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10940 /* Fall through */
10941 case 3:
10942 gen_base_offset_addr(ctx, t0, 29, 8);
10943 gen_load_gpr(t1, 6);
10944 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10945 /* Fall through */
10946 case 2:
10947 gen_base_offset_addr(ctx, t0, 29, 4);
10948 gen_load_gpr(t1, 5);
10949 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10950 /* Fall through */
10951 case 1:
10952 gen_base_offset_addr(ctx, t0, 29, 0);
10953 gen_load_gpr(t1, 4);
10954 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10957 gen_load_gpr(t0, 29);
10959 #define DECR_AND_STORE(reg) do { \
10960 tcg_gen_movi_tl(t2, -4); \
10961 gen_op_addr_add(ctx, t0, t0, t2); \
10962 gen_load_gpr(t1, reg); \
10963 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
10964 } while (0)
10966 if (do_ra) {
10967 DECR_AND_STORE(31);
10970 switch (xsregs) {
10971 case 7:
10972 DECR_AND_STORE(30);
10973 /* Fall through */
10974 case 6:
10975 DECR_AND_STORE(23);
10976 /* Fall through */
10977 case 5:
10978 DECR_AND_STORE(22);
10979 /* Fall through */
10980 case 4:
10981 DECR_AND_STORE(21);
10982 /* Fall through */
10983 case 3:
10984 DECR_AND_STORE(20);
10985 /* Fall through */
10986 case 2:
10987 DECR_AND_STORE(19);
10988 /* Fall through */
10989 case 1:
10990 DECR_AND_STORE(18);
10993 if (do_s1) {
10994 DECR_AND_STORE(17);
10996 if (do_s0) {
10997 DECR_AND_STORE(16);
11000 switch (aregs) {
11001 case 0:
11002 case 4:
11003 case 8:
11004 case 12:
11005 case 14:
11006 astatic = 0;
11007 break;
11008 case 1:
11009 case 5:
11010 case 9:
11011 case 13:
11012 astatic = 1;
11013 break;
11014 case 2:
11015 case 6:
11016 case 10:
11017 astatic = 2;
11018 break;
11019 case 3:
11020 case 7:
11021 astatic = 3;
11022 break;
11023 case 11:
11024 astatic = 4;
11025 break;
11026 default:
11027 generate_exception_end(ctx, EXCP_RI);
11028 return;
11031 if (astatic > 0) {
11032 DECR_AND_STORE(7);
11033 if (astatic > 1) {
11034 DECR_AND_STORE(6);
11035 if (astatic > 2) {
11036 DECR_AND_STORE(5);
11037 if (astatic > 3) {
11038 DECR_AND_STORE(4);
11043 #undef DECR_AND_STORE
11045 tcg_gen_movi_tl(t2, -framesize);
11046 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11047 tcg_temp_free(t0);
11048 tcg_temp_free(t1);
11049 tcg_temp_free(t2);
11052 static void gen_mips16_restore (DisasContext *ctx,
11053 int xsregs, int aregs,
11054 int do_ra, int do_s0, int do_s1,
11055 int framesize)
11057 int astatic;
11058 TCGv t0 = tcg_temp_new();
11059 TCGv t1 = tcg_temp_new();
11060 TCGv t2 = tcg_temp_new();
11062 tcg_gen_movi_tl(t2, framesize);
11063 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11065 #define DECR_AND_LOAD(reg) do { \
11066 tcg_gen_movi_tl(t2, -4); \
11067 gen_op_addr_add(ctx, t0, t0, t2); \
11068 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11069 gen_store_gpr(t1, reg); \
11070 } while (0)
11072 if (do_ra) {
11073 DECR_AND_LOAD(31);
11076 switch (xsregs) {
11077 case 7:
11078 DECR_AND_LOAD(30);
11079 /* Fall through */
11080 case 6:
11081 DECR_AND_LOAD(23);
11082 /* Fall through */
11083 case 5:
11084 DECR_AND_LOAD(22);
11085 /* Fall through */
11086 case 4:
11087 DECR_AND_LOAD(21);
11088 /* Fall through */
11089 case 3:
11090 DECR_AND_LOAD(20);
11091 /* Fall through */
11092 case 2:
11093 DECR_AND_LOAD(19);
11094 /* Fall through */
11095 case 1:
11096 DECR_AND_LOAD(18);
11099 if (do_s1) {
11100 DECR_AND_LOAD(17);
11102 if (do_s0) {
11103 DECR_AND_LOAD(16);
11106 switch (aregs) {
11107 case 0:
11108 case 4:
11109 case 8:
11110 case 12:
11111 case 14:
11112 astatic = 0;
11113 break;
11114 case 1:
11115 case 5:
11116 case 9:
11117 case 13:
11118 astatic = 1;
11119 break;
11120 case 2:
11121 case 6:
11122 case 10:
11123 astatic = 2;
11124 break;
11125 case 3:
11126 case 7:
11127 astatic = 3;
11128 break;
11129 case 11:
11130 astatic = 4;
11131 break;
11132 default:
11133 generate_exception_end(ctx, EXCP_RI);
11134 return;
11137 if (astatic > 0) {
11138 DECR_AND_LOAD(7);
11139 if (astatic > 1) {
11140 DECR_AND_LOAD(6);
11141 if (astatic > 2) {
11142 DECR_AND_LOAD(5);
11143 if (astatic > 3) {
11144 DECR_AND_LOAD(4);
11149 #undef DECR_AND_LOAD
11151 tcg_gen_movi_tl(t2, framesize);
11152 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11153 tcg_temp_free(t0);
11154 tcg_temp_free(t1);
11155 tcg_temp_free(t2);
11158 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11159 int is_64_bit, int extended)
11161 TCGv t0;
11163 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11164 generate_exception_end(ctx, EXCP_RI);
11165 return;
11168 t0 = tcg_temp_new();
11170 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11171 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11172 if (!is_64_bit) {
11173 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11176 tcg_temp_free(t0);
11179 #if defined(TARGET_MIPS64)
11180 static void decode_i64_mips16 (DisasContext *ctx,
11181 int ry, int funct, int16_t offset,
11182 int extended)
11184 switch (funct) {
11185 case I64_LDSP:
11186 check_insn(ctx, ISA_MIPS3);
11187 check_mips_64(ctx);
11188 offset = extended ? offset : offset << 3;
11189 gen_ld(ctx, OPC_LD, ry, 29, offset);
11190 break;
11191 case I64_SDSP:
11192 check_insn(ctx, ISA_MIPS3);
11193 check_mips_64(ctx);
11194 offset = extended ? offset : offset << 3;
11195 gen_st(ctx, OPC_SD, ry, 29, offset);
11196 break;
11197 case I64_SDRASP:
11198 check_insn(ctx, ISA_MIPS3);
11199 check_mips_64(ctx);
11200 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11201 gen_st(ctx, OPC_SD, 31, 29, offset);
11202 break;
11203 case I64_DADJSP:
11204 check_insn(ctx, ISA_MIPS3);
11205 check_mips_64(ctx);
11206 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11207 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11208 break;
11209 case I64_LDPC:
11210 check_insn(ctx, ISA_MIPS3);
11211 check_mips_64(ctx);
11212 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11213 generate_exception_end(ctx, EXCP_RI);
11214 } else {
11215 offset = extended ? offset : offset << 3;
11216 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11218 break;
11219 case I64_DADDIU5:
11220 check_insn(ctx, ISA_MIPS3);
11221 check_mips_64(ctx);
11222 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11223 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11224 break;
11225 case I64_DADDIUPC:
11226 check_insn(ctx, ISA_MIPS3);
11227 check_mips_64(ctx);
11228 offset = extended ? offset : offset << 2;
11229 gen_addiupc(ctx, ry, offset, 1, extended);
11230 break;
11231 case I64_DADDIUSP:
11232 check_insn(ctx, ISA_MIPS3);
11233 check_mips_64(ctx);
11234 offset = extended ? offset : offset << 2;
11235 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11236 break;
11239 #endif
11241 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11243 int extend = cpu_lduw_code(env, ctx->pc + 2);
11244 int op, rx, ry, funct, sa;
11245 int16_t imm, offset;
11247 ctx->opcode = (ctx->opcode << 16) | extend;
11248 op = (ctx->opcode >> 11) & 0x1f;
11249 sa = (ctx->opcode >> 22) & 0x1f;
11250 funct = (ctx->opcode >> 8) & 0x7;
11251 rx = xlat((ctx->opcode >> 8) & 0x7);
11252 ry = xlat((ctx->opcode >> 5) & 0x7);
11253 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11254 | ((ctx->opcode >> 21) & 0x3f) << 5
11255 | (ctx->opcode & 0x1f));
11257 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11258 counterparts. */
11259 switch (op) {
11260 case M16_OPC_ADDIUSP:
11261 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11262 break;
11263 case M16_OPC_ADDIUPC:
11264 gen_addiupc(ctx, rx, imm, 0, 1);
11265 break;
11266 case M16_OPC_B:
11267 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11268 /* No delay slot, so just process as a normal instruction */
11269 break;
11270 case M16_OPC_BEQZ:
11271 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11272 /* No delay slot, so just process as a normal instruction */
11273 break;
11274 case M16_OPC_BNEQZ:
11275 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11276 /* No delay slot, so just process as a normal instruction */
11277 break;
11278 case M16_OPC_SHIFT:
11279 switch (ctx->opcode & 0x3) {
11280 case 0x0:
11281 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11282 break;
11283 case 0x1:
11284 #if defined(TARGET_MIPS64)
11285 check_mips_64(ctx);
11286 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11287 #else
11288 generate_exception_end(ctx, EXCP_RI);
11289 #endif
11290 break;
11291 case 0x2:
11292 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11293 break;
11294 case 0x3:
11295 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11296 break;
11298 break;
11299 #if defined(TARGET_MIPS64)
11300 case M16_OPC_LD:
11301 check_insn(ctx, ISA_MIPS3);
11302 check_mips_64(ctx);
11303 gen_ld(ctx, OPC_LD, ry, rx, offset);
11304 break;
11305 #endif
11306 case M16_OPC_RRIA:
11307 imm = ctx->opcode & 0xf;
11308 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11309 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11310 imm = (int16_t) (imm << 1) >> 1;
11311 if ((ctx->opcode >> 4) & 0x1) {
11312 #if defined(TARGET_MIPS64)
11313 check_mips_64(ctx);
11314 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11315 #else
11316 generate_exception_end(ctx, EXCP_RI);
11317 #endif
11318 } else {
11319 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11321 break;
11322 case M16_OPC_ADDIU8:
11323 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11324 break;
11325 case M16_OPC_SLTI:
11326 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11327 break;
11328 case M16_OPC_SLTIU:
11329 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11330 break;
11331 case M16_OPC_I8:
11332 switch (funct) {
11333 case I8_BTEQZ:
11334 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11335 break;
11336 case I8_BTNEZ:
11337 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11338 break;
11339 case I8_SWRASP:
11340 gen_st(ctx, OPC_SW, 31, 29, imm);
11341 break;
11342 case I8_ADJSP:
11343 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11344 break;
11345 case I8_SVRS:
11346 check_insn(ctx, ISA_MIPS32);
11348 int xsregs = (ctx->opcode >> 24) & 0x7;
11349 int aregs = (ctx->opcode >> 16) & 0xf;
11350 int do_ra = (ctx->opcode >> 6) & 0x1;
11351 int do_s0 = (ctx->opcode >> 5) & 0x1;
11352 int do_s1 = (ctx->opcode >> 4) & 0x1;
11353 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11354 | (ctx->opcode & 0xf)) << 3;
11356 if (ctx->opcode & (1 << 7)) {
11357 gen_mips16_save(ctx, xsregs, aregs,
11358 do_ra, do_s0, do_s1,
11359 framesize);
11360 } else {
11361 gen_mips16_restore(ctx, xsregs, aregs,
11362 do_ra, do_s0, do_s1,
11363 framesize);
11366 break;
11367 default:
11368 generate_exception_end(ctx, EXCP_RI);
11369 break;
11371 break;
11372 case M16_OPC_LI:
11373 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11374 break;
11375 case M16_OPC_CMPI:
11376 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11377 break;
11378 #if defined(TARGET_MIPS64)
11379 case M16_OPC_SD:
11380 check_insn(ctx, ISA_MIPS3);
11381 check_mips_64(ctx);
11382 gen_st(ctx, OPC_SD, ry, rx, offset);
11383 break;
11384 #endif
11385 case M16_OPC_LB:
11386 gen_ld(ctx, OPC_LB, ry, rx, offset);
11387 break;
11388 case M16_OPC_LH:
11389 gen_ld(ctx, OPC_LH, ry, rx, offset);
11390 break;
11391 case M16_OPC_LWSP:
11392 gen_ld(ctx, OPC_LW, rx, 29, offset);
11393 break;
11394 case M16_OPC_LW:
11395 gen_ld(ctx, OPC_LW, ry, rx, offset);
11396 break;
11397 case M16_OPC_LBU:
11398 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11399 break;
11400 case M16_OPC_LHU:
11401 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11402 break;
11403 case M16_OPC_LWPC:
11404 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11405 break;
11406 #if defined(TARGET_MIPS64)
11407 case M16_OPC_LWU:
11408 check_insn(ctx, ISA_MIPS3);
11409 check_mips_64(ctx);
11410 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11411 break;
11412 #endif
11413 case M16_OPC_SB:
11414 gen_st(ctx, OPC_SB, ry, rx, offset);
11415 break;
11416 case M16_OPC_SH:
11417 gen_st(ctx, OPC_SH, ry, rx, offset);
11418 break;
11419 case M16_OPC_SWSP:
11420 gen_st(ctx, OPC_SW, rx, 29, offset);
11421 break;
11422 case M16_OPC_SW:
11423 gen_st(ctx, OPC_SW, ry, rx, offset);
11424 break;
11425 #if defined(TARGET_MIPS64)
11426 case M16_OPC_I64:
11427 decode_i64_mips16(ctx, ry, funct, offset, 1);
11428 break;
11429 #endif
11430 default:
11431 generate_exception_end(ctx, EXCP_RI);
11432 break;
11435 return 4;
11438 static inline bool is_uhi(int sdbbp_code)
11440 #ifdef CONFIG_USER_ONLY
11441 return false;
11442 #else
11443 return semihosting_enabled() && sdbbp_code == 1;
11444 #endif
11447 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11449 int rx, ry;
11450 int sa;
11451 int op, cnvt_op, op1, offset;
11452 int funct;
11453 int n_bytes;
11455 op = (ctx->opcode >> 11) & 0x1f;
11456 sa = (ctx->opcode >> 2) & 0x7;
11457 sa = sa == 0 ? 8 : sa;
11458 rx = xlat((ctx->opcode >> 8) & 0x7);
11459 cnvt_op = (ctx->opcode >> 5) & 0x7;
11460 ry = xlat((ctx->opcode >> 5) & 0x7);
11461 op1 = offset = ctx->opcode & 0x1f;
11463 n_bytes = 2;
11465 switch (op) {
11466 case M16_OPC_ADDIUSP:
11468 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11470 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11472 break;
11473 case M16_OPC_ADDIUPC:
11474 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11475 break;
11476 case M16_OPC_B:
11477 offset = (ctx->opcode & 0x7ff) << 1;
11478 offset = (int16_t)(offset << 4) >> 4;
11479 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11480 /* No delay slot, so just process as a normal instruction */
11481 break;
11482 case M16_OPC_JAL:
11483 offset = cpu_lduw_code(env, ctx->pc + 2);
11484 offset = (((ctx->opcode & 0x1f) << 21)
11485 | ((ctx->opcode >> 5) & 0x1f) << 16
11486 | offset) << 2;
11487 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11488 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11489 n_bytes = 4;
11490 break;
11491 case M16_OPC_BEQZ:
11492 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11493 ((int8_t)ctx->opcode) << 1, 0);
11494 /* No delay slot, so just process as a normal instruction */
11495 break;
11496 case M16_OPC_BNEQZ:
11497 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11498 ((int8_t)ctx->opcode) << 1, 0);
11499 /* No delay slot, so just process as a normal instruction */
11500 break;
11501 case M16_OPC_SHIFT:
11502 switch (ctx->opcode & 0x3) {
11503 case 0x0:
11504 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11505 break;
11506 case 0x1:
11507 #if defined(TARGET_MIPS64)
11508 check_insn(ctx, ISA_MIPS3);
11509 check_mips_64(ctx);
11510 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11511 #else
11512 generate_exception_end(ctx, EXCP_RI);
11513 #endif
11514 break;
11515 case 0x2:
11516 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11517 break;
11518 case 0x3:
11519 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11520 break;
11522 break;
11523 #if defined(TARGET_MIPS64)
11524 case M16_OPC_LD:
11525 check_insn(ctx, ISA_MIPS3);
11526 check_mips_64(ctx);
11527 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
11528 break;
11529 #endif
11530 case M16_OPC_RRIA:
11532 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
11534 if ((ctx->opcode >> 4) & 1) {
11535 #if defined(TARGET_MIPS64)
11536 check_insn(ctx, ISA_MIPS3);
11537 check_mips_64(ctx);
11538 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11539 #else
11540 generate_exception_end(ctx, EXCP_RI);
11541 #endif
11542 } else {
11543 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11546 break;
11547 case M16_OPC_ADDIU8:
11549 int16_t imm = (int8_t) ctx->opcode;
11551 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11553 break;
11554 case M16_OPC_SLTI:
11556 int16_t imm = (uint8_t) ctx->opcode;
11557 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11559 break;
11560 case M16_OPC_SLTIU:
11562 int16_t imm = (uint8_t) ctx->opcode;
11563 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11565 break;
11566 case M16_OPC_I8:
11568 int reg32;
11570 funct = (ctx->opcode >> 8) & 0x7;
11571 switch (funct) {
11572 case I8_BTEQZ:
11573 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
11574 ((int8_t)ctx->opcode) << 1, 0);
11575 break;
11576 case I8_BTNEZ:
11577 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
11578 ((int8_t)ctx->opcode) << 1, 0);
11579 break;
11580 case I8_SWRASP:
11581 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
11582 break;
11583 case I8_ADJSP:
11584 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
11585 ((int8_t)ctx->opcode) << 3);
11586 break;
11587 case I8_SVRS:
11588 check_insn(ctx, ISA_MIPS32);
11590 int do_ra = ctx->opcode & (1 << 6);
11591 int do_s0 = ctx->opcode & (1 << 5);
11592 int do_s1 = ctx->opcode & (1 << 4);
11593 int framesize = ctx->opcode & 0xf;
11595 if (framesize == 0) {
11596 framesize = 128;
11597 } else {
11598 framesize = framesize << 3;
11601 if (ctx->opcode & (1 << 7)) {
11602 gen_mips16_save(ctx, 0, 0,
11603 do_ra, do_s0, do_s1, framesize);
11604 } else {
11605 gen_mips16_restore(ctx, 0, 0,
11606 do_ra, do_s0, do_s1, framesize);
11609 break;
11610 case I8_MOV32R:
11612 int rz = xlat(ctx->opcode & 0x7);
11614 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
11615 ((ctx->opcode >> 5) & 0x7);
11616 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
11618 break;
11619 case I8_MOVR32:
11620 reg32 = ctx->opcode & 0x1f;
11621 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
11622 break;
11623 default:
11624 generate_exception_end(ctx, EXCP_RI);
11625 break;
11628 break;
11629 case M16_OPC_LI:
11631 int16_t imm = (uint8_t) ctx->opcode;
11633 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
11635 break;
11636 case M16_OPC_CMPI:
11638 int16_t imm = (uint8_t) ctx->opcode;
11639 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
11641 break;
11642 #if defined(TARGET_MIPS64)
11643 case M16_OPC_SD:
11644 check_insn(ctx, ISA_MIPS3);
11645 check_mips_64(ctx);
11646 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
11647 break;
11648 #endif
11649 case M16_OPC_LB:
11650 gen_ld(ctx, OPC_LB, ry, rx, offset);
11651 break;
11652 case M16_OPC_LH:
11653 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
11654 break;
11655 case M16_OPC_LWSP:
11656 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11657 break;
11658 case M16_OPC_LW:
11659 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
11660 break;
11661 case M16_OPC_LBU:
11662 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11663 break;
11664 case M16_OPC_LHU:
11665 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
11666 break;
11667 case M16_OPC_LWPC:
11668 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
11669 break;
11670 #if defined (TARGET_MIPS64)
11671 case M16_OPC_LWU:
11672 check_insn(ctx, ISA_MIPS3);
11673 check_mips_64(ctx);
11674 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
11675 break;
11676 #endif
11677 case M16_OPC_SB:
11678 gen_st(ctx, OPC_SB, ry, rx, offset);
11679 break;
11680 case M16_OPC_SH:
11681 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
11682 break;
11683 case M16_OPC_SWSP:
11684 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11685 break;
11686 case M16_OPC_SW:
11687 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
11688 break;
11689 case M16_OPC_RRR:
11691 int rz = xlat((ctx->opcode >> 2) & 0x7);
11692 int mips32_op;
11694 switch (ctx->opcode & 0x3) {
11695 case RRR_ADDU:
11696 mips32_op = OPC_ADDU;
11697 break;
11698 case RRR_SUBU:
11699 mips32_op = OPC_SUBU;
11700 break;
11701 #if defined(TARGET_MIPS64)
11702 case RRR_DADDU:
11703 mips32_op = OPC_DADDU;
11704 check_insn(ctx, ISA_MIPS3);
11705 check_mips_64(ctx);
11706 break;
11707 case RRR_DSUBU:
11708 mips32_op = OPC_DSUBU;
11709 check_insn(ctx, ISA_MIPS3);
11710 check_mips_64(ctx);
11711 break;
11712 #endif
11713 default:
11714 generate_exception_end(ctx, EXCP_RI);
11715 goto done;
11718 gen_arith(ctx, mips32_op, rz, rx, ry);
11719 done:
11722 break;
11723 case M16_OPC_RR:
11724 switch (op1) {
11725 case RR_JR:
11727 int nd = (ctx->opcode >> 7) & 0x1;
11728 int link = (ctx->opcode >> 6) & 0x1;
11729 int ra = (ctx->opcode >> 5) & 0x1;
11731 if (nd) {
11732 check_insn(ctx, ISA_MIPS32);
11735 if (link) {
11736 op = OPC_JALR;
11737 } else {
11738 op = OPC_JR;
11741 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
11742 (nd ? 0 : 2));
11744 break;
11745 case RR_SDBBP:
11746 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
11747 gen_helper_do_semihosting(cpu_env);
11748 } else {
11749 /* XXX: not clear which exception should be raised
11750 * when in debug mode...
11752 check_insn(ctx, ISA_MIPS32);
11753 generate_exception_end(ctx, EXCP_DBp);
11755 break;
11756 case RR_SLT:
11757 gen_slt(ctx, OPC_SLT, 24, rx, ry);
11758 break;
11759 case RR_SLTU:
11760 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
11761 break;
11762 case RR_BREAK:
11763 generate_exception_end(ctx, EXCP_BREAK);
11764 break;
11765 case RR_SLLV:
11766 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
11767 break;
11768 case RR_SRLV:
11769 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
11770 break;
11771 case RR_SRAV:
11772 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
11773 break;
11774 #if defined (TARGET_MIPS64)
11775 case RR_DSRL:
11776 check_insn(ctx, ISA_MIPS3);
11777 check_mips_64(ctx);
11778 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
11779 break;
11780 #endif
11781 case RR_CMP:
11782 gen_logic(ctx, OPC_XOR, 24, rx, ry);
11783 break;
11784 case RR_NEG:
11785 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
11786 break;
11787 case RR_AND:
11788 gen_logic(ctx, OPC_AND, rx, rx, ry);
11789 break;
11790 case RR_OR:
11791 gen_logic(ctx, OPC_OR, rx, rx, ry);
11792 break;
11793 case RR_XOR:
11794 gen_logic(ctx, OPC_XOR, rx, rx, ry);
11795 break;
11796 case RR_NOT:
11797 gen_logic(ctx, OPC_NOR, rx, ry, 0);
11798 break;
11799 case RR_MFHI:
11800 gen_HILO(ctx, OPC_MFHI, 0, rx);
11801 break;
11802 case RR_CNVT:
11803 check_insn(ctx, ISA_MIPS32);
11804 switch (cnvt_op) {
11805 case RR_RY_CNVT_ZEB:
11806 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11807 break;
11808 case RR_RY_CNVT_ZEH:
11809 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11810 break;
11811 case RR_RY_CNVT_SEB:
11812 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11813 break;
11814 case RR_RY_CNVT_SEH:
11815 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11816 break;
11817 #if defined (TARGET_MIPS64)
11818 case RR_RY_CNVT_ZEW:
11819 check_insn(ctx, ISA_MIPS64);
11820 check_mips_64(ctx);
11821 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11822 break;
11823 case RR_RY_CNVT_SEW:
11824 check_insn(ctx, ISA_MIPS64);
11825 check_mips_64(ctx);
11826 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11827 break;
11828 #endif
11829 default:
11830 generate_exception_end(ctx, EXCP_RI);
11831 break;
11833 break;
11834 case RR_MFLO:
11835 gen_HILO(ctx, OPC_MFLO, 0, rx);
11836 break;
11837 #if defined (TARGET_MIPS64)
11838 case RR_DSRA:
11839 check_insn(ctx, ISA_MIPS3);
11840 check_mips_64(ctx);
11841 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
11842 break;
11843 case RR_DSLLV:
11844 check_insn(ctx, ISA_MIPS3);
11845 check_mips_64(ctx);
11846 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
11847 break;
11848 case RR_DSRLV:
11849 check_insn(ctx, ISA_MIPS3);
11850 check_mips_64(ctx);
11851 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
11852 break;
11853 case RR_DSRAV:
11854 check_insn(ctx, ISA_MIPS3);
11855 check_mips_64(ctx);
11856 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
11857 break;
11858 #endif
11859 case RR_MULT:
11860 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
11861 break;
11862 case RR_MULTU:
11863 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
11864 break;
11865 case RR_DIV:
11866 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
11867 break;
11868 case RR_DIVU:
11869 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
11870 break;
11871 #if defined (TARGET_MIPS64)
11872 case RR_DMULT:
11873 check_insn(ctx, ISA_MIPS3);
11874 check_mips_64(ctx);
11875 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
11876 break;
11877 case RR_DMULTU:
11878 check_insn(ctx, ISA_MIPS3);
11879 check_mips_64(ctx);
11880 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
11881 break;
11882 case RR_DDIV:
11883 check_insn(ctx, ISA_MIPS3);
11884 check_mips_64(ctx);
11885 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
11886 break;
11887 case RR_DDIVU:
11888 check_insn(ctx, ISA_MIPS3);
11889 check_mips_64(ctx);
11890 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
11891 break;
11892 #endif
11893 default:
11894 generate_exception_end(ctx, EXCP_RI);
11895 break;
11897 break;
11898 case M16_OPC_EXTEND:
11899 decode_extended_mips16_opc(env, ctx);
11900 n_bytes = 4;
11901 break;
11902 #if defined(TARGET_MIPS64)
11903 case M16_OPC_I64:
11904 funct = (ctx->opcode >> 8) & 0x7;
11905 decode_i64_mips16(ctx, ry, funct, offset, 0);
11906 break;
11907 #endif
11908 default:
11909 generate_exception_end(ctx, EXCP_RI);
11910 break;
11913 return n_bytes;
11916 /* microMIPS extension to MIPS32/MIPS64 */
11919 * microMIPS32/microMIPS64 major opcodes
11921 * 1. MIPS Architecture for Programmers Volume II-B:
11922 * The microMIPS32 Instruction Set (Revision 3.05)
11924 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
11926 * 2. MIPS Architecture For Programmers Volume II-A:
11927 * The MIPS64 Instruction Set (Revision 3.51)
11930 enum {
11931 POOL32A = 0x00,
11932 POOL16A = 0x01,
11933 LBU16 = 0x02,
11934 MOVE16 = 0x03,
11935 ADDI32 = 0x04,
11936 R6_LUI = 0x04,
11937 AUI = 0x04,
11938 LBU32 = 0x05,
11939 SB32 = 0x06,
11940 LB32 = 0x07,
11942 POOL32B = 0x08,
11943 POOL16B = 0x09,
11944 LHU16 = 0x0a,
11945 ANDI16 = 0x0b,
11946 ADDIU32 = 0x0c,
11947 LHU32 = 0x0d,
11948 SH32 = 0x0e,
11949 LH32 = 0x0f,
11951 POOL32I = 0x10,
11952 POOL16C = 0x11,
11953 LWSP16 = 0x12,
11954 POOL16D = 0x13,
11955 ORI32 = 0x14,
11956 POOL32F = 0x15,
11957 POOL32S = 0x16, /* MIPS64 */
11958 DADDIU32 = 0x17, /* MIPS64 */
11960 POOL32C = 0x18,
11961 LWGP16 = 0x19,
11962 LW16 = 0x1a,
11963 POOL16E = 0x1b,
11964 XORI32 = 0x1c,
11965 JALS32 = 0x1d,
11966 BOVC = 0x1d,
11967 BEQC = 0x1d,
11968 BEQZALC = 0x1d,
11969 ADDIUPC = 0x1e,
11970 PCREL = 0x1e,
11971 BNVC = 0x1f,
11972 BNEC = 0x1f,
11973 BNEZALC = 0x1f,
11975 R6_BEQZC = 0x20,
11976 JIC = 0x20,
11977 POOL16F = 0x21,
11978 SB16 = 0x22,
11979 BEQZ16 = 0x23,
11980 BEQZC16 = 0x23,
11981 SLTI32 = 0x24,
11982 BEQ32 = 0x25,
11983 BC = 0x25,
11984 SWC132 = 0x26,
11985 LWC132 = 0x27,
11987 /* 0x29 is reserved */
11988 RES_29 = 0x29,
11989 R6_BNEZC = 0x28,
11990 JIALC = 0x28,
11991 SH16 = 0x2a,
11992 BNEZ16 = 0x2b,
11993 BNEZC16 = 0x2b,
11994 SLTIU32 = 0x2c,
11995 BNE32 = 0x2d,
11996 BALC = 0x2d,
11997 SDC132 = 0x2e,
11998 LDC132 = 0x2f,
12000 /* 0x31 is reserved */
12001 RES_31 = 0x31,
12002 BLEZALC = 0x30,
12003 BGEZALC = 0x30,
12004 BGEUC = 0x30,
12005 SWSP16 = 0x32,
12006 B16 = 0x33,
12007 BC16 = 0x33,
12008 ANDI32 = 0x34,
12009 J32 = 0x35,
12010 BGTZC = 0x35,
12011 BLTZC = 0x35,
12012 BLTC = 0x35,
12013 SD32 = 0x36, /* MIPS64 */
12014 LD32 = 0x37, /* MIPS64 */
12016 /* 0x39 is reserved */
12017 RES_39 = 0x39,
12018 BGTZALC = 0x38,
12019 BLTZALC = 0x38,
12020 BLTUC = 0x38,
12021 SW16 = 0x3a,
12022 LI16 = 0x3b,
12023 JALX32 = 0x3c,
12024 JAL32 = 0x3d,
12025 BLEZC = 0x3d,
12026 BGEZC = 0x3d,
12027 BGEC = 0x3d,
12028 SW32 = 0x3e,
12029 LW32 = 0x3f
12032 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12033 enum {
12034 ADDIUPC_00 = 0x00,
12035 ADDIUPC_07 = 0x07,
12036 AUIPC = 0x1e,
12037 ALUIPC = 0x1f,
12038 LWPC_08 = 0x08,
12039 LWPC_0F = 0x0F,
12042 /* POOL32A encoding of minor opcode field */
12044 enum {
12045 /* These opcodes are distinguished only by bits 9..6; those bits are
12046 * what are recorded below. */
12047 SLL32 = 0x0,
12048 SRL32 = 0x1,
12049 SRA = 0x2,
12050 ROTR = 0x3,
12051 SELEQZ = 0x5,
12052 SELNEZ = 0x6,
12053 R6_RDHWR = 0x7,
12055 SLLV = 0x0,
12056 SRLV = 0x1,
12057 SRAV = 0x2,
12058 ROTRV = 0x3,
12059 ADD = 0x4,
12060 ADDU32 = 0x5,
12061 SUB = 0x6,
12062 SUBU32 = 0x7,
12063 MUL = 0x8,
12064 AND = 0x9,
12065 OR32 = 0xa,
12066 NOR = 0xb,
12067 XOR32 = 0xc,
12068 SLT = 0xd,
12069 SLTU = 0xe,
12071 MOVN = 0x0,
12072 R6_MUL = 0x0,
12073 MOVZ = 0x1,
12074 MUH = 0x1,
12075 MULU = 0x2,
12076 MUHU = 0x3,
12077 LWXS = 0x4,
12078 R6_DIV = 0x4,
12079 MOD = 0x5,
12080 R6_DIVU = 0x6,
12081 MODU = 0x7,
12083 /* The following can be distinguished by their lower 6 bits. */
12084 BREAK32 = 0x07,
12085 INS = 0x0c,
12086 LSA = 0x0f,
12087 ALIGN = 0x1f,
12088 EXT = 0x2c,
12089 POOL32AXF = 0x3c,
12090 SIGRIE = 0x3f
12093 /* POOL32AXF encoding of minor opcode field extension */
12096 * 1. MIPS Architecture for Programmers Volume II-B:
12097 * The microMIPS32 Instruction Set (Revision 3.05)
12099 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12101 * 2. MIPS Architecture for Programmers VolumeIV-e:
12102 * The MIPS DSP Application-Specific Extension
12103 * to the microMIPS32 Architecture (Revision 2.34)
12105 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12108 enum {
12109 /* bits 11..6 */
12110 TEQ = 0x00,
12111 TGE = 0x08,
12112 TGEU = 0x10,
12113 TLT = 0x20,
12114 TLTU = 0x28,
12115 TNE = 0x30,
12117 MFC0 = 0x03,
12118 MTC0 = 0x0b,
12120 /* begin of microMIPS32 DSP */
12122 /* bits 13..12 for 0x01 */
12123 MFHI_ACC = 0x0,
12124 MFLO_ACC = 0x1,
12125 MTHI_ACC = 0x2,
12126 MTLO_ACC = 0x3,
12128 /* bits 13..12 for 0x2a */
12129 MADD_ACC = 0x0,
12130 MADDU_ACC = 0x1,
12131 MSUB_ACC = 0x2,
12132 MSUBU_ACC = 0x3,
12134 /* bits 13..12 for 0x32 */
12135 MULT_ACC = 0x0,
12136 MULTU_ACC = 0x1,
12138 /* end of microMIPS32 DSP */
12140 /* bits 15..12 for 0x2c */
12141 BITSWAP = 0x0,
12142 SEB = 0x2,
12143 SEH = 0x3,
12144 CLO = 0x4,
12145 CLZ = 0x5,
12146 RDHWR = 0x6,
12147 WSBH = 0x7,
12148 MULT = 0x8,
12149 MULTU = 0x9,
12150 DIV = 0xa,
12151 DIVU = 0xb,
12152 MADD = 0xc,
12153 MADDU = 0xd,
12154 MSUB = 0xe,
12155 MSUBU = 0xf,
12157 /* bits 15..12 for 0x34 */
12158 MFC2 = 0x4,
12159 MTC2 = 0x5,
12160 MFHC2 = 0x8,
12161 MTHC2 = 0x9,
12162 CFC2 = 0xc,
12163 CTC2 = 0xd,
12165 /* bits 15..12 for 0x3c */
12166 JALR = 0x0,
12167 JR = 0x0, /* alias */
12168 JALRC = 0x0,
12169 JRC = 0x0,
12170 JALR_HB = 0x1,
12171 JALRC_HB = 0x1,
12172 JALRS = 0x4,
12173 JALRS_HB = 0x5,
12175 /* bits 15..12 for 0x05 */
12176 RDPGPR = 0xe,
12177 WRPGPR = 0xf,
12179 /* bits 15..12 for 0x0d */
12180 TLBP = 0x0,
12181 TLBR = 0x1,
12182 TLBWI = 0x2,
12183 TLBWR = 0x3,
12184 TLBINV = 0x4,
12185 TLBINVF = 0x5,
12186 WAIT = 0x9,
12187 IRET = 0xd,
12188 DERET = 0xe,
12189 ERET = 0xf,
12191 /* bits 15..12 for 0x15 */
12192 DMT = 0x0,
12193 DVPE = 0x1,
12194 EMT = 0x2,
12195 EVPE = 0x3,
12197 /* bits 15..12 for 0x1d */
12198 DI = 0x4,
12199 EI = 0x5,
12201 /* bits 15..12 for 0x2d */
12202 SYNC = 0x6,
12203 SYSCALL = 0x8,
12204 SDBBP = 0xd,
12206 /* bits 15..12 for 0x35 */
12207 MFHI32 = 0x0,
12208 MFLO32 = 0x1,
12209 MTHI32 = 0x2,
12210 MTLO32 = 0x3,
12213 /* POOL32B encoding of minor opcode field (bits 15..12) */
12215 enum {
12216 LWC2 = 0x0,
12217 LWP = 0x1,
12218 LDP = 0x4,
12219 LWM32 = 0x5,
12220 CACHE = 0x6,
12221 LDM = 0x7,
12222 SWC2 = 0x8,
12223 SWP = 0x9,
12224 SDP = 0xc,
12225 SWM32 = 0xd,
12226 SDM = 0xf
12229 /* POOL32C encoding of minor opcode field (bits 15..12) */
12231 enum {
12232 LWL = 0x0,
12233 SWL = 0x8,
12234 LWR = 0x1,
12235 SWR = 0x9,
12236 PREF = 0x2,
12237 /* 0xa is reserved */
12238 LL = 0x3,
12239 SC = 0xb,
12240 LDL = 0x4,
12241 SDL = 0xc,
12242 LDR = 0x5,
12243 SDR = 0xd,
12244 /* 0x6 is reserved */
12245 LWU = 0xe,
12246 LLD = 0x7,
12247 SCD = 0xf
12250 /* POOL32F encoding of minor opcode field (bits 5..0) */
12252 enum {
12253 /* These are the bit 7..6 values */
12254 ADD_FMT = 0x0,
12256 SUB_FMT = 0x1,
12258 MUL_FMT = 0x2,
12260 DIV_FMT = 0x3,
12262 /* These are the bit 8..6 values */
12263 MOVN_FMT = 0x0,
12264 RSQRT2_FMT = 0x0,
12265 MOVF_FMT = 0x0,
12266 RINT_FMT = 0x0,
12267 SELNEZ_FMT = 0x0,
12269 MOVZ_FMT = 0x1,
12270 LWXC1 = 0x1,
12271 MOVT_FMT = 0x1,
12272 CLASS_FMT = 0x1,
12273 SELEQZ_FMT = 0x1,
12275 PLL_PS = 0x2,
12276 SWXC1 = 0x2,
12277 SEL_FMT = 0x2,
12279 PLU_PS = 0x3,
12280 LDXC1 = 0x3,
12282 MOVN_FMT_04 = 0x4,
12283 PUL_PS = 0x4,
12284 SDXC1 = 0x4,
12285 RECIP2_FMT = 0x4,
12287 MOVZ_FMT_05 = 0x05,
12288 PUU_PS = 0x5,
12289 LUXC1 = 0x5,
12291 CVT_PS_S = 0x6,
12292 SUXC1 = 0x6,
12293 ADDR_PS = 0x6,
12294 PREFX = 0x6,
12295 MADDF_FMT = 0x6,
12297 MULR_PS = 0x7,
12298 MSUBF_FMT = 0x7,
12300 MADD_S = 0x01,
12301 MADD_D = 0x09,
12302 MADD_PS = 0x11,
12303 ALNV_PS = 0x19,
12304 MSUB_S = 0x21,
12305 MSUB_D = 0x29,
12306 MSUB_PS = 0x31,
12308 NMADD_S = 0x02,
12309 NMADD_D = 0x0a,
12310 NMADD_PS = 0x12,
12311 NMSUB_S = 0x22,
12312 NMSUB_D = 0x2a,
12313 NMSUB_PS = 0x32,
12315 MIN_FMT = 0x3,
12316 MAX_FMT = 0xb,
12317 MINA_FMT = 0x23,
12318 MAXA_FMT = 0x2b,
12319 POOL32FXF = 0x3b,
12321 CABS_COND_FMT = 0x1c, /* MIPS3D */
12322 C_COND_FMT = 0x3c,
12324 CMP_CONDN_S = 0x5,
12325 CMP_CONDN_D = 0x15
12328 /* POOL32Fxf encoding of minor opcode extension field */
12330 enum {
12331 CVT_L = 0x04,
12332 RSQRT_FMT = 0x08,
12333 FLOOR_L = 0x0c,
12334 CVT_PW_PS = 0x1c,
12335 CVT_W = 0x24,
12336 SQRT_FMT = 0x28,
12337 FLOOR_W = 0x2c,
12338 CVT_PS_PW = 0x3c,
12339 CFC1 = 0x40,
12340 RECIP_FMT = 0x48,
12341 CEIL_L = 0x4c,
12342 CTC1 = 0x60,
12343 CEIL_W = 0x6c,
12344 MFC1 = 0x80,
12345 CVT_S_PL = 0x84,
12346 TRUNC_L = 0x8c,
12347 MTC1 = 0xa0,
12348 CVT_S_PU = 0xa4,
12349 TRUNC_W = 0xac,
12350 MFHC1 = 0xc0,
12351 ROUND_L = 0xcc,
12352 MTHC1 = 0xe0,
12353 ROUND_W = 0xec,
12355 MOV_FMT = 0x01,
12356 MOVF = 0x05,
12357 ABS_FMT = 0x0d,
12358 RSQRT1_FMT = 0x1d,
12359 MOVT = 0x25,
12360 NEG_FMT = 0x2d,
12361 CVT_D = 0x4d,
12362 RECIP1_FMT = 0x5d,
12363 CVT_S = 0x6d
12366 /* POOL32I encoding of minor opcode field (bits 25..21) */
12368 enum {
12369 BLTZ = 0x00,
12370 BLTZAL = 0x01,
12371 BGEZ = 0x02,
12372 BGEZAL = 0x03,
12373 BLEZ = 0x04,
12374 BNEZC = 0x05,
12375 BGTZ = 0x06,
12376 BEQZC = 0x07,
12377 TLTI = 0x08,
12378 BC1EQZC = 0x08,
12379 TGEI = 0x09,
12380 BC1NEZC = 0x09,
12381 TLTIU = 0x0a,
12382 BC2EQZC = 0x0a,
12383 TGEIU = 0x0b,
12384 BC2NEZC = 0x0a,
12385 TNEI = 0x0c,
12386 R6_SYNCI = 0x0c,
12387 LUI = 0x0d,
12388 TEQI = 0x0e,
12389 SYNCI = 0x10,
12390 BLTZALS = 0x11,
12391 BGEZALS = 0x13,
12392 BC2F = 0x14,
12393 BC2T = 0x15,
12394 BPOSGE64 = 0x1a,
12395 BPOSGE32 = 0x1b,
12396 /* These overlap and are distinguished by bit16 of the instruction */
12397 BC1F = 0x1c,
12398 BC1T = 0x1d,
12399 BC1ANY2F = 0x1c,
12400 BC1ANY2T = 0x1d,
12401 BC1ANY4F = 0x1e,
12402 BC1ANY4T = 0x1f
12405 /* POOL16A encoding of minor opcode field */
12407 enum {
12408 ADDU16 = 0x0,
12409 SUBU16 = 0x1
12412 /* POOL16B encoding of minor opcode field */
12414 enum {
12415 SLL16 = 0x0,
12416 SRL16 = 0x1
12419 /* POOL16C encoding of minor opcode field */
12421 enum {
12422 NOT16 = 0x00,
12423 XOR16 = 0x04,
12424 AND16 = 0x08,
12425 OR16 = 0x0c,
12426 LWM16 = 0x10,
12427 SWM16 = 0x14,
12428 JR16 = 0x18,
12429 JRC16 = 0x1a,
12430 JALR16 = 0x1c,
12431 JALR16S = 0x1e,
12432 MFHI16 = 0x20,
12433 MFLO16 = 0x24,
12434 BREAK16 = 0x28,
12435 SDBBP16 = 0x2c,
12436 JRADDIUSP = 0x30
12439 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
12441 enum {
12442 R6_NOT16 = 0x00,
12443 R6_AND16 = 0x01,
12444 R6_LWM16 = 0x02,
12445 R6_JRC16 = 0x03,
12446 MOVEP = 0x04,
12447 MOVEP_07 = 0x07,
12448 R6_XOR16 = 0x08,
12449 R6_OR16 = 0x09,
12450 R6_SWM16 = 0x0a,
12451 JALRC16 = 0x0b,
12452 MOVEP_0C = 0x0c,
12453 MOVEP_0F = 0x0f,
12454 JRCADDIUSP = 0x13,
12455 R6_BREAK16 = 0x1b,
12456 R6_SDBBP16 = 0x3b
12459 /* POOL16D encoding of minor opcode field */
12461 enum {
12462 ADDIUS5 = 0x0,
12463 ADDIUSP = 0x1
12466 /* POOL16E encoding of minor opcode field */
12468 enum {
12469 ADDIUR2 = 0x0,
12470 ADDIUR1SP = 0x1
12473 static int mmreg (int r)
12475 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12477 return map[r];
12480 /* Used for 16-bit store instructions. */
12481 static int mmreg2 (int r)
12483 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12485 return map[r];
12488 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12489 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12490 #define uMIPS_RS2(op) uMIPS_RS(op)
12491 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12492 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12493 #define uMIPS_RS5(op) (op & 0x1f)
12495 /* Signed immediate */
12496 #define SIMM(op, start, width) \
12497 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12498 << (32-width)) \
12499 >> (32-width))
12500 /* Zero-extended immediate */
12501 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12503 static void gen_addiur1sp(DisasContext *ctx)
12505 int rd = mmreg(uMIPS_RD(ctx->opcode));
12507 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12510 static void gen_addiur2(DisasContext *ctx)
12512 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12513 int rd = mmreg(uMIPS_RD(ctx->opcode));
12514 int rs = mmreg(uMIPS_RS(ctx->opcode));
12516 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12519 static void gen_addiusp(DisasContext *ctx)
12521 int encoded = ZIMM(ctx->opcode, 1, 9);
12522 int decoded;
12524 if (encoded <= 1) {
12525 decoded = 256 + encoded;
12526 } else if (encoded <= 255) {
12527 decoded = encoded;
12528 } else if (encoded <= 509) {
12529 decoded = encoded - 512;
12530 } else {
12531 decoded = encoded - 768;
12534 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
12537 static void gen_addius5(DisasContext *ctx)
12539 int imm = SIMM(ctx->opcode, 1, 4);
12540 int rd = (ctx->opcode >> 5) & 0x1f;
12542 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
12545 static void gen_andi16(DisasContext *ctx)
12547 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
12548 31, 32, 63, 64, 255, 32768, 65535 };
12549 int rd = mmreg(uMIPS_RD(ctx->opcode));
12550 int rs = mmreg(uMIPS_RS(ctx->opcode));
12551 int encoded = ZIMM(ctx->opcode, 0, 4);
12553 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
12556 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
12557 int base, int16_t offset)
12559 TCGv t0, t1;
12560 TCGv_i32 t2;
12562 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12563 generate_exception_end(ctx, EXCP_RI);
12564 return;
12567 t0 = tcg_temp_new();
12569 gen_base_offset_addr(ctx, t0, base, offset);
12571 t1 = tcg_const_tl(reglist);
12572 t2 = tcg_const_i32(ctx->mem_idx);
12574 save_cpu_state(ctx, 1);
12575 switch (opc) {
12576 case LWM32:
12577 gen_helper_lwm(cpu_env, t0, t1, t2);
12578 break;
12579 case SWM32:
12580 gen_helper_swm(cpu_env, t0, t1, t2);
12581 break;
12582 #ifdef TARGET_MIPS64
12583 case LDM:
12584 gen_helper_ldm(cpu_env, t0, t1, t2);
12585 break;
12586 case SDM:
12587 gen_helper_sdm(cpu_env, t0, t1, t2);
12588 break;
12589 #endif
12591 tcg_temp_free(t0);
12592 tcg_temp_free(t1);
12593 tcg_temp_free_i32(t2);
12597 static void gen_pool16c_insn(DisasContext *ctx)
12599 int rd = mmreg((ctx->opcode >> 3) & 0x7);
12600 int rs = mmreg(ctx->opcode & 0x7);
12602 switch (((ctx->opcode) >> 4) & 0x3f) {
12603 case NOT16 + 0:
12604 case NOT16 + 1:
12605 case NOT16 + 2:
12606 case NOT16 + 3:
12607 gen_logic(ctx, OPC_NOR, rd, rs, 0);
12608 break;
12609 case XOR16 + 0:
12610 case XOR16 + 1:
12611 case XOR16 + 2:
12612 case XOR16 + 3:
12613 gen_logic(ctx, OPC_XOR, rd, rd, rs);
12614 break;
12615 case AND16 + 0:
12616 case AND16 + 1:
12617 case AND16 + 2:
12618 case AND16 + 3:
12619 gen_logic(ctx, OPC_AND, rd, rd, rs);
12620 break;
12621 case OR16 + 0:
12622 case OR16 + 1:
12623 case OR16 + 2:
12624 case OR16 + 3:
12625 gen_logic(ctx, OPC_OR, rd, rd, rs);
12626 break;
12627 case LWM16 + 0:
12628 case LWM16 + 1:
12629 case LWM16 + 2:
12630 case LWM16 + 3:
12632 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12633 int offset = ZIMM(ctx->opcode, 0, 4);
12635 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
12636 29, offset << 2);
12638 break;
12639 case SWM16 + 0:
12640 case SWM16 + 1:
12641 case SWM16 + 2:
12642 case SWM16 + 3:
12644 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12645 int offset = ZIMM(ctx->opcode, 0, 4);
12647 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
12648 29, offset << 2);
12650 break;
12651 case JR16 + 0:
12652 case JR16 + 1:
12654 int reg = ctx->opcode & 0x1f;
12656 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
12658 break;
12659 case JRC16 + 0:
12660 case JRC16 + 1:
12662 int reg = ctx->opcode & 0x1f;
12663 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
12664 /* Let normal delay slot handling in our caller take us
12665 to the branch target. */
12667 break;
12668 case JALR16 + 0:
12669 case JALR16 + 1:
12670 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
12671 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12672 break;
12673 case JALR16S + 0:
12674 case JALR16S + 1:
12675 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
12676 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12677 break;
12678 case MFHI16 + 0:
12679 case MFHI16 + 1:
12680 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
12681 break;
12682 case MFLO16 + 0:
12683 case MFLO16 + 1:
12684 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
12685 break;
12686 case BREAK16:
12687 generate_exception_end(ctx, EXCP_BREAK);
12688 break;
12689 case SDBBP16:
12690 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
12691 gen_helper_do_semihosting(cpu_env);
12692 } else {
12693 /* XXX: not clear which exception should be raised
12694 * when in debug mode...
12696 check_insn(ctx, ISA_MIPS32);
12697 generate_exception_end(ctx, EXCP_DBp);
12699 break;
12700 case JRADDIUSP + 0:
12701 case JRADDIUSP + 1:
12703 int imm = ZIMM(ctx->opcode, 0, 5);
12704 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12705 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12706 /* Let normal delay slot handling in our caller take us
12707 to the branch target. */
12709 break;
12710 default:
12711 generate_exception_end(ctx, EXCP_RI);
12712 break;
12716 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
12717 int enc_rs)
12719 int rd, rs, re, rt;
12720 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
12721 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
12722 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
12723 rd = rd_enc[enc_dest];
12724 re = re_enc[enc_dest];
12725 rs = rs_rt_enc[enc_rs];
12726 rt = rs_rt_enc[enc_rt];
12727 if (rs) {
12728 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
12729 } else {
12730 tcg_gen_movi_tl(cpu_gpr[rd], 0);
12732 if (rt) {
12733 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
12734 } else {
12735 tcg_gen_movi_tl(cpu_gpr[re], 0);
12739 static void gen_pool16c_r6_insn(DisasContext *ctx)
12741 int rt = mmreg((ctx->opcode >> 7) & 0x7);
12742 int rs = mmreg((ctx->opcode >> 4) & 0x7);
12744 switch (ctx->opcode & 0xf) {
12745 case R6_NOT16:
12746 gen_logic(ctx, OPC_NOR, rt, rs, 0);
12747 break;
12748 case R6_AND16:
12749 gen_logic(ctx, OPC_AND, rt, rt, rs);
12750 break;
12751 case R6_LWM16:
12753 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
12754 int offset = extract32(ctx->opcode, 4, 4);
12755 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
12757 break;
12758 case R6_JRC16: /* JRCADDIUSP */
12759 if ((ctx->opcode >> 4) & 1) {
12760 /* JRCADDIUSP */
12761 int imm = extract32(ctx->opcode, 5, 5);
12762 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12763 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12764 } else {
12765 /* JRC16 */
12766 int rs = extract32(ctx->opcode, 5, 5);
12767 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
12769 break;
12770 case MOVEP ... MOVEP_07:
12771 case MOVEP_0C ... MOVEP_0F:
12773 int enc_dest = uMIPS_RD(ctx->opcode);
12774 int enc_rt = uMIPS_RS2(ctx->opcode);
12775 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
12776 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
12778 break;
12779 case R6_XOR16:
12780 gen_logic(ctx, OPC_XOR, rt, rt, rs);
12781 break;
12782 case R6_OR16:
12783 gen_logic(ctx, OPC_OR, rt, rt, rs);
12784 break;
12785 case R6_SWM16:
12787 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
12788 int offset = extract32(ctx->opcode, 4, 4);
12789 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
12791 break;
12792 case JALRC16: /* BREAK16, SDBBP16 */
12793 switch (ctx->opcode & 0x3f) {
12794 case JALRC16:
12795 case JALRC16 + 0x20:
12796 /* JALRC16 */
12797 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
12798 31, 0, 0);
12799 break;
12800 case R6_BREAK16:
12801 /* BREAK16 */
12802 generate_exception(ctx, EXCP_BREAK);
12803 break;
12804 case R6_SDBBP16:
12805 /* SDBBP16 */
12806 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
12807 gen_helper_do_semihosting(cpu_env);
12808 } else {
12809 if (ctx->hflags & MIPS_HFLAG_SBRI) {
12810 generate_exception(ctx, EXCP_RI);
12811 } else {
12812 generate_exception(ctx, EXCP_DBp);
12815 break;
12817 break;
12818 default:
12819 generate_exception(ctx, EXCP_RI);
12820 break;
12824 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
12826 TCGv t0 = tcg_temp_new();
12827 TCGv t1 = tcg_temp_new();
12829 gen_load_gpr(t0, base);
12831 if (index != 0) {
12832 gen_load_gpr(t1, index);
12833 tcg_gen_shli_tl(t1, t1, 2);
12834 gen_op_addr_add(ctx, t0, t1, t0);
12837 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12838 gen_store_gpr(t1, rd);
12840 tcg_temp_free(t0);
12841 tcg_temp_free(t1);
12844 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
12845 int base, int16_t offset)
12847 TCGv t0, t1;
12849 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
12850 generate_exception_end(ctx, EXCP_RI);
12851 return;
12854 t0 = tcg_temp_new();
12855 t1 = tcg_temp_new();
12857 gen_base_offset_addr(ctx, t0, base, offset);
12859 switch (opc) {
12860 case LWP:
12861 if (rd == base) {
12862 generate_exception_end(ctx, EXCP_RI);
12863 return;
12865 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12866 gen_store_gpr(t1, rd);
12867 tcg_gen_movi_tl(t1, 4);
12868 gen_op_addr_add(ctx, t0, t0, t1);
12869 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12870 gen_store_gpr(t1, rd+1);
12871 break;
12872 case SWP:
12873 gen_load_gpr(t1, rd);
12874 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12875 tcg_gen_movi_tl(t1, 4);
12876 gen_op_addr_add(ctx, t0, t0, t1);
12877 gen_load_gpr(t1, rd+1);
12878 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12879 break;
12880 #ifdef TARGET_MIPS64
12881 case LDP:
12882 if (rd == base) {
12883 generate_exception_end(ctx, EXCP_RI);
12884 return;
12886 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12887 gen_store_gpr(t1, rd);
12888 tcg_gen_movi_tl(t1, 8);
12889 gen_op_addr_add(ctx, t0, t0, t1);
12890 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12891 gen_store_gpr(t1, rd+1);
12892 break;
12893 case SDP:
12894 gen_load_gpr(t1, rd);
12895 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12896 tcg_gen_movi_tl(t1, 8);
12897 gen_op_addr_add(ctx, t0, t0, t1);
12898 gen_load_gpr(t1, rd+1);
12899 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12900 break;
12901 #endif
12903 tcg_temp_free(t0);
12904 tcg_temp_free(t1);
12907 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
12909 int extension = (ctx->opcode >> 6) & 0x3f;
12910 int minor = (ctx->opcode >> 12) & 0xf;
12911 uint32_t mips32_op;
12913 switch (extension) {
12914 case TEQ:
12915 mips32_op = OPC_TEQ;
12916 goto do_trap;
12917 case TGE:
12918 mips32_op = OPC_TGE;
12919 goto do_trap;
12920 case TGEU:
12921 mips32_op = OPC_TGEU;
12922 goto do_trap;
12923 case TLT:
12924 mips32_op = OPC_TLT;
12925 goto do_trap;
12926 case TLTU:
12927 mips32_op = OPC_TLTU;
12928 goto do_trap;
12929 case TNE:
12930 mips32_op = OPC_TNE;
12931 do_trap:
12932 gen_trap(ctx, mips32_op, rs, rt, -1);
12933 break;
12934 #ifndef CONFIG_USER_ONLY
12935 case MFC0:
12936 case MFC0 + 32:
12937 check_cp0_enabled(ctx);
12938 if (rt == 0) {
12939 /* Treat as NOP. */
12940 break;
12942 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
12943 break;
12944 case MTC0:
12945 case MTC0 + 32:
12946 check_cp0_enabled(ctx);
12948 TCGv t0 = tcg_temp_new();
12950 gen_load_gpr(t0, rt);
12951 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
12952 tcg_temp_free(t0);
12954 break;
12955 #endif
12956 case 0x2a:
12957 switch (minor & 3) {
12958 case MADD_ACC:
12959 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
12960 break;
12961 case MADDU_ACC:
12962 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
12963 break;
12964 case MSUB_ACC:
12965 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
12966 break;
12967 case MSUBU_ACC:
12968 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
12969 break;
12970 default:
12971 goto pool32axf_invalid;
12973 break;
12974 case 0x32:
12975 switch (minor & 3) {
12976 case MULT_ACC:
12977 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
12978 break;
12979 case MULTU_ACC:
12980 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
12981 break;
12982 default:
12983 goto pool32axf_invalid;
12985 break;
12986 case 0x2c:
12987 switch (minor) {
12988 case BITSWAP:
12989 check_insn(ctx, ISA_MIPS32R6);
12990 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
12991 break;
12992 case SEB:
12993 gen_bshfl(ctx, OPC_SEB, rs, rt);
12994 break;
12995 case SEH:
12996 gen_bshfl(ctx, OPC_SEH, rs, rt);
12997 break;
12998 case CLO:
12999 mips32_op = OPC_CLO;
13000 goto do_cl;
13001 case CLZ:
13002 mips32_op = OPC_CLZ;
13003 do_cl:
13004 check_insn(ctx, ISA_MIPS32);
13005 gen_cl(ctx, mips32_op, rt, rs);
13006 break;
13007 case RDHWR:
13008 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13009 gen_rdhwr(ctx, rt, rs, 0);
13010 break;
13011 case WSBH:
13012 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13013 break;
13014 case MULT:
13015 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13016 mips32_op = OPC_MULT;
13017 goto do_mul;
13018 case MULTU:
13019 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13020 mips32_op = OPC_MULTU;
13021 goto do_mul;
13022 case DIV:
13023 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13024 mips32_op = OPC_DIV;
13025 goto do_div;
13026 case DIVU:
13027 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13028 mips32_op = OPC_DIVU;
13029 goto do_div;
13030 do_div:
13031 check_insn(ctx, ISA_MIPS32);
13032 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13033 break;
13034 case MADD:
13035 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13036 mips32_op = OPC_MADD;
13037 goto do_mul;
13038 case MADDU:
13039 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13040 mips32_op = OPC_MADDU;
13041 goto do_mul;
13042 case MSUB:
13043 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13044 mips32_op = OPC_MSUB;
13045 goto do_mul;
13046 case MSUBU:
13047 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13048 mips32_op = OPC_MSUBU;
13049 do_mul:
13050 check_insn(ctx, ISA_MIPS32);
13051 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13052 break;
13053 default:
13054 goto pool32axf_invalid;
13056 break;
13057 case 0x34:
13058 switch (minor) {
13059 case MFC2:
13060 case MTC2:
13061 case MFHC2:
13062 case MTHC2:
13063 case CFC2:
13064 case CTC2:
13065 generate_exception_err(ctx, EXCP_CpU, 2);
13066 break;
13067 default:
13068 goto pool32axf_invalid;
13070 break;
13071 case 0x3c:
13072 switch (minor) {
13073 case JALR: /* JALRC */
13074 case JALR_HB: /* JALRC_HB */
13075 if (ctx->insn_flags & ISA_MIPS32R6) {
13076 /* JALRC, JALRC_HB */
13077 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13078 } else {
13079 /* JALR, JALR_HB */
13080 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13081 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13083 break;
13084 case JALRS:
13085 case JALRS_HB:
13086 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13087 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13088 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13089 break;
13090 default:
13091 goto pool32axf_invalid;
13093 break;
13094 case 0x05:
13095 switch (minor) {
13096 case RDPGPR:
13097 check_cp0_enabled(ctx);
13098 check_insn(ctx, ISA_MIPS32R2);
13099 gen_load_srsgpr(rs, rt);
13100 break;
13101 case WRPGPR:
13102 check_cp0_enabled(ctx);
13103 check_insn(ctx, ISA_MIPS32R2);
13104 gen_store_srsgpr(rs, rt);
13105 break;
13106 default:
13107 goto pool32axf_invalid;
13109 break;
13110 #ifndef CONFIG_USER_ONLY
13111 case 0x0d:
13112 switch (minor) {
13113 case TLBP:
13114 mips32_op = OPC_TLBP;
13115 goto do_cp0;
13116 case TLBR:
13117 mips32_op = OPC_TLBR;
13118 goto do_cp0;
13119 case TLBWI:
13120 mips32_op = OPC_TLBWI;
13121 goto do_cp0;
13122 case TLBWR:
13123 mips32_op = OPC_TLBWR;
13124 goto do_cp0;
13125 case TLBINV:
13126 mips32_op = OPC_TLBINV;
13127 goto do_cp0;
13128 case TLBINVF:
13129 mips32_op = OPC_TLBINVF;
13130 goto do_cp0;
13131 case WAIT:
13132 mips32_op = OPC_WAIT;
13133 goto do_cp0;
13134 case DERET:
13135 mips32_op = OPC_DERET;
13136 goto do_cp0;
13137 case ERET:
13138 mips32_op = OPC_ERET;
13139 do_cp0:
13140 gen_cp0(env, ctx, mips32_op, rt, rs);
13141 break;
13142 default:
13143 goto pool32axf_invalid;
13145 break;
13146 case 0x1d:
13147 switch (minor) {
13148 case DI:
13149 check_cp0_enabled(ctx);
13151 TCGv t0 = tcg_temp_new();
13153 save_cpu_state(ctx, 1);
13154 gen_helper_di(t0, cpu_env);
13155 gen_store_gpr(t0, rs);
13156 /* Stop translation as we may have switched the execution mode */
13157 ctx->bstate = BS_STOP;
13158 tcg_temp_free(t0);
13160 break;
13161 case EI:
13162 check_cp0_enabled(ctx);
13164 TCGv t0 = tcg_temp_new();
13166 save_cpu_state(ctx, 1);
13167 gen_helper_ei(t0, cpu_env);
13168 gen_store_gpr(t0, rs);
13169 /* Stop translation as we may have switched the execution mode */
13170 ctx->bstate = BS_STOP;
13171 tcg_temp_free(t0);
13173 break;
13174 default:
13175 goto pool32axf_invalid;
13177 break;
13178 #endif
13179 case 0x2d:
13180 switch (minor) {
13181 case SYNC:
13182 /* NOP */
13183 break;
13184 case SYSCALL:
13185 generate_exception_end(ctx, EXCP_SYSCALL);
13186 break;
13187 case SDBBP:
13188 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
13189 gen_helper_do_semihosting(cpu_env);
13190 } else {
13191 check_insn(ctx, ISA_MIPS32);
13192 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13193 generate_exception_end(ctx, EXCP_RI);
13194 } else {
13195 generate_exception_end(ctx, EXCP_DBp);
13198 break;
13199 default:
13200 goto pool32axf_invalid;
13202 break;
13203 case 0x01:
13204 switch (minor & 3) {
13205 case MFHI_ACC:
13206 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
13207 break;
13208 case MFLO_ACC:
13209 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
13210 break;
13211 case MTHI_ACC:
13212 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
13213 break;
13214 case MTLO_ACC:
13215 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
13216 break;
13217 default:
13218 goto pool32axf_invalid;
13220 break;
13221 case 0x35:
13222 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13223 switch (minor) {
13224 case MFHI32:
13225 gen_HILO(ctx, OPC_MFHI, 0, rs);
13226 break;
13227 case MFLO32:
13228 gen_HILO(ctx, OPC_MFLO, 0, rs);
13229 break;
13230 case MTHI32:
13231 gen_HILO(ctx, OPC_MTHI, 0, rs);
13232 break;
13233 case MTLO32:
13234 gen_HILO(ctx, OPC_MTLO, 0, rs);
13235 break;
13236 default:
13237 goto pool32axf_invalid;
13239 break;
13240 default:
13241 pool32axf_invalid:
13242 MIPS_INVAL("pool32axf");
13243 generate_exception_end(ctx, EXCP_RI);
13244 break;
13248 /* Values for microMIPS fmt field. Variable-width, depending on which
13249 formats the instruction supports. */
13251 enum {
13252 FMT_SD_S = 0,
13253 FMT_SD_D = 1,
13255 FMT_SDPS_S = 0,
13256 FMT_SDPS_D = 1,
13257 FMT_SDPS_PS = 2,
13259 FMT_SWL_S = 0,
13260 FMT_SWL_W = 1,
13261 FMT_SWL_L = 2,
13263 FMT_DWL_D = 0,
13264 FMT_DWL_W = 1,
13265 FMT_DWL_L = 2
13268 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
13270 int extension = (ctx->opcode >> 6) & 0x3ff;
13271 uint32_t mips32_op;
13273 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
13274 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
13275 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
13277 switch (extension) {
13278 case FLOAT_1BIT_FMT(CFC1, 0):
13279 mips32_op = OPC_CFC1;
13280 goto do_cp1;
13281 case FLOAT_1BIT_FMT(CTC1, 0):
13282 mips32_op = OPC_CTC1;
13283 goto do_cp1;
13284 case FLOAT_1BIT_FMT(MFC1, 0):
13285 mips32_op = OPC_MFC1;
13286 goto do_cp1;
13287 case FLOAT_1BIT_FMT(MTC1, 0):
13288 mips32_op = OPC_MTC1;
13289 goto do_cp1;
13290 case FLOAT_1BIT_FMT(MFHC1, 0):
13291 mips32_op = OPC_MFHC1;
13292 goto do_cp1;
13293 case FLOAT_1BIT_FMT(MTHC1, 0):
13294 mips32_op = OPC_MTHC1;
13295 do_cp1:
13296 gen_cp1(ctx, mips32_op, rt, rs);
13297 break;
13299 /* Reciprocal square root */
13300 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
13301 mips32_op = OPC_RSQRT_S;
13302 goto do_unaryfp;
13303 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
13304 mips32_op = OPC_RSQRT_D;
13305 goto do_unaryfp;
13307 /* Square root */
13308 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
13309 mips32_op = OPC_SQRT_S;
13310 goto do_unaryfp;
13311 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
13312 mips32_op = OPC_SQRT_D;
13313 goto do_unaryfp;
13315 /* Reciprocal */
13316 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
13317 mips32_op = OPC_RECIP_S;
13318 goto do_unaryfp;
13319 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
13320 mips32_op = OPC_RECIP_D;
13321 goto do_unaryfp;
13323 /* Floor */
13324 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
13325 mips32_op = OPC_FLOOR_L_S;
13326 goto do_unaryfp;
13327 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
13328 mips32_op = OPC_FLOOR_L_D;
13329 goto do_unaryfp;
13330 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
13331 mips32_op = OPC_FLOOR_W_S;
13332 goto do_unaryfp;
13333 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
13334 mips32_op = OPC_FLOOR_W_D;
13335 goto do_unaryfp;
13337 /* Ceiling */
13338 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
13339 mips32_op = OPC_CEIL_L_S;
13340 goto do_unaryfp;
13341 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
13342 mips32_op = OPC_CEIL_L_D;
13343 goto do_unaryfp;
13344 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
13345 mips32_op = OPC_CEIL_W_S;
13346 goto do_unaryfp;
13347 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
13348 mips32_op = OPC_CEIL_W_D;
13349 goto do_unaryfp;
13351 /* Truncation */
13352 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
13353 mips32_op = OPC_TRUNC_L_S;
13354 goto do_unaryfp;
13355 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
13356 mips32_op = OPC_TRUNC_L_D;
13357 goto do_unaryfp;
13358 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
13359 mips32_op = OPC_TRUNC_W_S;
13360 goto do_unaryfp;
13361 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
13362 mips32_op = OPC_TRUNC_W_D;
13363 goto do_unaryfp;
13365 /* Round */
13366 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
13367 mips32_op = OPC_ROUND_L_S;
13368 goto do_unaryfp;
13369 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
13370 mips32_op = OPC_ROUND_L_D;
13371 goto do_unaryfp;
13372 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
13373 mips32_op = OPC_ROUND_W_S;
13374 goto do_unaryfp;
13375 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
13376 mips32_op = OPC_ROUND_W_D;
13377 goto do_unaryfp;
13379 /* Integer to floating-point conversion */
13380 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
13381 mips32_op = OPC_CVT_L_S;
13382 goto do_unaryfp;
13383 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
13384 mips32_op = OPC_CVT_L_D;
13385 goto do_unaryfp;
13386 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
13387 mips32_op = OPC_CVT_W_S;
13388 goto do_unaryfp;
13389 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
13390 mips32_op = OPC_CVT_W_D;
13391 goto do_unaryfp;
13393 /* Paired-foo conversions */
13394 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
13395 mips32_op = OPC_CVT_S_PL;
13396 goto do_unaryfp;
13397 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13398 mips32_op = OPC_CVT_S_PU;
13399 goto do_unaryfp;
13400 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13401 mips32_op = OPC_CVT_PW_PS;
13402 goto do_unaryfp;
13403 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13404 mips32_op = OPC_CVT_PS_PW;
13405 goto do_unaryfp;
13407 /* Floating-point moves */
13408 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13409 mips32_op = OPC_MOV_S;
13410 goto do_unaryfp;
13411 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13412 mips32_op = OPC_MOV_D;
13413 goto do_unaryfp;
13414 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13415 mips32_op = OPC_MOV_PS;
13416 goto do_unaryfp;
13418 /* Absolute value */
13419 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13420 mips32_op = OPC_ABS_S;
13421 goto do_unaryfp;
13422 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13423 mips32_op = OPC_ABS_D;
13424 goto do_unaryfp;
13425 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13426 mips32_op = OPC_ABS_PS;
13427 goto do_unaryfp;
13429 /* Negation */
13430 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13431 mips32_op = OPC_NEG_S;
13432 goto do_unaryfp;
13433 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13434 mips32_op = OPC_NEG_D;
13435 goto do_unaryfp;
13436 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13437 mips32_op = OPC_NEG_PS;
13438 goto do_unaryfp;
13440 /* Reciprocal square root step */
13441 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13442 mips32_op = OPC_RSQRT1_S;
13443 goto do_unaryfp;
13444 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13445 mips32_op = OPC_RSQRT1_D;
13446 goto do_unaryfp;
13447 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13448 mips32_op = OPC_RSQRT1_PS;
13449 goto do_unaryfp;
13451 /* Reciprocal step */
13452 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13453 mips32_op = OPC_RECIP1_S;
13454 goto do_unaryfp;
13455 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13456 mips32_op = OPC_RECIP1_S;
13457 goto do_unaryfp;
13458 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13459 mips32_op = OPC_RECIP1_PS;
13460 goto do_unaryfp;
13462 /* Conversions from double */
13463 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13464 mips32_op = OPC_CVT_D_S;
13465 goto do_unaryfp;
13466 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13467 mips32_op = OPC_CVT_D_W;
13468 goto do_unaryfp;
13469 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13470 mips32_op = OPC_CVT_D_L;
13471 goto do_unaryfp;
13473 /* Conversions from single */
13474 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13475 mips32_op = OPC_CVT_S_D;
13476 goto do_unaryfp;
13477 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13478 mips32_op = OPC_CVT_S_W;
13479 goto do_unaryfp;
13480 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13481 mips32_op = OPC_CVT_S_L;
13482 do_unaryfp:
13483 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13484 break;
13486 /* Conditional moves on floating-point codes */
13487 case COND_FLOAT_MOV(MOVT, 0):
13488 case COND_FLOAT_MOV(MOVT, 1):
13489 case COND_FLOAT_MOV(MOVT, 2):
13490 case COND_FLOAT_MOV(MOVT, 3):
13491 case COND_FLOAT_MOV(MOVT, 4):
13492 case COND_FLOAT_MOV(MOVT, 5):
13493 case COND_FLOAT_MOV(MOVT, 6):
13494 case COND_FLOAT_MOV(MOVT, 7):
13495 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13496 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13497 break;
13498 case COND_FLOAT_MOV(MOVF, 0):
13499 case COND_FLOAT_MOV(MOVF, 1):
13500 case COND_FLOAT_MOV(MOVF, 2):
13501 case COND_FLOAT_MOV(MOVF, 3):
13502 case COND_FLOAT_MOV(MOVF, 4):
13503 case COND_FLOAT_MOV(MOVF, 5):
13504 case COND_FLOAT_MOV(MOVF, 6):
13505 case COND_FLOAT_MOV(MOVF, 7):
13506 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13507 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13508 break;
13509 default:
13510 MIPS_INVAL("pool32fxf");
13511 generate_exception_end(ctx, EXCP_RI);
13512 break;
13516 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
13518 int32_t offset;
13519 uint16_t insn;
13520 int rt, rs, rd, rr;
13521 int16_t imm;
13522 uint32_t op, minor, mips32_op;
13523 uint32_t cond, fmt, cc;
13525 insn = cpu_lduw_code(env, ctx->pc + 2);
13526 ctx->opcode = (ctx->opcode << 16) | insn;
13528 rt = (ctx->opcode >> 21) & 0x1f;
13529 rs = (ctx->opcode >> 16) & 0x1f;
13530 rd = (ctx->opcode >> 11) & 0x1f;
13531 rr = (ctx->opcode >> 6) & 0x1f;
13532 imm = (int16_t) ctx->opcode;
13534 op = (ctx->opcode >> 26) & 0x3f;
13535 switch (op) {
13536 case POOL32A:
13537 minor = ctx->opcode & 0x3f;
13538 switch (minor) {
13539 case 0x00:
13540 minor = (ctx->opcode >> 6) & 0xf;
13541 switch (minor) {
13542 case SLL32:
13543 mips32_op = OPC_SLL;
13544 goto do_shifti;
13545 case SRA:
13546 mips32_op = OPC_SRA;
13547 goto do_shifti;
13548 case SRL32:
13549 mips32_op = OPC_SRL;
13550 goto do_shifti;
13551 case ROTR:
13552 mips32_op = OPC_ROTR;
13553 do_shifti:
13554 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
13555 break;
13556 case SELEQZ:
13557 check_insn(ctx, ISA_MIPS32R6);
13558 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
13559 break;
13560 case SELNEZ:
13561 check_insn(ctx, ISA_MIPS32R6);
13562 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
13563 break;
13564 case R6_RDHWR:
13565 check_insn(ctx, ISA_MIPS32R6);
13566 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
13567 break;
13568 default:
13569 goto pool32a_invalid;
13571 break;
13572 case 0x10:
13573 minor = (ctx->opcode >> 6) & 0xf;
13574 switch (minor) {
13575 /* Arithmetic */
13576 case ADD:
13577 mips32_op = OPC_ADD;
13578 goto do_arith;
13579 case ADDU32:
13580 mips32_op = OPC_ADDU;
13581 goto do_arith;
13582 case SUB:
13583 mips32_op = OPC_SUB;
13584 goto do_arith;
13585 case SUBU32:
13586 mips32_op = OPC_SUBU;
13587 goto do_arith;
13588 case MUL:
13589 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13590 mips32_op = OPC_MUL;
13591 do_arith:
13592 gen_arith(ctx, mips32_op, rd, rs, rt);
13593 break;
13594 /* Shifts */
13595 case SLLV:
13596 mips32_op = OPC_SLLV;
13597 goto do_shift;
13598 case SRLV:
13599 mips32_op = OPC_SRLV;
13600 goto do_shift;
13601 case SRAV:
13602 mips32_op = OPC_SRAV;
13603 goto do_shift;
13604 case ROTRV:
13605 mips32_op = OPC_ROTRV;
13606 do_shift:
13607 gen_shift(ctx, mips32_op, rd, rs, rt);
13608 break;
13609 /* Logical operations */
13610 case AND:
13611 mips32_op = OPC_AND;
13612 goto do_logic;
13613 case OR32:
13614 mips32_op = OPC_OR;
13615 goto do_logic;
13616 case NOR:
13617 mips32_op = OPC_NOR;
13618 goto do_logic;
13619 case XOR32:
13620 mips32_op = OPC_XOR;
13621 do_logic:
13622 gen_logic(ctx, mips32_op, rd, rs, rt);
13623 break;
13624 /* Set less than */
13625 case SLT:
13626 mips32_op = OPC_SLT;
13627 goto do_slt;
13628 case SLTU:
13629 mips32_op = OPC_SLTU;
13630 do_slt:
13631 gen_slt(ctx, mips32_op, rd, rs, rt);
13632 break;
13633 default:
13634 goto pool32a_invalid;
13636 break;
13637 case 0x18:
13638 minor = (ctx->opcode >> 6) & 0xf;
13639 switch (minor) {
13640 /* Conditional moves */
13641 case MOVN: /* MUL */
13642 if (ctx->insn_flags & ISA_MIPS32R6) {
13643 /* MUL */
13644 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
13645 } else {
13646 /* MOVN */
13647 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
13649 break;
13650 case MOVZ: /* MUH */
13651 if (ctx->insn_flags & ISA_MIPS32R6) {
13652 /* MUH */
13653 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
13654 } else {
13655 /* MOVZ */
13656 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
13658 break;
13659 case MULU:
13660 check_insn(ctx, ISA_MIPS32R6);
13661 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
13662 break;
13663 case MUHU:
13664 check_insn(ctx, ISA_MIPS32R6);
13665 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
13666 break;
13667 case LWXS: /* DIV */
13668 if (ctx->insn_flags & ISA_MIPS32R6) {
13669 /* DIV */
13670 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
13671 } else {
13672 /* LWXS */
13673 gen_ldxs(ctx, rs, rt, rd);
13675 break;
13676 case MOD:
13677 check_insn(ctx, ISA_MIPS32R6);
13678 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
13679 break;
13680 case R6_DIVU:
13681 check_insn(ctx, ISA_MIPS32R6);
13682 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
13683 break;
13684 case MODU:
13685 check_insn(ctx, ISA_MIPS32R6);
13686 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
13687 break;
13688 default:
13689 goto pool32a_invalid;
13691 break;
13692 case INS:
13693 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
13694 return;
13695 case LSA:
13696 check_insn(ctx, ISA_MIPS32R6);
13697 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
13698 extract32(ctx->opcode, 9, 2));
13699 break;
13700 case ALIGN:
13701 check_insn(ctx, ISA_MIPS32R6);
13702 gen_align(ctx, OPC_ALIGN, rd, rs, rt,
13703 extract32(ctx->opcode, 9, 2));
13704 break;
13705 case EXT:
13706 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
13707 return;
13708 case POOL32AXF:
13709 gen_pool32axf(env, ctx, rt, rs);
13710 break;
13711 case BREAK32:
13712 generate_exception_end(ctx, EXCP_BREAK);
13713 break;
13714 case SIGRIE:
13715 check_insn(ctx, ISA_MIPS32R6);
13716 generate_exception_end(ctx, EXCP_RI);
13717 break;
13718 default:
13719 pool32a_invalid:
13720 MIPS_INVAL("pool32a");
13721 generate_exception_end(ctx, EXCP_RI);
13722 break;
13724 break;
13725 case POOL32B:
13726 minor = (ctx->opcode >> 12) & 0xf;
13727 switch (minor) {
13728 case CACHE:
13729 check_cp0_enabled(ctx);
13730 /* Treat as no-op. */
13731 break;
13732 case LWC2:
13733 case SWC2:
13734 /* COP2: Not implemented. */
13735 generate_exception_err(ctx, EXCP_CpU, 2);
13736 break;
13737 #ifdef TARGET_MIPS64
13738 case LDP:
13739 case SDP:
13740 check_insn(ctx, ISA_MIPS3);
13741 check_mips_64(ctx);
13742 /* Fallthrough */
13743 #endif
13744 case LWP:
13745 case SWP:
13746 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13747 break;
13748 #ifdef TARGET_MIPS64
13749 case LDM:
13750 case SDM:
13751 check_insn(ctx, ISA_MIPS3);
13752 check_mips_64(ctx);
13753 /* Fallthrough */
13754 #endif
13755 case LWM32:
13756 case SWM32:
13757 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13758 break;
13759 default:
13760 MIPS_INVAL("pool32b");
13761 generate_exception_end(ctx, EXCP_RI);
13762 break;
13764 break;
13765 case POOL32F:
13766 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
13767 minor = ctx->opcode & 0x3f;
13768 check_cp1_enabled(ctx);
13769 switch (minor) {
13770 case ALNV_PS:
13771 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13772 mips32_op = OPC_ALNV_PS;
13773 goto do_madd;
13774 case MADD_S:
13775 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13776 mips32_op = OPC_MADD_S;
13777 goto do_madd;
13778 case MADD_D:
13779 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13780 mips32_op = OPC_MADD_D;
13781 goto do_madd;
13782 case MADD_PS:
13783 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13784 mips32_op = OPC_MADD_PS;
13785 goto do_madd;
13786 case MSUB_S:
13787 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13788 mips32_op = OPC_MSUB_S;
13789 goto do_madd;
13790 case MSUB_D:
13791 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13792 mips32_op = OPC_MSUB_D;
13793 goto do_madd;
13794 case MSUB_PS:
13795 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13796 mips32_op = OPC_MSUB_PS;
13797 goto do_madd;
13798 case NMADD_S:
13799 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13800 mips32_op = OPC_NMADD_S;
13801 goto do_madd;
13802 case NMADD_D:
13803 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13804 mips32_op = OPC_NMADD_D;
13805 goto do_madd;
13806 case NMADD_PS:
13807 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13808 mips32_op = OPC_NMADD_PS;
13809 goto do_madd;
13810 case NMSUB_S:
13811 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13812 mips32_op = OPC_NMSUB_S;
13813 goto do_madd;
13814 case NMSUB_D:
13815 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13816 mips32_op = OPC_NMSUB_D;
13817 goto do_madd;
13818 case NMSUB_PS:
13819 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13820 mips32_op = OPC_NMSUB_PS;
13821 do_madd:
13822 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
13823 break;
13824 case CABS_COND_FMT:
13825 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13826 cond = (ctx->opcode >> 6) & 0xf;
13827 cc = (ctx->opcode >> 13) & 0x7;
13828 fmt = (ctx->opcode >> 10) & 0x3;
13829 switch (fmt) {
13830 case 0x0:
13831 gen_cmpabs_s(ctx, cond, rt, rs, cc);
13832 break;
13833 case 0x1:
13834 gen_cmpabs_d(ctx, cond, rt, rs, cc);
13835 break;
13836 case 0x2:
13837 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
13838 break;
13839 default:
13840 goto pool32f_invalid;
13842 break;
13843 case C_COND_FMT:
13844 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13845 cond = (ctx->opcode >> 6) & 0xf;
13846 cc = (ctx->opcode >> 13) & 0x7;
13847 fmt = (ctx->opcode >> 10) & 0x3;
13848 switch (fmt) {
13849 case 0x0:
13850 gen_cmp_s(ctx, cond, rt, rs, cc);
13851 break;
13852 case 0x1:
13853 gen_cmp_d(ctx, cond, rt, rs, cc);
13854 break;
13855 case 0x2:
13856 gen_cmp_ps(ctx, cond, rt, rs, cc);
13857 break;
13858 default:
13859 goto pool32f_invalid;
13861 break;
13862 case CMP_CONDN_S:
13863 check_insn(ctx, ISA_MIPS32R6);
13864 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
13865 break;
13866 case CMP_CONDN_D:
13867 check_insn(ctx, ISA_MIPS32R6);
13868 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
13869 break;
13870 case POOL32FXF:
13871 gen_pool32fxf(ctx, rt, rs);
13872 break;
13873 case 0x00:
13874 /* PLL foo */
13875 switch ((ctx->opcode >> 6) & 0x7) {
13876 case PLL_PS:
13877 mips32_op = OPC_PLL_PS;
13878 goto do_ps;
13879 case PLU_PS:
13880 mips32_op = OPC_PLU_PS;
13881 goto do_ps;
13882 case PUL_PS:
13883 mips32_op = OPC_PUL_PS;
13884 goto do_ps;
13885 case PUU_PS:
13886 mips32_op = OPC_PUU_PS;
13887 goto do_ps;
13888 case CVT_PS_S:
13889 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13890 mips32_op = OPC_CVT_PS_S;
13891 do_ps:
13892 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13893 break;
13894 default:
13895 goto pool32f_invalid;
13897 break;
13898 case MIN_FMT:
13899 check_insn(ctx, ISA_MIPS32R6);
13900 switch ((ctx->opcode >> 9) & 0x3) {
13901 case FMT_SDPS_S:
13902 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
13903 break;
13904 case FMT_SDPS_D:
13905 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
13906 break;
13907 default:
13908 goto pool32f_invalid;
13910 break;
13911 case 0x08:
13912 /* [LS][WDU]XC1 */
13913 switch ((ctx->opcode >> 6) & 0x7) {
13914 case LWXC1:
13915 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13916 mips32_op = OPC_LWXC1;
13917 goto do_ldst_cp1;
13918 case SWXC1:
13919 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13920 mips32_op = OPC_SWXC1;
13921 goto do_ldst_cp1;
13922 case LDXC1:
13923 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13924 mips32_op = OPC_LDXC1;
13925 goto do_ldst_cp1;
13926 case SDXC1:
13927 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13928 mips32_op = OPC_SDXC1;
13929 goto do_ldst_cp1;
13930 case LUXC1:
13931 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13932 mips32_op = OPC_LUXC1;
13933 goto do_ldst_cp1;
13934 case SUXC1:
13935 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13936 mips32_op = OPC_SUXC1;
13937 do_ldst_cp1:
13938 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
13939 break;
13940 default:
13941 goto pool32f_invalid;
13943 break;
13944 case MAX_FMT:
13945 check_insn(ctx, ISA_MIPS32R6);
13946 switch ((ctx->opcode >> 9) & 0x3) {
13947 case FMT_SDPS_S:
13948 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
13949 break;
13950 case FMT_SDPS_D:
13951 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
13952 break;
13953 default:
13954 goto pool32f_invalid;
13956 break;
13957 case 0x18:
13958 /* 3D insns */
13959 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13960 fmt = (ctx->opcode >> 9) & 0x3;
13961 switch ((ctx->opcode >> 6) & 0x7) {
13962 case RSQRT2_FMT:
13963 switch (fmt) {
13964 case FMT_SDPS_S:
13965 mips32_op = OPC_RSQRT2_S;
13966 goto do_3d;
13967 case FMT_SDPS_D:
13968 mips32_op = OPC_RSQRT2_D;
13969 goto do_3d;
13970 case FMT_SDPS_PS:
13971 mips32_op = OPC_RSQRT2_PS;
13972 goto do_3d;
13973 default:
13974 goto pool32f_invalid;
13976 break;
13977 case RECIP2_FMT:
13978 switch (fmt) {
13979 case FMT_SDPS_S:
13980 mips32_op = OPC_RECIP2_S;
13981 goto do_3d;
13982 case FMT_SDPS_D:
13983 mips32_op = OPC_RECIP2_D;
13984 goto do_3d;
13985 case FMT_SDPS_PS:
13986 mips32_op = OPC_RECIP2_PS;
13987 goto do_3d;
13988 default:
13989 goto pool32f_invalid;
13991 break;
13992 case ADDR_PS:
13993 mips32_op = OPC_ADDR_PS;
13994 goto do_3d;
13995 case MULR_PS:
13996 mips32_op = OPC_MULR_PS;
13997 do_3d:
13998 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13999 break;
14000 default:
14001 goto pool32f_invalid;
14003 break;
14004 case 0x20:
14005 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
14006 cc = (ctx->opcode >> 13) & 0x7;
14007 fmt = (ctx->opcode >> 9) & 0x3;
14008 switch ((ctx->opcode >> 6) & 0x7) {
14009 case MOVF_FMT: /* RINT_FMT */
14010 if (ctx->insn_flags & ISA_MIPS32R6) {
14011 /* RINT_FMT */
14012 switch (fmt) {
14013 case FMT_SDPS_S:
14014 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14015 break;
14016 case FMT_SDPS_D:
14017 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14018 break;
14019 default:
14020 goto pool32f_invalid;
14022 } else {
14023 /* MOVF_FMT */
14024 switch (fmt) {
14025 case FMT_SDPS_S:
14026 gen_movcf_s(ctx, rs, rt, cc, 0);
14027 break;
14028 case FMT_SDPS_D:
14029 gen_movcf_d(ctx, rs, rt, cc, 0);
14030 break;
14031 case FMT_SDPS_PS:
14032 check_ps(ctx);
14033 gen_movcf_ps(ctx, rs, rt, cc, 0);
14034 break;
14035 default:
14036 goto pool32f_invalid;
14039 break;
14040 case MOVT_FMT: /* CLASS_FMT */
14041 if (ctx->insn_flags & ISA_MIPS32R6) {
14042 /* CLASS_FMT */
14043 switch (fmt) {
14044 case FMT_SDPS_S:
14045 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14046 break;
14047 case FMT_SDPS_D:
14048 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14049 break;
14050 default:
14051 goto pool32f_invalid;
14053 } else {
14054 /* MOVT_FMT */
14055 switch (fmt) {
14056 case FMT_SDPS_S:
14057 gen_movcf_s(ctx, rs, rt, cc, 1);
14058 break;
14059 case FMT_SDPS_D:
14060 gen_movcf_d(ctx, rs, rt, cc, 1);
14061 break;
14062 case FMT_SDPS_PS:
14063 check_ps(ctx);
14064 gen_movcf_ps(ctx, rs, rt, cc, 1);
14065 break;
14066 default:
14067 goto pool32f_invalid;
14070 break;
14071 case PREFX:
14072 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14073 break;
14074 default:
14075 goto pool32f_invalid;
14077 break;
14078 #define FINSN_3ARG_SDPS(prfx) \
14079 switch ((ctx->opcode >> 8) & 0x3) { \
14080 case FMT_SDPS_S: \
14081 mips32_op = OPC_##prfx##_S; \
14082 goto do_fpop; \
14083 case FMT_SDPS_D: \
14084 mips32_op = OPC_##prfx##_D; \
14085 goto do_fpop; \
14086 case FMT_SDPS_PS: \
14087 check_ps(ctx); \
14088 mips32_op = OPC_##prfx##_PS; \
14089 goto do_fpop; \
14090 default: \
14091 goto pool32f_invalid; \
14093 case MINA_FMT:
14094 check_insn(ctx, ISA_MIPS32R6);
14095 switch ((ctx->opcode >> 9) & 0x3) {
14096 case FMT_SDPS_S:
14097 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14098 break;
14099 case FMT_SDPS_D:
14100 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14101 break;
14102 default:
14103 goto pool32f_invalid;
14105 break;
14106 case MAXA_FMT:
14107 check_insn(ctx, ISA_MIPS32R6);
14108 switch ((ctx->opcode >> 9) & 0x3) {
14109 case FMT_SDPS_S:
14110 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14111 break;
14112 case FMT_SDPS_D:
14113 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14114 break;
14115 default:
14116 goto pool32f_invalid;
14118 break;
14119 case 0x30:
14120 /* regular FP ops */
14121 switch ((ctx->opcode >> 6) & 0x3) {
14122 case ADD_FMT:
14123 FINSN_3ARG_SDPS(ADD);
14124 break;
14125 case SUB_FMT:
14126 FINSN_3ARG_SDPS(SUB);
14127 break;
14128 case MUL_FMT:
14129 FINSN_3ARG_SDPS(MUL);
14130 break;
14131 case DIV_FMT:
14132 fmt = (ctx->opcode >> 8) & 0x3;
14133 if (fmt == 1) {
14134 mips32_op = OPC_DIV_D;
14135 } else if (fmt == 0) {
14136 mips32_op = OPC_DIV_S;
14137 } else {
14138 goto pool32f_invalid;
14140 goto do_fpop;
14141 default:
14142 goto pool32f_invalid;
14144 break;
14145 case 0x38:
14146 /* cmovs */
14147 switch ((ctx->opcode >> 6) & 0x7) {
14148 case MOVN_FMT: /* SELNEZ_FMT */
14149 if (ctx->insn_flags & ISA_MIPS32R6) {
14150 /* SELNEZ_FMT */
14151 switch ((ctx->opcode >> 9) & 0x3) {
14152 case FMT_SDPS_S:
14153 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14154 break;
14155 case FMT_SDPS_D:
14156 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
14157 break;
14158 default:
14159 goto pool32f_invalid;
14161 } else {
14162 /* MOVN_FMT */
14163 FINSN_3ARG_SDPS(MOVN);
14165 break;
14166 case MOVN_FMT_04:
14167 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14168 FINSN_3ARG_SDPS(MOVN);
14169 break;
14170 case MOVZ_FMT: /* SELEQZ_FMT */
14171 if (ctx->insn_flags & ISA_MIPS32R6) {
14172 /* SELEQZ_FMT */
14173 switch ((ctx->opcode >> 9) & 0x3) {
14174 case FMT_SDPS_S:
14175 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
14176 break;
14177 case FMT_SDPS_D:
14178 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
14179 break;
14180 default:
14181 goto pool32f_invalid;
14183 } else {
14184 /* MOVZ_FMT */
14185 FINSN_3ARG_SDPS(MOVZ);
14187 break;
14188 case MOVZ_FMT_05:
14189 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14190 FINSN_3ARG_SDPS(MOVZ);
14191 break;
14192 case SEL_FMT:
14193 check_insn(ctx, ISA_MIPS32R6);
14194 switch ((ctx->opcode >> 9) & 0x3) {
14195 case FMT_SDPS_S:
14196 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
14197 break;
14198 case FMT_SDPS_D:
14199 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
14200 break;
14201 default:
14202 goto pool32f_invalid;
14204 break;
14205 case MADDF_FMT:
14206 check_insn(ctx, ISA_MIPS32R6);
14207 switch ((ctx->opcode >> 9) & 0x3) {
14208 case FMT_SDPS_S:
14209 mips32_op = OPC_MADDF_S;
14210 goto do_fpop;
14211 case FMT_SDPS_D:
14212 mips32_op = OPC_MADDF_D;
14213 goto do_fpop;
14214 default:
14215 goto pool32f_invalid;
14217 break;
14218 case MSUBF_FMT:
14219 check_insn(ctx, ISA_MIPS32R6);
14220 switch ((ctx->opcode >> 9) & 0x3) {
14221 case FMT_SDPS_S:
14222 mips32_op = OPC_MSUBF_S;
14223 goto do_fpop;
14224 case FMT_SDPS_D:
14225 mips32_op = OPC_MSUBF_D;
14226 goto do_fpop;
14227 default:
14228 goto pool32f_invalid;
14230 break;
14231 default:
14232 goto pool32f_invalid;
14234 break;
14235 do_fpop:
14236 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14237 break;
14238 default:
14239 pool32f_invalid:
14240 MIPS_INVAL("pool32f");
14241 generate_exception_end(ctx, EXCP_RI);
14242 break;
14244 } else {
14245 generate_exception_err(ctx, EXCP_CpU, 1);
14247 break;
14248 case POOL32I:
14249 minor = (ctx->opcode >> 21) & 0x1f;
14250 switch (minor) {
14251 case BLTZ:
14252 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14253 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
14254 break;
14255 case BLTZAL:
14256 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14257 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
14258 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14259 break;
14260 case BLTZALS:
14261 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14262 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
14263 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14264 break;
14265 case BGEZ:
14266 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14267 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
14268 break;
14269 case BGEZAL:
14270 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14271 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
14272 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14273 break;
14274 case BGEZALS:
14275 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14276 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
14277 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14278 break;
14279 case BLEZ:
14280 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14281 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
14282 break;
14283 case BGTZ:
14284 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14285 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
14286 break;
14288 /* Traps */
14289 case TLTI: /* BC1EQZC */
14290 if (ctx->insn_flags & ISA_MIPS32R6) {
14291 /* BC1EQZC */
14292 check_cp1_enabled(ctx);
14293 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
14294 } else {
14295 /* TLTI */
14296 mips32_op = OPC_TLTI;
14297 goto do_trapi;
14299 break;
14300 case TGEI: /* BC1NEZC */
14301 if (ctx->insn_flags & ISA_MIPS32R6) {
14302 /* BC1NEZC */
14303 check_cp1_enabled(ctx);
14304 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
14305 } else {
14306 /* TGEI */
14307 mips32_op = OPC_TGEI;
14308 goto do_trapi;
14310 break;
14311 case TLTIU:
14312 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14313 mips32_op = OPC_TLTIU;
14314 goto do_trapi;
14315 case TGEIU:
14316 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14317 mips32_op = OPC_TGEIU;
14318 goto do_trapi;
14319 case TNEI: /* SYNCI */
14320 if (ctx->insn_flags & ISA_MIPS32R6) {
14321 /* SYNCI */
14322 /* Break the TB to be able to sync copied instructions
14323 immediately */
14324 ctx->bstate = BS_STOP;
14325 } else {
14326 /* TNEI */
14327 mips32_op = OPC_TNEI;
14328 goto do_trapi;
14330 break;
14331 case TEQI:
14332 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14333 mips32_op = OPC_TEQI;
14334 do_trapi:
14335 gen_trap(ctx, mips32_op, rs, -1, imm);
14336 break;
14338 case BNEZC:
14339 case BEQZC:
14340 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14341 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
14342 4, rs, 0, imm << 1, 0);
14343 /* Compact branches don't have a delay slot, so just let
14344 the normal delay slot handling take us to the branch
14345 target. */
14346 break;
14347 case LUI:
14348 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14349 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
14350 break;
14351 case SYNCI:
14352 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14353 /* Break the TB to be able to sync copied instructions
14354 immediately */
14355 ctx->bstate = BS_STOP;
14356 break;
14357 case BC2F:
14358 case BC2T:
14359 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14360 /* COP2: Not implemented. */
14361 generate_exception_err(ctx, EXCP_CpU, 2);
14362 break;
14363 case BC1F:
14364 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14365 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
14366 goto do_cp1branch;
14367 case BC1T:
14368 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14369 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
14370 goto do_cp1branch;
14371 case BC1ANY4F:
14372 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14373 mips32_op = OPC_BC1FANY4;
14374 goto do_cp1mips3d;
14375 case BC1ANY4T:
14376 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14377 mips32_op = OPC_BC1TANY4;
14378 do_cp1mips3d:
14379 check_cop1x(ctx);
14380 check_insn(ctx, ASE_MIPS3D);
14381 /* Fall through */
14382 do_cp1branch:
14383 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14384 check_cp1_enabled(ctx);
14385 gen_compute_branch1(ctx, mips32_op,
14386 (ctx->opcode >> 18) & 0x7, imm << 1);
14387 } else {
14388 generate_exception_err(ctx, EXCP_CpU, 1);
14390 break;
14391 case BPOSGE64:
14392 case BPOSGE32:
14393 /* MIPS DSP: not implemented */
14394 /* Fall through */
14395 default:
14396 MIPS_INVAL("pool32i");
14397 generate_exception_end(ctx, EXCP_RI);
14398 break;
14400 break;
14401 case POOL32C:
14402 minor = (ctx->opcode >> 12) & 0xf;
14403 offset = sextract32(ctx->opcode, 0,
14404 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
14405 switch (minor) {
14406 case LWL:
14407 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14408 mips32_op = OPC_LWL;
14409 goto do_ld_lr;
14410 case SWL:
14411 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14412 mips32_op = OPC_SWL;
14413 goto do_st_lr;
14414 case LWR:
14415 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14416 mips32_op = OPC_LWR;
14417 goto do_ld_lr;
14418 case SWR:
14419 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14420 mips32_op = OPC_SWR;
14421 goto do_st_lr;
14422 #if defined(TARGET_MIPS64)
14423 case LDL:
14424 check_insn(ctx, ISA_MIPS3);
14425 check_mips_64(ctx);
14426 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14427 mips32_op = OPC_LDL;
14428 goto do_ld_lr;
14429 case SDL:
14430 check_insn(ctx, ISA_MIPS3);
14431 check_mips_64(ctx);
14432 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14433 mips32_op = OPC_SDL;
14434 goto do_st_lr;
14435 case LDR:
14436 check_insn(ctx, ISA_MIPS3);
14437 check_mips_64(ctx);
14438 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14439 mips32_op = OPC_LDR;
14440 goto do_ld_lr;
14441 case SDR:
14442 check_insn(ctx, ISA_MIPS3);
14443 check_mips_64(ctx);
14444 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14445 mips32_op = OPC_SDR;
14446 goto do_st_lr;
14447 case LWU:
14448 check_insn(ctx, ISA_MIPS3);
14449 check_mips_64(ctx);
14450 mips32_op = OPC_LWU;
14451 goto do_ld_lr;
14452 case LLD:
14453 check_insn(ctx, ISA_MIPS3);
14454 check_mips_64(ctx);
14455 mips32_op = OPC_LLD;
14456 goto do_ld_lr;
14457 #endif
14458 case LL:
14459 mips32_op = OPC_LL;
14460 goto do_ld_lr;
14461 do_ld_lr:
14462 gen_ld(ctx, mips32_op, rt, rs, offset);
14463 break;
14464 do_st_lr:
14465 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
14466 break;
14467 case SC:
14468 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
14469 break;
14470 #if defined(TARGET_MIPS64)
14471 case SCD:
14472 check_insn(ctx, ISA_MIPS3);
14473 check_mips_64(ctx);
14474 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
14475 break;
14476 #endif
14477 case PREF:
14478 /* Treat as no-op */
14479 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
14480 /* hint codes 24-31 are reserved and signal RI */
14481 generate_exception(ctx, EXCP_RI);
14483 break;
14484 default:
14485 MIPS_INVAL("pool32c");
14486 generate_exception_end(ctx, EXCP_RI);
14487 break;
14489 break;
14490 case ADDI32: /* AUI, LUI */
14491 if (ctx->insn_flags & ISA_MIPS32R6) {
14492 /* AUI, LUI */
14493 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
14494 } else {
14495 /* ADDI32 */
14496 mips32_op = OPC_ADDI;
14497 goto do_addi;
14499 break;
14500 case ADDIU32:
14501 mips32_op = OPC_ADDIU;
14502 do_addi:
14503 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
14504 break;
14506 /* Logical operations */
14507 case ORI32:
14508 mips32_op = OPC_ORI;
14509 goto do_logici;
14510 case XORI32:
14511 mips32_op = OPC_XORI;
14512 goto do_logici;
14513 case ANDI32:
14514 mips32_op = OPC_ANDI;
14515 do_logici:
14516 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
14517 break;
14519 /* Set less than immediate */
14520 case SLTI32:
14521 mips32_op = OPC_SLTI;
14522 goto do_slti;
14523 case SLTIU32:
14524 mips32_op = OPC_SLTIU;
14525 do_slti:
14526 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
14527 break;
14528 case JALX32:
14529 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14530 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14531 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
14532 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14533 break;
14534 case JALS32: /* BOVC, BEQC, BEQZALC */
14535 if (ctx->insn_flags & ISA_MIPS32R6) {
14536 if (rs >= rt) {
14537 /* BOVC */
14538 mips32_op = OPC_BOVC;
14539 } else if (rs < rt && rs == 0) {
14540 /* BEQZALC */
14541 mips32_op = OPC_BEQZALC;
14542 } else {
14543 /* BEQC */
14544 mips32_op = OPC_BEQC;
14546 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14547 } else {
14548 /* JALS32 */
14549 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
14550 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
14551 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14553 break;
14554 case BEQ32: /* BC */
14555 if (ctx->insn_flags & ISA_MIPS32R6) {
14556 /* BC */
14557 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
14558 sextract32(ctx->opcode << 1, 0, 27));
14559 } else {
14560 /* BEQ32 */
14561 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
14563 break;
14564 case BNE32: /* BALC */
14565 if (ctx->insn_flags & ISA_MIPS32R6) {
14566 /* BALC */
14567 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
14568 sextract32(ctx->opcode << 1, 0, 27));
14569 } else {
14570 /* BNE32 */
14571 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
14573 break;
14574 case J32: /* BGTZC, BLTZC, BLTC */
14575 if (ctx->insn_flags & ISA_MIPS32R6) {
14576 if (rs == 0 && rt != 0) {
14577 /* BGTZC */
14578 mips32_op = OPC_BGTZC;
14579 } else if (rs != 0 && rt != 0 && rs == rt) {
14580 /* BLTZC */
14581 mips32_op = OPC_BLTZC;
14582 } else {
14583 /* BLTC */
14584 mips32_op = OPC_BLTC;
14586 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14587 } else {
14588 /* J32 */
14589 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
14590 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14592 break;
14593 case JAL32: /* BLEZC, BGEZC, BGEC */
14594 if (ctx->insn_flags & ISA_MIPS32R6) {
14595 if (rs == 0 && rt != 0) {
14596 /* BLEZC */
14597 mips32_op = OPC_BLEZC;
14598 } else if (rs != 0 && rt != 0 && rs == rt) {
14599 /* BGEZC */
14600 mips32_op = OPC_BGEZC;
14601 } else {
14602 /* BGEC */
14603 mips32_op = OPC_BGEC;
14605 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14606 } else {
14607 /* JAL32 */
14608 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
14609 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14610 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14612 break;
14613 /* Floating point (COP1) */
14614 case LWC132:
14615 mips32_op = OPC_LWC1;
14616 goto do_cop1;
14617 case LDC132:
14618 mips32_op = OPC_LDC1;
14619 goto do_cop1;
14620 case SWC132:
14621 mips32_op = OPC_SWC1;
14622 goto do_cop1;
14623 case SDC132:
14624 mips32_op = OPC_SDC1;
14625 do_cop1:
14626 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
14627 break;
14628 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14629 if (ctx->insn_flags & ISA_MIPS32R6) {
14630 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14631 switch ((ctx->opcode >> 16) & 0x1f) {
14632 case ADDIUPC_00 ... ADDIUPC_07:
14633 gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
14634 break;
14635 case AUIPC:
14636 gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
14637 break;
14638 case ALUIPC:
14639 gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
14640 break;
14641 case LWPC_08 ... LWPC_0F:
14642 gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
14643 break;
14644 default:
14645 generate_exception(ctx, EXCP_RI);
14646 break;
14648 } else {
14649 /* ADDIUPC */
14650 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
14651 int offset = SIMM(ctx->opcode, 0, 23) << 2;
14653 gen_addiupc(ctx, reg, offset, 0, 0);
14655 break;
14656 case BNVC: /* BNEC, BNEZALC */
14657 check_insn(ctx, ISA_MIPS32R6);
14658 if (rs >= rt) {
14659 /* BNVC */
14660 mips32_op = OPC_BNVC;
14661 } else if (rs < rt && rs == 0) {
14662 /* BNEZALC */
14663 mips32_op = OPC_BNEZALC;
14664 } else {
14665 /* BNEC */
14666 mips32_op = OPC_BNEC;
14668 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14669 break;
14670 case R6_BNEZC: /* JIALC */
14671 check_insn(ctx, ISA_MIPS32R6);
14672 if (rt != 0) {
14673 /* BNEZC */
14674 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
14675 sextract32(ctx->opcode << 1, 0, 22));
14676 } else {
14677 /* JIALC */
14678 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
14680 break;
14681 case R6_BEQZC: /* JIC */
14682 check_insn(ctx, ISA_MIPS32R6);
14683 if (rt != 0) {
14684 /* BEQZC */
14685 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
14686 sextract32(ctx->opcode << 1, 0, 22));
14687 } else {
14688 /* JIC */
14689 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
14691 break;
14692 case BLEZALC: /* BGEZALC, BGEUC */
14693 check_insn(ctx, ISA_MIPS32R6);
14694 if (rs == 0 && rt != 0) {
14695 /* BLEZALC */
14696 mips32_op = OPC_BLEZALC;
14697 } else if (rs != 0 && rt != 0 && rs == rt) {
14698 /* BGEZALC */
14699 mips32_op = OPC_BGEZALC;
14700 } else {
14701 /* BGEUC */
14702 mips32_op = OPC_BGEUC;
14704 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14705 break;
14706 case BGTZALC: /* BLTZALC, BLTUC */
14707 check_insn(ctx, ISA_MIPS32R6);
14708 if (rs == 0 && rt != 0) {
14709 /* BGTZALC */
14710 mips32_op = OPC_BGTZALC;
14711 } else if (rs != 0 && rt != 0 && rs == rt) {
14712 /* BLTZALC */
14713 mips32_op = OPC_BLTZALC;
14714 } else {
14715 /* BLTUC */
14716 mips32_op = OPC_BLTUC;
14718 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14719 break;
14720 /* Loads and stores */
14721 case LB32:
14722 mips32_op = OPC_LB;
14723 goto do_ld;
14724 case LBU32:
14725 mips32_op = OPC_LBU;
14726 goto do_ld;
14727 case LH32:
14728 mips32_op = OPC_LH;
14729 goto do_ld;
14730 case LHU32:
14731 mips32_op = OPC_LHU;
14732 goto do_ld;
14733 case LW32:
14734 mips32_op = OPC_LW;
14735 goto do_ld;
14736 #ifdef TARGET_MIPS64
14737 case LD32:
14738 check_insn(ctx, ISA_MIPS3);
14739 check_mips_64(ctx);
14740 mips32_op = OPC_LD;
14741 goto do_ld;
14742 case SD32:
14743 check_insn(ctx, ISA_MIPS3);
14744 check_mips_64(ctx);
14745 mips32_op = OPC_SD;
14746 goto do_st;
14747 #endif
14748 case SB32:
14749 mips32_op = OPC_SB;
14750 goto do_st;
14751 case SH32:
14752 mips32_op = OPC_SH;
14753 goto do_st;
14754 case SW32:
14755 mips32_op = OPC_SW;
14756 goto do_st;
14757 do_ld:
14758 gen_ld(ctx, mips32_op, rt, rs, imm);
14759 break;
14760 do_st:
14761 gen_st(ctx, mips32_op, rt, rs, imm);
14762 break;
14763 default:
14764 generate_exception_end(ctx, EXCP_RI);
14765 break;
14769 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
14771 uint32_t op;
14773 /* make sure instructions are on a halfword boundary */
14774 if (ctx->pc & 0x1) {
14775 env->CP0_BadVAddr = ctx->pc;
14776 generate_exception_end(ctx, EXCP_AdEL);
14777 return 2;
14780 op = (ctx->opcode >> 10) & 0x3f;
14781 /* Enforce properly-sized instructions in a delay slot */
14782 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
14783 switch (op & 0x7) { /* MSB-3..MSB-5 */
14784 case 0:
14785 /* POOL32A, POOL32B, POOL32I, POOL32C */
14786 case 4:
14787 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
14788 case 5:
14789 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
14790 case 6:
14791 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
14792 case 7:
14793 /* LB32, LH32, LWC132, LDC132, LW32 */
14794 if (ctx->hflags & MIPS_HFLAG_BDS16) {
14795 generate_exception_end(ctx, EXCP_RI);
14796 return 2;
14798 break;
14799 case 1:
14800 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
14801 case 2:
14802 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
14803 case 3:
14804 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
14805 if (ctx->hflags & MIPS_HFLAG_BDS32) {
14806 generate_exception_end(ctx, EXCP_RI);
14807 return 2;
14809 break;
14813 switch (op) {
14814 case POOL16A:
14816 int rd = mmreg(uMIPS_RD(ctx->opcode));
14817 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
14818 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
14819 uint32_t opc = 0;
14821 switch (ctx->opcode & 0x1) {
14822 case ADDU16:
14823 opc = OPC_ADDU;
14824 break;
14825 case SUBU16:
14826 opc = OPC_SUBU;
14827 break;
14829 if (ctx->insn_flags & ISA_MIPS32R6) {
14830 /* In the Release 6 the register number location in
14831 * the instruction encoding has changed.
14833 gen_arith(ctx, opc, rs1, rd, rs2);
14834 } else {
14835 gen_arith(ctx, opc, rd, rs1, rs2);
14838 break;
14839 case POOL16B:
14841 int rd = mmreg(uMIPS_RD(ctx->opcode));
14842 int rs = mmreg(uMIPS_RS(ctx->opcode));
14843 int amount = (ctx->opcode >> 1) & 0x7;
14844 uint32_t opc = 0;
14845 amount = amount == 0 ? 8 : amount;
14847 switch (ctx->opcode & 0x1) {
14848 case SLL16:
14849 opc = OPC_SLL;
14850 break;
14851 case SRL16:
14852 opc = OPC_SRL;
14853 break;
14856 gen_shift_imm(ctx, opc, rd, rs, amount);
14858 break;
14859 case POOL16C:
14860 if (ctx->insn_flags & ISA_MIPS32R6) {
14861 gen_pool16c_r6_insn(ctx);
14862 } else {
14863 gen_pool16c_insn(ctx);
14865 break;
14866 case LWGP16:
14868 int rd = mmreg(uMIPS_RD(ctx->opcode));
14869 int rb = 28; /* GP */
14870 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
14872 gen_ld(ctx, OPC_LW, rd, rb, offset);
14874 break;
14875 case POOL16F:
14876 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14877 if (ctx->opcode & 1) {
14878 generate_exception_end(ctx, EXCP_RI);
14879 } else {
14880 /* MOVEP */
14881 int enc_dest = uMIPS_RD(ctx->opcode);
14882 int enc_rt = uMIPS_RS2(ctx->opcode);
14883 int enc_rs = uMIPS_RS1(ctx->opcode);
14884 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14886 break;
14887 case LBU16:
14889 int rd = mmreg(uMIPS_RD(ctx->opcode));
14890 int rb = mmreg(uMIPS_RS(ctx->opcode));
14891 int16_t offset = ZIMM(ctx->opcode, 0, 4);
14892 offset = (offset == 0xf ? -1 : offset);
14894 gen_ld(ctx, OPC_LBU, rd, rb, offset);
14896 break;
14897 case LHU16:
14899 int rd = mmreg(uMIPS_RD(ctx->opcode));
14900 int rb = mmreg(uMIPS_RS(ctx->opcode));
14901 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
14903 gen_ld(ctx, OPC_LHU, rd, rb, offset);
14905 break;
14906 case LWSP16:
14908 int rd = (ctx->opcode >> 5) & 0x1f;
14909 int rb = 29; /* SP */
14910 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
14912 gen_ld(ctx, OPC_LW, rd, rb, offset);
14914 break;
14915 case LW16:
14917 int rd = mmreg(uMIPS_RD(ctx->opcode));
14918 int rb = mmreg(uMIPS_RS(ctx->opcode));
14919 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
14921 gen_ld(ctx, OPC_LW, rd, rb, offset);
14923 break;
14924 case SB16:
14926 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14927 int rb = mmreg(uMIPS_RS(ctx->opcode));
14928 int16_t offset = ZIMM(ctx->opcode, 0, 4);
14930 gen_st(ctx, OPC_SB, rd, rb, offset);
14932 break;
14933 case SH16:
14935 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14936 int rb = mmreg(uMIPS_RS(ctx->opcode));
14937 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
14939 gen_st(ctx, OPC_SH, rd, rb, offset);
14941 break;
14942 case SWSP16:
14944 int rd = (ctx->opcode >> 5) & 0x1f;
14945 int rb = 29; /* SP */
14946 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
14948 gen_st(ctx, OPC_SW, rd, rb, offset);
14950 break;
14951 case SW16:
14953 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14954 int rb = mmreg(uMIPS_RS(ctx->opcode));
14955 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
14957 gen_st(ctx, OPC_SW, rd, rb, offset);
14959 break;
14960 case MOVE16:
14962 int rd = uMIPS_RD5(ctx->opcode);
14963 int rs = uMIPS_RS5(ctx->opcode);
14965 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
14967 break;
14968 case ANDI16:
14969 gen_andi16(ctx);
14970 break;
14971 case POOL16D:
14972 switch (ctx->opcode & 0x1) {
14973 case ADDIUS5:
14974 gen_addius5(ctx);
14975 break;
14976 case ADDIUSP:
14977 gen_addiusp(ctx);
14978 break;
14980 break;
14981 case POOL16E:
14982 switch (ctx->opcode & 0x1) {
14983 case ADDIUR2:
14984 gen_addiur2(ctx);
14985 break;
14986 case ADDIUR1SP:
14987 gen_addiur1sp(ctx);
14988 break;
14990 break;
14991 case B16: /* BC16 */
14992 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
14993 sextract32(ctx->opcode, 0, 10) << 1,
14994 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
14995 break;
14996 case BNEZ16: /* BNEZC16 */
14997 case BEQZ16: /* BEQZC16 */
14998 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
14999 mmreg(uMIPS_RD(ctx->opcode)),
15000 0, sextract32(ctx->opcode, 0, 7) << 1,
15001 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15003 break;
15004 case LI16:
15006 int reg = mmreg(uMIPS_RD(ctx->opcode));
15007 int imm = ZIMM(ctx->opcode, 0, 7);
15009 imm = (imm == 0x7f ? -1 : imm);
15010 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15012 break;
15013 case RES_29:
15014 case RES_31:
15015 case RES_39:
15016 generate_exception_end(ctx, EXCP_RI);
15017 break;
15018 default:
15019 decode_micromips32_opc(env, ctx);
15020 return 4;
15023 return 2;
15026 /* SmartMIPS extension to MIPS32 */
15028 #if defined(TARGET_MIPS64)
15030 /* MDMX extension to MIPS64 */
15032 #endif
15034 /* MIPSDSP functions. */
15035 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
15036 int rd, int base, int offset)
15038 TCGv t0;
15040 check_dsp(ctx);
15041 t0 = tcg_temp_new();
15043 if (base == 0) {
15044 gen_load_gpr(t0, offset);
15045 } else if (offset == 0) {
15046 gen_load_gpr(t0, base);
15047 } else {
15048 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
15051 switch (opc) {
15052 case OPC_LBUX:
15053 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
15054 gen_store_gpr(t0, rd);
15055 break;
15056 case OPC_LHX:
15057 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
15058 gen_store_gpr(t0, rd);
15059 break;
15060 case OPC_LWX:
15061 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
15062 gen_store_gpr(t0, rd);
15063 break;
15064 #if defined(TARGET_MIPS64)
15065 case OPC_LDX:
15066 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
15067 gen_store_gpr(t0, rd);
15068 break;
15069 #endif
15071 tcg_temp_free(t0);
15074 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
15075 int ret, int v1, int v2)
15077 TCGv v1_t;
15078 TCGv v2_t;
15080 if (ret == 0) {
15081 /* Treat as NOP. */
15082 return;
15085 v1_t = tcg_temp_new();
15086 v2_t = tcg_temp_new();
15088 gen_load_gpr(v1_t, v1);
15089 gen_load_gpr(v2_t, v2);
15091 switch (op1) {
15092 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
15093 case OPC_MULT_G_2E:
15094 check_dspr2(ctx);
15095 switch (op2) {
15096 case OPC_ADDUH_QB:
15097 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
15098 break;
15099 case OPC_ADDUH_R_QB:
15100 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15101 break;
15102 case OPC_ADDQH_PH:
15103 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
15104 break;
15105 case OPC_ADDQH_R_PH:
15106 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15107 break;
15108 case OPC_ADDQH_W:
15109 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
15110 break;
15111 case OPC_ADDQH_R_W:
15112 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15113 break;
15114 case OPC_SUBUH_QB:
15115 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
15116 break;
15117 case OPC_SUBUH_R_QB:
15118 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15119 break;
15120 case OPC_SUBQH_PH:
15121 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
15122 break;
15123 case OPC_SUBQH_R_PH:
15124 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15125 break;
15126 case OPC_SUBQH_W:
15127 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
15128 break;
15129 case OPC_SUBQH_R_W:
15130 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15131 break;
15133 break;
15134 case OPC_ABSQ_S_PH_DSP:
15135 switch (op2) {
15136 case OPC_ABSQ_S_QB:
15137 check_dspr2(ctx);
15138 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
15139 break;
15140 case OPC_ABSQ_S_PH:
15141 check_dsp(ctx);
15142 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
15143 break;
15144 case OPC_ABSQ_S_W:
15145 check_dsp(ctx);
15146 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
15147 break;
15148 case OPC_PRECEQ_W_PHL:
15149 check_dsp(ctx);
15150 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
15151 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15152 break;
15153 case OPC_PRECEQ_W_PHR:
15154 check_dsp(ctx);
15155 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
15156 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
15157 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15158 break;
15159 case OPC_PRECEQU_PH_QBL:
15160 check_dsp(ctx);
15161 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
15162 break;
15163 case OPC_PRECEQU_PH_QBR:
15164 check_dsp(ctx);
15165 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
15166 break;
15167 case OPC_PRECEQU_PH_QBLA:
15168 check_dsp(ctx);
15169 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
15170 break;
15171 case OPC_PRECEQU_PH_QBRA:
15172 check_dsp(ctx);
15173 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
15174 break;
15175 case OPC_PRECEU_PH_QBL:
15176 check_dsp(ctx);
15177 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
15178 break;
15179 case OPC_PRECEU_PH_QBR:
15180 check_dsp(ctx);
15181 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
15182 break;
15183 case OPC_PRECEU_PH_QBLA:
15184 check_dsp(ctx);
15185 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
15186 break;
15187 case OPC_PRECEU_PH_QBRA:
15188 check_dsp(ctx);
15189 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
15190 break;
15192 break;
15193 case OPC_ADDU_QB_DSP:
15194 switch (op2) {
15195 case OPC_ADDQ_PH:
15196 check_dsp(ctx);
15197 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15198 break;
15199 case OPC_ADDQ_S_PH:
15200 check_dsp(ctx);
15201 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15202 break;
15203 case OPC_ADDQ_S_W:
15204 check_dsp(ctx);
15205 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15206 break;
15207 case OPC_ADDU_QB:
15208 check_dsp(ctx);
15209 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15210 break;
15211 case OPC_ADDU_S_QB:
15212 check_dsp(ctx);
15213 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15214 break;
15215 case OPC_ADDU_PH:
15216 check_dspr2(ctx);
15217 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15218 break;
15219 case OPC_ADDU_S_PH:
15220 check_dspr2(ctx);
15221 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15222 break;
15223 case OPC_SUBQ_PH:
15224 check_dsp(ctx);
15225 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15226 break;
15227 case OPC_SUBQ_S_PH:
15228 check_dsp(ctx);
15229 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15230 break;
15231 case OPC_SUBQ_S_W:
15232 check_dsp(ctx);
15233 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15234 break;
15235 case OPC_SUBU_QB:
15236 check_dsp(ctx);
15237 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15238 break;
15239 case OPC_SUBU_S_QB:
15240 check_dsp(ctx);
15241 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15242 break;
15243 case OPC_SUBU_PH:
15244 check_dspr2(ctx);
15245 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15246 break;
15247 case OPC_SUBU_S_PH:
15248 check_dspr2(ctx);
15249 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15250 break;
15251 case OPC_ADDSC:
15252 check_dsp(ctx);
15253 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15254 break;
15255 case OPC_ADDWC:
15256 check_dsp(ctx);
15257 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15258 break;
15259 case OPC_MODSUB:
15260 check_dsp(ctx);
15261 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
15262 break;
15263 case OPC_RADDU_W_QB:
15264 check_dsp(ctx);
15265 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
15266 break;
15268 break;
15269 case OPC_CMPU_EQ_QB_DSP:
15270 switch (op2) {
15271 case OPC_PRECR_QB_PH:
15272 check_dspr2(ctx);
15273 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15274 break;
15275 case OPC_PRECRQ_QB_PH:
15276 check_dsp(ctx);
15277 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15278 break;
15279 case OPC_PRECR_SRA_PH_W:
15280 check_dspr2(ctx);
15282 TCGv_i32 sa_t = tcg_const_i32(v2);
15283 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
15284 cpu_gpr[ret]);
15285 tcg_temp_free_i32(sa_t);
15286 break;
15288 case OPC_PRECR_SRA_R_PH_W:
15289 check_dspr2(ctx);
15291 TCGv_i32 sa_t = tcg_const_i32(v2);
15292 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
15293 cpu_gpr[ret]);
15294 tcg_temp_free_i32(sa_t);
15295 break;
15297 case OPC_PRECRQ_PH_W:
15298 check_dsp(ctx);
15299 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
15300 break;
15301 case OPC_PRECRQ_RS_PH_W:
15302 check_dsp(ctx);
15303 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15304 break;
15305 case OPC_PRECRQU_S_QB_PH:
15306 check_dsp(ctx);
15307 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15308 break;
15310 break;
15311 #ifdef TARGET_MIPS64
15312 case OPC_ABSQ_S_QH_DSP:
15313 switch (op2) {
15314 case OPC_PRECEQ_L_PWL:
15315 check_dsp(ctx);
15316 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
15317 break;
15318 case OPC_PRECEQ_L_PWR:
15319 check_dsp(ctx);
15320 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
15321 break;
15322 case OPC_PRECEQ_PW_QHL:
15323 check_dsp(ctx);
15324 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
15325 break;
15326 case OPC_PRECEQ_PW_QHR:
15327 check_dsp(ctx);
15328 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
15329 break;
15330 case OPC_PRECEQ_PW_QHLA:
15331 check_dsp(ctx);
15332 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
15333 break;
15334 case OPC_PRECEQ_PW_QHRA:
15335 check_dsp(ctx);
15336 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
15337 break;
15338 case OPC_PRECEQU_QH_OBL:
15339 check_dsp(ctx);
15340 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
15341 break;
15342 case OPC_PRECEQU_QH_OBR:
15343 check_dsp(ctx);
15344 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
15345 break;
15346 case OPC_PRECEQU_QH_OBLA:
15347 check_dsp(ctx);
15348 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
15349 break;
15350 case OPC_PRECEQU_QH_OBRA:
15351 check_dsp(ctx);
15352 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
15353 break;
15354 case OPC_PRECEU_QH_OBL:
15355 check_dsp(ctx);
15356 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
15357 break;
15358 case OPC_PRECEU_QH_OBR:
15359 check_dsp(ctx);
15360 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
15361 break;
15362 case OPC_PRECEU_QH_OBLA:
15363 check_dsp(ctx);
15364 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
15365 break;
15366 case OPC_PRECEU_QH_OBRA:
15367 check_dsp(ctx);
15368 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
15369 break;
15370 case OPC_ABSQ_S_OB:
15371 check_dspr2(ctx);
15372 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
15373 break;
15374 case OPC_ABSQ_S_PW:
15375 check_dsp(ctx);
15376 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
15377 break;
15378 case OPC_ABSQ_S_QH:
15379 check_dsp(ctx);
15380 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
15381 break;
15383 break;
15384 case OPC_ADDU_OB_DSP:
15385 switch (op2) {
15386 case OPC_RADDU_L_OB:
15387 check_dsp(ctx);
15388 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
15389 break;
15390 case OPC_SUBQ_PW:
15391 check_dsp(ctx);
15392 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15393 break;
15394 case OPC_SUBQ_S_PW:
15395 check_dsp(ctx);
15396 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15397 break;
15398 case OPC_SUBQ_QH:
15399 check_dsp(ctx);
15400 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15401 break;
15402 case OPC_SUBQ_S_QH:
15403 check_dsp(ctx);
15404 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15405 break;
15406 case OPC_SUBU_OB:
15407 check_dsp(ctx);
15408 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15409 break;
15410 case OPC_SUBU_S_OB:
15411 check_dsp(ctx);
15412 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15413 break;
15414 case OPC_SUBU_QH:
15415 check_dspr2(ctx);
15416 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15417 break;
15418 case OPC_SUBU_S_QH:
15419 check_dspr2(ctx);
15420 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15421 break;
15422 case OPC_SUBUH_OB:
15423 check_dspr2(ctx);
15424 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
15425 break;
15426 case OPC_SUBUH_R_OB:
15427 check_dspr2(ctx);
15428 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15429 break;
15430 case OPC_ADDQ_PW:
15431 check_dsp(ctx);
15432 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15433 break;
15434 case OPC_ADDQ_S_PW:
15435 check_dsp(ctx);
15436 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15437 break;
15438 case OPC_ADDQ_QH:
15439 check_dsp(ctx);
15440 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15441 break;
15442 case OPC_ADDQ_S_QH:
15443 check_dsp(ctx);
15444 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15445 break;
15446 case OPC_ADDU_OB:
15447 check_dsp(ctx);
15448 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15449 break;
15450 case OPC_ADDU_S_OB:
15451 check_dsp(ctx);
15452 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15453 break;
15454 case OPC_ADDU_QH:
15455 check_dspr2(ctx);
15456 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15457 break;
15458 case OPC_ADDU_S_QH:
15459 check_dspr2(ctx);
15460 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15461 break;
15462 case OPC_ADDUH_OB:
15463 check_dspr2(ctx);
15464 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
15465 break;
15466 case OPC_ADDUH_R_OB:
15467 check_dspr2(ctx);
15468 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15469 break;
15471 break;
15472 case OPC_CMPU_EQ_OB_DSP:
15473 switch (op2) {
15474 case OPC_PRECR_OB_QH:
15475 check_dspr2(ctx);
15476 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15477 break;
15478 case OPC_PRECR_SRA_QH_PW:
15479 check_dspr2(ctx);
15481 TCGv_i32 ret_t = tcg_const_i32(ret);
15482 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
15483 tcg_temp_free_i32(ret_t);
15484 break;
15486 case OPC_PRECR_SRA_R_QH_PW:
15487 check_dspr2(ctx);
15489 TCGv_i32 sa_v = tcg_const_i32(ret);
15490 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
15491 tcg_temp_free_i32(sa_v);
15492 break;
15494 case OPC_PRECRQ_OB_QH:
15495 check_dsp(ctx);
15496 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15497 break;
15498 case OPC_PRECRQ_PW_L:
15499 check_dsp(ctx);
15500 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
15501 break;
15502 case OPC_PRECRQ_QH_PW:
15503 check_dsp(ctx);
15504 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
15505 break;
15506 case OPC_PRECRQ_RS_QH_PW:
15507 check_dsp(ctx);
15508 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15509 break;
15510 case OPC_PRECRQU_S_OB_QH:
15511 check_dsp(ctx);
15512 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15513 break;
15515 break;
15516 #endif
15519 tcg_temp_free(v1_t);
15520 tcg_temp_free(v2_t);
15523 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
15524 int ret, int v1, int v2)
15526 uint32_t op2;
15527 TCGv t0;
15528 TCGv v1_t;
15529 TCGv v2_t;
15531 if (ret == 0) {
15532 /* Treat as NOP. */
15533 return;
15536 t0 = tcg_temp_new();
15537 v1_t = tcg_temp_new();
15538 v2_t = tcg_temp_new();
15540 tcg_gen_movi_tl(t0, v1);
15541 gen_load_gpr(v1_t, v1);
15542 gen_load_gpr(v2_t, v2);
15544 switch (opc) {
15545 case OPC_SHLL_QB_DSP:
15547 op2 = MASK_SHLL_QB(ctx->opcode);
15548 switch (op2) {
15549 case OPC_SHLL_QB:
15550 check_dsp(ctx);
15551 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
15552 break;
15553 case OPC_SHLLV_QB:
15554 check_dsp(ctx);
15555 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15556 break;
15557 case OPC_SHLL_PH:
15558 check_dsp(ctx);
15559 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15560 break;
15561 case OPC_SHLLV_PH:
15562 check_dsp(ctx);
15563 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15564 break;
15565 case OPC_SHLL_S_PH:
15566 check_dsp(ctx);
15567 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15568 break;
15569 case OPC_SHLLV_S_PH:
15570 check_dsp(ctx);
15571 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15572 break;
15573 case OPC_SHLL_S_W:
15574 check_dsp(ctx);
15575 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
15576 break;
15577 case OPC_SHLLV_S_W:
15578 check_dsp(ctx);
15579 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15580 break;
15581 case OPC_SHRL_QB:
15582 check_dsp(ctx);
15583 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
15584 break;
15585 case OPC_SHRLV_QB:
15586 check_dsp(ctx);
15587 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
15588 break;
15589 case OPC_SHRL_PH:
15590 check_dspr2(ctx);
15591 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
15592 break;
15593 case OPC_SHRLV_PH:
15594 check_dspr2(ctx);
15595 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
15596 break;
15597 case OPC_SHRA_QB:
15598 check_dspr2(ctx);
15599 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
15600 break;
15601 case OPC_SHRA_R_QB:
15602 check_dspr2(ctx);
15603 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
15604 break;
15605 case OPC_SHRAV_QB:
15606 check_dspr2(ctx);
15607 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
15608 break;
15609 case OPC_SHRAV_R_QB:
15610 check_dspr2(ctx);
15611 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
15612 break;
15613 case OPC_SHRA_PH:
15614 check_dsp(ctx);
15615 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
15616 break;
15617 case OPC_SHRA_R_PH:
15618 check_dsp(ctx);
15619 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
15620 break;
15621 case OPC_SHRAV_PH:
15622 check_dsp(ctx);
15623 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
15624 break;
15625 case OPC_SHRAV_R_PH:
15626 check_dsp(ctx);
15627 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
15628 break;
15629 case OPC_SHRA_R_W:
15630 check_dsp(ctx);
15631 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
15632 break;
15633 case OPC_SHRAV_R_W:
15634 check_dsp(ctx);
15635 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
15636 break;
15637 default: /* Invalid */
15638 MIPS_INVAL("MASK SHLL.QB");
15639 generate_exception_end(ctx, EXCP_RI);
15640 break;
15642 break;
15644 #ifdef TARGET_MIPS64
15645 case OPC_SHLL_OB_DSP:
15646 op2 = MASK_SHLL_OB(ctx->opcode);
15647 switch (op2) {
15648 case OPC_SHLL_PW:
15649 check_dsp(ctx);
15650 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15651 break;
15652 case OPC_SHLLV_PW:
15653 check_dsp(ctx);
15654 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15655 break;
15656 case OPC_SHLL_S_PW:
15657 check_dsp(ctx);
15658 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15659 break;
15660 case OPC_SHLLV_S_PW:
15661 check_dsp(ctx);
15662 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15663 break;
15664 case OPC_SHLL_OB:
15665 check_dsp(ctx);
15666 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
15667 break;
15668 case OPC_SHLLV_OB:
15669 check_dsp(ctx);
15670 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15671 break;
15672 case OPC_SHLL_QH:
15673 check_dsp(ctx);
15674 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15675 break;
15676 case OPC_SHLLV_QH:
15677 check_dsp(ctx);
15678 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15679 break;
15680 case OPC_SHLL_S_QH:
15681 check_dsp(ctx);
15682 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15683 break;
15684 case OPC_SHLLV_S_QH:
15685 check_dsp(ctx);
15686 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15687 break;
15688 case OPC_SHRA_OB:
15689 check_dspr2(ctx);
15690 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
15691 break;
15692 case OPC_SHRAV_OB:
15693 check_dspr2(ctx);
15694 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
15695 break;
15696 case OPC_SHRA_R_OB:
15697 check_dspr2(ctx);
15698 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
15699 break;
15700 case OPC_SHRAV_R_OB:
15701 check_dspr2(ctx);
15702 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
15703 break;
15704 case OPC_SHRA_PW:
15705 check_dsp(ctx);
15706 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
15707 break;
15708 case OPC_SHRAV_PW:
15709 check_dsp(ctx);
15710 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
15711 break;
15712 case OPC_SHRA_R_PW:
15713 check_dsp(ctx);
15714 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
15715 break;
15716 case OPC_SHRAV_R_PW:
15717 check_dsp(ctx);
15718 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
15719 break;
15720 case OPC_SHRA_QH:
15721 check_dsp(ctx);
15722 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
15723 break;
15724 case OPC_SHRAV_QH:
15725 check_dsp(ctx);
15726 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
15727 break;
15728 case OPC_SHRA_R_QH:
15729 check_dsp(ctx);
15730 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
15731 break;
15732 case OPC_SHRAV_R_QH:
15733 check_dsp(ctx);
15734 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
15735 break;
15736 case OPC_SHRL_OB:
15737 check_dsp(ctx);
15738 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
15739 break;
15740 case OPC_SHRLV_OB:
15741 check_dsp(ctx);
15742 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
15743 break;
15744 case OPC_SHRL_QH:
15745 check_dspr2(ctx);
15746 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
15747 break;
15748 case OPC_SHRLV_QH:
15749 check_dspr2(ctx);
15750 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
15751 break;
15752 default: /* Invalid */
15753 MIPS_INVAL("MASK SHLL.OB");
15754 generate_exception_end(ctx, EXCP_RI);
15755 break;
15757 break;
15758 #endif
15761 tcg_temp_free(t0);
15762 tcg_temp_free(v1_t);
15763 tcg_temp_free(v2_t);
15766 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
15767 int ret, int v1, int v2, int check_ret)
15769 TCGv_i32 t0;
15770 TCGv v1_t;
15771 TCGv v2_t;
15773 if ((ret == 0) && (check_ret == 1)) {
15774 /* Treat as NOP. */
15775 return;
15778 t0 = tcg_temp_new_i32();
15779 v1_t = tcg_temp_new();
15780 v2_t = tcg_temp_new();
15782 tcg_gen_movi_i32(t0, ret);
15783 gen_load_gpr(v1_t, v1);
15784 gen_load_gpr(v2_t, v2);
15786 switch (op1) {
15787 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
15788 * the same mask and op1. */
15789 case OPC_MULT_G_2E:
15790 check_dspr2(ctx);
15791 switch (op2) {
15792 case OPC_MUL_PH:
15793 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15794 break;
15795 case OPC_MUL_S_PH:
15796 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15797 break;
15798 case OPC_MULQ_S_W:
15799 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15800 break;
15801 case OPC_MULQ_RS_W:
15802 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15803 break;
15805 break;
15806 case OPC_DPA_W_PH_DSP:
15807 switch (op2) {
15808 case OPC_DPAU_H_QBL:
15809 check_dsp(ctx);
15810 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
15811 break;
15812 case OPC_DPAU_H_QBR:
15813 check_dsp(ctx);
15814 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
15815 break;
15816 case OPC_DPSU_H_QBL:
15817 check_dsp(ctx);
15818 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
15819 break;
15820 case OPC_DPSU_H_QBR:
15821 check_dsp(ctx);
15822 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
15823 break;
15824 case OPC_DPA_W_PH:
15825 check_dspr2(ctx);
15826 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
15827 break;
15828 case OPC_DPAX_W_PH:
15829 check_dspr2(ctx);
15830 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
15831 break;
15832 case OPC_DPAQ_S_W_PH:
15833 check_dsp(ctx);
15834 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15835 break;
15836 case OPC_DPAQX_S_W_PH:
15837 check_dspr2(ctx);
15838 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
15839 break;
15840 case OPC_DPAQX_SA_W_PH:
15841 check_dspr2(ctx);
15842 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
15843 break;
15844 case OPC_DPS_W_PH:
15845 check_dspr2(ctx);
15846 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
15847 break;
15848 case OPC_DPSX_W_PH:
15849 check_dspr2(ctx);
15850 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
15851 break;
15852 case OPC_DPSQ_S_W_PH:
15853 check_dsp(ctx);
15854 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15855 break;
15856 case OPC_DPSQX_S_W_PH:
15857 check_dspr2(ctx);
15858 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
15859 break;
15860 case OPC_DPSQX_SA_W_PH:
15861 check_dspr2(ctx);
15862 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
15863 break;
15864 case OPC_MULSAQ_S_W_PH:
15865 check_dsp(ctx);
15866 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15867 break;
15868 case OPC_DPAQ_SA_L_W:
15869 check_dsp(ctx);
15870 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
15871 break;
15872 case OPC_DPSQ_SA_L_W:
15873 check_dsp(ctx);
15874 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
15875 break;
15876 case OPC_MAQ_S_W_PHL:
15877 check_dsp(ctx);
15878 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
15879 break;
15880 case OPC_MAQ_S_W_PHR:
15881 check_dsp(ctx);
15882 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
15883 break;
15884 case OPC_MAQ_SA_W_PHL:
15885 check_dsp(ctx);
15886 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
15887 break;
15888 case OPC_MAQ_SA_W_PHR:
15889 check_dsp(ctx);
15890 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
15891 break;
15892 case OPC_MULSA_W_PH:
15893 check_dspr2(ctx);
15894 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
15895 break;
15897 break;
15898 #ifdef TARGET_MIPS64
15899 case OPC_DPAQ_W_QH_DSP:
15901 int ac = ret & 0x03;
15902 tcg_gen_movi_i32(t0, ac);
15904 switch (op2) {
15905 case OPC_DMADD:
15906 check_dsp(ctx);
15907 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
15908 break;
15909 case OPC_DMADDU:
15910 check_dsp(ctx);
15911 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
15912 break;
15913 case OPC_DMSUB:
15914 check_dsp(ctx);
15915 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
15916 break;
15917 case OPC_DMSUBU:
15918 check_dsp(ctx);
15919 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
15920 break;
15921 case OPC_DPA_W_QH:
15922 check_dspr2(ctx);
15923 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
15924 break;
15925 case OPC_DPAQ_S_W_QH:
15926 check_dsp(ctx);
15927 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15928 break;
15929 case OPC_DPAQ_SA_L_PW:
15930 check_dsp(ctx);
15931 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
15932 break;
15933 case OPC_DPAU_H_OBL:
15934 check_dsp(ctx);
15935 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
15936 break;
15937 case OPC_DPAU_H_OBR:
15938 check_dsp(ctx);
15939 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
15940 break;
15941 case OPC_DPS_W_QH:
15942 check_dspr2(ctx);
15943 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
15944 break;
15945 case OPC_DPSQ_S_W_QH:
15946 check_dsp(ctx);
15947 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15948 break;
15949 case OPC_DPSQ_SA_L_PW:
15950 check_dsp(ctx);
15951 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
15952 break;
15953 case OPC_DPSU_H_OBL:
15954 check_dsp(ctx);
15955 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
15956 break;
15957 case OPC_DPSU_H_OBR:
15958 check_dsp(ctx);
15959 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
15960 break;
15961 case OPC_MAQ_S_L_PWL:
15962 check_dsp(ctx);
15963 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
15964 break;
15965 case OPC_MAQ_S_L_PWR:
15966 check_dsp(ctx);
15967 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
15968 break;
15969 case OPC_MAQ_S_W_QHLL:
15970 check_dsp(ctx);
15971 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
15972 break;
15973 case OPC_MAQ_SA_W_QHLL:
15974 check_dsp(ctx);
15975 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
15976 break;
15977 case OPC_MAQ_S_W_QHLR:
15978 check_dsp(ctx);
15979 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
15980 break;
15981 case OPC_MAQ_SA_W_QHLR:
15982 check_dsp(ctx);
15983 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
15984 break;
15985 case OPC_MAQ_S_W_QHRL:
15986 check_dsp(ctx);
15987 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
15988 break;
15989 case OPC_MAQ_SA_W_QHRL:
15990 check_dsp(ctx);
15991 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
15992 break;
15993 case OPC_MAQ_S_W_QHRR:
15994 check_dsp(ctx);
15995 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
15996 break;
15997 case OPC_MAQ_SA_W_QHRR:
15998 check_dsp(ctx);
15999 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
16000 break;
16001 case OPC_MULSAQ_S_L_PW:
16002 check_dsp(ctx);
16003 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
16004 break;
16005 case OPC_MULSAQ_S_W_QH:
16006 check_dsp(ctx);
16007 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16008 break;
16011 break;
16012 #endif
16013 case OPC_ADDU_QB_DSP:
16014 switch (op2) {
16015 case OPC_MULEU_S_PH_QBL:
16016 check_dsp(ctx);
16017 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16018 break;
16019 case OPC_MULEU_S_PH_QBR:
16020 check_dsp(ctx);
16021 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16022 break;
16023 case OPC_MULQ_RS_PH:
16024 check_dsp(ctx);
16025 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16026 break;
16027 case OPC_MULEQ_S_W_PHL:
16028 check_dsp(ctx);
16029 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16030 break;
16031 case OPC_MULEQ_S_W_PHR:
16032 check_dsp(ctx);
16033 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16034 break;
16035 case OPC_MULQ_S_PH:
16036 check_dspr2(ctx);
16037 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16038 break;
16040 break;
16041 #ifdef TARGET_MIPS64
16042 case OPC_ADDU_OB_DSP:
16043 switch (op2) {
16044 case OPC_MULEQ_S_PW_QHL:
16045 check_dsp(ctx);
16046 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16047 break;
16048 case OPC_MULEQ_S_PW_QHR:
16049 check_dsp(ctx);
16050 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16051 break;
16052 case OPC_MULEU_S_QH_OBL:
16053 check_dsp(ctx);
16054 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16055 break;
16056 case OPC_MULEU_S_QH_OBR:
16057 check_dsp(ctx);
16058 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16059 break;
16060 case OPC_MULQ_RS_QH:
16061 check_dsp(ctx);
16062 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16063 break;
16065 break;
16066 #endif
16069 tcg_temp_free_i32(t0);
16070 tcg_temp_free(v1_t);
16071 tcg_temp_free(v2_t);
16074 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16075 int ret, int val)
16077 int16_t imm;
16078 TCGv t0;
16079 TCGv val_t;
16081 if (ret == 0) {
16082 /* Treat as NOP. */
16083 return;
16086 t0 = tcg_temp_new();
16087 val_t = tcg_temp_new();
16088 gen_load_gpr(val_t, val);
16090 switch (op1) {
16091 case OPC_ABSQ_S_PH_DSP:
16092 switch (op2) {
16093 case OPC_BITREV:
16094 check_dsp(ctx);
16095 gen_helper_bitrev(cpu_gpr[ret], val_t);
16096 break;
16097 case OPC_REPL_QB:
16098 check_dsp(ctx);
16100 target_long result;
16101 imm = (ctx->opcode >> 16) & 0xFF;
16102 result = (uint32_t)imm << 24 |
16103 (uint32_t)imm << 16 |
16104 (uint32_t)imm << 8 |
16105 (uint32_t)imm;
16106 result = (int32_t)result;
16107 tcg_gen_movi_tl(cpu_gpr[ret], result);
16109 break;
16110 case OPC_REPLV_QB:
16111 check_dsp(ctx);
16112 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16113 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16114 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16115 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16116 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16117 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16118 break;
16119 case OPC_REPL_PH:
16120 check_dsp(ctx);
16122 imm = (ctx->opcode >> 16) & 0x03FF;
16123 imm = (int16_t)(imm << 6) >> 6;
16124 tcg_gen_movi_tl(cpu_gpr[ret], \
16125 (target_long)((int32_t)imm << 16 | \
16126 (uint16_t)imm));
16128 break;
16129 case OPC_REPLV_PH:
16130 check_dsp(ctx);
16131 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16132 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16133 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16134 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16135 break;
16137 break;
16138 #ifdef TARGET_MIPS64
16139 case OPC_ABSQ_S_QH_DSP:
16140 switch (op2) {
16141 case OPC_REPL_OB:
16142 check_dsp(ctx);
16144 target_long temp;
16146 imm = (ctx->opcode >> 16) & 0xFF;
16147 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
16148 temp = (temp << 16) | temp;
16149 temp = (temp << 32) | temp;
16150 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16151 break;
16153 case OPC_REPL_PW:
16154 check_dsp(ctx);
16156 target_long temp;
16158 imm = (ctx->opcode >> 16) & 0x03FF;
16159 imm = (int16_t)(imm << 6) >> 6;
16160 temp = ((target_long)imm << 32) \
16161 | ((target_long)imm & 0xFFFFFFFF);
16162 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16163 break;
16165 case OPC_REPL_QH:
16166 check_dsp(ctx);
16168 target_long temp;
16170 imm = (ctx->opcode >> 16) & 0x03FF;
16171 imm = (int16_t)(imm << 6) >> 6;
16173 temp = ((uint64_t)(uint16_t)imm << 48) |
16174 ((uint64_t)(uint16_t)imm << 32) |
16175 ((uint64_t)(uint16_t)imm << 16) |
16176 (uint64_t)(uint16_t)imm;
16177 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16178 break;
16180 case OPC_REPLV_OB:
16181 check_dsp(ctx);
16182 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16183 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16184 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16185 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16186 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16187 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16188 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16189 break;
16190 case OPC_REPLV_PW:
16191 check_dsp(ctx);
16192 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
16193 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16194 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16195 break;
16196 case OPC_REPLV_QH:
16197 check_dsp(ctx);
16198 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16199 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16200 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16201 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16202 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16203 break;
16205 break;
16206 #endif
16208 tcg_temp_free(t0);
16209 tcg_temp_free(val_t);
16212 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
16213 uint32_t op1, uint32_t op2,
16214 int ret, int v1, int v2, int check_ret)
16216 TCGv t1;
16217 TCGv v1_t;
16218 TCGv v2_t;
16220 if ((ret == 0) && (check_ret == 1)) {
16221 /* Treat as NOP. */
16222 return;
16225 t1 = tcg_temp_new();
16226 v1_t = tcg_temp_new();
16227 v2_t = tcg_temp_new();
16229 gen_load_gpr(v1_t, v1);
16230 gen_load_gpr(v2_t, v2);
16232 switch (op1) {
16233 case OPC_CMPU_EQ_QB_DSP:
16234 switch (op2) {
16235 case OPC_CMPU_EQ_QB:
16236 check_dsp(ctx);
16237 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
16238 break;
16239 case OPC_CMPU_LT_QB:
16240 check_dsp(ctx);
16241 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
16242 break;
16243 case OPC_CMPU_LE_QB:
16244 check_dsp(ctx);
16245 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
16246 break;
16247 case OPC_CMPGU_EQ_QB:
16248 check_dsp(ctx);
16249 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
16250 break;
16251 case OPC_CMPGU_LT_QB:
16252 check_dsp(ctx);
16253 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
16254 break;
16255 case OPC_CMPGU_LE_QB:
16256 check_dsp(ctx);
16257 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
16258 break;
16259 case OPC_CMPGDU_EQ_QB:
16260 check_dspr2(ctx);
16261 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
16262 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16263 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16264 tcg_gen_shli_tl(t1, t1, 24);
16265 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16266 break;
16267 case OPC_CMPGDU_LT_QB:
16268 check_dspr2(ctx);
16269 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
16270 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16271 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16272 tcg_gen_shli_tl(t1, t1, 24);
16273 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16274 break;
16275 case OPC_CMPGDU_LE_QB:
16276 check_dspr2(ctx);
16277 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
16278 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16279 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16280 tcg_gen_shli_tl(t1, t1, 24);
16281 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16282 break;
16283 case OPC_CMP_EQ_PH:
16284 check_dsp(ctx);
16285 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
16286 break;
16287 case OPC_CMP_LT_PH:
16288 check_dsp(ctx);
16289 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
16290 break;
16291 case OPC_CMP_LE_PH:
16292 check_dsp(ctx);
16293 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
16294 break;
16295 case OPC_PICK_QB:
16296 check_dsp(ctx);
16297 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16298 break;
16299 case OPC_PICK_PH:
16300 check_dsp(ctx);
16301 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16302 break;
16303 case OPC_PACKRL_PH:
16304 check_dsp(ctx);
16305 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
16306 break;
16308 break;
16309 #ifdef TARGET_MIPS64
16310 case OPC_CMPU_EQ_OB_DSP:
16311 switch (op2) {
16312 case OPC_CMP_EQ_PW:
16313 check_dsp(ctx);
16314 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
16315 break;
16316 case OPC_CMP_LT_PW:
16317 check_dsp(ctx);
16318 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
16319 break;
16320 case OPC_CMP_LE_PW:
16321 check_dsp(ctx);
16322 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
16323 break;
16324 case OPC_CMP_EQ_QH:
16325 check_dsp(ctx);
16326 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
16327 break;
16328 case OPC_CMP_LT_QH:
16329 check_dsp(ctx);
16330 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
16331 break;
16332 case OPC_CMP_LE_QH:
16333 check_dsp(ctx);
16334 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
16335 break;
16336 case OPC_CMPGDU_EQ_OB:
16337 check_dspr2(ctx);
16338 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16339 break;
16340 case OPC_CMPGDU_LT_OB:
16341 check_dspr2(ctx);
16342 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16343 break;
16344 case OPC_CMPGDU_LE_OB:
16345 check_dspr2(ctx);
16346 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16347 break;
16348 case OPC_CMPGU_EQ_OB:
16349 check_dsp(ctx);
16350 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
16351 break;
16352 case OPC_CMPGU_LT_OB:
16353 check_dsp(ctx);
16354 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
16355 break;
16356 case OPC_CMPGU_LE_OB:
16357 check_dsp(ctx);
16358 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
16359 break;
16360 case OPC_CMPU_EQ_OB:
16361 check_dsp(ctx);
16362 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
16363 break;
16364 case OPC_CMPU_LT_OB:
16365 check_dsp(ctx);
16366 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
16367 break;
16368 case OPC_CMPU_LE_OB:
16369 check_dsp(ctx);
16370 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
16371 break;
16372 case OPC_PACKRL_PW:
16373 check_dsp(ctx);
16374 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
16375 break;
16376 case OPC_PICK_OB:
16377 check_dsp(ctx);
16378 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16379 break;
16380 case OPC_PICK_PW:
16381 check_dsp(ctx);
16382 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16383 break;
16384 case OPC_PICK_QH:
16385 check_dsp(ctx);
16386 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16387 break;
16389 break;
16390 #endif
16393 tcg_temp_free(t1);
16394 tcg_temp_free(v1_t);
16395 tcg_temp_free(v2_t);
16398 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
16399 uint32_t op1, int rt, int rs, int sa)
16401 TCGv t0;
16403 check_dspr2(ctx);
16405 if (rt == 0) {
16406 /* Treat as NOP. */
16407 return;
16410 t0 = tcg_temp_new();
16411 gen_load_gpr(t0, rs);
16413 switch (op1) {
16414 case OPC_APPEND_DSP:
16415 switch (MASK_APPEND(ctx->opcode)) {
16416 case OPC_APPEND:
16417 if (sa != 0) {
16418 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
16420 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16421 break;
16422 case OPC_PREPEND:
16423 if (sa != 0) {
16424 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
16425 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16426 tcg_gen_shli_tl(t0, t0, 32 - sa);
16427 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16429 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16430 break;
16431 case OPC_BALIGN:
16432 sa &= 3;
16433 if (sa != 0 && sa != 2) {
16434 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16435 tcg_gen_ext32u_tl(t0, t0);
16436 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
16437 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16439 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16440 break;
16441 default: /* Invalid */
16442 MIPS_INVAL("MASK APPEND");
16443 generate_exception_end(ctx, EXCP_RI);
16444 break;
16446 break;
16447 #ifdef TARGET_MIPS64
16448 case OPC_DAPPEND_DSP:
16449 switch (MASK_DAPPEND(ctx->opcode)) {
16450 case OPC_DAPPEND:
16451 if (sa != 0) {
16452 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
16454 break;
16455 case OPC_PREPENDD:
16456 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
16457 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
16458 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
16459 break;
16460 case OPC_PREPENDW:
16461 if (sa != 0) {
16462 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16463 tcg_gen_shli_tl(t0, t0, 64 - sa);
16464 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16466 break;
16467 case OPC_DBALIGN:
16468 sa &= 7;
16469 if (sa != 0 && sa != 2 && sa != 4) {
16470 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16471 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
16472 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16474 break;
16475 default: /* Invalid */
16476 MIPS_INVAL("MASK DAPPEND");
16477 generate_exception_end(ctx, EXCP_RI);
16478 break;
16480 break;
16481 #endif
16483 tcg_temp_free(t0);
16486 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16487 int ret, int v1, int v2, int check_ret)
16490 TCGv t0;
16491 TCGv t1;
16492 TCGv v1_t;
16493 TCGv v2_t;
16494 int16_t imm;
16496 if ((ret == 0) && (check_ret == 1)) {
16497 /* Treat as NOP. */
16498 return;
16501 t0 = tcg_temp_new();
16502 t1 = tcg_temp_new();
16503 v1_t = tcg_temp_new();
16504 v2_t = tcg_temp_new();
16506 gen_load_gpr(v1_t, v1);
16507 gen_load_gpr(v2_t, v2);
16509 switch (op1) {
16510 case OPC_EXTR_W_DSP:
16511 check_dsp(ctx);
16512 switch (op2) {
16513 case OPC_EXTR_W:
16514 tcg_gen_movi_tl(t0, v2);
16515 tcg_gen_movi_tl(t1, v1);
16516 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
16517 break;
16518 case OPC_EXTR_R_W:
16519 tcg_gen_movi_tl(t0, v2);
16520 tcg_gen_movi_tl(t1, v1);
16521 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16522 break;
16523 case OPC_EXTR_RS_W:
16524 tcg_gen_movi_tl(t0, v2);
16525 tcg_gen_movi_tl(t1, v1);
16526 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16527 break;
16528 case OPC_EXTR_S_H:
16529 tcg_gen_movi_tl(t0, v2);
16530 tcg_gen_movi_tl(t1, v1);
16531 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16532 break;
16533 case OPC_EXTRV_S_H:
16534 tcg_gen_movi_tl(t0, v2);
16535 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
16536 break;
16537 case OPC_EXTRV_W:
16538 tcg_gen_movi_tl(t0, v2);
16539 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16540 break;
16541 case OPC_EXTRV_R_W:
16542 tcg_gen_movi_tl(t0, v2);
16543 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16544 break;
16545 case OPC_EXTRV_RS_W:
16546 tcg_gen_movi_tl(t0, v2);
16547 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16548 break;
16549 case OPC_EXTP:
16550 tcg_gen_movi_tl(t0, v2);
16551 tcg_gen_movi_tl(t1, v1);
16552 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
16553 break;
16554 case OPC_EXTPV:
16555 tcg_gen_movi_tl(t0, v2);
16556 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
16557 break;
16558 case OPC_EXTPDP:
16559 tcg_gen_movi_tl(t0, v2);
16560 tcg_gen_movi_tl(t1, v1);
16561 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
16562 break;
16563 case OPC_EXTPDPV:
16564 tcg_gen_movi_tl(t0, v2);
16565 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16566 break;
16567 case OPC_SHILO:
16568 imm = (ctx->opcode >> 20) & 0x3F;
16569 tcg_gen_movi_tl(t0, ret);
16570 tcg_gen_movi_tl(t1, imm);
16571 gen_helper_shilo(t0, t1, cpu_env);
16572 break;
16573 case OPC_SHILOV:
16574 tcg_gen_movi_tl(t0, ret);
16575 gen_helper_shilo(t0, v1_t, cpu_env);
16576 break;
16577 case OPC_MTHLIP:
16578 tcg_gen_movi_tl(t0, ret);
16579 gen_helper_mthlip(t0, v1_t, cpu_env);
16580 break;
16581 case OPC_WRDSP:
16582 imm = (ctx->opcode >> 11) & 0x3FF;
16583 tcg_gen_movi_tl(t0, imm);
16584 gen_helper_wrdsp(v1_t, t0, cpu_env);
16585 break;
16586 case OPC_RDDSP:
16587 imm = (ctx->opcode >> 16) & 0x03FF;
16588 tcg_gen_movi_tl(t0, imm);
16589 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
16590 break;
16592 break;
16593 #ifdef TARGET_MIPS64
16594 case OPC_DEXTR_W_DSP:
16595 check_dsp(ctx);
16596 switch (op2) {
16597 case OPC_DMTHLIP:
16598 tcg_gen_movi_tl(t0, ret);
16599 gen_helper_dmthlip(v1_t, t0, cpu_env);
16600 break;
16601 case OPC_DSHILO:
16603 int shift = (ctx->opcode >> 19) & 0x7F;
16604 int ac = (ctx->opcode >> 11) & 0x03;
16605 tcg_gen_movi_tl(t0, shift);
16606 tcg_gen_movi_tl(t1, ac);
16607 gen_helper_dshilo(t0, t1, cpu_env);
16608 break;
16610 case OPC_DSHILOV:
16612 int ac = (ctx->opcode >> 11) & 0x03;
16613 tcg_gen_movi_tl(t0, ac);
16614 gen_helper_dshilo(v1_t, t0, cpu_env);
16615 break;
16617 case OPC_DEXTP:
16618 tcg_gen_movi_tl(t0, v2);
16619 tcg_gen_movi_tl(t1, v1);
16621 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
16622 break;
16623 case OPC_DEXTPV:
16624 tcg_gen_movi_tl(t0, v2);
16625 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
16626 break;
16627 case OPC_DEXTPDP:
16628 tcg_gen_movi_tl(t0, v2);
16629 tcg_gen_movi_tl(t1, v1);
16630 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
16631 break;
16632 case OPC_DEXTPDPV:
16633 tcg_gen_movi_tl(t0, v2);
16634 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16635 break;
16636 case OPC_DEXTR_L:
16637 tcg_gen_movi_tl(t0, v2);
16638 tcg_gen_movi_tl(t1, v1);
16639 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
16640 break;
16641 case OPC_DEXTR_R_L:
16642 tcg_gen_movi_tl(t0, v2);
16643 tcg_gen_movi_tl(t1, v1);
16644 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
16645 break;
16646 case OPC_DEXTR_RS_L:
16647 tcg_gen_movi_tl(t0, v2);
16648 tcg_gen_movi_tl(t1, v1);
16649 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
16650 break;
16651 case OPC_DEXTR_W:
16652 tcg_gen_movi_tl(t0, v2);
16653 tcg_gen_movi_tl(t1, v1);
16654 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
16655 break;
16656 case OPC_DEXTR_R_W:
16657 tcg_gen_movi_tl(t0, v2);
16658 tcg_gen_movi_tl(t1, v1);
16659 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16660 break;
16661 case OPC_DEXTR_RS_W:
16662 tcg_gen_movi_tl(t0, v2);
16663 tcg_gen_movi_tl(t1, v1);
16664 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16665 break;
16666 case OPC_DEXTR_S_H:
16667 tcg_gen_movi_tl(t0, v2);
16668 tcg_gen_movi_tl(t1, v1);
16669 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16670 break;
16671 case OPC_DEXTRV_S_H:
16672 tcg_gen_movi_tl(t0, v2);
16673 tcg_gen_movi_tl(t1, v1);
16674 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16675 break;
16676 case OPC_DEXTRV_L:
16677 tcg_gen_movi_tl(t0, v2);
16678 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16679 break;
16680 case OPC_DEXTRV_R_L:
16681 tcg_gen_movi_tl(t0, v2);
16682 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16683 break;
16684 case OPC_DEXTRV_RS_L:
16685 tcg_gen_movi_tl(t0, v2);
16686 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16687 break;
16688 case OPC_DEXTRV_W:
16689 tcg_gen_movi_tl(t0, v2);
16690 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16691 break;
16692 case OPC_DEXTRV_R_W:
16693 tcg_gen_movi_tl(t0, v2);
16694 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16695 break;
16696 case OPC_DEXTRV_RS_W:
16697 tcg_gen_movi_tl(t0, v2);
16698 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16699 break;
16701 break;
16702 #endif
16705 tcg_temp_free(t0);
16706 tcg_temp_free(t1);
16707 tcg_temp_free(v1_t);
16708 tcg_temp_free(v2_t);
16711 /* End MIPSDSP functions. */
16713 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
16715 int rs, rt, rd, sa;
16716 uint32_t op1, op2;
16718 rs = (ctx->opcode >> 21) & 0x1f;
16719 rt = (ctx->opcode >> 16) & 0x1f;
16720 rd = (ctx->opcode >> 11) & 0x1f;
16721 sa = (ctx->opcode >> 6) & 0x1f;
16723 op1 = MASK_SPECIAL(ctx->opcode);
16724 switch (op1) {
16725 case OPC_LSA:
16726 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
16727 break;
16728 case OPC_MULT ... OPC_DIVU:
16729 op2 = MASK_R6_MULDIV(ctx->opcode);
16730 switch (op2) {
16731 case R6_OPC_MUL:
16732 case R6_OPC_MUH:
16733 case R6_OPC_MULU:
16734 case R6_OPC_MUHU:
16735 case R6_OPC_DIV:
16736 case R6_OPC_MOD:
16737 case R6_OPC_DIVU:
16738 case R6_OPC_MODU:
16739 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16740 break;
16741 default:
16742 MIPS_INVAL("special_r6 muldiv");
16743 generate_exception_end(ctx, EXCP_RI);
16744 break;
16746 break;
16747 case OPC_SELEQZ:
16748 case OPC_SELNEZ:
16749 gen_cond_move(ctx, op1, rd, rs, rt);
16750 break;
16751 case R6_OPC_CLO:
16752 case R6_OPC_CLZ:
16753 if (rt == 0 && sa == 1) {
16754 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16755 We need additionally to check other fields */
16756 gen_cl(ctx, op1, rd, rs);
16757 } else {
16758 generate_exception_end(ctx, EXCP_RI);
16760 break;
16761 case R6_OPC_SDBBP:
16762 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
16763 gen_helper_do_semihosting(cpu_env);
16764 } else {
16765 if (ctx->hflags & MIPS_HFLAG_SBRI) {
16766 generate_exception_end(ctx, EXCP_RI);
16767 } else {
16768 generate_exception_end(ctx, EXCP_DBp);
16771 break;
16772 #if defined(TARGET_MIPS64)
16773 case OPC_DLSA:
16774 check_mips_64(ctx);
16775 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
16776 break;
16777 case R6_OPC_DCLO:
16778 case R6_OPC_DCLZ:
16779 if (rt == 0 && sa == 1) {
16780 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16781 We need additionally to check other fields */
16782 check_mips_64(ctx);
16783 gen_cl(ctx, op1, rd, rs);
16784 } else {
16785 generate_exception_end(ctx, EXCP_RI);
16787 break;
16788 case OPC_DMULT ... OPC_DDIVU:
16789 op2 = MASK_R6_MULDIV(ctx->opcode);
16790 switch (op2) {
16791 case R6_OPC_DMUL:
16792 case R6_OPC_DMUH:
16793 case R6_OPC_DMULU:
16794 case R6_OPC_DMUHU:
16795 case R6_OPC_DDIV:
16796 case R6_OPC_DMOD:
16797 case R6_OPC_DDIVU:
16798 case R6_OPC_DMODU:
16799 check_mips_64(ctx);
16800 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16801 break;
16802 default:
16803 MIPS_INVAL("special_r6 muldiv");
16804 generate_exception_end(ctx, EXCP_RI);
16805 break;
16807 break;
16808 #endif
16809 default: /* Invalid */
16810 MIPS_INVAL("special_r6");
16811 generate_exception_end(ctx, EXCP_RI);
16812 break;
16816 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
16818 int rs, rt, rd, sa;
16819 uint32_t op1;
16821 rs = (ctx->opcode >> 21) & 0x1f;
16822 rt = (ctx->opcode >> 16) & 0x1f;
16823 rd = (ctx->opcode >> 11) & 0x1f;
16824 sa = (ctx->opcode >> 6) & 0x1f;
16826 op1 = MASK_SPECIAL(ctx->opcode);
16827 switch (op1) {
16828 case OPC_MOVN: /* Conditional move */
16829 case OPC_MOVZ:
16830 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
16831 INSN_LOONGSON2E | INSN_LOONGSON2F);
16832 gen_cond_move(ctx, op1, rd, rs, rt);
16833 break;
16834 case OPC_MFHI: /* Move from HI/LO */
16835 case OPC_MFLO:
16836 gen_HILO(ctx, op1, rs & 3, rd);
16837 break;
16838 case OPC_MTHI:
16839 case OPC_MTLO: /* Move to HI/LO */
16840 gen_HILO(ctx, op1, rd & 3, rs);
16841 break;
16842 case OPC_MOVCI:
16843 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
16844 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16845 check_cp1_enabled(ctx);
16846 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
16847 (ctx->opcode >> 16) & 1);
16848 } else {
16849 generate_exception_err(ctx, EXCP_CpU, 1);
16851 break;
16852 case OPC_MULT:
16853 case OPC_MULTU:
16854 if (sa) {
16855 check_insn(ctx, INSN_VR54XX);
16856 op1 = MASK_MUL_VR54XX(ctx->opcode);
16857 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
16858 } else {
16859 gen_muldiv(ctx, op1, rd & 3, rs, rt);
16861 break;
16862 case OPC_DIV:
16863 case OPC_DIVU:
16864 gen_muldiv(ctx, op1, 0, rs, rt);
16865 break;
16866 #if defined(TARGET_MIPS64)
16867 case OPC_DMULT ... OPC_DDIVU:
16868 check_insn(ctx, ISA_MIPS3);
16869 check_mips_64(ctx);
16870 gen_muldiv(ctx, op1, 0, rs, rt);
16871 break;
16872 #endif
16873 case OPC_JR:
16874 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
16875 break;
16876 case OPC_SPIM:
16877 #ifdef MIPS_STRICT_STANDARD
16878 MIPS_INVAL("SPIM");
16879 generate_exception_end(ctx, EXCP_RI);
16880 #else
16881 /* Implemented as RI exception for now. */
16882 MIPS_INVAL("spim (unofficial)");
16883 generate_exception_end(ctx, EXCP_RI);
16884 #endif
16885 break;
16886 default: /* Invalid */
16887 MIPS_INVAL("special_legacy");
16888 generate_exception_end(ctx, EXCP_RI);
16889 break;
16893 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
16895 int rs, rt, rd, sa;
16896 uint32_t op1;
16898 rs = (ctx->opcode >> 21) & 0x1f;
16899 rt = (ctx->opcode >> 16) & 0x1f;
16900 rd = (ctx->opcode >> 11) & 0x1f;
16901 sa = (ctx->opcode >> 6) & 0x1f;
16903 op1 = MASK_SPECIAL(ctx->opcode);
16904 switch (op1) {
16905 case OPC_SLL: /* Shift with immediate */
16906 if (sa == 5 && rd == 0 &&
16907 rs == 0 && rt == 0) { /* PAUSE */
16908 if ((ctx->insn_flags & ISA_MIPS32R6) &&
16909 (ctx->hflags & MIPS_HFLAG_BMASK)) {
16910 generate_exception_end(ctx, EXCP_RI);
16911 break;
16914 /* Fallthrough */
16915 case OPC_SRA:
16916 gen_shift_imm(ctx, op1, rd, rt, sa);
16917 break;
16918 case OPC_SRL:
16919 switch ((ctx->opcode >> 21) & 0x1f) {
16920 case 1:
16921 /* rotr is decoded as srl on non-R2 CPUs */
16922 if (ctx->insn_flags & ISA_MIPS32R2) {
16923 op1 = OPC_ROTR;
16925 /* Fallthrough */
16926 case 0:
16927 gen_shift_imm(ctx, op1, rd, rt, sa);
16928 break;
16929 default:
16930 generate_exception_end(ctx, EXCP_RI);
16931 break;
16933 break;
16934 case OPC_ADD ... OPC_SUBU:
16935 gen_arith(ctx, op1, rd, rs, rt);
16936 break;
16937 case OPC_SLLV: /* Shifts */
16938 case OPC_SRAV:
16939 gen_shift(ctx, op1, rd, rs, rt);
16940 break;
16941 case OPC_SRLV:
16942 switch ((ctx->opcode >> 6) & 0x1f) {
16943 case 1:
16944 /* rotrv is decoded as srlv on non-R2 CPUs */
16945 if (ctx->insn_flags & ISA_MIPS32R2) {
16946 op1 = OPC_ROTRV;
16948 /* Fallthrough */
16949 case 0:
16950 gen_shift(ctx, op1, rd, rs, rt);
16951 break;
16952 default:
16953 generate_exception_end(ctx, EXCP_RI);
16954 break;
16956 break;
16957 case OPC_SLT: /* Set on less than */
16958 case OPC_SLTU:
16959 gen_slt(ctx, op1, rd, rs, rt);
16960 break;
16961 case OPC_AND: /* Logic*/
16962 case OPC_OR:
16963 case OPC_NOR:
16964 case OPC_XOR:
16965 gen_logic(ctx, op1, rd, rs, rt);
16966 break;
16967 case OPC_JALR:
16968 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
16969 break;
16970 case OPC_TGE ... OPC_TEQ: /* Traps */
16971 case OPC_TNE:
16972 check_insn(ctx, ISA_MIPS2);
16973 gen_trap(ctx, op1, rs, rt, -1);
16974 break;
16975 case OPC_LSA: /* OPC_PMON */
16976 if ((ctx->insn_flags & ISA_MIPS32R6) ||
16977 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
16978 decode_opc_special_r6(env, ctx);
16979 } else {
16980 /* Pmon entry point, also R4010 selsl */
16981 #ifdef MIPS_STRICT_STANDARD
16982 MIPS_INVAL("PMON / selsl");
16983 generate_exception_end(ctx, EXCP_RI);
16984 #else
16985 gen_helper_0e0i(pmon, sa);
16986 #endif
16988 break;
16989 case OPC_SYSCALL:
16990 generate_exception_end(ctx, EXCP_SYSCALL);
16991 break;
16992 case OPC_BREAK:
16993 generate_exception_end(ctx, EXCP_BREAK);
16994 break;
16995 case OPC_SYNC:
16996 check_insn(ctx, ISA_MIPS2);
16997 /* Treat as NOP. */
16998 break;
17000 #if defined(TARGET_MIPS64)
17001 /* MIPS64 specific opcodes */
17002 case OPC_DSLL:
17003 case OPC_DSRA:
17004 case OPC_DSLL32:
17005 case OPC_DSRA32:
17006 check_insn(ctx, ISA_MIPS3);
17007 check_mips_64(ctx);
17008 gen_shift_imm(ctx, op1, rd, rt, sa);
17009 break;
17010 case OPC_DSRL:
17011 switch ((ctx->opcode >> 21) & 0x1f) {
17012 case 1:
17013 /* drotr is decoded as dsrl on non-R2 CPUs */
17014 if (ctx->insn_flags & ISA_MIPS32R2) {
17015 op1 = OPC_DROTR;
17017 /* Fallthrough */
17018 case 0:
17019 check_insn(ctx, ISA_MIPS3);
17020 check_mips_64(ctx);
17021 gen_shift_imm(ctx, op1, rd, rt, sa);
17022 break;
17023 default:
17024 generate_exception_end(ctx, EXCP_RI);
17025 break;
17027 break;
17028 case OPC_DSRL32:
17029 switch ((ctx->opcode >> 21) & 0x1f) {
17030 case 1:
17031 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
17032 if (ctx->insn_flags & ISA_MIPS32R2) {
17033 op1 = OPC_DROTR32;
17035 /* Fallthrough */
17036 case 0:
17037 check_insn(ctx, ISA_MIPS3);
17038 check_mips_64(ctx);
17039 gen_shift_imm(ctx, op1, rd, rt, sa);
17040 break;
17041 default:
17042 generate_exception_end(ctx, EXCP_RI);
17043 break;
17045 break;
17046 case OPC_DADD ... OPC_DSUBU:
17047 check_insn(ctx, ISA_MIPS3);
17048 check_mips_64(ctx);
17049 gen_arith(ctx, op1, rd, rs, rt);
17050 break;
17051 case OPC_DSLLV:
17052 case OPC_DSRAV:
17053 check_insn(ctx, ISA_MIPS3);
17054 check_mips_64(ctx);
17055 gen_shift(ctx, op1, rd, rs, rt);
17056 break;
17057 case OPC_DSRLV:
17058 switch ((ctx->opcode >> 6) & 0x1f) {
17059 case 1:
17060 /* drotrv is decoded as dsrlv on non-R2 CPUs */
17061 if (ctx->insn_flags & ISA_MIPS32R2) {
17062 op1 = OPC_DROTRV;
17064 /* Fallthrough */
17065 case 0:
17066 check_insn(ctx, ISA_MIPS3);
17067 check_mips_64(ctx);
17068 gen_shift(ctx, op1, rd, rs, rt);
17069 break;
17070 default:
17071 generate_exception_end(ctx, EXCP_RI);
17072 break;
17074 break;
17075 case OPC_DLSA:
17076 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17077 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17078 decode_opc_special_r6(env, ctx);
17080 break;
17081 #endif
17082 default:
17083 if (ctx->insn_flags & ISA_MIPS32R6) {
17084 decode_opc_special_r6(env, ctx);
17085 } else {
17086 decode_opc_special_legacy(env, ctx);
17091 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
17093 int rs, rt, rd;
17094 uint32_t op1;
17096 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17098 rs = (ctx->opcode >> 21) & 0x1f;
17099 rt = (ctx->opcode >> 16) & 0x1f;
17100 rd = (ctx->opcode >> 11) & 0x1f;
17102 op1 = MASK_SPECIAL2(ctx->opcode);
17103 switch (op1) {
17104 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
17105 case OPC_MSUB ... OPC_MSUBU:
17106 check_insn(ctx, ISA_MIPS32);
17107 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17108 break;
17109 case OPC_MUL:
17110 gen_arith(ctx, op1, rd, rs, rt);
17111 break;
17112 case OPC_DIV_G_2F:
17113 case OPC_DIVU_G_2F:
17114 case OPC_MULT_G_2F:
17115 case OPC_MULTU_G_2F:
17116 case OPC_MOD_G_2F:
17117 case OPC_MODU_G_2F:
17118 check_insn(ctx, INSN_LOONGSON2F);
17119 gen_loongson_integer(ctx, op1, rd, rs, rt);
17120 break;
17121 case OPC_CLO:
17122 case OPC_CLZ:
17123 check_insn(ctx, ISA_MIPS32);
17124 gen_cl(ctx, op1, rd, rs);
17125 break;
17126 case OPC_SDBBP:
17127 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17128 gen_helper_do_semihosting(cpu_env);
17129 } else {
17130 /* XXX: not clear which exception should be raised
17131 * when in debug mode...
17133 check_insn(ctx, ISA_MIPS32);
17134 generate_exception_end(ctx, EXCP_DBp);
17136 break;
17137 #if defined(TARGET_MIPS64)
17138 case OPC_DCLO:
17139 case OPC_DCLZ:
17140 check_insn(ctx, ISA_MIPS64);
17141 check_mips_64(ctx);
17142 gen_cl(ctx, op1, rd, rs);
17143 break;
17144 case OPC_DMULT_G_2F:
17145 case OPC_DMULTU_G_2F:
17146 case OPC_DDIV_G_2F:
17147 case OPC_DDIVU_G_2F:
17148 case OPC_DMOD_G_2F:
17149 case OPC_DMODU_G_2F:
17150 check_insn(ctx, INSN_LOONGSON2F);
17151 gen_loongson_integer(ctx, op1, rd, rs, rt);
17152 break;
17153 #endif
17154 default: /* Invalid */
17155 MIPS_INVAL("special2_legacy");
17156 generate_exception_end(ctx, EXCP_RI);
17157 break;
17161 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
17163 int rs, rt, rd, sa;
17164 uint32_t op1, op2;
17165 int16_t imm;
17167 rs = (ctx->opcode >> 21) & 0x1f;
17168 rt = (ctx->opcode >> 16) & 0x1f;
17169 rd = (ctx->opcode >> 11) & 0x1f;
17170 sa = (ctx->opcode >> 6) & 0x1f;
17171 imm = (int16_t)ctx->opcode >> 7;
17173 op1 = MASK_SPECIAL3(ctx->opcode);
17174 switch (op1) {
17175 case R6_OPC_PREF:
17176 if (rt >= 24) {
17177 /* hint codes 24-31 are reserved and signal RI */
17178 generate_exception_end(ctx, EXCP_RI);
17180 /* Treat as NOP. */
17181 break;
17182 case R6_OPC_CACHE:
17183 /* Treat as NOP. */
17184 break;
17185 case R6_OPC_SC:
17186 gen_st_cond(ctx, op1, rt, rs, imm);
17187 break;
17188 case R6_OPC_LL:
17189 gen_ld(ctx, op1, rt, rs, imm);
17190 break;
17191 case OPC_BSHFL:
17193 if (rd == 0) {
17194 /* Treat as NOP. */
17195 break;
17197 op2 = MASK_BSHFL(ctx->opcode);
17198 switch (op2) {
17199 case OPC_ALIGN ... OPC_ALIGN_END:
17200 gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3);
17201 break;
17202 case OPC_BITSWAP:
17203 gen_bitswap(ctx, op2, rd, rt);
17204 break;
17207 break;
17208 #if defined(TARGET_MIPS64)
17209 case R6_OPC_SCD:
17210 gen_st_cond(ctx, op1, rt, rs, imm);
17211 break;
17212 case R6_OPC_LLD:
17213 gen_ld(ctx, op1, rt, rs, imm);
17214 break;
17215 case OPC_DBSHFL:
17216 check_mips_64(ctx);
17218 if (rd == 0) {
17219 /* Treat as NOP. */
17220 break;
17222 op2 = MASK_DBSHFL(ctx->opcode);
17223 switch (op2) {
17224 case OPC_DALIGN ... OPC_DALIGN_END:
17225 gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7);
17226 break;
17227 case OPC_DBITSWAP:
17228 gen_bitswap(ctx, op2, rd, rt);
17229 break;
17233 break;
17234 #endif
17235 default: /* Invalid */
17236 MIPS_INVAL("special3_r6");
17237 generate_exception_end(ctx, EXCP_RI);
17238 break;
17242 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
17244 int rs, rt, rd;
17245 uint32_t op1, op2;
17247 rs = (ctx->opcode >> 21) & 0x1f;
17248 rt = (ctx->opcode >> 16) & 0x1f;
17249 rd = (ctx->opcode >> 11) & 0x1f;
17251 op1 = MASK_SPECIAL3(ctx->opcode);
17252 switch (op1) {
17253 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
17254 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
17255 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
17256 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
17257 * the same mask and op1. */
17258 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
17259 op2 = MASK_ADDUH_QB(ctx->opcode);
17260 switch (op2) {
17261 case OPC_ADDUH_QB:
17262 case OPC_ADDUH_R_QB:
17263 case OPC_ADDQH_PH:
17264 case OPC_ADDQH_R_PH:
17265 case OPC_ADDQH_W:
17266 case OPC_ADDQH_R_W:
17267 case OPC_SUBUH_QB:
17268 case OPC_SUBUH_R_QB:
17269 case OPC_SUBQH_PH:
17270 case OPC_SUBQH_R_PH:
17271 case OPC_SUBQH_W:
17272 case OPC_SUBQH_R_W:
17273 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17274 break;
17275 case OPC_MUL_PH:
17276 case OPC_MUL_S_PH:
17277 case OPC_MULQ_S_W:
17278 case OPC_MULQ_RS_W:
17279 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17280 break;
17281 default:
17282 MIPS_INVAL("MASK ADDUH.QB");
17283 generate_exception_end(ctx, EXCP_RI);
17284 break;
17286 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
17287 gen_loongson_integer(ctx, op1, rd, rs, rt);
17288 } else {
17289 generate_exception_end(ctx, EXCP_RI);
17291 break;
17292 case OPC_LX_DSP:
17293 op2 = MASK_LX(ctx->opcode);
17294 switch (op2) {
17295 #if defined(TARGET_MIPS64)
17296 case OPC_LDX:
17297 #endif
17298 case OPC_LBUX:
17299 case OPC_LHX:
17300 case OPC_LWX:
17301 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
17302 break;
17303 default: /* Invalid */
17304 MIPS_INVAL("MASK LX");
17305 generate_exception_end(ctx, EXCP_RI);
17306 break;
17308 break;
17309 case OPC_ABSQ_S_PH_DSP:
17310 op2 = MASK_ABSQ_S_PH(ctx->opcode);
17311 switch (op2) {
17312 case OPC_ABSQ_S_QB:
17313 case OPC_ABSQ_S_PH:
17314 case OPC_ABSQ_S_W:
17315 case OPC_PRECEQ_W_PHL:
17316 case OPC_PRECEQ_W_PHR:
17317 case OPC_PRECEQU_PH_QBL:
17318 case OPC_PRECEQU_PH_QBR:
17319 case OPC_PRECEQU_PH_QBLA:
17320 case OPC_PRECEQU_PH_QBRA:
17321 case OPC_PRECEU_PH_QBL:
17322 case OPC_PRECEU_PH_QBR:
17323 case OPC_PRECEU_PH_QBLA:
17324 case OPC_PRECEU_PH_QBRA:
17325 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17326 break;
17327 case OPC_BITREV:
17328 case OPC_REPL_QB:
17329 case OPC_REPLV_QB:
17330 case OPC_REPL_PH:
17331 case OPC_REPLV_PH:
17332 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17333 break;
17334 default:
17335 MIPS_INVAL("MASK ABSQ_S.PH");
17336 generate_exception_end(ctx, EXCP_RI);
17337 break;
17339 break;
17340 case OPC_ADDU_QB_DSP:
17341 op2 = MASK_ADDU_QB(ctx->opcode);
17342 switch (op2) {
17343 case OPC_ADDQ_PH:
17344 case OPC_ADDQ_S_PH:
17345 case OPC_ADDQ_S_W:
17346 case OPC_ADDU_QB:
17347 case OPC_ADDU_S_QB:
17348 case OPC_ADDU_PH:
17349 case OPC_ADDU_S_PH:
17350 case OPC_SUBQ_PH:
17351 case OPC_SUBQ_S_PH:
17352 case OPC_SUBQ_S_W:
17353 case OPC_SUBU_QB:
17354 case OPC_SUBU_S_QB:
17355 case OPC_SUBU_PH:
17356 case OPC_SUBU_S_PH:
17357 case OPC_ADDSC:
17358 case OPC_ADDWC:
17359 case OPC_MODSUB:
17360 case OPC_RADDU_W_QB:
17361 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17362 break;
17363 case OPC_MULEU_S_PH_QBL:
17364 case OPC_MULEU_S_PH_QBR:
17365 case OPC_MULQ_RS_PH:
17366 case OPC_MULEQ_S_W_PHL:
17367 case OPC_MULEQ_S_W_PHR:
17368 case OPC_MULQ_S_PH:
17369 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17370 break;
17371 default: /* Invalid */
17372 MIPS_INVAL("MASK ADDU.QB");
17373 generate_exception_end(ctx, EXCP_RI);
17374 break;
17377 break;
17378 case OPC_CMPU_EQ_QB_DSP:
17379 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
17380 switch (op2) {
17381 case OPC_PRECR_SRA_PH_W:
17382 case OPC_PRECR_SRA_R_PH_W:
17383 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17384 break;
17385 case OPC_PRECR_QB_PH:
17386 case OPC_PRECRQ_QB_PH:
17387 case OPC_PRECRQ_PH_W:
17388 case OPC_PRECRQ_RS_PH_W:
17389 case OPC_PRECRQU_S_QB_PH:
17390 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17391 break;
17392 case OPC_CMPU_EQ_QB:
17393 case OPC_CMPU_LT_QB:
17394 case OPC_CMPU_LE_QB:
17395 case OPC_CMP_EQ_PH:
17396 case OPC_CMP_LT_PH:
17397 case OPC_CMP_LE_PH:
17398 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17399 break;
17400 case OPC_CMPGU_EQ_QB:
17401 case OPC_CMPGU_LT_QB:
17402 case OPC_CMPGU_LE_QB:
17403 case OPC_CMPGDU_EQ_QB:
17404 case OPC_CMPGDU_LT_QB:
17405 case OPC_CMPGDU_LE_QB:
17406 case OPC_PICK_QB:
17407 case OPC_PICK_PH:
17408 case OPC_PACKRL_PH:
17409 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17410 break;
17411 default: /* Invalid */
17412 MIPS_INVAL("MASK CMPU.EQ.QB");
17413 generate_exception_end(ctx, EXCP_RI);
17414 break;
17416 break;
17417 case OPC_SHLL_QB_DSP:
17418 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17419 break;
17420 case OPC_DPA_W_PH_DSP:
17421 op2 = MASK_DPA_W_PH(ctx->opcode);
17422 switch (op2) {
17423 case OPC_DPAU_H_QBL:
17424 case OPC_DPAU_H_QBR:
17425 case OPC_DPSU_H_QBL:
17426 case OPC_DPSU_H_QBR:
17427 case OPC_DPA_W_PH:
17428 case OPC_DPAX_W_PH:
17429 case OPC_DPAQ_S_W_PH:
17430 case OPC_DPAQX_S_W_PH:
17431 case OPC_DPAQX_SA_W_PH:
17432 case OPC_DPS_W_PH:
17433 case OPC_DPSX_W_PH:
17434 case OPC_DPSQ_S_W_PH:
17435 case OPC_DPSQX_S_W_PH:
17436 case OPC_DPSQX_SA_W_PH:
17437 case OPC_MULSAQ_S_W_PH:
17438 case OPC_DPAQ_SA_L_W:
17439 case OPC_DPSQ_SA_L_W:
17440 case OPC_MAQ_S_W_PHL:
17441 case OPC_MAQ_S_W_PHR:
17442 case OPC_MAQ_SA_W_PHL:
17443 case OPC_MAQ_SA_W_PHR:
17444 case OPC_MULSA_W_PH:
17445 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17446 break;
17447 default: /* Invalid */
17448 MIPS_INVAL("MASK DPAW.PH");
17449 generate_exception_end(ctx, EXCP_RI);
17450 break;
17452 break;
17453 case OPC_INSV_DSP:
17454 op2 = MASK_INSV(ctx->opcode);
17455 switch (op2) {
17456 case OPC_INSV:
17457 check_dsp(ctx);
17459 TCGv t0, t1;
17461 if (rt == 0) {
17462 break;
17465 t0 = tcg_temp_new();
17466 t1 = tcg_temp_new();
17468 gen_load_gpr(t0, rt);
17469 gen_load_gpr(t1, rs);
17471 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
17473 tcg_temp_free(t0);
17474 tcg_temp_free(t1);
17475 break;
17477 default: /* Invalid */
17478 MIPS_INVAL("MASK INSV");
17479 generate_exception_end(ctx, EXCP_RI);
17480 break;
17482 break;
17483 case OPC_APPEND_DSP:
17484 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17485 break;
17486 case OPC_EXTR_W_DSP:
17487 op2 = MASK_EXTR_W(ctx->opcode);
17488 switch (op2) {
17489 case OPC_EXTR_W:
17490 case OPC_EXTR_R_W:
17491 case OPC_EXTR_RS_W:
17492 case OPC_EXTR_S_H:
17493 case OPC_EXTRV_S_H:
17494 case OPC_EXTRV_W:
17495 case OPC_EXTRV_R_W:
17496 case OPC_EXTRV_RS_W:
17497 case OPC_EXTP:
17498 case OPC_EXTPV:
17499 case OPC_EXTPDP:
17500 case OPC_EXTPDPV:
17501 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17502 break;
17503 case OPC_RDDSP:
17504 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
17505 break;
17506 case OPC_SHILO:
17507 case OPC_SHILOV:
17508 case OPC_MTHLIP:
17509 case OPC_WRDSP:
17510 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17511 break;
17512 default: /* Invalid */
17513 MIPS_INVAL("MASK EXTR.W");
17514 generate_exception_end(ctx, EXCP_RI);
17515 break;
17517 break;
17518 #if defined(TARGET_MIPS64)
17519 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
17520 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
17521 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
17522 check_insn(ctx, INSN_LOONGSON2E);
17523 gen_loongson_integer(ctx, op1, rd, rs, rt);
17524 break;
17525 case OPC_ABSQ_S_QH_DSP:
17526 op2 = MASK_ABSQ_S_QH(ctx->opcode);
17527 switch (op2) {
17528 case OPC_PRECEQ_L_PWL:
17529 case OPC_PRECEQ_L_PWR:
17530 case OPC_PRECEQ_PW_QHL:
17531 case OPC_PRECEQ_PW_QHR:
17532 case OPC_PRECEQ_PW_QHLA:
17533 case OPC_PRECEQ_PW_QHRA:
17534 case OPC_PRECEQU_QH_OBL:
17535 case OPC_PRECEQU_QH_OBR:
17536 case OPC_PRECEQU_QH_OBLA:
17537 case OPC_PRECEQU_QH_OBRA:
17538 case OPC_PRECEU_QH_OBL:
17539 case OPC_PRECEU_QH_OBR:
17540 case OPC_PRECEU_QH_OBLA:
17541 case OPC_PRECEU_QH_OBRA:
17542 case OPC_ABSQ_S_OB:
17543 case OPC_ABSQ_S_PW:
17544 case OPC_ABSQ_S_QH:
17545 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17546 break;
17547 case OPC_REPL_OB:
17548 case OPC_REPL_PW:
17549 case OPC_REPL_QH:
17550 case OPC_REPLV_OB:
17551 case OPC_REPLV_PW:
17552 case OPC_REPLV_QH:
17553 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17554 break;
17555 default: /* Invalid */
17556 MIPS_INVAL("MASK ABSQ_S.QH");
17557 generate_exception_end(ctx, EXCP_RI);
17558 break;
17560 break;
17561 case OPC_ADDU_OB_DSP:
17562 op2 = MASK_ADDU_OB(ctx->opcode);
17563 switch (op2) {
17564 case OPC_RADDU_L_OB:
17565 case OPC_SUBQ_PW:
17566 case OPC_SUBQ_S_PW:
17567 case OPC_SUBQ_QH:
17568 case OPC_SUBQ_S_QH:
17569 case OPC_SUBU_OB:
17570 case OPC_SUBU_S_OB:
17571 case OPC_SUBU_QH:
17572 case OPC_SUBU_S_QH:
17573 case OPC_SUBUH_OB:
17574 case OPC_SUBUH_R_OB:
17575 case OPC_ADDQ_PW:
17576 case OPC_ADDQ_S_PW:
17577 case OPC_ADDQ_QH:
17578 case OPC_ADDQ_S_QH:
17579 case OPC_ADDU_OB:
17580 case OPC_ADDU_S_OB:
17581 case OPC_ADDU_QH:
17582 case OPC_ADDU_S_QH:
17583 case OPC_ADDUH_OB:
17584 case OPC_ADDUH_R_OB:
17585 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17586 break;
17587 case OPC_MULEQ_S_PW_QHL:
17588 case OPC_MULEQ_S_PW_QHR:
17589 case OPC_MULEU_S_QH_OBL:
17590 case OPC_MULEU_S_QH_OBR:
17591 case OPC_MULQ_RS_QH:
17592 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17593 break;
17594 default: /* Invalid */
17595 MIPS_INVAL("MASK ADDU.OB");
17596 generate_exception_end(ctx, EXCP_RI);
17597 break;
17599 break;
17600 case OPC_CMPU_EQ_OB_DSP:
17601 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
17602 switch (op2) {
17603 case OPC_PRECR_SRA_QH_PW:
17604 case OPC_PRECR_SRA_R_QH_PW:
17605 /* Return value is rt. */
17606 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17607 break;
17608 case OPC_PRECR_OB_QH:
17609 case OPC_PRECRQ_OB_QH:
17610 case OPC_PRECRQ_PW_L:
17611 case OPC_PRECRQ_QH_PW:
17612 case OPC_PRECRQ_RS_QH_PW:
17613 case OPC_PRECRQU_S_OB_QH:
17614 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17615 break;
17616 case OPC_CMPU_EQ_OB:
17617 case OPC_CMPU_LT_OB:
17618 case OPC_CMPU_LE_OB:
17619 case OPC_CMP_EQ_QH:
17620 case OPC_CMP_LT_QH:
17621 case OPC_CMP_LE_QH:
17622 case OPC_CMP_EQ_PW:
17623 case OPC_CMP_LT_PW:
17624 case OPC_CMP_LE_PW:
17625 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17626 break;
17627 case OPC_CMPGDU_EQ_OB:
17628 case OPC_CMPGDU_LT_OB:
17629 case OPC_CMPGDU_LE_OB:
17630 case OPC_CMPGU_EQ_OB:
17631 case OPC_CMPGU_LT_OB:
17632 case OPC_CMPGU_LE_OB:
17633 case OPC_PACKRL_PW:
17634 case OPC_PICK_OB:
17635 case OPC_PICK_PW:
17636 case OPC_PICK_QH:
17637 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17638 break;
17639 default: /* Invalid */
17640 MIPS_INVAL("MASK CMPU_EQ.OB");
17641 generate_exception_end(ctx, EXCP_RI);
17642 break;
17644 break;
17645 case OPC_DAPPEND_DSP:
17646 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17647 break;
17648 case OPC_DEXTR_W_DSP:
17649 op2 = MASK_DEXTR_W(ctx->opcode);
17650 switch (op2) {
17651 case OPC_DEXTP:
17652 case OPC_DEXTPDP:
17653 case OPC_DEXTPDPV:
17654 case OPC_DEXTPV:
17655 case OPC_DEXTR_L:
17656 case OPC_DEXTR_R_L:
17657 case OPC_DEXTR_RS_L:
17658 case OPC_DEXTR_W:
17659 case OPC_DEXTR_R_W:
17660 case OPC_DEXTR_RS_W:
17661 case OPC_DEXTR_S_H:
17662 case OPC_DEXTRV_L:
17663 case OPC_DEXTRV_R_L:
17664 case OPC_DEXTRV_RS_L:
17665 case OPC_DEXTRV_S_H:
17666 case OPC_DEXTRV_W:
17667 case OPC_DEXTRV_R_W:
17668 case OPC_DEXTRV_RS_W:
17669 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17670 break;
17671 case OPC_DMTHLIP:
17672 case OPC_DSHILO:
17673 case OPC_DSHILOV:
17674 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17675 break;
17676 default: /* Invalid */
17677 MIPS_INVAL("MASK EXTR.W");
17678 generate_exception_end(ctx, EXCP_RI);
17679 break;
17681 break;
17682 case OPC_DPAQ_W_QH_DSP:
17683 op2 = MASK_DPAQ_W_QH(ctx->opcode);
17684 switch (op2) {
17685 case OPC_DPAU_H_OBL:
17686 case OPC_DPAU_H_OBR:
17687 case OPC_DPSU_H_OBL:
17688 case OPC_DPSU_H_OBR:
17689 case OPC_DPA_W_QH:
17690 case OPC_DPAQ_S_W_QH:
17691 case OPC_DPS_W_QH:
17692 case OPC_DPSQ_S_W_QH:
17693 case OPC_MULSAQ_S_W_QH:
17694 case OPC_DPAQ_SA_L_PW:
17695 case OPC_DPSQ_SA_L_PW:
17696 case OPC_MULSAQ_S_L_PW:
17697 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17698 break;
17699 case OPC_MAQ_S_W_QHLL:
17700 case OPC_MAQ_S_W_QHLR:
17701 case OPC_MAQ_S_W_QHRL:
17702 case OPC_MAQ_S_W_QHRR:
17703 case OPC_MAQ_SA_W_QHLL:
17704 case OPC_MAQ_SA_W_QHLR:
17705 case OPC_MAQ_SA_W_QHRL:
17706 case OPC_MAQ_SA_W_QHRR:
17707 case OPC_MAQ_S_L_PWL:
17708 case OPC_MAQ_S_L_PWR:
17709 case OPC_DMADD:
17710 case OPC_DMADDU:
17711 case OPC_DMSUB:
17712 case OPC_DMSUBU:
17713 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17714 break;
17715 default: /* Invalid */
17716 MIPS_INVAL("MASK DPAQ.W.QH");
17717 generate_exception_end(ctx, EXCP_RI);
17718 break;
17720 break;
17721 case OPC_DINSV_DSP:
17722 op2 = MASK_INSV(ctx->opcode);
17723 switch (op2) {
17724 case OPC_DINSV:
17726 TCGv t0, t1;
17728 if (rt == 0) {
17729 break;
17731 check_dsp(ctx);
17733 t0 = tcg_temp_new();
17734 t1 = tcg_temp_new();
17736 gen_load_gpr(t0, rt);
17737 gen_load_gpr(t1, rs);
17739 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
17741 tcg_temp_free(t0);
17742 tcg_temp_free(t1);
17743 break;
17745 default: /* Invalid */
17746 MIPS_INVAL("MASK DINSV");
17747 generate_exception_end(ctx, EXCP_RI);
17748 break;
17750 break;
17751 case OPC_SHLL_OB_DSP:
17752 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17753 break;
17754 #endif
17755 default: /* Invalid */
17756 MIPS_INVAL("special3_legacy");
17757 generate_exception_end(ctx, EXCP_RI);
17758 break;
17762 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
17764 int rs, rt, rd, sa;
17765 uint32_t op1, op2;
17767 rs = (ctx->opcode >> 21) & 0x1f;
17768 rt = (ctx->opcode >> 16) & 0x1f;
17769 rd = (ctx->opcode >> 11) & 0x1f;
17770 sa = (ctx->opcode >> 6) & 0x1f;
17772 op1 = MASK_SPECIAL3(ctx->opcode);
17773 switch (op1) {
17774 case OPC_EXT:
17775 case OPC_INS:
17776 check_insn(ctx, ISA_MIPS32R2);
17777 gen_bitops(ctx, op1, rt, rs, sa, rd);
17778 break;
17779 case OPC_BSHFL:
17780 op2 = MASK_BSHFL(ctx->opcode);
17781 switch (op2) {
17782 case OPC_ALIGN ... OPC_ALIGN_END:
17783 case OPC_BITSWAP:
17784 check_insn(ctx, ISA_MIPS32R6);
17785 decode_opc_special3_r6(env, ctx);
17786 break;
17787 default:
17788 check_insn(ctx, ISA_MIPS32R2);
17789 gen_bshfl(ctx, op2, rt, rd);
17790 break;
17792 break;
17793 #if defined(TARGET_MIPS64)
17794 case OPC_DEXTM ... OPC_DEXT:
17795 case OPC_DINSM ... OPC_DINS:
17796 check_insn(ctx, ISA_MIPS64R2);
17797 check_mips_64(ctx);
17798 gen_bitops(ctx, op1, rt, rs, sa, rd);
17799 break;
17800 case OPC_DBSHFL:
17801 op2 = MASK_DBSHFL(ctx->opcode);
17802 switch (op2) {
17803 case OPC_DALIGN ... OPC_DALIGN_END:
17804 case OPC_DBITSWAP:
17805 check_insn(ctx, ISA_MIPS32R6);
17806 decode_opc_special3_r6(env, ctx);
17807 break;
17808 default:
17809 check_insn(ctx, ISA_MIPS64R2);
17810 check_mips_64(ctx);
17811 op2 = MASK_DBSHFL(ctx->opcode);
17812 gen_bshfl(ctx, op2, rt, rd);
17813 break;
17815 break;
17816 #endif
17817 case OPC_RDHWR:
17818 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
17819 break;
17820 case OPC_FORK:
17821 check_insn(ctx, ASE_MT);
17823 TCGv t0 = tcg_temp_new();
17824 TCGv t1 = tcg_temp_new();
17826 gen_load_gpr(t0, rt);
17827 gen_load_gpr(t1, rs);
17828 gen_helper_fork(t0, t1);
17829 tcg_temp_free(t0);
17830 tcg_temp_free(t1);
17832 break;
17833 case OPC_YIELD:
17834 check_insn(ctx, ASE_MT);
17836 TCGv t0 = tcg_temp_new();
17838 gen_load_gpr(t0, rs);
17839 gen_helper_yield(t0, cpu_env, t0);
17840 gen_store_gpr(t0, rd);
17841 tcg_temp_free(t0);
17843 break;
17844 default:
17845 if (ctx->insn_flags & ISA_MIPS32R6) {
17846 decode_opc_special3_r6(env, ctx);
17847 } else {
17848 decode_opc_special3_legacy(env, ctx);
17853 /* MIPS SIMD Architecture (MSA) */
17854 static inline int check_msa_access(DisasContext *ctx)
17856 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
17857 !(ctx->hflags & MIPS_HFLAG_F64))) {
17858 generate_exception_end(ctx, EXCP_RI);
17859 return 0;
17862 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
17863 if (ctx->insn_flags & ASE_MSA) {
17864 generate_exception_end(ctx, EXCP_MSADIS);
17865 return 0;
17866 } else {
17867 generate_exception_end(ctx, EXCP_RI);
17868 return 0;
17871 return 1;
17874 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
17876 /* generates tcg ops to check if any element is 0 */
17877 /* Note this function only works with MSA_WRLEN = 128 */
17878 uint64_t eval_zero_or_big = 0;
17879 uint64_t eval_big = 0;
17880 TCGv_i64 t0 = tcg_temp_new_i64();
17881 TCGv_i64 t1 = tcg_temp_new_i64();
17882 switch (df) {
17883 case DF_BYTE:
17884 eval_zero_or_big = 0x0101010101010101ULL;
17885 eval_big = 0x8080808080808080ULL;
17886 break;
17887 case DF_HALF:
17888 eval_zero_or_big = 0x0001000100010001ULL;
17889 eval_big = 0x8000800080008000ULL;
17890 break;
17891 case DF_WORD:
17892 eval_zero_or_big = 0x0000000100000001ULL;
17893 eval_big = 0x8000000080000000ULL;
17894 break;
17895 case DF_DOUBLE:
17896 eval_zero_or_big = 0x0000000000000001ULL;
17897 eval_big = 0x8000000000000000ULL;
17898 break;
17900 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
17901 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
17902 tcg_gen_andi_i64(t0, t0, eval_big);
17903 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
17904 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
17905 tcg_gen_andi_i64(t1, t1, eval_big);
17906 tcg_gen_or_i64(t0, t0, t1);
17907 /* if all bits are zero then all elements are not zero */
17908 /* if some bit is non-zero then some element is zero */
17909 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
17910 tcg_gen_trunc_i64_tl(tresult, t0);
17911 tcg_temp_free_i64(t0);
17912 tcg_temp_free_i64(t1);
17915 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
17917 uint8_t df = (ctx->opcode >> 21) & 0x3;
17918 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
17919 int64_t s16 = (int16_t)ctx->opcode;
17921 check_msa_access(ctx);
17923 if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
17924 generate_exception_end(ctx, EXCP_RI);
17925 return;
17927 switch (op1) {
17928 case OPC_BZ_V:
17929 case OPC_BNZ_V:
17931 TCGv_i64 t0 = tcg_temp_new_i64();
17932 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
17933 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
17934 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
17935 tcg_gen_trunc_i64_tl(bcond, t0);
17936 tcg_temp_free_i64(t0);
17938 break;
17939 case OPC_BZ_B:
17940 case OPC_BZ_H:
17941 case OPC_BZ_W:
17942 case OPC_BZ_D:
17943 gen_check_zero_element(bcond, df, wt);
17944 break;
17945 case OPC_BNZ_B:
17946 case OPC_BNZ_H:
17947 case OPC_BNZ_W:
17948 case OPC_BNZ_D:
17949 gen_check_zero_element(bcond, df, wt);
17950 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
17951 break;
17954 ctx->btarget = ctx->pc + (s16 << 2) + 4;
17956 ctx->hflags |= MIPS_HFLAG_BC;
17957 ctx->hflags |= MIPS_HFLAG_BDS32;
17960 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
17962 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
17963 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
17964 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17965 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17967 TCGv_i32 twd = tcg_const_i32(wd);
17968 TCGv_i32 tws = tcg_const_i32(ws);
17969 TCGv_i32 ti8 = tcg_const_i32(i8);
17971 switch (MASK_MSA_I8(ctx->opcode)) {
17972 case OPC_ANDI_B:
17973 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
17974 break;
17975 case OPC_ORI_B:
17976 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
17977 break;
17978 case OPC_NORI_B:
17979 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
17980 break;
17981 case OPC_XORI_B:
17982 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
17983 break;
17984 case OPC_BMNZI_B:
17985 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
17986 break;
17987 case OPC_BMZI_B:
17988 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
17989 break;
17990 case OPC_BSELI_B:
17991 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
17992 break;
17993 case OPC_SHF_B:
17994 case OPC_SHF_H:
17995 case OPC_SHF_W:
17997 uint8_t df = (ctx->opcode >> 24) & 0x3;
17998 if (df == DF_DOUBLE) {
17999 generate_exception_end(ctx, EXCP_RI);
18000 } else {
18001 TCGv_i32 tdf = tcg_const_i32(df);
18002 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
18003 tcg_temp_free_i32(tdf);
18006 break;
18007 default:
18008 MIPS_INVAL("MSA instruction");
18009 generate_exception_end(ctx, EXCP_RI);
18010 break;
18013 tcg_temp_free_i32(twd);
18014 tcg_temp_free_i32(tws);
18015 tcg_temp_free_i32(ti8);
18018 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
18020 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18021 uint8_t df = (ctx->opcode >> 21) & 0x3;
18022 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
18023 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
18024 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18025 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18027 TCGv_i32 tdf = tcg_const_i32(df);
18028 TCGv_i32 twd = tcg_const_i32(wd);
18029 TCGv_i32 tws = tcg_const_i32(ws);
18030 TCGv_i32 timm = tcg_temp_new_i32();
18031 tcg_gen_movi_i32(timm, u5);
18033 switch (MASK_MSA_I5(ctx->opcode)) {
18034 case OPC_ADDVI_df:
18035 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
18036 break;
18037 case OPC_SUBVI_df:
18038 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
18039 break;
18040 case OPC_MAXI_S_df:
18041 tcg_gen_movi_i32(timm, s5);
18042 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
18043 break;
18044 case OPC_MAXI_U_df:
18045 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
18046 break;
18047 case OPC_MINI_S_df:
18048 tcg_gen_movi_i32(timm, s5);
18049 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
18050 break;
18051 case OPC_MINI_U_df:
18052 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
18053 break;
18054 case OPC_CEQI_df:
18055 tcg_gen_movi_i32(timm, s5);
18056 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
18057 break;
18058 case OPC_CLTI_S_df:
18059 tcg_gen_movi_i32(timm, s5);
18060 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
18061 break;
18062 case OPC_CLTI_U_df:
18063 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
18064 break;
18065 case OPC_CLEI_S_df:
18066 tcg_gen_movi_i32(timm, s5);
18067 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
18068 break;
18069 case OPC_CLEI_U_df:
18070 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
18071 break;
18072 case OPC_LDI_df:
18074 int32_t s10 = sextract32(ctx->opcode, 11, 10);
18075 tcg_gen_movi_i32(timm, s10);
18076 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
18078 break;
18079 default:
18080 MIPS_INVAL("MSA instruction");
18081 generate_exception_end(ctx, EXCP_RI);
18082 break;
18085 tcg_temp_free_i32(tdf);
18086 tcg_temp_free_i32(twd);
18087 tcg_temp_free_i32(tws);
18088 tcg_temp_free_i32(timm);
18091 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
18093 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18094 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
18095 uint32_t df = 0, m = 0;
18096 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18097 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18099 TCGv_i32 tdf;
18100 TCGv_i32 tm;
18101 TCGv_i32 twd;
18102 TCGv_i32 tws;
18104 if ((dfm & 0x40) == 0x00) {
18105 m = dfm & 0x3f;
18106 df = DF_DOUBLE;
18107 } else if ((dfm & 0x60) == 0x40) {
18108 m = dfm & 0x1f;
18109 df = DF_WORD;
18110 } else if ((dfm & 0x70) == 0x60) {
18111 m = dfm & 0x0f;
18112 df = DF_HALF;
18113 } else if ((dfm & 0x78) == 0x70) {
18114 m = dfm & 0x7;
18115 df = DF_BYTE;
18116 } else {
18117 generate_exception_end(ctx, EXCP_RI);
18118 return;
18121 tdf = tcg_const_i32(df);
18122 tm = tcg_const_i32(m);
18123 twd = tcg_const_i32(wd);
18124 tws = tcg_const_i32(ws);
18126 switch (MASK_MSA_BIT(ctx->opcode)) {
18127 case OPC_SLLI_df:
18128 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
18129 break;
18130 case OPC_SRAI_df:
18131 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
18132 break;
18133 case OPC_SRLI_df:
18134 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
18135 break;
18136 case OPC_BCLRI_df:
18137 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
18138 break;
18139 case OPC_BSETI_df:
18140 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
18141 break;
18142 case OPC_BNEGI_df:
18143 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
18144 break;
18145 case OPC_BINSLI_df:
18146 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
18147 break;
18148 case OPC_BINSRI_df:
18149 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
18150 break;
18151 case OPC_SAT_S_df:
18152 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
18153 break;
18154 case OPC_SAT_U_df:
18155 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
18156 break;
18157 case OPC_SRARI_df:
18158 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
18159 break;
18160 case OPC_SRLRI_df:
18161 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
18162 break;
18163 default:
18164 MIPS_INVAL("MSA instruction");
18165 generate_exception_end(ctx, EXCP_RI);
18166 break;
18169 tcg_temp_free_i32(tdf);
18170 tcg_temp_free_i32(tm);
18171 tcg_temp_free_i32(twd);
18172 tcg_temp_free_i32(tws);
18175 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
18177 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18178 uint8_t df = (ctx->opcode >> 21) & 0x3;
18179 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18180 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18181 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18183 TCGv_i32 tdf = tcg_const_i32(df);
18184 TCGv_i32 twd = tcg_const_i32(wd);
18185 TCGv_i32 tws = tcg_const_i32(ws);
18186 TCGv_i32 twt = tcg_const_i32(wt);
18188 switch (MASK_MSA_3R(ctx->opcode)) {
18189 case OPC_SLL_df:
18190 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
18191 break;
18192 case OPC_ADDV_df:
18193 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
18194 break;
18195 case OPC_CEQ_df:
18196 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
18197 break;
18198 case OPC_ADD_A_df:
18199 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
18200 break;
18201 case OPC_SUBS_S_df:
18202 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
18203 break;
18204 case OPC_MULV_df:
18205 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
18206 break;
18207 case OPC_SLD_df:
18208 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
18209 break;
18210 case OPC_VSHF_df:
18211 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
18212 break;
18213 case OPC_SRA_df:
18214 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
18215 break;
18216 case OPC_SUBV_df:
18217 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
18218 break;
18219 case OPC_ADDS_A_df:
18220 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
18221 break;
18222 case OPC_SUBS_U_df:
18223 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
18224 break;
18225 case OPC_MADDV_df:
18226 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
18227 break;
18228 case OPC_SPLAT_df:
18229 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
18230 break;
18231 case OPC_SRAR_df:
18232 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
18233 break;
18234 case OPC_SRL_df:
18235 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
18236 break;
18237 case OPC_MAX_S_df:
18238 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
18239 break;
18240 case OPC_CLT_S_df:
18241 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
18242 break;
18243 case OPC_ADDS_S_df:
18244 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
18245 break;
18246 case OPC_SUBSUS_U_df:
18247 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
18248 break;
18249 case OPC_MSUBV_df:
18250 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
18251 break;
18252 case OPC_PCKEV_df:
18253 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
18254 break;
18255 case OPC_SRLR_df:
18256 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
18257 break;
18258 case OPC_BCLR_df:
18259 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
18260 break;
18261 case OPC_MAX_U_df:
18262 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
18263 break;
18264 case OPC_CLT_U_df:
18265 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
18266 break;
18267 case OPC_ADDS_U_df:
18268 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
18269 break;
18270 case OPC_SUBSUU_S_df:
18271 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
18272 break;
18273 case OPC_PCKOD_df:
18274 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
18275 break;
18276 case OPC_BSET_df:
18277 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
18278 break;
18279 case OPC_MIN_S_df:
18280 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
18281 break;
18282 case OPC_CLE_S_df:
18283 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
18284 break;
18285 case OPC_AVE_S_df:
18286 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
18287 break;
18288 case OPC_ASUB_S_df:
18289 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
18290 break;
18291 case OPC_DIV_S_df:
18292 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
18293 break;
18294 case OPC_ILVL_df:
18295 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
18296 break;
18297 case OPC_BNEG_df:
18298 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
18299 break;
18300 case OPC_MIN_U_df:
18301 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
18302 break;
18303 case OPC_CLE_U_df:
18304 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
18305 break;
18306 case OPC_AVE_U_df:
18307 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
18308 break;
18309 case OPC_ASUB_U_df:
18310 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
18311 break;
18312 case OPC_DIV_U_df:
18313 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
18314 break;
18315 case OPC_ILVR_df:
18316 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
18317 break;
18318 case OPC_BINSL_df:
18319 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
18320 break;
18321 case OPC_MAX_A_df:
18322 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
18323 break;
18324 case OPC_AVER_S_df:
18325 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
18326 break;
18327 case OPC_MOD_S_df:
18328 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
18329 break;
18330 case OPC_ILVEV_df:
18331 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
18332 break;
18333 case OPC_BINSR_df:
18334 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
18335 break;
18336 case OPC_MIN_A_df:
18337 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
18338 break;
18339 case OPC_AVER_U_df:
18340 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
18341 break;
18342 case OPC_MOD_U_df:
18343 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
18344 break;
18345 case OPC_ILVOD_df:
18346 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
18347 break;
18349 case OPC_DOTP_S_df:
18350 case OPC_DOTP_U_df:
18351 case OPC_DPADD_S_df:
18352 case OPC_DPADD_U_df:
18353 case OPC_DPSUB_S_df:
18354 case OPC_HADD_S_df:
18355 case OPC_DPSUB_U_df:
18356 case OPC_HADD_U_df:
18357 case OPC_HSUB_S_df:
18358 case OPC_HSUB_U_df:
18359 if (df == DF_BYTE) {
18360 generate_exception_end(ctx, EXCP_RI);
18361 break;
18363 switch (MASK_MSA_3R(ctx->opcode)) {
18364 case OPC_DOTP_S_df:
18365 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
18366 break;
18367 case OPC_DOTP_U_df:
18368 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
18369 break;
18370 case OPC_DPADD_S_df:
18371 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
18372 break;
18373 case OPC_DPADD_U_df:
18374 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
18375 break;
18376 case OPC_DPSUB_S_df:
18377 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
18378 break;
18379 case OPC_HADD_S_df:
18380 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
18381 break;
18382 case OPC_DPSUB_U_df:
18383 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
18384 break;
18385 case OPC_HADD_U_df:
18386 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
18387 break;
18388 case OPC_HSUB_S_df:
18389 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
18390 break;
18391 case OPC_HSUB_U_df:
18392 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
18393 break;
18395 break;
18396 default:
18397 MIPS_INVAL("MSA instruction");
18398 generate_exception_end(ctx, EXCP_RI);
18399 break;
18401 tcg_temp_free_i32(twd);
18402 tcg_temp_free_i32(tws);
18403 tcg_temp_free_i32(twt);
18404 tcg_temp_free_i32(tdf);
18407 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
18409 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
18410 uint8_t source = (ctx->opcode >> 11) & 0x1f;
18411 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
18412 TCGv telm = tcg_temp_new();
18413 TCGv_i32 tsr = tcg_const_i32(source);
18414 TCGv_i32 tdt = tcg_const_i32(dest);
18416 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
18417 case OPC_CTCMSA:
18418 gen_load_gpr(telm, source);
18419 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
18420 break;
18421 case OPC_CFCMSA:
18422 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
18423 gen_store_gpr(telm, dest);
18424 break;
18425 case OPC_MOVE_V:
18426 gen_helper_msa_move_v(cpu_env, tdt, tsr);
18427 break;
18428 default:
18429 MIPS_INVAL("MSA instruction");
18430 generate_exception_end(ctx, EXCP_RI);
18431 break;
18434 tcg_temp_free(telm);
18435 tcg_temp_free_i32(tdt);
18436 tcg_temp_free_i32(tsr);
18439 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
18440 uint32_t n)
18442 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18443 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18444 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18446 TCGv_i32 tws = tcg_const_i32(ws);
18447 TCGv_i32 twd = tcg_const_i32(wd);
18448 TCGv_i32 tn = tcg_const_i32(n);
18449 TCGv_i32 tdf = tcg_const_i32(df);
18451 switch (MASK_MSA_ELM(ctx->opcode)) {
18452 case OPC_SLDI_df:
18453 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
18454 break;
18455 case OPC_SPLATI_df:
18456 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
18457 break;
18458 case OPC_INSVE_df:
18459 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
18460 break;
18461 case OPC_COPY_S_df:
18462 case OPC_COPY_U_df:
18463 case OPC_INSERT_df:
18464 #if !defined(TARGET_MIPS64)
18465 /* Double format valid only for MIPS64 */
18466 if (df == DF_DOUBLE) {
18467 generate_exception_end(ctx, EXCP_RI);
18468 break;
18470 #endif
18471 switch (MASK_MSA_ELM(ctx->opcode)) {
18472 case OPC_COPY_S_df:
18473 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
18474 break;
18475 case OPC_COPY_U_df:
18476 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
18477 break;
18478 case OPC_INSERT_df:
18479 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
18480 break;
18482 break;
18483 default:
18484 MIPS_INVAL("MSA instruction");
18485 generate_exception_end(ctx, EXCP_RI);
18487 tcg_temp_free_i32(twd);
18488 tcg_temp_free_i32(tws);
18489 tcg_temp_free_i32(tn);
18490 tcg_temp_free_i32(tdf);
18493 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
18495 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
18496 uint32_t df = 0, n = 0;
18498 if ((dfn & 0x30) == 0x00) {
18499 n = dfn & 0x0f;
18500 df = DF_BYTE;
18501 } else if ((dfn & 0x38) == 0x20) {
18502 n = dfn & 0x07;
18503 df = DF_HALF;
18504 } else if ((dfn & 0x3c) == 0x30) {
18505 n = dfn & 0x03;
18506 df = DF_WORD;
18507 } else if ((dfn & 0x3e) == 0x38) {
18508 n = dfn & 0x01;
18509 df = DF_DOUBLE;
18510 } else if (dfn == 0x3E) {
18511 /* CTCMSA, CFCMSA, MOVE.V */
18512 gen_msa_elm_3e(env, ctx);
18513 return;
18514 } else {
18515 generate_exception_end(ctx, EXCP_RI);
18516 return;
18519 gen_msa_elm_df(env, ctx, df, n);
18522 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
18524 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18525 uint8_t df = (ctx->opcode >> 21) & 0x1;
18526 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18527 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18528 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18530 TCGv_i32 twd = tcg_const_i32(wd);
18531 TCGv_i32 tws = tcg_const_i32(ws);
18532 TCGv_i32 twt = tcg_const_i32(wt);
18533 TCGv_i32 tdf = tcg_temp_new_i32();
18535 /* adjust df value for floating-point instruction */
18536 tcg_gen_movi_i32(tdf, df + 2);
18538 switch (MASK_MSA_3RF(ctx->opcode)) {
18539 case OPC_FCAF_df:
18540 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
18541 break;
18542 case OPC_FADD_df:
18543 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
18544 break;
18545 case OPC_FCUN_df:
18546 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
18547 break;
18548 case OPC_FSUB_df:
18549 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
18550 break;
18551 case OPC_FCOR_df:
18552 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
18553 break;
18554 case OPC_FCEQ_df:
18555 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
18556 break;
18557 case OPC_FMUL_df:
18558 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
18559 break;
18560 case OPC_FCUNE_df:
18561 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
18562 break;
18563 case OPC_FCUEQ_df:
18564 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
18565 break;
18566 case OPC_FDIV_df:
18567 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
18568 break;
18569 case OPC_FCNE_df:
18570 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
18571 break;
18572 case OPC_FCLT_df:
18573 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
18574 break;
18575 case OPC_FMADD_df:
18576 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
18577 break;
18578 case OPC_MUL_Q_df:
18579 tcg_gen_movi_i32(tdf, df + 1);
18580 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
18581 break;
18582 case OPC_FCULT_df:
18583 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
18584 break;
18585 case OPC_FMSUB_df:
18586 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
18587 break;
18588 case OPC_MADD_Q_df:
18589 tcg_gen_movi_i32(tdf, df + 1);
18590 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
18591 break;
18592 case OPC_FCLE_df:
18593 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
18594 break;
18595 case OPC_MSUB_Q_df:
18596 tcg_gen_movi_i32(tdf, df + 1);
18597 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
18598 break;
18599 case OPC_FCULE_df:
18600 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
18601 break;
18602 case OPC_FEXP2_df:
18603 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
18604 break;
18605 case OPC_FSAF_df:
18606 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
18607 break;
18608 case OPC_FEXDO_df:
18609 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
18610 break;
18611 case OPC_FSUN_df:
18612 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
18613 break;
18614 case OPC_FSOR_df:
18615 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
18616 break;
18617 case OPC_FSEQ_df:
18618 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
18619 break;
18620 case OPC_FTQ_df:
18621 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
18622 break;
18623 case OPC_FSUNE_df:
18624 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
18625 break;
18626 case OPC_FSUEQ_df:
18627 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
18628 break;
18629 case OPC_FSNE_df:
18630 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
18631 break;
18632 case OPC_FSLT_df:
18633 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
18634 break;
18635 case OPC_FMIN_df:
18636 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
18637 break;
18638 case OPC_MULR_Q_df:
18639 tcg_gen_movi_i32(tdf, df + 1);
18640 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
18641 break;
18642 case OPC_FSULT_df:
18643 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
18644 break;
18645 case OPC_FMIN_A_df:
18646 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
18647 break;
18648 case OPC_MADDR_Q_df:
18649 tcg_gen_movi_i32(tdf, df + 1);
18650 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
18651 break;
18652 case OPC_FSLE_df:
18653 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
18654 break;
18655 case OPC_FMAX_df:
18656 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
18657 break;
18658 case OPC_MSUBR_Q_df:
18659 tcg_gen_movi_i32(tdf, df + 1);
18660 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
18661 break;
18662 case OPC_FSULE_df:
18663 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
18664 break;
18665 case OPC_FMAX_A_df:
18666 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
18667 break;
18668 default:
18669 MIPS_INVAL("MSA instruction");
18670 generate_exception_end(ctx, EXCP_RI);
18671 break;
18674 tcg_temp_free_i32(twd);
18675 tcg_temp_free_i32(tws);
18676 tcg_temp_free_i32(twt);
18677 tcg_temp_free_i32(tdf);
18680 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
18682 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18683 (op & (0x7 << 18)))
18684 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18685 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18686 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18687 uint8_t df = (ctx->opcode >> 16) & 0x3;
18688 TCGv_i32 twd = tcg_const_i32(wd);
18689 TCGv_i32 tws = tcg_const_i32(ws);
18690 TCGv_i32 twt = tcg_const_i32(wt);
18691 TCGv_i32 tdf = tcg_const_i32(df);
18693 switch (MASK_MSA_2R(ctx->opcode)) {
18694 case OPC_FILL_df:
18695 #if !defined(TARGET_MIPS64)
18696 /* Double format valid only for MIPS64 */
18697 if (df == DF_DOUBLE) {
18698 generate_exception_end(ctx, EXCP_RI);
18699 break;
18701 #endif
18702 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
18703 break;
18704 case OPC_PCNT_df:
18705 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
18706 break;
18707 case OPC_NLOC_df:
18708 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
18709 break;
18710 case OPC_NLZC_df:
18711 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
18712 break;
18713 default:
18714 MIPS_INVAL("MSA instruction");
18715 generate_exception_end(ctx, EXCP_RI);
18716 break;
18719 tcg_temp_free_i32(twd);
18720 tcg_temp_free_i32(tws);
18721 tcg_temp_free_i32(twt);
18722 tcg_temp_free_i32(tdf);
18725 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
18727 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18728 (op & (0xf << 17)))
18729 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18730 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18731 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18732 uint8_t df = (ctx->opcode >> 16) & 0x1;
18733 TCGv_i32 twd = tcg_const_i32(wd);
18734 TCGv_i32 tws = tcg_const_i32(ws);
18735 TCGv_i32 twt = tcg_const_i32(wt);
18736 /* adjust df value for floating-point instruction */
18737 TCGv_i32 tdf = tcg_const_i32(df + 2);
18739 switch (MASK_MSA_2RF(ctx->opcode)) {
18740 case OPC_FCLASS_df:
18741 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
18742 break;
18743 case OPC_FTRUNC_S_df:
18744 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
18745 break;
18746 case OPC_FTRUNC_U_df:
18747 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
18748 break;
18749 case OPC_FSQRT_df:
18750 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
18751 break;
18752 case OPC_FRSQRT_df:
18753 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
18754 break;
18755 case OPC_FRCP_df:
18756 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
18757 break;
18758 case OPC_FRINT_df:
18759 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
18760 break;
18761 case OPC_FLOG2_df:
18762 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
18763 break;
18764 case OPC_FEXUPL_df:
18765 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
18766 break;
18767 case OPC_FEXUPR_df:
18768 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
18769 break;
18770 case OPC_FFQL_df:
18771 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
18772 break;
18773 case OPC_FFQR_df:
18774 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
18775 break;
18776 case OPC_FTINT_S_df:
18777 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
18778 break;
18779 case OPC_FTINT_U_df:
18780 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
18781 break;
18782 case OPC_FFINT_S_df:
18783 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
18784 break;
18785 case OPC_FFINT_U_df:
18786 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
18787 break;
18790 tcg_temp_free_i32(twd);
18791 tcg_temp_free_i32(tws);
18792 tcg_temp_free_i32(twt);
18793 tcg_temp_free_i32(tdf);
18796 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
18798 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
18799 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18800 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18801 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18802 TCGv_i32 twd = tcg_const_i32(wd);
18803 TCGv_i32 tws = tcg_const_i32(ws);
18804 TCGv_i32 twt = tcg_const_i32(wt);
18806 switch (MASK_MSA_VEC(ctx->opcode)) {
18807 case OPC_AND_V:
18808 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
18809 break;
18810 case OPC_OR_V:
18811 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
18812 break;
18813 case OPC_NOR_V:
18814 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
18815 break;
18816 case OPC_XOR_V:
18817 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
18818 break;
18819 case OPC_BMNZ_V:
18820 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
18821 break;
18822 case OPC_BMZ_V:
18823 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
18824 break;
18825 case OPC_BSEL_V:
18826 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
18827 break;
18828 default:
18829 MIPS_INVAL("MSA instruction");
18830 generate_exception_end(ctx, EXCP_RI);
18831 break;
18834 tcg_temp_free_i32(twd);
18835 tcg_temp_free_i32(tws);
18836 tcg_temp_free_i32(twt);
18839 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
18841 switch (MASK_MSA_VEC(ctx->opcode)) {
18842 case OPC_AND_V:
18843 case OPC_OR_V:
18844 case OPC_NOR_V:
18845 case OPC_XOR_V:
18846 case OPC_BMNZ_V:
18847 case OPC_BMZ_V:
18848 case OPC_BSEL_V:
18849 gen_msa_vec_v(env, ctx);
18850 break;
18851 case OPC_MSA_2R:
18852 gen_msa_2r(env, ctx);
18853 break;
18854 case OPC_MSA_2RF:
18855 gen_msa_2rf(env, ctx);
18856 break;
18857 default:
18858 MIPS_INVAL("MSA instruction");
18859 generate_exception_end(ctx, EXCP_RI);
18860 break;
18864 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
18866 uint32_t opcode = ctx->opcode;
18867 check_insn(ctx, ASE_MSA);
18868 check_msa_access(ctx);
18870 switch (MASK_MSA_MINOR(opcode)) {
18871 case OPC_MSA_I8_00:
18872 case OPC_MSA_I8_01:
18873 case OPC_MSA_I8_02:
18874 gen_msa_i8(env, ctx);
18875 break;
18876 case OPC_MSA_I5_06:
18877 case OPC_MSA_I5_07:
18878 gen_msa_i5(env, ctx);
18879 break;
18880 case OPC_MSA_BIT_09:
18881 case OPC_MSA_BIT_0A:
18882 gen_msa_bit(env, ctx);
18883 break;
18884 case OPC_MSA_3R_0D:
18885 case OPC_MSA_3R_0E:
18886 case OPC_MSA_3R_0F:
18887 case OPC_MSA_3R_10:
18888 case OPC_MSA_3R_11:
18889 case OPC_MSA_3R_12:
18890 case OPC_MSA_3R_13:
18891 case OPC_MSA_3R_14:
18892 case OPC_MSA_3R_15:
18893 gen_msa_3r(env, ctx);
18894 break;
18895 case OPC_MSA_ELM:
18896 gen_msa_elm(env, ctx);
18897 break;
18898 case OPC_MSA_3RF_1A:
18899 case OPC_MSA_3RF_1B:
18900 case OPC_MSA_3RF_1C:
18901 gen_msa_3rf(env, ctx);
18902 break;
18903 case OPC_MSA_VEC:
18904 gen_msa_vec(env, ctx);
18905 break;
18906 case OPC_LD_B:
18907 case OPC_LD_H:
18908 case OPC_LD_W:
18909 case OPC_LD_D:
18910 case OPC_ST_B:
18911 case OPC_ST_H:
18912 case OPC_ST_W:
18913 case OPC_ST_D:
18915 int32_t s10 = sextract32(ctx->opcode, 16, 10);
18916 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
18917 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18918 uint8_t df = (ctx->opcode >> 0) & 0x3;
18920 TCGv_i32 twd = tcg_const_i32(wd);
18921 TCGv taddr = tcg_temp_new();
18922 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
18924 switch (MASK_MSA_MINOR(opcode)) {
18925 case OPC_LD_B:
18926 gen_helper_msa_ld_b(cpu_env, twd, taddr);
18927 break;
18928 case OPC_LD_H:
18929 gen_helper_msa_ld_h(cpu_env, twd, taddr);
18930 break;
18931 case OPC_LD_W:
18932 gen_helper_msa_ld_w(cpu_env, twd, taddr);
18933 break;
18934 case OPC_LD_D:
18935 gen_helper_msa_ld_d(cpu_env, twd, taddr);
18936 break;
18937 case OPC_ST_B:
18938 gen_helper_msa_st_b(cpu_env, twd, taddr);
18939 break;
18940 case OPC_ST_H:
18941 gen_helper_msa_st_h(cpu_env, twd, taddr);
18942 break;
18943 case OPC_ST_W:
18944 gen_helper_msa_st_w(cpu_env, twd, taddr);
18945 break;
18946 case OPC_ST_D:
18947 gen_helper_msa_st_d(cpu_env, twd, taddr);
18948 break;
18951 tcg_temp_free_i32(twd);
18952 tcg_temp_free(taddr);
18954 break;
18955 default:
18956 MIPS_INVAL("MSA instruction");
18957 generate_exception_end(ctx, EXCP_RI);
18958 break;
18963 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
18965 int32_t offset;
18966 int rs, rt, rd, sa;
18967 uint32_t op, op1;
18968 int16_t imm;
18970 /* make sure instructions are on a word boundary */
18971 if (ctx->pc & 0x3) {
18972 env->CP0_BadVAddr = ctx->pc;
18973 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
18974 return;
18977 /* Handle blikely not taken case */
18978 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
18979 TCGLabel *l1 = gen_new_label();
18981 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
18982 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
18983 gen_goto_tb(ctx, 1, ctx->pc + 4);
18984 gen_set_label(l1);
18987 op = MASK_OP_MAJOR(ctx->opcode);
18988 rs = (ctx->opcode >> 21) & 0x1f;
18989 rt = (ctx->opcode >> 16) & 0x1f;
18990 rd = (ctx->opcode >> 11) & 0x1f;
18991 sa = (ctx->opcode >> 6) & 0x1f;
18992 imm = (int16_t)ctx->opcode;
18993 switch (op) {
18994 case OPC_SPECIAL:
18995 decode_opc_special(env, ctx);
18996 break;
18997 case OPC_SPECIAL2:
18998 decode_opc_special2_legacy(env, ctx);
18999 break;
19000 case OPC_SPECIAL3:
19001 decode_opc_special3(env, ctx);
19002 break;
19003 case OPC_REGIMM:
19004 op1 = MASK_REGIMM(ctx->opcode);
19005 switch (op1) {
19006 case OPC_BLTZL: /* REGIMM branches */
19007 case OPC_BGEZL:
19008 case OPC_BLTZALL:
19009 case OPC_BGEZALL:
19010 check_insn(ctx, ISA_MIPS2);
19011 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19012 /* Fallthrough */
19013 case OPC_BLTZ:
19014 case OPC_BGEZ:
19015 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19016 break;
19017 case OPC_BLTZAL:
19018 case OPC_BGEZAL:
19019 if (ctx->insn_flags & ISA_MIPS32R6) {
19020 if (rs == 0) {
19021 /* OPC_NAL, OPC_BAL */
19022 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
19023 } else {
19024 generate_exception_end(ctx, EXCP_RI);
19026 } else {
19027 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19029 break;
19030 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
19031 case OPC_TNEI:
19032 check_insn(ctx, ISA_MIPS2);
19033 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19034 gen_trap(ctx, op1, rs, -1, imm);
19035 break;
19036 case OPC_SIGRIE:
19037 check_insn(ctx, ISA_MIPS32R6);
19038 generate_exception_end(ctx, EXCP_RI);
19039 break;
19040 case OPC_SYNCI:
19041 check_insn(ctx, ISA_MIPS32R2);
19042 /* Break the TB to be able to sync copied instructions
19043 immediately */
19044 ctx->bstate = BS_STOP;
19045 break;
19046 case OPC_BPOSGE32: /* MIPS DSP branch */
19047 #if defined(TARGET_MIPS64)
19048 case OPC_BPOSGE64:
19049 #endif
19050 check_dsp(ctx);
19051 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
19052 break;
19053 #if defined(TARGET_MIPS64)
19054 case OPC_DAHI:
19055 check_insn(ctx, ISA_MIPS32R6);
19056 check_mips_64(ctx);
19057 if (rs != 0) {
19058 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
19060 break;
19061 case OPC_DATI:
19062 check_insn(ctx, ISA_MIPS32R6);
19063 check_mips_64(ctx);
19064 if (rs != 0) {
19065 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
19067 break;
19068 #endif
19069 default: /* Invalid */
19070 MIPS_INVAL("regimm");
19071 generate_exception_end(ctx, EXCP_RI);
19072 break;
19074 break;
19075 case OPC_CP0:
19076 check_cp0_enabled(ctx);
19077 op1 = MASK_CP0(ctx->opcode);
19078 switch (op1) {
19079 case OPC_MFC0:
19080 case OPC_MTC0:
19081 case OPC_MFTR:
19082 case OPC_MTTR:
19083 case OPC_MFHC0:
19084 case OPC_MTHC0:
19085 #if defined(TARGET_MIPS64)
19086 case OPC_DMFC0:
19087 case OPC_DMTC0:
19088 #endif
19089 #ifndef CONFIG_USER_ONLY
19090 gen_cp0(env, ctx, op1, rt, rd);
19091 #endif /* !CONFIG_USER_ONLY */
19092 break;
19093 case OPC_C0_FIRST ... OPC_C0_LAST:
19094 #ifndef CONFIG_USER_ONLY
19095 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
19096 #endif /* !CONFIG_USER_ONLY */
19097 break;
19098 case OPC_MFMC0:
19099 #ifndef CONFIG_USER_ONLY
19101 uint32_t op2;
19102 TCGv t0 = tcg_temp_new();
19104 op2 = MASK_MFMC0(ctx->opcode);
19105 switch (op2) {
19106 case OPC_DMT:
19107 check_insn(ctx, ASE_MT);
19108 gen_helper_dmt(t0);
19109 gen_store_gpr(t0, rt);
19110 break;
19111 case OPC_EMT:
19112 check_insn(ctx, ASE_MT);
19113 gen_helper_emt(t0);
19114 gen_store_gpr(t0, rt);
19115 break;
19116 case OPC_DVPE:
19117 check_insn(ctx, ASE_MT);
19118 gen_helper_dvpe(t0, cpu_env);
19119 gen_store_gpr(t0, rt);
19120 break;
19121 case OPC_EVPE:
19122 check_insn(ctx, ASE_MT);
19123 gen_helper_evpe(t0, cpu_env);
19124 gen_store_gpr(t0, rt);
19125 break;
19126 case OPC_DVP:
19127 check_insn(ctx, ISA_MIPS32R6);
19128 if (ctx->vp) {
19129 gen_helper_dvp(t0, cpu_env);
19130 gen_store_gpr(t0, rt);
19132 break;
19133 case OPC_EVP:
19134 check_insn(ctx, ISA_MIPS32R6);
19135 if (ctx->vp) {
19136 gen_helper_evp(t0, cpu_env);
19137 gen_store_gpr(t0, rt);
19139 break;
19140 case OPC_DI:
19141 check_insn(ctx, ISA_MIPS32R2);
19142 save_cpu_state(ctx, 1);
19143 gen_helper_di(t0, cpu_env);
19144 gen_store_gpr(t0, rt);
19145 /* Stop translation as we may have switched
19146 the execution mode. */
19147 ctx->bstate = BS_STOP;
19148 break;
19149 case OPC_EI:
19150 check_insn(ctx, ISA_MIPS32R2);
19151 save_cpu_state(ctx, 1);
19152 gen_helper_ei(t0, cpu_env);
19153 gen_store_gpr(t0, rt);
19154 /* Stop translation as we may have switched
19155 the execution mode. */
19156 ctx->bstate = BS_STOP;
19157 break;
19158 default: /* Invalid */
19159 MIPS_INVAL("mfmc0");
19160 generate_exception_end(ctx, EXCP_RI);
19161 break;
19163 tcg_temp_free(t0);
19165 #endif /* !CONFIG_USER_ONLY */
19166 break;
19167 case OPC_RDPGPR:
19168 check_insn(ctx, ISA_MIPS32R2);
19169 gen_load_srsgpr(rt, rd);
19170 break;
19171 case OPC_WRPGPR:
19172 check_insn(ctx, ISA_MIPS32R2);
19173 gen_store_srsgpr(rt, rd);
19174 break;
19175 default:
19176 MIPS_INVAL("cp0");
19177 generate_exception_end(ctx, EXCP_RI);
19178 break;
19180 break;
19181 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
19182 if (ctx->insn_flags & ISA_MIPS32R6) {
19183 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
19184 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19185 } else {
19186 /* OPC_ADDI */
19187 /* Arithmetic with immediate opcode */
19188 gen_arith_imm(ctx, op, rt, rs, imm);
19190 break;
19191 case OPC_ADDIU:
19192 gen_arith_imm(ctx, op, rt, rs, imm);
19193 break;
19194 case OPC_SLTI: /* Set on less than with immediate opcode */
19195 case OPC_SLTIU:
19196 gen_slt_imm(ctx, op, rt, rs, imm);
19197 break;
19198 case OPC_ANDI: /* Arithmetic with immediate opcode */
19199 case OPC_LUI: /* OPC_AUI */
19200 case OPC_ORI:
19201 case OPC_XORI:
19202 gen_logic_imm(ctx, op, rt, rs, imm);
19203 break;
19204 case OPC_J ... OPC_JAL: /* Jump */
19205 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19206 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19207 break;
19208 /* Branch */
19209 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
19210 if (ctx->insn_flags & ISA_MIPS32R6) {
19211 if (rt == 0) {
19212 generate_exception_end(ctx, EXCP_RI);
19213 break;
19215 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
19216 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19217 } else {
19218 /* OPC_BLEZL */
19219 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19221 break;
19222 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
19223 if (ctx->insn_flags & ISA_MIPS32R6) {
19224 if (rt == 0) {
19225 generate_exception_end(ctx, EXCP_RI);
19226 break;
19228 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
19229 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19230 } else {
19231 /* OPC_BGTZL */
19232 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19234 break;
19235 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
19236 if (rt == 0) {
19237 /* OPC_BLEZ */
19238 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19239 } else {
19240 check_insn(ctx, ISA_MIPS32R6);
19241 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
19242 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19244 break;
19245 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
19246 if (rt == 0) {
19247 /* OPC_BGTZ */
19248 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19249 } else {
19250 check_insn(ctx, ISA_MIPS32R6);
19251 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
19252 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19254 break;
19255 case OPC_BEQL:
19256 case OPC_BNEL:
19257 check_insn(ctx, ISA_MIPS2);
19258 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19259 /* Fallthrough */
19260 case OPC_BEQ:
19261 case OPC_BNE:
19262 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19263 break;
19264 case OPC_LL: /* Load and stores */
19265 check_insn(ctx, ISA_MIPS2);
19266 /* Fallthrough */
19267 case OPC_LWL:
19268 case OPC_LWR:
19269 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19270 /* Fallthrough */
19271 case OPC_LB ... OPC_LH:
19272 case OPC_LW ... OPC_LHU:
19273 gen_ld(ctx, op, rt, rs, imm);
19274 break;
19275 case OPC_SWL:
19276 case OPC_SWR:
19277 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19278 /* fall through */
19279 case OPC_SB ... OPC_SH:
19280 case OPC_SW:
19281 gen_st(ctx, op, rt, rs, imm);
19282 break;
19283 case OPC_SC:
19284 check_insn(ctx, ISA_MIPS2);
19285 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19286 gen_st_cond(ctx, op, rt, rs, imm);
19287 break;
19288 case OPC_CACHE:
19289 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19290 check_cp0_enabled(ctx);
19291 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
19292 /* Treat as NOP. */
19293 break;
19294 case OPC_PREF:
19295 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19296 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
19297 /* Treat as NOP. */
19298 break;
19300 /* Floating point (COP1). */
19301 case OPC_LWC1:
19302 case OPC_LDC1:
19303 case OPC_SWC1:
19304 case OPC_SDC1:
19305 gen_cop1_ldst(ctx, op, rt, rs, imm);
19306 break;
19308 case OPC_CP1:
19309 op1 = MASK_CP1(ctx->opcode);
19311 switch (op1) {
19312 case OPC_MFHC1:
19313 case OPC_MTHC1:
19314 check_cp1_enabled(ctx);
19315 check_insn(ctx, ISA_MIPS32R2);
19316 case OPC_MFC1:
19317 case OPC_CFC1:
19318 case OPC_MTC1:
19319 case OPC_CTC1:
19320 check_cp1_enabled(ctx);
19321 gen_cp1(ctx, op1, rt, rd);
19322 break;
19323 #if defined(TARGET_MIPS64)
19324 case OPC_DMFC1:
19325 case OPC_DMTC1:
19326 check_cp1_enabled(ctx);
19327 check_insn(ctx, ISA_MIPS3);
19328 check_mips_64(ctx);
19329 gen_cp1(ctx, op1, rt, rd);
19330 break;
19331 #endif
19332 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
19333 check_cp1_enabled(ctx);
19334 if (ctx->insn_flags & ISA_MIPS32R6) {
19335 /* OPC_BC1EQZ */
19336 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19337 rt, imm << 2, 4);
19338 } else {
19339 /* OPC_BC1ANY2 */
19340 check_cop1x(ctx);
19341 check_insn(ctx, ASE_MIPS3D);
19342 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19343 (rt >> 2) & 0x7, imm << 2);
19345 break;
19346 case OPC_BC1NEZ:
19347 check_cp1_enabled(ctx);
19348 check_insn(ctx, ISA_MIPS32R6);
19349 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19350 rt, imm << 2, 4);
19351 break;
19352 case OPC_BC1ANY4:
19353 check_cp1_enabled(ctx);
19354 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19355 check_cop1x(ctx);
19356 check_insn(ctx, ASE_MIPS3D);
19357 /* fall through */
19358 case OPC_BC1:
19359 check_cp1_enabled(ctx);
19360 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19361 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19362 (rt >> 2) & 0x7, imm << 2);
19363 break;
19364 case OPC_PS_FMT:
19365 check_ps(ctx);
19366 /* fall through */
19367 case OPC_S_FMT:
19368 case OPC_D_FMT:
19369 check_cp1_enabled(ctx);
19370 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19371 (imm >> 8) & 0x7);
19372 break;
19373 case OPC_W_FMT:
19374 case OPC_L_FMT:
19376 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
19377 check_cp1_enabled(ctx);
19378 if (ctx->insn_flags & ISA_MIPS32R6) {
19379 switch (r6_op) {
19380 case R6_OPC_CMP_AF_S:
19381 case R6_OPC_CMP_UN_S:
19382 case R6_OPC_CMP_EQ_S:
19383 case R6_OPC_CMP_UEQ_S:
19384 case R6_OPC_CMP_LT_S:
19385 case R6_OPC_CMP_ULT_S:
19386 case R6_OPC_CMP_LE_S:
19387 case R6_OPC_CMP_ULE_S:
19388 case R6_OPC_CMP_SAF_S:
19389 case R6_OPC_CMP_SUN_S:
19390 case R6_OPC_CMP_SEQ_S:
19391 case R6_OPC_CMP_SEUQ_S:
19392 case R6_OPC_CMP_SLT_S:
19393 case R6_OPC_CMP_SULT_S:
19394 case R6_OPC_CMP_SLE_S:
19395 case R6_OPC_CMP_SULE_S:
19396 case R6_OPC_CMP_OR_S:
19397 case R6_OPC_CMP_UNE_S:
19398 case R6_OPC_CMP_NE_S:
19399 case R6_OPC_CMP_SOR_S:
19400 case R6_OPC_CMP_SUNE_S:
19401 case R6_OPC_CMP_SNE_S:
19402 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19403 break;
19404 case R6_OPC_CMP_AF_D:
19405 case R6_OPC_CMP_UN_D:
19406 case R6_OPC_CMP_EQ_D:
19407 case R6_OPC_CMP_UEQ_D:
19408 case R6_OPC_CMP_LT_D:
19409 case R6_OPC_CMP_ULT_D:
19410 case R6_OPC_CMP_LE_D:
19411 case R6_OPC_CMP_ULE_D:
19412 case R6_OPC_CMP_SAF_D:
19413 case R6_OPC_CMP_SUN_D:
19414 case R6_OPC_CMP_SEQ_D:
19415 case R6_OPC_CMP_SEUQ_D:
19416 case R6_OPC_CMP_SLT_D:
19417 case R6_OPC_CMP_SULT_D:
19418 case R6_OPC_CMP_SLE_D:
19419 case R6_OPC_CMP_SULE_D:
19420 case R6_OPC_CMP_OR_D:
19421 case R6_OPC_CMP_UNE_D:
19422 case R6_OPC_CMP_NE_D:
19423 case R6_OPC_CMP_SOR_D:
19424 case R6_OPC_CMP_SUNE_D:
19425 case R6_OPC_CMP_SNE_D:
19426 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19427 break;
19428 default:
19429 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
19430 rt, rd, sa, (imm >> 8) & 0x7);
19432 break;
19434 } else {
19435 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19436 (imm >> 8) & 0x7);
19438 break;
19440 case OPC_BZ_V:
19441 case OPC_BNZ_V:
19442 case OPC_BZ_B:
19443 case OPC_BZ_H:
19444 case OPC_BZ_W:
19445 case OPC_BZ_D:
19446 case OPC_BNZ_B:
19447 case OPC_BNZ_H:
19448 case OPC_BNZ_W:
19449 case OPC_BNZ_D:
19450 check_insn(ctx, ASE_MSA);
19451 gen_msa_branch(env, ctx, op1);
19452 break;
19453 default:
19454 MIPS_INVAL("cp1");
19455 generate_exception_end(ctx, EXCP_RI);
19456 break;
19458 break;
19460 /* Compact branches [R6] and COP2 [non-R6] */
19461 case OPC_BC: /* OPC_LWC2 */
19462 case OPC_BALC: /* OPC_SWC2 */
19463 if (ctx->insn_flags & ISA_MIPS32R6) {
19464 /* OPC_BC, OPC_BALC */
19465 gen_compute_compact_branch(ctx, op, 0, 0,
19466 sextract32(ctx->opcode << 2, 0, 28));
19467 } else {
19468 /* OPC_LWC2, OPC_SWC2 */
19469 /* COP2: Not implemented. */
19470 generate_exception_err(ctx, EXCP_CpU, 2);
19472 break;
19473 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
19474 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
19475 if (ctx->insn_flags & ISA_MIPS32R6) {
19476 if (rs != 0) {
19477 /* OPC_BEQZC, OPC_BNEZC */
19478 gen_compute_compact_branch(ctx, op, rs, 0,
19479 sextract32(ctx->opcode << 2, 0, 23));
19480 } else {
19481 /* OPC_JIC, OPC_JIALC */
19482 gen_compute_compact_branch(ctx, op, 0, rt, imm);
19484 } else {
19485 /* OPC_LWC2, OPC_SWC2 */
19486 /* COP2: Not implemented. */
19487 generate_exception_err(ctx, EXCP_CpU, 2);
19489 break;
19490 case OPC_CP2:
19491 check_insn(ctx, INSN_LOONGSON2F);
19492 /* Note that these instructions use different fields. */
19493 gen_loongson_multimedia(ctx, sa, rd, rt);
19494 break;
19496 case OPC_CP3:
19497 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19498 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19499 check_cp1_enabled(ctx);
19500 op1 = MASK_CP3(ctx->opcode);
19501 switch (op1) {
19502 case OPC_LUXC1:
19503 case OPC_SUXC1:
19504 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19505 /* Fallthrough */
19506 case OPC_LWXC1:
19507 case OPC_LDXC1:
19508 case OPC_SWXC1:
19509 case OPC_SDXC1:
19510 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19511 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
19512 break;
19513 case OPC_PREFX:
19514 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19515 /* Treat as NOP. */
19516 break;
19517 case OPC_ALNV_PS:
19518 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19519 /* Fallthrough */
19520 case OPC_MADD_S:
19521 case OPC_MADD_D:
19522 case OPC_MADD_PS:
19523 case OPC_MSUB_S:
19524 case OPC_MSUB_D:
19525 case OPC_MSUB_PS:
19526 case OPC_NMADD_S:
19527 case OPC_NMADD_D:
19528 case OPC_NMADD_PS:
19529 case OPC_NMSUB_S:
19530 case OPC_NMSUB_D:
19531 case OPC_NMSUB_PS:
19532 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19533 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
19534 break;
19535 default:
19536 MIPS_INVAL("cp3");
19537 generate_exception_end(ctx, EXCP_RI);
19538 break;
19540 } else {
19541 generate_exception_err(ctx, EXCP_CpU, 1);
19543 break;
19545 #if defined(TARGET_MIPS64)
19546 /* MIPS64 opcodes */
19547 case OPC_LDL ... OPC_LDR:
19548 case OPC_LLD:
19549 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19550 /* fall through */
19551 case OPC_LWU:
19552 case OPC_LD:
19553 check_insn(ctx, ISA_MIPS3);
19554 check_mips_64(ctx);
19555 gen_ld(ctx, op, rt, rs, imm);
19556 break;
19557 case OPC_SDL ... OPC_SDR:
19558 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19559 /* fall through */
19560 case OPC_SD:
19561 check_insn(ctx, ISA_MIPS3);
19562 check_mips_64(ctx);
19563 gen_st(ctx, op, rt, rs, imm);
19564 break;
19565 case OPC_SCD:
19566 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19567 check_insn(ctx, ISA_MIPS3);
19568 check_mips_64(ctx);
19569 gen_st_cond(ctx, op, rt, rs, imm);
19570 break;
19571 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
19572 if (ctx->insn_flags & ISA_MIPS32R6) {
19573 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
19574 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19575 } else {
19576 /* OPC_DADDI */
19577 check_insn(ctx, ISA_MIPS3);
19578 check_mips_64(ctx);
19579 gen_arith_imm(ctx, op, rt, rs, imm);
19581 break;
19582 case OPC_DADDIU:
19583 check_insn(ctx, ISA_MIPS3);
19584 check_mips_64(ctx);
19585 gen_arith_imm(ctx, op, rt, rs, imm);
19586 break;
19587 #else
19588 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
19589 if (ctx->insn_flags & ISA_MIPS32R6) {
19590 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19591 } else {
19592 MIPS_INVAL("major opcode");
19593 generate_exception_end(ctx, EXCP_RI);
19595 break;
19596 #endif
19597 case OPC_DAUI: /* OPC_JALX */
19598 if (ctx->insn_flags & ISA_MIPS32R6) {
19599 #if defined(TARGET_MIPS64)
19600 /* OPC_DAUI */
19601 check_mips_64(ctx);
19602 if (rs == 0) {
19603 generate_exception(ctx, EXCP_RI);
19604 } else if (rt != 0) {
19605 TCGv t0 = tcg_temp_new();
19606 gen_load_gpr(t0, rs);
19607 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
19608 tcg_temp_free(t0);
19610 #else
19611 generate_exception_end(ctx, EXCP_RI);
19612 MIPS_INVAL("major opcode");
19613 #endif
19614 } else {
19615 /* OPC_JALX */
19616 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
19617 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19618 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19620 break;
19621 case OPC_MSA: /* OPC_MDMX */
19622 /* MDMX: Not implemented. */
19623 gen_msa(env, ctx);
19624 break;
19625 case OPC_PCREL:
19626 check_insn(ctx, ISA_MIPS32R6);
19627 gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
19628 break;
19629 default: /* Invalid */
19630 MIPS_INVAL("major opcode");
19631 generate_exception_end(ctx, EXCP_RI);
19632 break;
19636 void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
19638 MIPSCPU *cpu = mips_env_get_cpu(env);
19639 CPUState *cs = CPU(cpu);
19640 DisasContext ctx;
19641 target_ulong pc_start;
19642 target_ulong next_page_start;
19643 int num_insns;
19644 int max_insns;
19645 int insn_bytes;
19646 int is_slot;
19648 pc_start = tb->pc;
19649 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
19650 ctx.pc = pc_start;
19651 ctx.saved_pc = -1;
19652 ctx.singlestep_enabled = cs->singlestep_enabled;
19653 ctx.insn_flags = env->insn_flags;
19654 ctx.CP0_Config1 = env->CP0_Config1;
19655 ctx.tb = tb;
19656 ctx.bstate = BS_NONE;
19657 ctx.btarget = 0;
19658 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
19659 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
19660 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
19661 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
19662 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
19663 ctx.PAMask = env->PAMask;
19664 ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
19665 ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
19666 /* Restore delay slot state from the tb context. */
19667 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
19668 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
19669 ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
19670 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
19671 ctx.vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
19672 restore_cpu_state(env, &ctx);
19673 #ifdef CONFIG_USER_ONLY
19674 ctx.mem_idx = MIPS_HFLAG_UM;
19675 #else
19676 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
19677 #endif
19678 ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
19679 MO_UNALN : MO_ALIGN;
19680 num_insns = 0;
19681 max_insns = tb->cflags & CF_COUNT_MASK;
19682 if (max_insns == 0) {
19683 max_insns = CF_COUNT_MASK;
19685 if (max_insns > TCG_MAX_INSNS) {
19686 max_insns = TCG_MAX_INSNS;
19689 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
19690 gen_tb_start(tb);
19691 while (ctx.bstate == BS_NONE) {
19692 tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
19693 num_insns++;
19695 if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
19696 save_cpu_state(&ctx, 1);
19697 ctx.bstate = BS_BRANCH;
19698 gen_helper_raise_exception_debug(cpu_env);
19699 /* The address covered by the breakpoint must be included in
19700 [tb->pc, tb->pc + tb->size) in order to for it to be
19701 properly cleared -- thus we increment the PC here so that
19702 the logic setting tb->size below does the right thing. */
19703 ctx.pc += 4;
19704 goto done_generating;
19707 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
19708 gen_io_start();
19711 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
19712 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
19713 ctx.opcode = cpu_ldl_code(env, ctx.pc);
19714 insn_bytes = 4;
19715 decode_opc(env, &ctx);
19716 } else if (ctx.insn_flags & ASE_MICROMIPS) {
19717 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19718 insn_bytes = decode_micromips_opc(env, &ctx);
19719 } else if (ctx.insn_flags & ASE_MIPS16) {
19720 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19721 insn_bytes = decode_mips16_opc(env, &ctx);
19722 } else {
19723 generate_exception_end(&ctx, EXCP_RI);
19724 break;
19727 if (ctx.hflags & MIPS_HFLAG_BMASK) {
19728 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
19729 MIPS_HFLAG_FBNSLOT))) {
19730 /* force to generate branch as there is neither delay nor
19731 forbidden slot */
19732 is_slot = 1;
19734 if ((ctx.hflags & MIPS_HFLAG_M16) &&
19735 (ctx.hflags & MIPS_HFLAG_FBNSLOT)) {
19736 /* Force to generate branch as microMIPS R6 doesn't restrict
19737 branches in the forbidden slot. */
19738 is_slot = 1;
19741 if (is_slot) {
19742 gen_branch(&ctx, insn_bytes);
19744 ctx.pc += insn_bytes;
19746 /* Execute a branch and its delay slot as a single instruction.
19747 This is what GDB expects and is consistent with what the
19748 hardware does (e.g. if a delay slot instruction faults, the
19749 reported PC is the PC of the branch). */
19750 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
19751 break;
19754 if (ctx.pc >= next_page_start) {
19755 break;
19758 if (tcg_op_buf_full()) {
19759 break;
19762 if (num_insns >= max_insns)
19763 break;
19765 if (singlestep)
19766 break;
19768 if (tb->cflags & CF_LAST_IO) {
19769 gen_io_end();
19771 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
19772 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
19773 gen_helper_raise_exception_debug(cpu_env);
19774 } else {
19775 switch (ctx.bstate) {
19776 case BS_STOP:
19777 gen_goto_tb(&ctx, 0, ctx.pc);
19778 break;
19779 case BS_NONE:
19780 save_cpu_state(&ctx, 0);
19781 gen_goto_tb(&ctx, 0, ctx.pc);
19782 break;
19783 case BS_EXCP:
19784 tcg_gen_exit_tb(0);
19785 break;
19786 case BS_BRANCH:
19787 default:
19788 break;
19791 done_generating:
19792 gen_tb_end(tb, num_insns);
19794 tb->size = ctx.pc - pc_start;
19795 tb->icount = num_insns;
19797 #ifdef DEBUG_DISAS
19798 LOG_DISAS("\n");
19799 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
19800 qemu_log("IN: %s\n", lookup_symbol(pc_start));
19801 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
19802 qemu_log("\n");
19804 #endif
19807 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
19808 int flags)
19810 int i;
19811 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
19813 #define printfpr(fp) \
19814 do { \
19815 if (is_fpu64) \
19816 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19817 " fd:%13g fs:%13g psu: %13g\n", \
19818 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
19819 (double)(fp)->fd, \
19820 (double)(fp)->fs[FP_ENDIAN_IDX], \
19821 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
19822 else { \
19823 fpr_t tmp; \
19824 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
19825 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
19826 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19827 " fd:%13g fs:%13g psu:%13g\n", \
19828 tmp.w[FP_ENDIAN_IDX], tmp.d, \
19829 (double)tmp.fd, \
19830 (double)tmp.fs[FP_ENDIAN_IDX], \
19831 (double)tmp.fs[!FP_ENDIAN_IDX]); \
19833 } while(0)
19836 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
19837 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
19838 get_float_exception_flags(&env->active_fpu.fp_status));
19839 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
19840 fpu_fprintf(f, "%3s: ", fregnames[i]);
19841 printfpr(&env->active_fpu.fpr[i]);
19844 #undef printfpr
19847 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
19848 int flags)
19850 MIPSCPU *cpu = MIPS_CPU(cs);
19851 CPUMIPSState *env = &cpu->env;
19852 int i;
19854 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
19855 " LO=0x" TARGET_FMT_lx " ds %04x "
19856 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
19857 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
19858 env->hflags, env->btarget, env->bcond);
19859 for (i = 0; i < 32; i++) {
19860 if ((i & 3) == 0)
19861 cpu_fprintf(f, "GPR%02d:", i);
19862 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
19863 if ((i & 3) == 3)
19864 cpu_fprintf(f, "\n");
19867 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
19868 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
19869 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
19870 PRIx64 "\n",
19871 env->CP0_Config0, env->CP0_Config1, env->lladdr);
19872 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
19873 env->CP0_Config2, env->CP0_Config3);
19874 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
19875 env->CP0_Config4, env->CP0_Config5);
19876 if (env->hflags & MIPS_HFLAG_FPU)
19877 fpu_dump_state(env, f, cpu_fprintf, flags);
19880 void mips_tcg_init(void)
19882 int i;
19883 static int inited;
19885 /* Initialize various static tables. */
19886 if (inited)
19887 return;
19889 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
19891 TCGV_UNUSED(cpu_gpr[0]);
19892 for (i = 1; i < 32; i++)
19893 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
19894 offsetof(CPUMIPSState, active_tc.gpr[i]),
19895 regnames[i]);
19897 for (i = 0; i < 32; i++) {
19898 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
19899 msa_wr_d[i * 2] =
19900 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
19901 /* The scalar floating-point unit (FPU) registers are mapped on
19902 * the MSA vector registers. */
19903 fpu_f64[i] = msa_wr_d[i * 2];
19904 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
19905 msa_wr_d[i * 2 + 1] =
19906 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
19909 cpu_PC = tcg_global_mem_new(cpu_env,
19910 offsetof(CPUMIPSState, active_tc.PC), "PC");
19911 for (i = 0; i < MIPS_DSP_ACC; i++) {
19912 cpu_HI[i] = tcg_global_mem_new(cpu_env,
19913 offsetof(CPUMIPSState, active_tc.HI[i]),
19914 regnames_HI[i]);
19915 cpu_LO[i] = tcg_global_mem_new(cpu_env,
19916 offsetof(CPUMIPSState, active_tc.LO[i]),
19917 regnames_LO[i]);
19919 cpu_dspctrl = tcg_global_mem_new(cpu_env,
19920 offsetof(CPUMIPSState, active_tc.DSPControl),
19921 "DSPControl");
19922 bcond = tcg_global_mem_new(cpu_env,
19923 offsetof(CPUMIPSState, bcond), "bcond");
19924 btarget = tcg_global_mem_new(cpu_env,
19925 offsetof(CPUMIPSState, btarget), "btarget");
19926 hflags = tcg_global_mem_new_i32(cpu_env,
19927 offsetof(CPUMIPSState, hflags), "hflags");
19929 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
19930 offsetof(CPUMIPSState, active_fpu.fcr0),
19931 "fcr0");
19932 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
19933 offsetof(CPUMIPSState, active_fpu.fcr31),
19934 "fcr31");
19936 inited = 1;
19939 #include "translate_init.c"
19941 MIPSCPU *cpu_mips_init(const char *cpu_model)
19943 MIPSCPU *cpu;
19944 CPUMIPSState *env;
19945 const mips_def_t *def;
19947 def = cpu_mips_find_by_name(cpu_model);
19948 if (!def)
19949 return NULL;
19950 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
19951 env = &cpu->env;
19952 env->cpu_model = def;
19954 #ifndef CONFIG_USER_ONLY
19955 mmu_init(env, def);
19956 #endif
19957 fpu_init(env, def);
19958 mvp_init(env, def);
19960 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
19962 return cpu;
19965 void cpu_state_reset(CPUMIPSState *env)
19967 MIPSCPU *cpu = mips_env_get_cpu(env);
19968 CPUState *cs = CPU(cpu);
19970 /* Reset registers to their default values */
19971 env->CP0_PRid = env->cpu_model->CP0_PRid;
19972 env->CP0_Config0 = env->cpu_model->CP0_Config0;
19973 #ifdef TARGET_WORDS_BIGENDIAN
19974 env->CP0_Config0 |= (1 << CP0C0_BE);
19975 #endif
19976 env->CP0_Config1 = env->cpu_model->CP0_Config1;
19977 env->CP0_Config2 = env->cpu_model->CP0_Config2;
19978 env->CP0_Config3 = env->cpu_model->CP0_Config3;
19979 env->CP0_Config4 = env->cpu_model->CP0_Config4;
19980 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
19981 env->CP0_Config5 = env->cpu_model->CP0_Config5;
19982 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
19983 env->CP0_Config6 = env->cpu_model->CP0_Config6;
19984 env->CP0_Config7 = env->cpu_model->CP0_Config7;
19985 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
19986 << env->cpu_model->CP0_LLAddr_shift;
19987 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
19988 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
19989 env->CCRes = env->cpu_model->CCRes;
19990 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
19991 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
19992 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
19993 env->current_tc = 0;
19994 env->SEGBITS = env->cpu_model->SEGBITS;
19995 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
19996 #if defined(TARGET_MIPS64)
19997 if (env->cpu_model->insn_flags & ISA_MIPS3) {
19998 env->SEGMask |= 3ULL << 62;
20000 #endif
20001 env->PABITS = env->cpu_model->PABITS;
20002 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
20003 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
20004 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
20005 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
20006 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
20007 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
20008 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
20009 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
20010 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
20011 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
20012 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
20013 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
20014 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
20015 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
20016 env->msair = env->cpu_model->MSAIR;
20017 env->insn_flags = env->cpu_model->insn_flags;
20019 #if defined(CONFIG_USER_ONLY)
20020 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
20021 # ifdef TARGET_MIPS64
20022 /* Enable 64-bit register mode. */
20023 env->CP0_Status |= (1 << CP0St_PX);
20024 # endif
20025 # ifdef TARGET_ABI_MIPSN64
20026 /* Enable 64-bit address mode. */
20027 env->CP0_Status |= (1 << CP0St_UX);
20028 # endif
20029 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
20030 hardware registers. */
20031 env->CP0_HWREna |= 0x0000000F;
20032 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
20033 env->CP0_Status |= (1 << CP0St_CU1);
20035 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
20036 env->CP0_Status |= (1 << CP0St_MX);
20038 # if defined(TARGET_MIPS64)
20039 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
20040 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
20041 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
20042 env->CP0_Status |= (1 << CP0St_FR);
20044 # endif
20045 #else
20046 if (env->hflags & MIPS_HFLAG_BMASK) {
20047 /* If the exception was raised from a delay slot,
20048 come back to the jump. */
20049 env->CP0_ErrorEPC = (env->active_tc.PC
20050 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
20051 } else {
20052 env->CP0_ErrorEPC = env->active_tc.PC;
20054 env->active_tc.PC = (int32_t)0xBFC00000;
20055 env->CP0_Random = env->tlb->nb_tlb - 1;
20056 env->tlb->tlb_in_use = env->tlb->nb_tlb;
20057 env->CP0_Wired = 0;
20058 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
20059 env->CP0_EBase = (cs->cpu_index & 0x3FF);
20060 if (kvm_enabled()) {
20061 env->CP0_EBase |= 0x40000000;
20062 } else {
20063 env->CP0_EBase |= 0x80000000;
20065 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
20066 /* vectored interrupts not implemented, timer on int 7,
20067 no performance counters. */
20068 env->CP0_IntCtl = 0xe0000000;
20070 int i;
20072 for (i = 0; i < 7; i++) {
20073 env->CP0_WatchLo[i] = 0;
20074 env->CP0_WatchHi[i] = 0x80000000;
20076 env->CP0_WatchLo[7] = 0;
20077 env->CP0_WatchHi[7] = 0;
20079 /* Count register increments in debug mode, EJTAG version 1 */
20080 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
20082 cpu_mips_store_count(env, 1);
20084 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
20085 int i;
20087 /* Only TC0 on VPE 0 starts as active. */
20088 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
20089 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
20090 env->tcs[i].CP0_TCHalt = 1;
20092 env->active_tc.CP0_TCHalt = 1;
20093 cs->halted = 1;
20095 if (cs->cpu_index == 0) {
20096 /* VPE0 starts up enabled. */
20097 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
20098 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
20100 /* TC0 starts up unhalted. */
20101 cs->halted = 0;
20102 env->active_tc.CP0_TCHalt = 0;
20103 env->tcs[0].CP0_TCHalt = 0;
20104 /* With thread 0 active. */
20105 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
20106 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
20109 #endif
20110 if ((env->insn_flags & ISA_MIPS32R6) &&
20111 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
20112 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
20113 env->CP0_Status |= (1 << CP0St_FR);
20116 /* MSA */
20117 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
20118 msa_reset(env);
20121 compute_hflags(env);
20122 restore_rounding_mode(env);
20123 restore_flush_mode(env);
20124 restore_pamask(env);
20125 cs->exception_index = EXCP_NONE;
20127 if (semihosting_get_argc()) {
20128 /* UHI interface can be used to obtain argc and argv */
20129 env->active_tc.gpr[4] = -1;
20133 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
20134 target_ulong *data)
20136 env->active_tc.PC = data[0];
20137 env->hflags &= ~MIPS_HFLAG_BMASK;
20138 env->hflags |= data[1];
20139 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
20140 case MIPS_HFLAG_BR:
20141 break;
20142 case MIPS_HFLAG_BC:
20143 case MIPS_HFLAG_BL:
20144 case MIPS_HFLAG_B:
20145 env->btarget = data[2];
20146 break;