m68k: is_mem is useless
[qemu.git] / target-mips / translate.c
blob73028572c940c865532c14c14f5438494385dcdf
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "cpu.h"
25 #include "disas/disas.h"
26 #include "tcg-op.h"
27 #include "exec/cpu_ldst.h"
29 #include "exec/helper-proto.h"
30 #include "exec/helper-gen.h"
31 #include "sysemu/kvm.h"
32 #include "exec/semihost.h"
34 #include "trace-tcg.h"
37 #define MIPS_DEBUG_DISAS 0
38 //#define MIPS_DEBUG_SIGN_EXTENSIONS
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_SYNCI = (0x1F << 16) | OPC_REGIMM,
330 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
331 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
334 /* Special2 opcodes */
335 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
337 enum {
338 /* Multiply & xxx operations */
339 OPC_MADD = 0x00 | OPC_SPECIAL2,
340 OPC_MADDU = 0x01 | OPC_SPECIAL2,
341 OPC_MUL = 0x02 | OPC_SPECIAL2,
342 OPC_MSUB = 0x04 | OPC_SPECIAL2,
343 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
344 /* Loongson 2F */
345 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
346 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
347 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
348 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
349 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
350 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
351 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
352 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
353 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
354 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
355 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
356 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
357 /* Misc */
358 OPC_CLZ = 0x20 | OPC_SPECIAL2,
359 OPC_CLO = 0x21 | OPC_SPECIAL2,
360 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
361 OPC_DCLO = 0x25 | OPC_SPECIAL2,
362 /* Special */
363 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
366 /* Special3 opcodes */
367 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
369 enum {
370 OPC_EXT = 0x00 | OPC_SPECIAL3,
371 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
372 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
373 OPC_DEXT = 0x03 | OPC_SPECIAL3,
374 OPC_INS = 0x04 | OPC_SPECIAL3,
375 OPC_DINSM = 0x05 | OPC_SPECIAL3,
376 OPC_DINSU = 0x06 | OPC_SPECIAL3,
377 OPC_DINS = 0x07 | OPC_SPECIAL3,
378 OPC_FORK = 0x08 | OPC_SPECIAL3,
379 OPC_YIELD = 0x09 | OPC_SPECIAL3,
380 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
381 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
382 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
384 /* Loongson 2E */
385 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
386 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
387 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
388 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
389 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
390 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
391 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
392 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
393 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
394 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
395 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
396 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
398 /* MIPS DSP Load */
399 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
400 /* MIPS DSP Arithmetic */
401 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
402 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
403 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
404 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
405 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
406 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
407 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
408 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
409 /* MIPS DSP GPR-Based Shift Sub-class */
410 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
411 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
412 /* MIPS DSP Multiply Sub-class insns */
413 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
414 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
415 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
416 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
417 /* DSP Bit/Manipulation Sub-class */
418 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
419 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
420 /* MIPS DSP Append Sub-class */
421 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
422 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
423 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
424 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
425 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
427 /* R6 */
428 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
429 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
430 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
431 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
432 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
433 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
436 /* BSHFL opcodes */
437 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
439 enum {
440 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
441 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
442 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
443 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
444 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
445 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
448 /* DBSHFL opcodes */
449 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
451 enum {
452 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
453 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
454 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
455 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
456 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
459 /* MIPS DSP REGIMM opcodes */
460 enum {
461 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
462 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
465 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
466 /* MIPS DSP Load */
467 enum {
468 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
469 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
470 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
471 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
474 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
475 enum {
476 /* MIPS DSP Arithmetic Sub-class */
477 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
478 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
479 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
480 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
481 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
482 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
483 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
484 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
485 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
486 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
487 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
488 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
489 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
490 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
491 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
492 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
493 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
494 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
495 /* MIPS DSP Multiply Sub-class insns */
496 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
497 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
498 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
499 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
500 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
501 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
504 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
505 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
506 enum {
507 /* MIPS DSP Arithmetic Sub-class */
508 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
509 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
510 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
511 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
512 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
513 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
514 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
515 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
516 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
517 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
518 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
519 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
520 /* MIPS DSP Multiply Sub-class insns */
521 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
522 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
523 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
524 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
527 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
528 enum {
529 /* MIPS DSP Arithmetic Sub-class */
530 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
531 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
532 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
533 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
534 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
535 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
536 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
537 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
538 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
539 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
540 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
541 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
542 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
543 /* DSP Bit/Manipulation Sub-class */
544 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
545 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
546 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
547 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
548 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
551 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
552 enum {
553 /* MIPS DSP Arithmetic Sub-class */
554 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
555 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
556 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
557 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
558 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
559 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
560 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
561 /* DSP Compare-Pick Sub-class */
562 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
563 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
564 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
565 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
566 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
567 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
568 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
569 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
570 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
571 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
572 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
573 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
574 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
575 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
576 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
579 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
580 enum {
581 /* MIPS DSP GPR-Based Shift Sub-class */
582 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
583 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
584 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
585 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
586 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
587 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
588 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
589 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
590 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
591 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
592 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
593 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
594 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
595 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
596 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
597 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
598 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
599 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
600 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
601 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
602 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
603 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
606 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
607 enum {
608 /* MIPS DSP Multiply Sub-class insns */
609 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
610 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
611 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
612 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
613 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
614 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
615 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
616 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
617 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
618 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
619 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
620 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
621 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
622 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
623 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
624 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
625 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
626 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
627 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
628 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
629 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
630 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
633 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
634 enum {
635 /* DSP Bit/Manipulation Sub-class */
636 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
639 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
640 enum {
641 /* MIPS DSP Append Sub-class */
642 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
643 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
644 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
647 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
648 enum {
649 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
650 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
651 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
652 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
653 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
654 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
655 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
656 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
657 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
658 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
659 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
660 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
661 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
662 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
663 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
664 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
665 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
666 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
669 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
670 enum {
671 /* MIPS DSP Arithmetic Sub-class */
672 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
673 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
674 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
675 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
676 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
677 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
678 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
679 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
680 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
681 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
682 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
683 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
684 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
685 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
686 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
687 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
688 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
689 /* DSP Bit/Manipulation Sub-class */
690 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
691 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
692 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
693 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
694 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
695 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
698 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
699 enum {
700 /* MIPS DSP Multiply Sub-class insns */
701 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
702 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
703 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
704 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
705 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
706 /* MIPS DSP Arithmetic Sub-class */
707 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
708 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
709 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
710 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
711 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
712 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
713 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
714 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
715 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
716 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
717 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
718 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
719 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
720 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
721 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
722 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
723 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
724 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
725 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
726 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
727 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
730 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
731 enum {
732 /* DSP Compare-Pick Sub-class */
733 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
734 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
735 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
736 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
737 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
738 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
739 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
740 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
741 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
742 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
743 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
744 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
745 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
746 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
747 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
748 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
749 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
750 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
751 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
752 /* MIPS DSP Arithmetic Sub-class */
753 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
754 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
755 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
756 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
763 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
764 enum {
765 /* DSP Append Sub-class */
766 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
767 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
768 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
769 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
772 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
773 enum {
774 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
775 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
776 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
777 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
778 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
779 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
780 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
781 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
782 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
783 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
784 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
785 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
786 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
787 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
788 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
789 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
790 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
791 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
792 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
793 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
794 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
795 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
798 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
799 enum {
800 /* DSP Bit/Manipulation Sub-class */
801 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
804 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
805 enum {
806 /* MIPS DSP Multiply Sub-class insns */
807 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
808 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
809 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
810 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
811 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
812 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
813 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
814 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
815 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
816 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
817 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
818 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
819 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
820 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
821 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
822 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
823 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
824 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
825 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
826 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
827 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
828 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
829 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
830 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
835 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
836 enum {
837 /* MIPS DSP GPR-Based Shift Sub-class */
838 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
839 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
840 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
841 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
842 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
843 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
844 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
845 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
846 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
847 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
848 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
849 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
850 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
851 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
852 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
853 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
854 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
855 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
856 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
857 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
858 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
859 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
860 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
861 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
866 /* Coprocessor 0 (rs field) */
867 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
869 enum {
870 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
871 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
872 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
873 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
874 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
875 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
876 OPC_MFTR = (0x08 << 21) | OPC_CP0,
877 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
878 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
879 OPC_MTTR = (0x0C << 21) | OPC_CP0,
880 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
881 OPC_C0 = (0x10 << 21) | OPC_CP0,
882 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
883 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
886 /* MFMC0 opcodes */
887 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
889 enum {
890 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
891 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
892 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
893 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
894 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
895 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
898 /* Coprocessor 0 (with rs == C0) */
899 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
901 enum {
902 OPC_TLBR = 0x01 | OPC_C0,
903 OPC_TLBWI = 0x02 | OPC_C0,
904 OPC_TLBINV = 0x03 | OPC_C0,
905 OPC_TLBINVF = 0x04 | OPC_C0,
906 OPC_TLBWR = 0x06 | OPC_C0,
907 OPC_TLBP = 0x08 | OPC_C0,
908 OPC_RFE = 0x10 | OPC_C0,
909 OPC_ERET = 0x18 | OPC_C0,
910 OPC_DERET = 0x1F | OPC_C0,
911 OPC_WAIT = 0x20 | OPC_C0,
914 /* Coprocessor 1 (rs field) */
915 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
917 /* Values for the fmt field in FP instructions */
918 enum {
919 /* 0 - 15 are reserved */
920 FMT_S = 16, /* single fp */
921 FMT_D = 17, /* double fp */
922 FMT_E = 18, /* extended fp */
923 FMT_Q = 19, /* quad fp */
924 FMT_W = 20, /* 32-bit fixed */
925 FMT_L = 21, /* 64-bit fixed */
926 FMT_PS = 22, /* paired single fp */
927 /* 23 - 31 are reserved */
930 enum {
931 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
932 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
933 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
934 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
935 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
936 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
937 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
938 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
939 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
940 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
941 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
942 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
943 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
944 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
945 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
946 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
947 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
948 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
949 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
950 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
951 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
952 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
953 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
954 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
955 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
956 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
957 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
958 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
959 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
960 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
963 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
964 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
966 enum {
967 OPC_BC1F = (0x00 << 16) | OPC_BC1,
968 OPC_BC1T = (0x01 << 16) | OPC_BC1,
969 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
970 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
973 enum {
974 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
975 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
978 enum {
979 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
980 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
983 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
985 enum {
986 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
987 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
988 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
989 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
990 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
991 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
992 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
993 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
994 OPC_BC2 = (0x08 << 21) | OPC_CP2,
995 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
996 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
999 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1001 enum {
1002 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1003 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1004 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1005 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1006 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1007 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1008 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1009 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1011 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1012 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1013 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1014 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1015 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1016 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1018 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1020 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1021 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1022 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1023 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1024 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1025 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1026 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1027 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1029 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1030 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1031 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1032 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1033 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1034 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1035 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1036 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1038 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1039 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1040 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1041 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1042 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1043 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1045 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1046 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1047 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1048 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1049 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1050 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1052 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1053 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1054 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1055 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1056 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1057 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1059 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1060 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1061 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1062 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1063 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1064 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1066 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1067 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1068 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1069 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1070 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1071 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1073 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1074 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1075 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1076 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1077 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1078 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1080 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1081 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1082 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1083 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1084 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1085 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1087 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1088 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1089 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1090 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1091 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1092 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1096 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1098 enum {
1099 OPC_LWXC1 = 0x00 | OPC_CP3,
1100 OPC_LDXC1 = 0x01 | OPC_CP3,
1101 OPC_LUXC1 = 0x05 | OPC_CP3,
1102 OPC_SWXC1 = 0x08 | OPC_CP3,
1103 OPC_SDXC1 = 0x09 | OPC_CP3,
1104 OPC_SUXC1 = 0x0D | OPC_CP3,
1105 OPC_PREFX = 0x0F | OPC_CP3,
1106 OPC_ALNV_PS = 0x1E | OPC_CP3,
1107 OPC_MADD_S = 0x20 | OPC_CP3,
1108 OPC_MADD_D = 0x21 | OPC_CP3,
1109 OPC_MADD_PS = 0x26 | OPC_CP3,
1110 OPC_MSUB_S = 0x28 | OPC_CP3,
1111 OPC_MSUB_D = 0x29 | OPC_CP3,
1112 OPC_MSUB_PS = 0x2E | OPC_CP3,
1113 OPC_NMADD_S = 0x30 | OPC_CP3,
1114 OPC_NMADD_D = 0x31 | OPC_CP3,
1115 OPC_NMADD_PS= 0x36 | OPC_CP3,
1116 OPC_NMSUB_S = 0x38 | OPC_CP3,
1117 OPC_NMSUB_D = 0x39 | OPC_CP3,
1118 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1121 /* MSA Opcodes */
1122 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1123 enum {
1124 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1125 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1126 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1127 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1128 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1129 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1130 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1131 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1132 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1133 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1134 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1135 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1136 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1137 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1138 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1139 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1140 OPC_MSA_ELM = 0x19 | OPC_MSA,
1141 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1142 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1143 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1144 OPC_MSA_VEC = 0x1E | OPC_MSA,
1146 /* MI10 instruction */
1147 OPC_LD_B = (0x20) | OPC_MSA,
1148 OPC_LD_H = (0x21) | OPC_MSA,
1149 OPC_LD_W = (0x22) | OPC_MSA,
1150 OPC_LD_D = (0x23) | OPC_MSA,
1151 OPC_ST_B = (0x24) | OPC_MSA,
1152 OPC_ST_H = (0x25) | OPC_MSA,
1153 OPC_ST_W = (0x26) | OPC_MSA,
1154 OPC_ST_D = (0x27) | OPC_MSA,
1157 enum {
1158 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1159 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1160 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1161 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1162 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1163 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1164 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1165 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1166 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1167 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1168 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1169 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1170 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1172 /* I8 instruction */
1173 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1174 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1175 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1176 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1177 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1178 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1179 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1180 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1181 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1182 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1184 /* VEC/2R/2RF instruction */
1185 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1186 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1187 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1188 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1189 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1190 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1191 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1193 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1194 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1196 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1197 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1198 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1199 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1200 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1202 /* 2RF instruction df(bit 16) = _w, _d */
1203 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1204 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1205 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1206 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1207 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1208 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1209 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1210 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1211 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1212 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1213 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1214 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1215 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1216 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1217 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1218 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1220 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1221 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1222 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1223 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1224 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1225 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1226 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1227 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1228 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1229 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1230 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1231 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1232 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1233 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1234 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1235 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1236 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1237 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1238 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1239 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1240 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1241 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1242 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1243 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1244 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1245 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1246 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1247 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1248 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1249 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1250 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1251 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1252 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1253 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1254 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1255 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1256 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1257 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1258 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1259 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1260 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1261 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1262 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1263 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1264 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1265 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1266 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1267 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1268 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1269 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1270 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1271 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1272 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1273 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1274 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1275 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1276 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1277 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1278 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1279 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1280 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1281 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1282 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1283 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1285 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1286 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1287 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1288 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1289 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1290 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1291 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1292 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1293 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1294 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1296 /* 3RF instruction _df(bit 21) = _w, _d */
1297 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1298 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1299 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1300 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1301 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1302 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1303 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1304 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1305 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1306 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1307 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1308 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1309 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1310 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1311 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1312 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1313 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1314 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1315 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1316 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1317 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1318 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1319 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1320 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1321 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1322 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1323 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1324 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1325 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1326 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1327 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1328 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1329 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1330 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1331 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1332 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1333 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1334 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1335 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1336 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1337 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1339 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1340 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1341 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1342 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1343 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1344 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1345 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1346 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1347 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1348 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1349 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1350 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1351 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1354 /* global register indices */
1355 static TCGv_ptr cpu_env;
1356 static TCGv cpu_gpr[32], cpu_PC;
1357 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1358 static TCGv cpu_dspctrl, btarget, bcond;
1359 static TCGv_i32 hflags;
1360 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1361 static TCGv_i64 fpu_f64[32];
1362 static TCGv_i64 msa_wr_d[64];
1364 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
1365 static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
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 } DisasContext;
1436 enum {
1437 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1438 * exception condition */
1439 BS_STOP = 1, /* We want to stop translation for any reason */
1440 BS_BRANCH = 2, /* We reached a branch condition */
1441 BS_EXCP = 3, /* We reached an exception condition */
1444 static const char * const regnames[] = {
1445 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1446 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1447 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1448 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1451 static const char * const regnames_HI[] = {
1452 "HI0", "HI1", "HI2", "HI3",
1455 static const char * const regnames_LO[] = {
1456 "LO0", "LO1", "LO2", "LO3",
1459 static const char * const fregnames[] = {
1460 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1461 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1462 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1463 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1466 static const char * const msaregnames[] = {
1467 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1468 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1469 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1470 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1471 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1472 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1473 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1474 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1475 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1476 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1477 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1478 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1479 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1480 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1481 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1482 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1485 #define MIPS_DEBUG(fmt, ...) \
1486 do { \
1487 if (MIPS_DEBUG_DISAS) { \
1488 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1489 TARGET_FMT_lx ": %08x " fmt "\n", \
1490 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
1492 } while (0)
1494 #define LOG_DISAS(...) \
1495 do { \
1496 if (MIPS_DEBUG_DISAS) { \
1497 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1499 } while (0)
1501 #define MIPS_INVAL(op) \
1502 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
1503 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
1505 /* General purpose registers moves. */
1506 static inline void gen_load_gpr (TCGv t, int reg)
1508 if (reg == 0)
1509 tcg_gen_movi_tl(t, 0);
1510 else
1511 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1514 static inline void gen_store_gpr (TCGv t, int reg)
1516 if (reg != 0)
1517 tcg_gen_mov_tl(cpu_gpr[reg], t);
1520 /* Moves to/from shadow registers. */
1521 static inline void gen_load_srsgpr (int from, int to)
1523 TCGv t0 = tcg_temp_new();
1525 if (from == 0)
1526 tcg_gen_movi_tl(t0, 0);
1527 else {
1528 TCGv_i32 t2 = tcg_temp_new_i32();
1529 TCGv_ptr addr = tcg_temp_new_ptr();
1531 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1532 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1533 tcg_gen_andi_i32(t2, t2, 0xf);
1534 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1535 tcg_gen_ext_i32_ptr(addr, t2);
1536 tcg_gen_add_ptr(addr, cpu_env, addr);
1538 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1539 tcg_temp_free_ptr(addr);
1540 tcg_temp_free_i32(t2);
1542 gen_store_gpr(t0, to);
1543 tcg_temp_free(t0);
1546 static inline void gen_store_srsgpr (int from, int to)
1548 if (to != 0) {
1549 TCGv t0 = tcg_temp_new();
1550 TCGv_i32 t2 = tcg_temp_new_i32();
1551 TCGv_ptr addr = tcg_temp_new_ptr();
1553 gen_load_gpr(t0, from);
1554 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1555 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1556 tcg_gen_andi_i32(t2, t2, 0xf);
1557 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1558 tcg_gen_ext_i32_ptr(addr, t2);
1559 tcg_gen_add_ptr(addr, cpu_env, addr);
1561 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1562 tcg_temp_free_ptr(addr);
1563 tcg_temp_free_i32(t2);
1564 tcg_temp_free(t0);
1568 /* Tests */
1569 static inline void gen_save_pc(target_ulong pc)
1571 tcg_gen_movi_tl(cpu_PC, pc);
1574 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1576 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1577 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1578 gen_save_pc(ctx->pc);
1579 ctx->saved_pc = ctx->pc;
1581 if (ctx->hflags != ctx->saved_hflags) {
1582 tcg_gen_movi_i32(hflags, ctx->hflags);
1583 ctx->saved_hflags = ctx->hflags;
1584 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1585 case MIPS_HFLAG_BR:
1586 break;
1587 case MIPS_HFLAG_BC:
1588 case MIPS_HFLAG_BL:
1589 case MIPS_HFLAG_B:
1590 tcg_gen_movi_tl(btarget, ctx->btarget);
1591 break;
1596 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1598 ctx->saved_hflags = ctx->hflags;
1599 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1600 case MIPS_HFLAG_BR:
1601 break;
1602 case MIPS_HFLAG_BC:
1603 case MIPS_HFLAG_BL:
1604 case MIPS_HFLAG_B:
1605 ctx->btarget = env->btarget;
1606 break;
1610 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1612 TCGv_i32 texcp = tcg_const_i32(excp);
1613 TCGv_i32 terr = tcg_const_i32(err);
1614 save_cpu_state(ctx, 1);
1615 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1616 tcg_temp_free_i32(terr);
1617 tcg_temp_free_i32(texcp);
1620 static inline void generate_exception(DisasContext *ctx, int excp)
1622 save_cpu_state(ctx, 1);
1623 gen_helper_0e0i(raise_exception, excp);
1626 /* Floating point register moves. */
1627 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1629 if (ctx->hflags & MIPS_HFLAG_FRE) {
1630 generate_exception(ctx, EXCP_RI);
1632 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
1635 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1637 TCGv_i64 t64;
1638 if (ctx->hflags & MIPS_HFLAG_FRE) {
1639 generate_exception(ctx, EXCP_RI);
1641 t64 = tcg_temp_new_i64();
1642 tcg_gen_extu_i32_i64(t64, t);
1643 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1644 tcg_temp_free_i64(t64);
1647 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1649 if (ctx->hflags & MIPS_HFLAG_F64) {
1650 TCGv_i64 t64 = tcg_temp_new_i64();
1651 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
1652 tcg_gen_trunc_i64_i32(t, t64);
1653 tcg_temp_free_i64(t64);
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 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
1730 #if defined(TARGET_MIPS64)
1731 tcg_gen_ext32s_tl(ret, arg);
1732 #else
1733 tcg_gen_trunc_i64_tl(ret, arg);
1734 #endif
1737 static inline void check_cp0_enabled(DisasContext *ctx)
1739 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1740 generate_exception_err(ctx, EXCP_CpU, 0);
1743 static inline void check_cp1_enabled(DisasContext *ctx)
1745 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1746 generate_exception_err(ctx, EXCP_CpU, 1);
1749 /* Verify that the processor is running with COP1X instructions enabled.
1750 This is associated with the nabla symbol in the MIPS32 and MIPS64
1751 opcode tables. */
1753 static inline void check_cop1x(DisasContext *ctx)
1755 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1756 generate_exception(ctx, EXCP_RI);
1759 /* Verify that the processor is running with 64-bit floating-point
1760 operations enabled. */
1762 static inline void check_cp1_64bitmode(DisasContext *ctx)
1764 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1765 generate_exception(ctx, EXCP_RI);
1769 * Verify if floating point register is valid; an operation is not defined
1770 * if bit 0 of any register specification is set and the FR bit in the
1771 * Status register equals zero, since the register numbers specify an
1772 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1773 * in the Status register equals one, both even and odd register numbers
1774 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1776 * Multiple 64 bit wide registers can be checked by calling
1777 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1779 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1781 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1782 generate_exception(ctx, EXCP_RI);
1785 /* Verify that the processor is running with DSP instructions enabled.
1786 This is enabled by CP0 Status register MX(24) bit.
1789 static inline void check_dsp(DisasContext *ctx)
1791 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1792 if (ctx->insn_flags & ASE_DSP) {
1793 generate_exception(ctx, EXCP_DSPDIS);
1794 } else {
1795 generate_exception(ctx, EXCP_RI);
1800 static inline void check_dspr2(DisasContext *ctx)
1802 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1803 if (ctx->insn_flags & ASE_DSP) {
1804 generate_exception(ctx, EXCP_DSPDIS);
1805 } else {
1806 generate_exception(ctx, EXCP_RI);
1811 /* This code generates a "reserved instruction" exception if the
1812 CPU does not support the instruction set corresponding to flags. */
1813 static inline void check_insn(DisasContext *ctx, int flags)
1815 if (unlikely(!(ctx->insn_flags & flags))) {
1816 generate_exception(ctx, EXCP_RI);
1820 /* This code generates a "reserved instruction" exception if the
1821 CPU has corresponding flag set which indicates that the instruction
1822 has been removed. */
1823 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1825 if (unlikely(ctx->insn_flags & flags)) {
1826 generate_exception(ctx, EXCP_RI);
1830 /* This code generates a "reserved instruction" exception if the
1831 CPU does not support 64-bit paired-single (PS) floating point data type */
1832 static inline void check_ps(DisasContext *ctx)
1834 if (unlikely(!ctx->ps)) {
1835 generate_exception(ctx, EXCP_RI);
1837 check_cp1_64bitmode(ctx);
1840 #ifdef TARGET_MIPS64
1841 /* This code generates a "reserved instruction" exception if 64-bit
1842 instructions are not enabled. */
1843 static inline void check_mips_64(DisasContext *ctx)
1845 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1846 generate_exception(ctx, EXCP_RI);
1848 #endif
1850 #ifndef CONFIG_USER_ONLY
1851 static inline void check_mvh(DisasContext *ctx)
1853 if (unlikely(!ctx->mvh)) {
1854 generate_exception(ctx, EXCP_RI);
1857 #endif
1859 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1860 calling interface for 32 and 64-bit FPRs. No sense in changing
1861 all callers for gen_load_fpr32 when we need the CTX parameter for
1862 this one use. */
1863 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1864 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1865 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1866 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1867 int ft, int fs, int cc) \
1869 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1870 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1871 switch (ifmt) { \
1872 case FMT_PS: \
1873 check_ps(ctx); \
1874 break; \
1875 case FMT_D: \
1876 if (abs) { \
1877 check_cop1x(ctx); \
1879 check_cp1_registers(ctx, fs | ft); \
1880 break; \
1881 case FMT_S: \
1882 if (abs) { \
1883 check_cop1x(ctx); \
1885 break; \
1887 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1888 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1889 switch (n) { \
1890 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1891 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1892 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1893 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1894 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1895 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1896 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1897 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1898 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1899 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1900 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1901 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1902 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1903 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1904 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1905 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1906 default: abort(); \
1908 tcg_temp_free_i##bits (fp0); \
1909 tcg_temp_free_i##bits (fp1); \
1912 FOP_CONDS(, 0, d, FMT_D, 64)
1913 FOP_CONDS(abs, 1, d, FMT_D, 64)
1914 FOP_CONDS(, 0, s, FMT_S, 32)
1915 FOP_CONDS(abs, 1, s, FMT_S, 32)
1916 FOP_CONDS(, 0, ps, FMT_PS, 64)
1917 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1918 #undef FOP_CONDS
1920 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1921 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1922 int ft, int fs, int fd) \
1924 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1925 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1926 if (ifmt == FMT_D) { \
1927 check_cp1_registers(ctx, fs | ft | fd); \
1929 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1930 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1931 switch (n) { \
1932 case 0: \
1933 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1934 break; \
1935 case 1: \
1936 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1937 break; \
1938 case 2: \
1939 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1940 break; \
1941 case 3: \
1942 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1943 break; \
1944 case 4: \
1945 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1946 break; \
1947 case 5: \
1948 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1949 break; \
1950 case 6: \
1951 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1952 break; \
1953 case 7: \
1954 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1955 break; \
1956 case 8: \
1957 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1958 break; \
1959 case 9: \
1960 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1961 break; \
1962 case 10: \
1963 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1964 break; \
1965 case 11: \
1966 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1967 break; \
1968 case 12: \
1969 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1970 break; \
1971 case 13: \
1972 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1973 break; \
1974 case 14: \
1975 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1976 break; \
1977 case 15: \
1978 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1979 break; \
1980 case 17: \
1981 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1982 break; \
1983 case 18: \
1984 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1985 break; \
1986 case 19: \
1987 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1988 break; \
1989 case 25: \
1990 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1991 break; \
1992 case 26: \
1993 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
1994 break; \
1995 case 27: \
1996 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
1997 break; \
1998 default: \
1999 abort(); \
2001 STORE; \
2002 tcg_temp_free_i ## bits (fp0); \
2003 tcg_temp_free_i ## bits (fp1); \
2006 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2007 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2008 #undef FOP_CONDNS
2009 #undef gen_ldcmp_fpr32
2010 #undef gen_ldcmp_fpr64
2012 /* load/store instructions. */
2013 #ifdef CONFIG_USER_ONLY
2014 #define OP_LD_ATOMIC(insn,fname) \
2015 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2017 TCGv t0 = tcg_temp_new(); \
2018 tcg_gen_mov_tl(t0, arg1); \
2019 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2020 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2021 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2022 tcg_temp_free(t0); \
2024 #else
2025 #define OP_LD_ATOMIC(insn,fname) \
2026 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2028 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
2030 #endif
2031 OP_LD_ATOMIC(ll,ld32s);
2032 #if defined(TARGET_MIPS64)
2033 OP_LD_ATOMIC(lld,ld64);
2034 #endif
2035 #undef OP_LD_ATOMIC
2037 #ifdef CONFIG_USER_ONLY
2038 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2039 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2041 TCGv t0 = tcg_temp_new(); \
2042 TCGLabel *l1 = gen_new_label(); \
2043 TCGLabel *l2 = gen_new_label(); \
2045 tcg_gen_andi_tl(t0, arg2, almask); \
2046 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2047 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2048 generate_exception(ctx, EXCP_AdES); \
2049 gen_set_label(l1); \
2050 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2051 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2052 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2053 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2054 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2055 gen_helper_0e0i(raise_exception, EXCP_SC); \
2056 gen_set_label(l2); \
2057 tcg_gen_movi_tl(t0, 0); \
2058 gen_store_gpr(t0, rt); \
2059 tcg_temp_free(t0); \
2061 #else
2062 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2063 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2065 TCGv t0 = tcg_temp_new(); \
2066 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
2067 gen_store_gpr(t0, rt); \
2068 tcg_temp_free(t0); \
2070 #endif
2071 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2072 #if defined(TARGET_MIPS64)
2073 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2074 #endif
2075 #undef OP_ST_ATOMIC
2077 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2078 int base, int16_t offset)
2080 if (base == 0) {
2081 tcg_gen_movi_tl(addr, offset);
2082 } else if (offset == 0) {
2083 gen_load_gpr(addr, base);
2084 } else {
2085 tcg_gen_movi_tl(addr, offset);
2086 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2090 static target_ulong pc_relative_pc (DisasContext *ctx)
2092 target_ulong pc = ctx->pc;
2094 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2095 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2097 pc -= branch_bytes;
2100 pc &= ~(target_ulong)3;
2101 return pc;
2104 /* Load */
2105 static void gen_ld(DisasContext *ctx, uint32_t opc,
2106 int rt, int base, int16_t offset)
2108 const char *opn = "ld";
2109 TCGv t0, t1, t2;
2111 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2112 /* Loongson CPU uses a load to zero register for prefetch.
2113 We emulate it as a NOP. On other CPU we must perform the
2114 actual memory access. */
2115 MIPS_DEBUG("NOP");
2116 return;
2119 t0 = tcg_temp_new();
2120 gen_base_offset_addr(ctx, t0, base, offset);
2122 switch (opc) {
2123 #if defined(TARGET_MIPS64)
2124 case OPC_LWU:
2125 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL |
2126 ctx->default_tcg_memop_mask);
2127 gen_store_gpr(t0, rt);
2128 opn = "lwu";
2129 break;
2130 case OPC_LD:
2131 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
2132 ctx->default_tcg_memop_mask);
2133 gen_store_gpr(t0, rt);
2134 opn = "ld";
2135 break;
2136 case OPC_LLD:
2137 case R6_OPC_LLD:
2138 save_cpu_state(ctx, 1);
2139 op_ld_lld(t0, t0, ctx);
2140 gen_store_gpr(t0, rt);
2141 opn = "lld";
2142 break;
2143 case OPC_LDL:
2144 t1 = tcg_temp_new();
2145 tcg_gen_andi_tl(t1, t0, 7);
2146 #ifndef TARGET_WORDS_BIGENDIAN
2147 tcg_gen_xori_tl(t1, t1, 7);
2148 #endif
2149 tcg_gen_shli_tl(t1, t1, 3);
2150 tcg_gen_andi_tl(t0, t0, ~7);
2151 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2152 tcg_gen_shl_tl(t0, t0, t1);
2153 tcg_gen_xori_tl(t1, t1, 63);
2154 t2 = tcg_const_tl(0x7fffffffffffffffull);
2155 tcg_gen_shr_tl(t2, t2, t1);
2156 gen_load_gpr(t1, rt);
2157 tcg_gen_and_tl(t1, t1, t2);
2158 tcg_temp_free(t2);
2159 tcg_gen_or_tl(t0, t0, t1);
2160 tcg_temp_free(t1);
2161 gen_store_gpr(t0, rt);
2162 opn = "ldl";
2163 break;
2164 case OPC_LDR:
2165 t1 = tcg_temp_new();
2166 tcg_gen_andi_tl(t1, t0, 7);
2167 #ifdef TARGET_WORDS_BIGENDIAN
2168 tcg_gen_xori_tl(t1, t1, 7);
2169 #endif
2170 tcg_gen_shli_tl(t1, t1, 3);
2171 tcg_gen_andi_tl(t0, t0, ~7);
2172 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2173 tcg_gen_shr_tl(t0, t0, t1);
2174 tcg_gen_xori_tl(t1, t1, 63);
2175 t2 = tcg_const_tl(0xfffffffffffffffeull);
2176 tcg_gen_shl_tl(t2, t2, t1);
2177 gen_load_gpr(t1, rt);
2178 tcg_gen_and_tl(t1, t1, t2);
2179 tcg_temp_free(t2);
2180 tcg_gen_or_tl(t0, t0, t1);
2181 tcg_temp_free(t1);
2182 gen_store_gpr(t0, rt);
2183 opn = "ldr";
2184 break;
2185 case OPC_LDPC:
2186 t1 = tcg_const_tl(pc_relative_pc(ctx));
2187 gen_op_addr_add(ctx, t0, t0, t1);
2188 tcg_temp_free(t1);
2189 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2190 gen_store_gpr(t0, rt);
2191 opn = "ldpc";
2192 break;
2193 #endif
2194 case OPC_LWPC:
2195 t1 = tcg_const_tl(pc_relative_pc(ctx));
2196 gen_op_addr_add(ctx, t0, t0, t1);
2197 tcg_temp_free(t1);
2198 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2199 gen_store_gpr(t0, rt);
2200 opn = "lwpc";
2201 break;
2202 case OPC_LW:
2203 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
2204 ctx->default_tcg_memop_mask);
2205 gen_store_gpr(t0, rt);
2206 opn = "lw";
2207 break;
2208 case OPC_LH:
2209 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
2210 ctx->default_tcg_memop_mask);
2211 gen_store_gpr(t0, rt);
2212 opn = "lh";
2213 break;
2214 case OPC_LHU:
2215 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW |
2216 ctx->default_tcg_memop_mask);
2217 gen_store_gpr(t0, rt);
2218 opn = "lhu";
2219 break;
2220 case OPC_LB:
2221 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
2222 gen_store_gpr(t0, rt);
2223 opn = "lb";
2224 break;
2225 case OPC_LBU:
2226 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
2227 gen_store_gpr(t0, rt);
2228 opn = "lbu";
2229 break;
2230 case OPC_LWL:
2231 t1 = tcg_temp_new();
2232 tcg_gen_andi_tl(t1, t0, 3);
2233 #ifndef TARGET_WORDS_BIGENDIAN
2234 tcg_gen_xori_tl(t1, t1, 3);
2235 #endif
2236 tcg_gen_shli_tl(t1, t1, 3);
2237 tcg_gen_andi_tl(t0, t0, ~3);
2238 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2239 tcg_gen_shl_tl(t0, t0, t1);
2240 tcg_gen_xori_tl(t1, t1, 31);
2241 t2 = tcg_const_tl(0x7fffffffull);
2242 tcg_gen_shr_tl(t2, t2, t1);
2243 gen_load_gpr(t1, rt);
2244 tcg_gen_and_tl(t1, t1, t2);
2245 tcg_temp_free(t2);
2246 tcg_gen_or_tl(t0, t0, t1);
2247 tcg_temp_free(t1);
2248 tcg_gen_ext32s_tl(t0, t0);
2249 gen_store_gpr(t0, rt);
2250 opn = "lwl";
2251 break;
2252 case OPC_LWR:
2253 t1 = tcg_temp_new();
2254 tcg_gen_andi_tl(t1, t0, 3);
2255 #ifdef TARGET_WORDS_BIGENDIAN
2256 tcg_gen_xori_tl(t1, t1, 3);
2257 #endif
2258 tcg_gen_shli_tl(t1, t1, 3);
2259 tcg_gen_andi_tl(t0, t0, ~3);
2260 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2261 tcg_gen_shr_tl(t0, t0, t1);
2262 tcg_gen_xori_tl(t1, t1, 31);
2263 t2 = tcg_const_tl(0xfffffffeull);
2264 tcg_gen_shl_tl(t2, t2, t1);
2265 gen_load_gpr(t1, rt);
2266 tcg_gen_and_tl(t1, t1, t2);
2267 tcg_temp_free(t2);
2268 tcg_gen_or_tl(t0, t0, t1);
2269 tcg_temp_free(t1);
2270 tcg_gen_ext32s_tl(t0, t0);
2271 gen_store_gpr(t0, rt);
2272 opn = "lwr";
2273 break;
2274 case OPC_LL:
2275 case R6_OPC_LL:
2276 save_cpu_state(ctx, 1);
2277 op_ld_ll(t0, t0, ctx);
2278 gen_store_gpr(t0, rt);
2279 opn = "ll";
2280 break;
2282 (void)opn; /* avoid a compiler warning */
2283 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
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 const char *opn = "st";
2292 TCGv t0 = tcg_temp_new();
2293 TCGv t1 = tcg_temp_new();
2295 gen_base_offset_addr(ctx, t0, base, offset);
2296 gen_load_gpr(t1, rt);
2297 switch (opc) {
2298 #if defined(TARGET_MIPS64)
2299 case OPC_SD:
2300 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
2301 ctx->default_tcg_memop_mask);
2302 opn = "sd";
2303 break;
2304 case OPC_SDL:
2305 save_cpu_state(ctx, 1);
2306 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
2307 opn = "sdl";
2308 break;
2309 case OPC_SDR:
2310 save_cpu_state(ctx, 1);
2311 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2312 opn = "sdr";
2313 break;
2314 #endif
2315 case OPC_SW:
2316 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
2317 ctx->default_tcg_memop_mask);
2318 opn = "sw";
2319 break;
2320 case OPC_SH:
2321 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
2322 ctx->default_tcg_memop_mask);
2323 opn = "sh";
2324 break;
2325 case OPC_SB:
2326 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2327 opn = "sb";
2328 break;
2329 case OPC_SWL:
2330 save_cpu_state(ctx, 1);
2331 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2332 opn = "swl";
2333 break;
2334 case OPC_SWR:
2335 save_cpu_state(ctx, 1);
2336 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2337 opn = "swr";
2338 break;
2340 (void)opn; /* avoid a compiler warning */
2341 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2342 tcg_temp_free(t0);
2343 tcg_temp_free(t1);
2347 /* Store conditional */
2348 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2349 int base, int16_t offset)
2351 const char *opn = "st_cond";
2352 TCGv t0, t1;
2354 #ifdef CONFIG_USER_ONLY
2355 t0 = tcg_temp_local_new();
2356 t1 = tcg_temp_local_new();
2357 #else
2358 t0 = tcg_temp_new();
2359 t1 = tcg_temp_new();
2360 #endif
2361 gen_base_offset_addr(ctx, t0, base, offset);
2362 gen_load_gpr(t1, rt);
2363 switch (opc) {
2364 #if defined(TARGET_MIPS64)
2365 case OPC_SCD:
2366 case R6_OPC_SCD:
2367 save_cpu_state(ctx, 1);
2368 op_st_scd(t1, t0, rt, ctx);
2369 opn = "scd";
2370 break;
2371 #endif
2372 case OPC_SC:
2373 case R6_OPC_SC:
2374 save_cpu_state(ctx, 1);
2375 op_st_sc(t1, t0, rt, ctx);
2376 opn = "sc";
2377 break;
2379 (void)opn; /* avoid a compiler warning */
2380 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2381 tcg_temp_free(t1);
2382 tcg_temp_free(t0);
2385 /* Load and store */
2386 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2387 int base, int16_t offset)
2389 const char *opn = "flt_ldst";
2390 TCGv t0 = tcg_temp_new();
2392 gen_base_offset_addr(ctx, t0, base, offset);
2393 /* Don't do NOP if destination is zero: we must perform the actual
2394 memory access. */
2395 switch (opc) {
2396 case OPC_LWC1:
2398 TCGv_i32 fp0 = tcg_temp_new_i32();
2399 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2400 ctx->default_tcg_memop_mask);
2401 gen_store_fpr32(ctx, fp0, ft);
2402 tcg_temp_free_i32(fp0);
2404 opn = "lwc1";
2405 break;
2406 case OPC_SWC1:
2408 TCGv_i32 fp0 = tcg_temp_new_i32();
2409 gen_load_fpr32(ctx, fp0, ft);
2410 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2411 ctx->default_tcg_memop_mask);
2412 tcg_temp_free_i32(fp0);
2414 opn = "swc1";
2415 break;
2416 case OPC_LDC1:
2418 TCGv_i64 fp0 = tcg_temp_new_i64();
2419 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2420 ctx->default_tcg_memop_mask);
2421 gen_store_fpr64(ctx, fp0, ft);
2422 tcg_temp_free_i64(fp0);
2424 opn = "ldc1";
2425 break;
2426 case OPC_SDC1:
2428 TCGv_i64 fp0 = tcg_temp_new_i64();
2429 gen_load_fpr64(ctx, fp0, ft);
2430 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2431 ctx->default_tcg_memop_mask);
2432 tcg_temp_free_i64(fp0);
2434 opn = "sdc1";
2435 break;
2436 default:
2437 MIPS_INVAL(opn);
2438 generate_exception(ctx, EXCP_RI);
2439 goto out;
2441 (void)opn; /* avoid a compiler warning */
2442 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
2443 out:
2444 tcg_temp_free(t0);
2447 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2448 int rs, int16_t imm)
2450 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2451 check_cp1_enabled(ctx);
2452 switch (op) {
2453 case OPC_LDC1:
2454 case OPC_SDC1:
2455 check_insn(ctx, ISA_MIPS2);
2456 /* Fallthrough */
2457 default:
2458 gen_flt_ldst(ctx, op, rt, rs, imm);
2460 } else {
2461 generate_exception_err(ctx, EXCP_CpU, 1);
2465 /* Arithmetic with immediate operand */
2466 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2467 int rt, int rs, int16_t imm)
2469 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2470 const char *opn = "imm arith";
2472 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2473 /* If no destination, treat it as a NOP.
2474 For addi, we must generate the overflow exception when needed. */
2475 MIPS_DEBUG("NOP");
2476 return;
2478 switch (opc) {
2479 case OPC_ADDI:
2481 TCGv t0 = tcg_temp_local_new();
2482 TCGv t1 = tcg_temp_new();
2483 TCGv t2 = tcg_temp_new();
2484 TCGLabel *l1 = gen_new_label();
2486 gen_load_gpr(t1, rs);
2487 tcg_gen_addi_tl(t0, t1, uimm);
2488 tcg_gen_ext32s_tl(t0, t0);
2490 tcg_gen_xori_tl(t1, t1, ~uimm);
2491 tcg_gen_xori_tl(t2, t0, uimm);
2492 tcg_gen_and_tl(t1, t1, t2);
2493 tcg_temp_free(t2);
2494 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2495 tcg_temp_free(t1);
2496 /* operands of same sign, result different sign */
2497 generate_exception(ctx, EXCP_OVERFLOW);
2498 gen_set_label(l1);
2499 tcg_gen_ext32s_tl(t0, t0);
2500 gen_store_gpr(t0, rt);
2501 tcg_temp_free(t0);
2503 opn = "addi";
2504 break;
2505 case OPC_ADDIU:
2506 if (rs != 0) {
2507 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2508 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2509 } else {
2510 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2512 opn = "addiu";
2513 break;
2514 #if defined(TARGET_MIPS64)
2515 case OPC_DADDI:
2517 TCGv t0 = tcg_temp_local_new();
2518 TCGv t1 = tcg_temp_new();
2519 TCGv t2 = tcg_temp_new();
2520 TCGLabel *l1 = gen_new_label();
2522 gen_load_gpr(t1, rs);
2523 tcg_gen_addi_tl(t0, t1, uimm);
2525 tcg_gen_xori_tl(t1, t1, ~uimm);
2526 tcg_gen_xori_tl(t2, t0, uimm);
2527 tcg_gen_and_tl(t1, t1, t2);
2528 tcg_temp_free(t2);
2529 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2530 tcg_temp_free(t1);
2531 /* operands of same sign, result different sign */
2532 generate_exception(ctx, EXCP_OVERFLOW);
2533 gen_set_label(l1);
2534 gen_store_gpr(t0, rt);
2535 tcg_temp_free(t0);
2537 opn = "daddi";
2538 break;
2539 case OPC_DADDIU:
2540 if (rs != 0) {
2541 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2542 } else {
2543 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2545 opn = "daddiu";
2546 break;
2547 #endif
2549 (void)opn; /* avoid a compiler warning */
2550 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2553 /* Logic with immediate operand */
2554 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2555 int rt, int rs, int16_t imm)
2557 target_ulong uimm;
2559 if (rt == 0) {
2560 /* If no destination, treat it as a NOP. */
2561 MIPS_DEBUG("NOP");
2562 return;
2564 uimm = (uint16_t)imm;
2565 switch (opc) {
2566 case OPC_ANDI:
2567 if (likely(rs != 0))
2568 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2569 else
2570 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2571 MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
2572 regnames[rs], uimm);
2573 break;
2574 case OPC_ORI:
2575 if (rs != 0)
2576 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2577 else
2578 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2579 MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
2580 regnames[rs], uimm);
2581 break;
2582 case OPC_XORI:
2583 if (likely(rs != 0))
2584 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2585 else
2586 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2587 MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
2588 regnames[rs], uimm);
2589 break;
2590 case OPC_LUI:
2591 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2592 /* OPC_AUI */
2593 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2594 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2595 MIPS_DEBUG("aui %s, %s, %04x", regnames[rt], regnames[rs], imm);
2596 } else {
2597 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2598 MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
2600 break;
2602 default:
2603 MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
2604 break;
2608 /* Set on less than with immediate operand */
2609 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2610 int rt, int rs, int16_t imm)
2612 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2613 const char *opn = "imm arith";
2614 TCGv t0;
2616 if (rt == 0) {
2617 /* If no destination, treat it as a NOP. */
2618 MIPS_DEBUG("NOP");
2619 return;
2621 t0 = tcg_temp_new();
2622 gen_load_gpr(t0, rs);
2623 switch (opc) {
2624 case OPC_SLTI:
2625 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2626 opn = "slti";
2627 break;
2628 case OPC_SLTIU:
2629 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2630 opn = "sltiu";
2631 break;
2633 (void)opn; /* avoid a compiler warning */
2634 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2635 tcg_temp_free(t0);
2638 /* Shifts with immediate operand */
2639 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2640 int rt, int rs, int16_t imm)
2642 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2643 const char *opn = "imm shift";
2644 TCGv t0;
2646 if (rt == 0) {
2647 /* If no destination, treat it as a NOP. */
2648 MIPS_DEBUG("NOP");
2649 return;
2652 t0 = tcg_temp_new();
2653 gen_load_gpr(t0, rs);
2654 switch (opc) {
2655 case OPC_SLL:
2656 tcg_gen_shli_tl(t0, t0, uimm);
2657 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2658 opn = "sll";
2659 break;
2660 case OPC_SRA:
2661 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2662 opn = "sra";
2663 break;
2664 case OPC_SRL:
2665 if (uimm != 0) {
2666 tcg_gen_ext32u_tl(t0, t0);
2667 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2668 } else {
2669 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2671 opn = "srl";
2672 break;
2673 case OPC_ROTR:
2674 if (uimm != 0) {
2675 TCGv_i32 t1 = tcg_temp_new_i32();
2677 tcg_gen_trunc_tl_i32(t1, t0);
2678 tcg_gen_rotri_i32(t1, t1, uimm);
2679 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2680 tcg_temp_free_i32(t1);
2681 } else {
2682 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2684 opn = "rotr";
2685 break;
2686 #if defined(TARGET_MIPS64)
2687 case OPC_DSLL:
2688 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2689 opn = "dsll";
2690 break;
2691 case OPC_DSRA:
2692 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2693 opn = "dsra";
2694 break;
2695 case OPC_DSRL:
2696 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2697 opn = "dsrl";
2698 break;
2699 case OPC_DROTR:
2700 if (uimm != 0) {
2701 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2702 } else {
2703 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2705 opn = "drotr";
2706 break;
2707 case OPC_DSLL32:
2708 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2709 opn = "dsll32";
2710 break;
2711 case OPC_DSRA32:
2712 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2713 opn = "dsra32";
2714 break;
2715 case OPC_DSRL32:
2716 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2717 opn = "dsrl32";
2718 break;
2719 case OPC_DROTR32:
2720 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2721 opn = "drotr32";
2722 break;
2723 #endif
2725 (void)opn; /* avoid a compiler warning */
2726 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2727 tcg_temp_free(t0);
2730 /* Arithmetic */
2731 static void gen_arith(DisasContext *ctx, uint32_t opc,
2732 int rd, int rs, int rt)
2734 const char *opn = "arith";
2736 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2737 && opc != OPC_DADD && opc != OPC_DSUB) {
2738 /* If no destination, treat it as a NOP.
2739 For add & sub, we must generate the overflow exception when needed. */
2740 MIPS_DEBUG("NOP");
2741 return;
2744 switch (opc) {
2745 case OPC_ADD:
2747 TCGv t0 = tcg_temp_local_new();
2748 TCGv t1 = tcg_temp_new();
2749 TCGv t2 = tcg_temp_new();
2750 TCGLabel *l1 = gen_new_label();
2752 gen_load_gpr(t1, rs);
2753 gen_load_gpr(t2, rt);
2754 tcg_gen_add_tl(t0, t1, t2);
2755 tcg_gen_ext32s_tl(t0, t0);
2756 tcg_gen_xor_tl(t1, t1, t2);
2757 tcg_gen_xor_tl(t2, t0, t2);
2758 tcg_gen_andc_tl(t1, t2, t1);
2759 tcg_temp_free(t2);
2760 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2761 tcg_temp_free(t1);
2762 /* operands of same sign, result different sign */
2763 generate_exception(ctx, EXCP_OVERFLOW);
2764 gen_set_label(l1);
2765 gen_store_gpr(t0, rd);
2766 tcg_temp_free(t0);
2768 opn = "add";
2769 break;
2770 case OPC_ADDU:
2771 if (rs != 0 && rt != 0) {
2772 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2773 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2774 } else if (rs == 0 && rt != 0) {
2775 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2776 } else if (rs != 0 && rt == 0) {
2777 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2778 } else {
2779 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2781 opn = "addu";
2782 break;
2783 case OPC_SUB:
2785 TCGv t0 = tcg_temp_local_new();
2786 TCGv t1 = tcg_temp_new();
2787 TCGv t2 = tcg_temp_new();
2788 TCGLabel *l1 = gen_new_label();
2790 gen_load_gpr(t1, rs);
2791 gen_load_gpr(t2, rt);
2792 tcg_gen_sub_tl(t0, t1, t2);
2793 tcg_gen_ext32s_tl(t0, t0);
2794 tcg_gen_xor_tl(t2, t1, t2);
2795 tcg_gen_xor_tl(t1, t0, t1);
2796 tcg_gen_and_tl(t1, t1, t2);
2797 tcg_temp_free(t2);
2798 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2799 tcg_temp_free(t1);
2800 /* operands of different sign, first operand and result different sign */
2801 generate_exception(ctx, EXCP_OVERFLOW);
2802 gen_set_label(l1);
2803 gen_store_gpr(t0, rd);
2804 tcg_temp_free(t0);
2806 opn = "sub";
2807 break;
2808 case OPC_SUBU:
2809 if (rs != 0 && rt != 0) {
2810 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2811 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2812 } else if (rs == 0 && rt != 0) {
2813 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2814 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2815 } else if (rs != 0 && rt == 0) {
2816 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2817 } else {
2818 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2820 opn = "subu";
2821 break;
2822 #if defined(TARGET_MIPS64)
2823 case OPC_DADD:
2825 TCGv t0 = tcg_temp_local_new();
2826 TCGv t1 = tcg_temp_new();
2827 TCGv t2 = tcg_temp_new();
2828 TCGLabel *l1 = gen_new_label();
2830 gen_load_gpr(t1, rs);
2831 gen_load_gpr(t2, rt);
2832 tcg_gen_add_tl(t0, t1, t2);
2833 tcg_gen_xor_tl(t1, t1, t2);
2834 tcg_gen_xor_tl(t2, t0, t2);
2835 tcg_gen_andc_tl(t1, t2, t1);
2836 tcg_temp_free(t2);
2837 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2838 tcg_temp_free(t1);
2839 /* operands of same sign, result different sign */
2840 generate_exception(ctx, EXCP_OVERFLOW);
2841 gen_set_label(l1);
2842 gen_store_gpr(t0, rd);
2843 tcg_temp_free(t0);
2845 opn = "dadd";
2846 break;
2847 case OPC_DADDU:
2848 if (rs != 0 && rt != 0) {
2849 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2850 } else if (rs == 0 && rt != 0) {
2851 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2852 } else if (rs != 0 && rt == 0) {
2853 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2854 } else {
2855 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2857 opn = "daddu";
2858 break;
2859 case OPC_DSUB:
2861 TCGv t0 = tcg_temp_local_new();
2862 TCGv t1 = tcg_temp_new();
2863 TCGv t2 = tcg_temp_new();
2864 TCGLabel *l1 = gen_new_label();
2866 gen_load_gpr(t1, rs);
2867 gen_load_gpr(t2, rt);
2868 tcg_gen_sub_tl(t0, t1, t2);
2869 tcg_gen_xor_tl(t2, t1, t2);
2870 tcg_gen_xor_tl(t1, t0, t1);
2871 tcg_gen_and_tl(t1, t1, t2);
2872 tcg_temp_free(t2);
2873 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2874 tcg_temp_free(t1);
2875 /* operands of different sign, first operand and result different sign */
2876 generate_exception(ctx, EXCP_OVERFLOW);
2877 gen_set_label(l1);
2878 gen_store_gpr(t0, rd);
2879 tcg_temp_free(t0);
2881 opn = "dsub";
2882 break;
2883 case OPC_DSUBU:
2884 if (rs != 0 && rt != 0) {
2885 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2886 } else if (rs == 0 && rt != 0) {
2887 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2888 } else if (rs != 0 && rt == 0) {
2889 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2890 } else {
2891 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2893 opn = "dsubu";
2894 break;
2895 #endif
2896 case OPC_MUL:
2897 if (likely(rs != 0 && rt != 0)) {
2898 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2899 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2900 } else {
2901 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2903 opn = "mul";
2904 break;
2906 (void)opn; /* avoid a compiler warning */
2907 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2910 /* Conditional move */
2911 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2912 int rd, int rs, int rt)
2914 const char *opn = "cond move";
2915 TCGv t0, t1, t2;
2917 if (rd == 0) {
2918 /* If no destination, treat it as a NOP. */
2919 MIPS_DEBUG("NOP");
2920 return;
2923 t0 = tcg_temp_new();
2924 gen_load_gpr(t0, rt);
2925 t1 = tcg_const_tl(0);
2926 t2 = tcg_temp_new();
2927 gen_load_gpr(t2, rs);
2928 switch (opc) {
2929 case OPC_MOVN:
2930 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2931 opn = "movn";
2932 break;
2933 case OPC_MOVZ:
2934 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2935 opn = "movz";
2936 break;
2937 case OPC_SELNEZ:
2938 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2939 opn = "selnez";
2940 break;
2941 case OPC_SELEQZ:
2942 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2943 opn = "seleqz";
2944 break;
2946 tcg_temp_free(t2);
2947 tcg_temp_free(t1);
2948 tcg_temp_free(t0);
2950 (void)opn; /* avoid a compiler warning */
2951 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2954 /* Logic */
2955 static void gen_logic(DisasContext *ctx, uint32_t opc,
2956 int rd, int rs, int rt)
2958 const char *opn = "logic";
2960 if (rd == 0) {
2961 /* If no destination, treat it as a NOP. */
2962 MIPS_DEBUG("NOP");
2963 return;
2966 switch (opc) {
2967 case OPC_AND:
2968 if (likely(rs != 0 && rt != 0)) {
2969 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2970 } else {
2971 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2973 opn = "and";
2974 break;
2975 case OPC_NOR:
2976 if (rs != 0 && rt != 0) {
2977 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2978 } else if (rs == 0 && rt != 0) {
2979 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2980 } else if (rs != 0 && rt == 0) {
2981 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2982 } else {
2983 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2985 opn = "nor";
2986 break;
2987 case OPC_OR:
2988 if (likely(rs != 0 && rt != 0)) {
2989 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2990 } else if (rs == 0 && rt != 0) {
2991 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2992 } else if (rs != 0 && rt == 0) {
2993 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2994 } else {
2995 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2997 opn = "or";
2998 break;
2999 case OPC_XOR:
3000 if (likely(rs != 0 && rt != 0)) {
3001 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3002 } else if (rs == 0 && rt != 0) {
3003 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3004 } else if (rs != 0 && rt == 0) {
3005 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3006 } else {
3007 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3009 opn = "xor";
3010 break;
3012 (void)opn; /* avoid a compiler warning */
3013 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3016 /* Set on lower than */
3017 static void gen_slt(DisasContext *ctx, uint32_t opc,
3018 int rd, int rs, int rt)
3020 const char *opn = "slt";
3021 TCGv t0, t1;
3023 if (rd == 0) {
3024 /* If no destination, treat it as a NOP. */
3025 MIPS_DEBUG("NOP");
3026 return;
3029 t0 = tcg_temp_new();
3030 t1 = tcg_temp_new();
3031 gen_load_gpr(t0, rs);
3032 gen_load_gpr(t1, rt);
3033 switch (opc) {
3034 case OPC_SLT:
3035 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3036 opn = "slt";
3037 break;
3038 case OPC_SLTU:
3039 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3040 opn = "sltu";
3041 break;
3043 (void)opn; /* avoid a compiler warning */
3044 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3045 tcg_temp_free(t0);
3046 tcg_temp_free(t1);
3049 /* Shifts */
3050 static void gen_shift(DisasContext *ctx, uint32_t opc,
3051 int rd, int rs, int rt)
3053 const char *opn = "shifts";
3054 TCGv t0, t1;
3056 if (rd == 0) {
3057 /* If no destination, treat it as a NOP.
3058 For add & sub, we must generate the overflow exception when needed. */
3059 MIPS_DEBUG("NOP");
3060 return;
3063 t0 = tcg_temp_new();
3064 t1 = tcg_temp_new();
3065 gen_load_gpr(t0, rs);
3066 gen_load_gpr(t1, rt);
3067 switch (opc) {
3068 case OPC_SLLV:
3069 tcg_gen_andi_tl(t0, t0, 0x1f);
3070 tcg_gen_shl_tl(t0, t1, t0);
3071 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3072 opn = "sllv";
3073 break;
3074 case OPC_SRAV:
3075 tcg_gen_andi_tl(t0, t0, 0x1f);
3076 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3077 opn = "srav";
3078 break;
3079 case OPC_SRLV:
3080 tcg_gen_ext32u_tl(t1, t1);
3081 tcg_gen_andi_tl(t0, t0, 0x1f);
3082 tcg_gen_shr_tl(t0, t1, t0);
3083 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3084 opn = "srlv";
3085 break;
3086 case OPC_ROTRV:
3088 TCGv_i32 t2 = tcg_temp_new_i32();
3089 TCGv_i32 t3 = tcg_temp_new_i32();
3091 tcg_gen_trunc_tl_i32(t2, t0);
3092 tcg_gen_trunc_tl_i32(t3, t1);
3093 tcg_gen_andi_i32(t2, t2, 0x1f);
3094 tcg_gen_rotr_i32(t2, t3, t2);
3095 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3096 tcg_temp_free_i32(t2);
3097 tcg_temp_free_i32(t3);
3098 opn = "rotrv";
3100 break;
3101 #if defined(TARGET_MIPS64)
3102 case OPC_DSLLV:
3103 tcg_gen_andi_tl(t0, t0, 0x3f);
3104 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3105 opn = "dsllv";
3106 break;
3107 case OPC_DSRAV:
3108 tcg_gen_andi_tl(t0, t0, 0x3f);
3109 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3110 opn = "dsrav";
3111 break;
3112 case OPC_DSRLV:
3113 tcg_gen_andi_tl(t0, t0, 0x3f);
3114 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3115 opn = "dsrlv";
3116 break;
3117 case OPC_DROTRV:
3118 tcg_gen_andi_tl(t0, t0, 0x3f);
3119 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3120 opn = "drotrv";
3121 break;
3122 #endif
3124 (void)opn; /* avoid a compiler warning */
3125 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3126 tcg_temp_free(t0);
3127 tcg_temp_free(t1);
3130 /* Arithmetic on HI/LO registers */
3131 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3133 const char *opn = "hilo";
3135 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3136 /* Treat as NOP. */
3137 MIPS_DEBUG("NOP");
3138 return;
3141 if (acc != 0) {
3142 check_dsp(ctx);
3145 switch (opc) {
3146 case OPC_MFHI:
3147 #if defined(TARGET_MIPS64)
3148 if (acc != 0) {
3149 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3150 } else
3151 #endif
3153 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3155 opn = "mfhi";
3156 break;
3157 case OPC_MFLO:
3158 #if defined(TARGET_MIPS64)
3159 if (acc != 0) {
3160 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3161 } else
3162 #endif
3164 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3166 opn = "mflo";
3167 break;
3168 case OPC_MTHI:
3169 if (reg != 0) {
3170 #if defined(TARGET_MIPS64)
3171 if (acc != 0) {
3172 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3173 } else
3174 #endif
3176 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3178 } else {
3179 tcg_gen_movi_tl(cpu_HI[acc], 0);
3181 opn = "mthi";
3182 break;
3183 case OPC_MTLO:
3184 if (reg != 0) {
3185 #if defined(TARGET_MIPS64)
3186 if (acc != 0) {
3187 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3188 } else
3189 #endif
3191 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3193 } else {
3194 tcg_gen_movi_tl(cpu_LO[acc], 0);
3196 opn = "mtlo";
3197 break;
3199 (void)opn; /* avoid a compiler warning */
3200 MIPS_DEBUG("%s %s", opn, regnames[reg]);
3203 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3204 TCGMemOp memop)
3206 TCGv t0 = tcg_const_tl(addr);
3207 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3208 gen_store_gpr(t0, reg);
3209 tcg_temp_free(t0);
3212 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3213 int rs)
3215 target_long offset;
3216 target_long addr;
3218 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3219 case OPC_ADDIUPC:
3220 if (rs != 0) {
3221 offset = sextract32(ctx->opcode << 2, 0, 21);
3222 addr = addr_add(ctx, pc, offset);
3223 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3225 break;
3226 case R6_OPC_LWPC:
3227 offset = sextract32(ctx->opcode << 2, 0, 21);
3228 addr = addr_add(ctx, pc, offset);
3229 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3230 break;
3231 #if defined(TARGET_MIPS64)
3232 case OPC_LWUPC:
3233 check_mips_64(ctx);
3234 offset = sextract32(ctx->opcode << 2, 0, 21);
3235 addr = addr_add(ctx, pc, offset);
3236 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3237 break;
3238 #endif
3239 default:
3240 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3241 case OPC_AUIPC:
3242 if (rs != 0) {
3243 offset = sextract32(ctx->opcode, 0, 16) << 16;
3244 addr = addr_add(ctx, pc, offset);
3245 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3247 break;
3248 case OPC_ALUIPC:
3249 if (rs != 0) {
3250 offset = sextract32(ctx->opcode, 0, 16) << 16;
3251 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3252 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3254 break;
3255 #if defined(TARGET_MIPS64)
3256 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3257 case R6_OPC_LDPC + (1 << 16):
3258 case R6_OPC_LDPC + (2 << 16):
3259 case R6_OPC_LDPC + (3 << 16):
3260 check_mips_64(ctx);
3261 offset = sextract32(ctx->opcode << 3, 0, 21);
3262 addr = addr_add(ctx, (pc & ~0x7), offset);
3263 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3264 break;
3265 #endif
3266 default:
3267 MIPS_INVAL("OPC_PCREL");
3268 generate_exception(ctx, EXCP_RI);
3269 break;
3271 break;
3275 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3277 const char *opn = "r6 mul/div";
3278 TCGv t0, t1;
3280 if (rd == 0) {
3281 /* Treat as NOP. */
3282 MIPS_DEBUG("NOP");
3283 return;
3286 t0 = tcg_temp_new();
3287 t1 = tcg_temp_new();
3289 gen_load_gpr(t0, rs);
3290 gen_load_gpr(t1, rt);
3292 switch (opc) {
3293 case R6_OPC_DIV:
3295 TCGv t2 = tcg_temp_new();
3296 TCGv t3 = tcg_temp_new();
3297 tcg_gen_ext32s_tl(t0, t0);
3298 tcg_gen_ext32s_tl(t1, t1);
3299 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3300 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3301 tcg_gen_and_tl(t2, t2, t3);
3302 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3303 tcg_gen_or_tl(t2, t2, t3);
3304 tcg_gen_movi_tl(t3, 0);
3305 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3306 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3307 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3308 tcg_temp_free(t3);
3309 tcg_temp_free(t2);
3311 opn = "div";
3312 break;
3313 case R6_OPC_MOD:
3315 TCGv t2 = tcg_temp_new();
3316 TCGv t3 = tcg_temp_new();
3317 tcg_gen_ext32s_tl(t0, t0);
3318 tcg_gen_ext32s_tl(t1, t1);
3319 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3320 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3321 tcg_gen_and_tl(t2, t2, t3);
3322 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3323 tcg_gen_or_tl(t2, t2, t3);
3324 tcg_gen_movi_tl(t3, 0);
3325 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3326 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3327 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3328 tcg_temp_free(t3);
3329 tcg_temp_free(t2);
3331 opn = "mod";
3332 break;
3333 case R6_OPC_DIVU:
3335 TCGv t2 = tcg_const_tl(0);
3336 TCGv t3 = tcg_const_tl(1);
3337 tcg_gen_ext32u_tl(t0, t0);
3338 tcg_gen_ext32u_tl(t1, t1);
3339 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3340 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3341 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3342 tcg_temp_free(t3);
3343 tcg_temp_free(t2);
3345 opn = "divu";
3346 break;
3347 case R6_OPC_MODU:
3349 TCGv t2 = tcg_const_tl(0);
3350 TCGv t3 = tcg_const_tl(1);
3351 tcg_gen_ext32u_tl(t0, t0);
3352 tcg_gen_ext32u_tl(t1, t1);
3353 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3354 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3355 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3356 tcg_temp_free(t3);
3357 tcg_temp_free(t2);
3359 opn = "modu";
3360 break;
3361 case R6_OPC_MUL:
3363 TCGv_i32 t2 = tcg_temp_new_i32();
3364 TCGv_i32 t3 = tcg_temp_new_i32();
3365 tcg_gen_trunc_tl_i32(t2, t0);
3366 tcg_gen_trunc_tl_i32(t3, t1);
3367 tcg_gen_mul_i32(t2, t2, t3);
3368 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3369 tcg_temp_free_i32(t2);
3370 tcg_temp_free_i32(t3);
3372 opn = "mul";
3373 break;
3374 case R6_OPC_MUH:
3376 TCGv_i32 t2 = tcg_temp_new_i32();
3377 TCGv_i32 t3 = tcg_temp_new_i32();
3378 tcg_gen_trunc_tl_i32(t2, t0);
3379 tcg_gen_trunc_tl_i32(t3, t1);
3380 tcg_gen_muls2_i32(t2, t3, t2, t3);
3381 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3382 tcg_temp_free_i32(t2);
3383 tcg_temp_free_i32(t3);
3385 opn = "muh";
3386 break;
3387 case R6_OPC_MULU:
3389 TCGv_i32 t2 = tcg_temp_new_i32();
3390 TCGv_i32 t3 = tcg_temp_new_i32();
3391 tcg_gen_trunc_tl_i32(t2, t0);
3392 tcg_gen_trunc_tl_i32(t3, t1);
3393 tcg_gen_mul_i32(t2, t2, t3);
3394 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3395 tcg_temp_free_i32(t2);
3396 tcg_temp_free_i32(t3);
3398 opn = "mulu";
3399 break;
3400 case R6_OPC_MUHU:
3402 TCGv_i32 t2 = tcg_temp_new_i32();
3403 TCGv_i32 t3 = tcg_temp_new_i32();
3404 tcg_gen_trunc_tl_i32(t2, t0);
3405 tcg_gen_trunc_tl_i32(t3, t1);
3406 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3407 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3408 tcg_temp_free_i32(t2);
3409 tcg_temp_free_i32(t3);
3411 opn = "muhu";
3412 break;
3413 #if defined(TARGET_MIPS64)
3414 case R6_OPC_DDIV:
3416 TCGv t2 = tcg_temp_new();
3417 TCGv t3 = tcg_temp_new();
3418 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3419 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3420 tcg_gen_and_tl(t2, t2, t3);
3421 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3422 tcg_gen_or_tl(t2, t2, t3);
3423 tcg_gen_movi_tl(t3, 0);
3424 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3425 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3426 tcg_temp_free(t3);
3427 tcg_temp_free(t2);
3429 opn = "ddiv";
3430 break;
3431 case R6_OPC_DMOD:
3433 TCGv t2 = tcg_temp_new();
3434 TCGv t3 = tcg_temp_new();
3435 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3436 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3437 tcg_gen_and_tl(t2, t2, t3);
3438 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3439 tcg_gen_or_tl(t2, t2, t3);
3440 tcg_gen_movi_tl(t3, 0);
3441 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3442 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3443 tcg_temp_free(t3);
3444 tcg_temp_free(t2);
3446 opn = "dmod";
3447 break;
3448 case R6_OPC_DDIVU:
3450 TCGv t2 = tcg_const_tl(0);
3451 TCGv t3 = tcg_const_tl(1);
3452 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3453 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3454 tcg_temp_free(t3);
3455 tcg_temp_free(t2);
3457 opn = "ddivu";
3458 break;
3459 case R6_OPC_DMODU:
3461 TCGv t2 = tcg_const_tl(0);
3462 TCGv t3 = tcg_const_tl(1);
3463 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3464 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3465 tcg_temp_free(t3);
3466 tcg_temp_free(t2);
3468 opn = "dmodu";
3469 break;
3470 case R6_OPC_DMUL:
3471 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3472 opn = "dmul";
3473 break;
3474 case R6_OPC_DMUH:
3476 TCGv t2 = tcg_temp_new();
3477 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3478 tcg_temp_free(t2);
3480 opn = "dmuh";
3481 break;
3482 case R6_OPC_DMULU:
3483 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3484 opn = "dmulu";
3485 break;
3486 case R6_OPC_DMUHU:
3488 TCGv t2 = tcg_temp_new();
3489 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3490 tcg_temp_free(t2);
3492 opn = "dmuhu";
3493 break;
3494 #endif
3495 default:
3496 MIPS_INVAL(opn);
3497 generate_exception(ctx, EXCP_RI);
3498 goto out;
3500 (void)opn; /* avoid a compiler warning */
3501 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3502 out:
3503 tcg_temp_free(t0);
3504 tcg_temp_free(t1);
3507 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3508 int acc, int rs, int rt)
3510 const char *opn = "mul/div";
3511 TCGv t0, t1;
3513 t0 = tcg_temp_new();
3514 t1 = tcg_temp_new();
3516 gen_load_gpr(t0, rs);
3517 gen_load_gpr(t1, rt);
3519 if (acc != 0) {
3520 check_dsp(ctx);
3523 switch (opc) {
3524 case OPC_DIV:
3526 TCGv t2 = tcg_temp_new();
3527 TCGv t3 = tcg_temp_new();
3528 tcg_gen_ext32s_tl(t0, t0);
3529 tcg_gen_ext32s_tl(t1, t1);
3530 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3531 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3532 tcg_gen_and_tl(t2, t2, t3);
3533 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3534 tcg_gen_or_tl(t2, t2, t3);
3535 tcg_gen_movi_tl(t3, 0);
3536 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3537 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3538 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3539 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3540 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3541 tcg_temp_free(t3);
3542 tcg_temp_free(t2);
3544 opn = "div";
3545 break;
3546 case OPC_DIVU:
3548 TCGv t2 = tcg_const_tl(0);
3549 TCGv t3 = tcg_const_tl(1);
3550 tcg_gen_ext32u_tl(t0, t0);
3551 tcg_gen_ext32u_tl(t1, t1);
3552 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3553 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3554 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3555 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3556 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3557 tcg_temp_free(t3);
3558 tcg_temp_free(t2);
3560 opn = "divu";
3561 break;
3562 case OPC_MULT:
3564 TCGv_i32 t2 = tcg_temp_new_i32();
3565 TCGv_i32 t3 = tcg_temp_new_i32();
3566 tcg_gen_trunc_tl_i32(t2, t0);
3567 tcg_gen_trunc_tl_i32(t3, t1);
3568 tcg_gen_muls2_i32(t2, t3, t2, t3);
3569 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3570 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3571 tcg_temp_free_i32(t2);
3572 tcg_temp_free_i32(t3);
3574 opn = "mult";
3575 break;
3576 case OPC_MULTU:
3578 TCGv_i32 t2 = tcg_temp_new_i32();
3579 TCGv_i32 t3 = tcg_temp_new_i32();
3580 tcg_gen_trunc_tl_i32(t2, t0);
3581 tcg_gen_trunc_tl_i32(t3, t1);
3582 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3583 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3584 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3585 tcg_temp_free_i32(t2);
3586 tcg_temp_free_i32(t3);
3588 opn = "multu";
3589 break;
3590 #if defined(TARGET_MIPS64)
3591 case OPC_DDIV:
3593 TCGv t2 = tcg_temp_new();
3594 TCGv t3 = tcg_temp_new();
3595 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3596 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3597 tcg_gen_and_tl(t2, t2, t3);
3598 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3599 tcg_gen_or_tl(t2, t2, t3);
3600 tcg_gen_movi_tl(t3, 0);
3601 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3602 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3603 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3604 tcg_temp_free(t3);
3605 tcg_temp_free(t2);
3607 opn = "ddiv";
3608 break;
3609 case OPC_DDIVU:
3611 TCGv t2 = tcg_const_tl(0);
3612 TCGv t3 = tcg_const_tl(1);
3613 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3614 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3615 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3616 tcg_temp_free(t3);
3617 tcg_temp_free(t2);
3619 opn = "ddivu";
3620 break;
3621 case OPC_DMULT:
3622 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3623 opn = "dmult";
3624 break;
3625 case OPC_DMULTU:
3626 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3627 opn = "dmultu";
3628 break;
3629 #endif
3630 case OPC_MADD:
3632 TCGv_i64 t2 = tcg_temp_new_i64();
3633 TCGv_i64 t3 = tcg_temp_new_i64();
3635 tcg_gen_ext_tl_i64(t2, t0);
3636 tcg_gen_ext_tl_i64(t3, t1);
3637 tcg_gen_mul_i64(t2, t2, t3);
3638 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3639 tcg_gen_add_i64(t2, t2, t3);
3640 tcg_temp_free_i64(t3);
3641 tcg_gen_trunc_i64_tl(t0, t2);
3642 tcg_gen_shri_i64(t2, t2, 32);
3643 tcg_gen_trunc_i64_tl(t1, t2);
3644 tcg_temp_free_i64(t2);
3645 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3646 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3648 opn = "madd";
3649 break;
3650 case OPC_MADDU:
3652 TCGv_i64 t2 = tcg_temp_new_i64();
3653 TCGv_i64 t3 = tcg_temp_new_i64();
3655 tcg_gen_ext32u_tl(t0, t0);
3656 tcg_gen_ext32u_tl(t1, t1);
3657 tcg_gen_extu_tl_i64(t2, t0);
3658 tcg_gen_extu_tl_i64(t3, t1);
3659 tcg_gen_mul_i64(t2, t2, t3);
3660 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3661 tcg_gen_add_i64(t2, t2, t3);
3662 tcg_temp_free_i64(t3);
3663 tcg_gen_trunc_i64_tl(t0, t2);
3664 tcg_gen_shri_i64(t2, t2, 32);
3665 tcg_gen_trunc_i64_tl(t1, t2);
3666 tcg_temp_free_i64(t2);
3667 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3668 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3670 opn = "maddu";
3671 break;
3672 case OPC_MSUB:
3674 TCGv_i64 t2 = tcg_temp_new_i64();
3675 TCGv_i64 t3 = tcg_temp_new_i64();
3677 tcg_gen_ext_tl_i64(t2, t0);
3678 tcg_gen_ext_tl_i64(t3, t1);
3679 tcg_gen_mul_i64(t2, t2, t3);
3680 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3681 tcg_gen_sub_i64(t2, t3, t2);
3682 tcg_temp_free_i64(t3);
3683 tcg_gen_trunc_i64_tl(t0, t2);
3684 tcg_gen_shri_i64(t2, t2, 32);
3685 tcg_gen_trunc_i64_tl(t1, t2);
3686 tcg_temp_free_i64(t2);
3687 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3688 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3690 opn = "msub";
3691 break;
3692 case OPC_MSUBU:
3694 TCGv_i64 t2 = tcg_temp_new_i64();
3695 TCGv_i64 t3 = tcg_temp_new_i64();
3697 tcg_gen_ext32u_tl(t0, t0);
3698 tcg_gen_ext32u_tl(t1, t1);
3699 tcg_gen_extu_tl_i64(t2, t0);
3700 tcg_gen_extu_tl_i64(t3, t1);
3701 tcg_gen_mul_i64(t2, t2, t3);
3702 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3703 tcg_gen_sub_i64(t2, t3, t2);
3704 tcg_temp_free_i64(t3);
3705 tcg_gen_trunc_i64_tl(t0, t2);
3706 tcg_gen_shri_i64(t2, t2, 32);
3707 tcg_gen_trunc_i64_tl(t1, t2);
3708 tcg_temp_free_i64(t2);
3709 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3710 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3712 opn = "msubu";
3713 break;
3714 default:
3715 MIPS_INVAL(opn);
3716 generate_exception(ctx, EXCP_RI);
3717 goto out;
3719 (void)opn; /* avoid a compiler warning */
3720 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3721 out:
3722 tcg_temp_free(t0);
3723 tcg_temp_free(t1);
3726 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3727 int rd, int rs, int rt)
3729 const char *opn = "mul vr54xx";
3730 TCGv t0 = tcg_temp_new();
3731 TCGv t1 = tcg_temp_new();
3733 gen_load_gpr(t0, rs);
3734 gen_load_gpr(t1, rt);
3736 switch (opc) {
3737 case OPC_VR54XX_MULS:
3738 gen_helper_muls(t0, cpu_env, t0, t1);
3739 opn = "muls";
3740 break;
3741 case OPC_VR54XX_MULSU:
3742 gen_helper_mulsu(t0, cpu_env, t0, t1);
3743 opn = "mulsu";
3744 break;
3745 case OPC_VR54XX_MACC:
3746 gen_helper_macc(t0, cpu_env, t0, t1);
3747 opn = "macc";
3748 break;
3749 case OPC_VR54XX_MACCU:
3750 gen_helper_maccu(t0, cpu_env, t0, t1);
3751 opn = "maccu";
3752 break;
3753 case OPC_VR54XX_MSAC:
3754 gen_helper_msac(t0, cpu_env, t0, t1);
3755 opn = "msac";
3756 break;
3757 case OPC_VR54XX_MSACU:
3758 gen_helper_msacu(t0, cpu_env, t0, t1);
3759 opn = "msacu";
3760 break;
3761 case OPC_VR54XX_MULHI:
3762 gen_helper_mulhi(t0, cpu_env, t0, t1);
3763 opn = "mulhi";
3764 break;
3765 case OPC_VR54XX_MULHIU:
3766 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3767 opn = "mulhiu";
3768 break;
3769 case OPC_VR54XX_MULSHI:
3770 gen_helper_mulshi(t0, cpu_env, t0, t1);
3771 opn = "mulshi";
3772 break;
3773 case OPC_VR54XX_MULSHIU:
3774 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3775 opn = "mulshiu";
3776 break;
3777 case OPC_VR54XX_MACCHI:
3778 gen_helper_macchi(t0, cpu_env, t0, t1);
3779 opn = "macchi";
3780 break;
3781 case OPC_VR54XX_MACCHIU:
3782 gen_helper_macchiu(t0, cpu_env, t0, t1);
3783 opn = "macchiu";
3784 break;
3785 case OPC_VR54XX_MSACHI:
3786 gen_helper_msachi(t0, cpu_env, t0, t1);
3787 opn = "msachi";
3788 break;
3789 case OPC_VR54XX_MSACHIU:
3790 gen_helper_msachiu(t0, cpu_env, t0, t1);
3791 opn = "msachiu";
3792 break;
3793 default:
3794 MIPS_INVAL("mul vr54xx");
3795 generate_exception(ctx, EXCP_RI);
3796 goto out;
3798 gen_store_gpr(t0, rd);
3799 (void)opn; /* avoid a compiler warning */
3800 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3802 out:
3803 tcg_temp_free(t0);
3804 tcg_temp_free(t1);
3807 static void gen_cl (DisasContext *ctx, uint32_t opc,
3808 int rd, int rs)
3810 const char *opn = "CLx";
3811 TCGv t0;
3813 if (rd == 0) {
3814 /* Treat as NOP. */
3815 MIPS_DEBUG("NOP");
3816 return;
3818 t0 = tcg_temp_new();
3819 gen_load_gpr(t0, rs);
3820 switch (opc) {
3821 case OPC_CLO:
3822 case R6_OPC_CLO:
3823 gen_helper_clo(cpu_gpr[rd], t0);
3824 opn = "clo";
3825 break;
3826 case OPC_CLZ:
3827 case R6_OPC_CLZ:
3828 gen_helper_clz(cpu_gpr[rd], t0);
3829 opn = "clz";
3830 break;
3831 #if defined(TARGET_MIPS64)
3832 case OPC_DCLO:
3833 case R6_OPC_DCLO:
3834 gen_helper_dclo(cpu_gpr[rd], t0);
3835 opn = "dclo";
3836 break;
3837 case OPC_DCLZ:
3838 case R6_OPC_DCLZ:
3839 gen_helper_dclz(cpu_gpr[rd], t0);
3840 opn = "dclz";
3841 break;
3842 #endif
3844 (void)opn; /* avoid a compiler warning */
3845 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3846 tcg_temp_free(t0);
3849 /* Godson integer instructions */
3850 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3851 int rd, int rs, int rt)
3853 const char *opn = "loongson";
3854 TCGv t0, t1;
3856 if (rd == 0) {
3857 /* Treat as NOP. */
3858 MIPS_DEBUG("NOP");
3859 return;
3862 switch (opc) {
3863 case OPC_MULT_G_2E:
3864 case OPC_MULT_G_2F:
3865 case OPC_MULTU_G_2E:
3866 case OPC_MULTU_G_2F:
3867 #if defined(TARGET_MIPS64)
3868 case OPC_DMULT_G_2E:
3869 case OPC_DMULT_G_2F:
3870 case OPC_DMULTU_G_2E:
3871 case OPC_DMULTU_G_2F:
3872 #endif
3873 t0 = tcg_temp_new();
3874 t1 = tcg_temp_new();
3875 break;
3876 default:
3877 t0 = tcg_temp_local_new();
3878 t1 = tcg_temp_local_new();
3879 break;
3882 gen_load_gpr(t0, rs);
3883 gen_load_gpr(t1, rt);
3885 switch (opc) {
3886 case OPC_MULT_G_2E:
3887 case OPC_MULT_G_2F:
3888 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3889 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3890 opn = "mult.g";
3891 break;
3892 case OPC_MULTU_G_2E:
3893 case OPC_MULTU_G_2F:
3894 tcg_gen_ext32u_tl(t0, t0);
3895 tcg_gen_ext32u_tl(t1, t1);
3896 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3897 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3898 opn = "multu.g";
3899 break;
3900 case OPC_DIV_G_2E:
3901 case OPC_DIV_G_2F:
3903 TCGLabel *l1 = gen_new_label();
3904 TCGLabel *l2 = gen_new_label();
3905 TCGLabel *l3 = gen_new_label();
3906 tcg_gen_ext32s_tl(t0, t0);
3907 tcg_gen_ext32s_tl(t1, t1);
3908 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3909 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3910 tcg_gen_br(l3);
3911 gen_set_label(l1);
3912 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3913 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3914 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3915 tcg_gen_br(l3);
3916 gen_set_label(l2);
3917 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3918 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3919 gen_set_label(l3);
3921 opn = "div.g";
3922 break;
3923 case OPC_DIVU_G_2E:
3924 case OPC_DIVU_G_2F:
3926 TCGLabel *l1 = gen_new_label();
3927 TCGLabel *l2 = gen_new_label();
3928 tcg_gen_ext32u_tl(t0, t0);
3929 tcg_gen_ext32u_tl(t1, t1);
3930 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3931 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3932 tcg_gen_br(l2);
3933 gen_set_label(l1);
3934 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3935 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3936 gen_set_label(l2);
3938 opn = "divu.g";
3939 break;
3940 case OPC_MOD_G_2E:
3941 case OPC_MOD_G_2F:
3943 TCGLabel *l1 = gen_new_label();
3944 TCGLabel *l2 = gen_new_label();
3945 TCGLabel *l3 = gen_new_label();
3946 tcg_gen_ext32u_tl(t0, t0);
3947 tcg_gen_ext32u_tl(t1, t1);
3948 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3949 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3950 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3951 gen_set_label(l1);
3952 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3953 tcg_gen_br(l3);
3954 gen_set_label(l2);
3955 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3956 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3957 gen_set_label(l3);
3959 opn = "mod.g";
3960 break;
3961 case OPC_MODU_G_2E:
3962 case OPC_MODU_G_2F:
3964 TCGLabel *l1 = gen_new_label();
3965 TCGLabel *l2 = gen_new_label();
3966 tcg_gen_ext32u_tl(t0, t0);
3967 tcg_gen_ext32u_tl(t1, t1);
3968 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3969 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3970 tcg_gen_br(l2);
3971 gen_set_label(l1);
3972 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3973 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3974 gen_set_label(l2);
3976 opn = "modu.g";
3977 break;
3978 #if defined(TARGET_MIPS64)
3979 case OPC_DMULT_G_2E:
3980 case OPC_DMULT_G_2F:
3981 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3982 opn = "dmult.g";
3983 break;
3984 case OPC_DMULTU_G_2E:
3985 case OPC_DMULTU_G_2F:
3986 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3987 opn = "dmultu.g";
3988 break;
3989 case OPC_DDIV_G_2E:
3990 case OPC_DDIV_G_2F:
3992 TCGLabel *l1 = gen_new_label();
3993 TCGLabel *l2 = gen_new_label();
3994 TCGLabel *l3 = gen_new_label();
3995 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3996 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3997 tcg_gen_br(l3);
3998 gen_set_label(l1);
3999 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4000 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4001 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4002 tcg_gen_br(l3);
4003 gen_set_label(l2);
4004 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4005 gen_set_label(l3);
4007 opn = "ddiv.g";
4008 break;
4009 case OPC_DDIVU_G_2E:
4010 case OPC_DDIVU_G_2F:
4012 TCGLabel *l1 = gen_new_label();
4013 TCGLabel *l2 = gen_new_label();
4014 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4015 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4016 tcg_gen_br(l2);
4017 gen_set_label(l1);
4018 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4019 gen_set_label(l2);
4021 opn = "ddivu.g";
4022 break;
4023 case OPC_DMOD_G_2E:
4024 case OPC_DMOD_G_2F:
4026 TCGLabel *l1 = gen_new_label();
4027 TCGLabel *l2 = gen_new_label();
4028 TCGLabel *l3 = gen_new_label();
4029 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4030 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4031 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4032 gen_set_label(l1);
4033 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4034 tcg_gen_br(l3);
4035 gen_set_label(l2);
4036 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4037 gen_set_label(l3);
4039 opn = "dmod.g";
4040 break;
4041 case OPC_DMODU_G_2E:
4042 case OPC_DMODU_G_2F:
4044 TCGLabel *l1 = gen_new_label();
4045 TCGLabel *l2 = gen_new_label();
4046 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4047 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4048 tcg_gen_br(l2);
4049 gen_set_label(l1);
4050 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4051 gen_set_label(l2);
4053 opn = "dmodu.g";
4054 break;
4055 #endif
4058 (void)opn; /* avoid a compiler warning */
4059 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
4060 tcg_temp_free(t0);
4061 tcg_temp_free(t1);
4064 /* Loongson multimedia instructions */
4065 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4067 const char *opn = "loongson_cp2";
4068 uint32_t opc, shift_max;
4069 TCGv_i64 t0, t1;
4071 opc = MASK_LMI(ctx->opcode);
4072 switch (opc) {
4073 case OPC_ADD_CP2:
4074 case OPC_SUB_CP2:
4075 case OPC_DADD_CP2:
4076 case OPC_DSUB_CP2:
4077 t0 = tcg_temp_local_new_i64();
4078 t1 = tcg_temp_local_new_i64();
4079 break;
4080 default:
4081 t0 = tcg_temp_new_i64();
4082 t1 = tcg_temp_new_i64();
4083 break;
4086 gen_load_fpr64(ctx, t0, rs);
4087 gen_load_fpr64(ctx, t1, rt);
4089 #define LMI_HELPER(UP, LO) \
4090 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
4091 #define LMI_HELPER_1(UP, LO) \
4092 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
4093 #define LMI_DIRECT(UP, LO, OP) \
4094 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
4096 switch (opc) {
4097 LMI_HELPER(PADDSH, paddsh);
4098 LMI_HELPER(PADDUSH, paddush);
4099 LMI_HELPER(PADDH, paddh);
4100 LMI_HELPER(PADDW, paddw);
4101 LMI_HELPER(PADDSB, paddsb);
4102 LMI_HELPER(PADDUSB, paddusb);
4103 LMI_HELPER(PADDB, paddb);
4105 LMI_HELPER(PSUBSH, psubsh);
4106 LMI_HELPER(PSUBUSH, psubush);
4107 LMI_HELPER(PSUBH, psubh);
4108 LMI_HELPER(PSUBW, psubw);
4109 LMI_HELPER(PSUBSB, psubsb);
4110 LMI_HELPER(PSUBUSB, psubusb);
4111 LMI_HELPER(PSUBB, psubb);
4113 LMI_HELPER(PSHUFH, pshufh);
4114 LMI_HELPER(PACKSSWH, packsswh);
4115 LMI_HELPER(PACKSSHB, packsshb);
4116 LMI_HELPER(PACKUSHB, packushb);
4118 LMI_HELPER(PUNPCKLHW, punpcklhw);
4119 LMI_HELPER(PUNPCKHHW, punpckhhw);
4120 LMI_HELPER(PUNPCKLBH, punpcklbh);
4121 LMI_HELPER(PUNPCKHBH, punpckhbh);
4122 LMI_HELPER(PUNPCKLWD, punpcklwd);
4123 LMI_HELPER(PUNPCKHWD, punpckhwd);
4125 LMI_HELPER(PAVGH, pavgh);
4126 LMI_HELPER(PAVGB, pavgb);
4127 LMI_HELPER(PMAXSH, pmaxsh);
4128 LMI_HELPER(PMINSH, pminsh);
4129 LMI_HELPER(PMAXUB, pmaxub);
4130 LMI_HELPER(PMINUB, pminub);
4132 LMI_HELPER(PCMPEQW, pcmpeqw);
4133 LMI_HELPER(PCMPGTW, pcmpgtw);
4134 LMI_HELPER(PCMPEQH, pcmpeqh);
4135 LMI_HELPER(PCMPGTH, pcmpgth);
4136 LMI_HELPER(PCMPEQB, pcmpeqb);
4137 LMI_HELPER(PCMPGTB, pcmpgtb);
4139 LMI_HELPER(PSLLW, psllw);
4140 LMI_HELPER(PSLLH, psllh);
4141 LMI_HELPER(PSRLW, psrlw);
4142 LMI_HELPER(PSRLH, psrlh);
4143 LMI_HELPER(PSRAW, psraw);
4144 LMI_HELPER(PSRAH, psrah);
4146 LMI_HELPER(PMULLH, pmullh);
4147 LMI_HELPER(PMULHH, pmulhh);
4148 LMI_HELPER(PMULHUH, pmulhuh);
4149 LMI_HELPER(PMADDHW, pmaddhw);
4151 LMI_HELPER(PASUBUB, pasubub);
4152 LMI_HELPER_1(BIADD, biadd);
4153 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4155 LMI_DIRECT(PADDD, paddd, add);
4156 LMI_DIRECT(PSUBD, psubd, sub);
4157 LMI_DIRECT(XOR_CP2, xor, xor);
4158 LMI_DIRECT(NOR_CP2, nor, nor);
4159 LMI_DIRECT(AND_CP2, and, and);
4160 LMI_DIRECT(PANDN, pandn, andc);
4161 LMI_DIRECT(OR, or, or);
4163 case OPC_PINSRH_0:
4164 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4165 opn = "pinsrh_0";
4166 break;
4167 case OPC_PINSRH_1:
4168 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4169 opn = "pinsrh_1";
4170 break;
4171 case OPC_PINSRH_2:
4172 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4173 opn = "pinsrh_2";
4174 break;
4175 case OPC_PINSRH_3:
4176 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4177 opn = "pinsrh_3";
4178 break;
4180 case OPC_PEXTRH:
4181 tcg_gen_andi_i64(t1, t1, 3);
4182 tcg_gen_shli_i64(t1, t1, 4);
4183 tcg_gen_shr_i64(t0, t0, t1);
4184 tcg_gen_ext16u_i64(t0, t0);
4185 opn = "pextrh";
4186 break;
4188 case OPC_ADDU_CP2:
4189 tcg_gen_add_i64(t0, t0, t1);
4190 tcg_gen_ext32s_i64(t0, t0);
4191 opn = "addu";
4192 break;
4193 case OPC_SUBU_CP2:
4194 tcg_gen_sub_i64(t0, t0, t1);
4195 tcg_gen_ext32s_i64(t0, t0);
4196 opn = "addu";
4197 break;
4199 case OPC_SLL_CP2:
4200 opn = "sll";
4201 shift_max = 32;
4202 goto do_shift;
4203 case OPC_SRL_CP2:
4204 opn = "srl";
4205 shift_max = 32;
4206 goto do_shift;
4207 case OPC_SRA_CP2:
4208 opn = "sra";
4209 shift_max = 32;
4210 goto do_shift;
4211 case OPC_DSLL_CP2:
4212 opn = "dsll";
4213 shift_max = 64;
4214 goto do_shift;
4215 case OPC_DSRL_CP2:
4216 opn = "dsrl";
4217 shift_max = 64;
4218 goto do_shift;
4219 case OPC_DSRA_CP2:
4220 opn = "dsra";
4221 shift_max = 64;
4222 goto do_shift;
4223 do_shift:
4224 /* Make sure shift count isn't TCG undefined behaviour. */
4225 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4227 switch (opc) {
4228 case OPC_SLL_CP2:
4229 case OPC_DSLL_CP2:
4230 tcg_gen_shl_i64(t0, t0, t1);
4231 break;
4232 case OPC_SRA_CP2:
4233 case OPC_DSRA_CP2:
4234 /* Since SRA is UndefinedResult without sign-extended inputs,
4235 we can treat SRA and DSRA the same. */
4236 tcg_gen_sar_i64(t0, t0, t1);
4237 break;
4238 case OPC_SRL_CP2:
4239 /* We want to shift in zeros for SRL; zero-extend first. */
4240 tcg_gen_ext32u_i64(t0, t0);
4241 /* FALLTHRU */
4242 case OPC_DSRL_CP2:
4243 tcg_gen_shr_i64(t0, t0, t1);
4244 break;
4247 if (shift_max == 32) {
4248 tcg_gen_ext32s_i64(t0, t0);
4251 /* Shifts larger than MAX produce zero. */
4252 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4253 tcg_gen_neg_i64(t1, t1);
4254 tcg_gen_and_i64(t0, t0, t1);
4255 break;
4257 case OPC_ADD_CP2:
4258 case OPC_DADD_CP2:
4260 TCGv_i64 t2 = tcg_temp_new_i64();
4261 TCGLabel *lab = gen_new_label();
4263 tcg_gen_mov_i64(t2, t0);
4264 tcg_gen_add_i64(t0, t1, t2);
4265 if (opc == OPC_ADD_CP2) {
4266 tcg_gen_ext32s_i64(t0, t0);
4268 tcg_gen_xor_i64(t1, t1, t2);
4269 tcg_gen_xor_i64(t2, t2, t0);
4270 tcg_gen_andc_i64(t1, t2, t1);
4271 tcg_temp_free_i64(t2);
4272 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4273 generate_exception(ctx, EXCP_OVERFLOW);
4274 gen_set_label(lab);
4276 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
4277 break;
4280 case OPC_SUB_CP2:
4281 case OPC_DSUB_CP2:
4283 TCGv_i64 t2 = tcg_temp_new_i64();
4284 TCGLabel *lab = gen_new_label();
4286 tcg_gen_mov_i64(t2, t0);
4287 tcg_gen_sub_i64(t0, t1, t2);
4288 if (opc == OPC_SUB_CP2) {
4289 tcg_gen_ext32s_i64(t0, t0);
4291 tcg_gen_xor_i64(t1, t1, t2);
4292 tcg_gen_xor_i64(t2, t2, t0);
4293 tcg_gen_and_i64(t1, t1, t2);
4294 tcg_temp_free_i64(t2);
4295 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4296 generate_exception(ctx, EXCP_OVERFLOW);
4297 gen_set_label(lab);
4299 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
4300 break;
4303 case OPC_PMULUW:
4304 tcg_gen_ext32u_i64(t0, t0);
4305 tcg_gen_ext32u_i64(t1, t1);
4306 tcg_gen_mul_i64(t0, t0, t1);
4307 opn = "pmuluw";
4308 break;
4310 case OPC_SEQU_CP2:
4311 case OPC_SEQ_CP2:
4312 case OPC_SLTU_CP2:
4313 case OPC_SLT_CP2:
4314 case OPC_SLEU_CP2:
4315 case OPC_SLE_CP2:
4316 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4317 FD field is the CC field? */
4318 default:
4319 MIPS_INVAL(opn);
4320 generate_exception(ctx, EXCP_RI);
4321 return;
4324 #undef LMI_HELPER
4325 #undef LMI_DIRECT
4327 gen_store_fpr64(ctx, t0, rd);
4329 (void)opn; /* avoid a compiler warning */
4330 MIPS_DEBUG("%s %s, %s, %s", opn,
4331 fregnames[rd], fregnames[rs], fregnames[rt]);
4332 tcg_temp_free_i64(t0);
4333 tcg_temp_free_i64(t1);
4336 /* Traps */
4337 static void gen_trap (DisasContext *ctx, uint32_t opc,
4338 int rs, int rt, int16_t imm)
4340 int cond;
4341 TCGv t0 = tcg_temp_new();
4342 TCGv t1 = tcg_temp_new();
4344 cond = 0;
4345 /* Load needed operands */
4346 switch (opc) {
4347 case OPC_TEQ:
4348 case OPC_TGE:
4349 case OPC_TGEU:
4350 case OPC_TLT:
4351 case OPC_TLTU:
4352 case OPC_TNE:
4353 /* Compare two registers */
4354 if (rs != rt) {
4355 gen_load_gpr(t0, rs);
4356 gen_load_gpr(t1, rt);
4357 cond = 1;
4359 break;
4360 case OPC_TEQI:
4361 case OPC_TGEI:
4362 case OPC_TGEIU:
4363 case OPC_TLTI:
4364 case OPC_TLTIU:
4365 case OPC_TNEI:
4366 /* Compare register to immediate */
4367 if (rs != 0 || imm != 0) {
4368 gen_load_gpr(t0, rs);
4369 tcg_gen_movi_tl(t1, (int32_t)imm);
4370 cond = 1;
4372 break;
4374 if (cond == 0) {
4375 switch (opc) {
4376 case OPC_TEQ: /* rs == rs */
4377 case OPC_TEQI: /* r0 == 0 */
4378 case OPC_TGE: /* rs >= rs */
4379 case OPC_TGEI: /* r0 >= 0 */
4380 case OPC_TGEU: /* rs >= rs unsigned */
4381 case OPC_TGEIU: /* r0 >= 0 unsigned */
4382 /* Always trap */
4383 generate_exception(ctx, EXCP_TRAP);
4384 break;
4385 case OPC_TLT: /* rs < rs */
4386 case OPC_TLTI: /* r0 < 0 */
4387 case OPC_TLTU: /* rs < rs unsigned */
4388 case OPC_TLTIU: /* r0 < 0 unsigned */
4389 case OPC_TNE: /* rs != rs */
4390 case OPC_TNEI: /* r0 != 0 */
4391 /* Never trap: treat as NOP. */
4392 break;
4394 } else {
4395 TCGLabel *l1 = gen_new_label();
4397 switch (opc) {
4398 case OPC_TEQ:
4399 case OPC_TEQI:
4400 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4401 break;
4402 case OPC_TGE:
4403 case OPC_TGEI:
4404 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4405 break;
4406 case OPC_TGEU:
4407 case OPC_TGEIU:
4408 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4409 break;
4410 case OPC_TLT:
4411 case OPC_TLTI:
4412 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4413 break;
4414 case OPC_TLTU:
4415 case OPC_TLTIU:
4416 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4417 break;
4418 case OPC_TNE:
4419 case OPC_TNEI:
4420 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4421 break;
4423 generate_exception(ctx, EXCP_TRAP);
4424 gen_set_label(l1);
4426 tcg_temp_free(t0);
4427 tcg_temp_free(t1);
4430 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4432 TranslationBlock *tb;
4433 tb = ctx->tb;
4434 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
4435 likely(!ctx->singlestep_enabled)) {
4436 tcg_gen_goto_tb(n);
4437 gen_save_pc(dest);
4438 tcg_gen_exit_tb((uintptr_t)tb + n);
4439 } else {
4440 gen_save_pc(dest);
4441 if (ctx->singlestep_enabled) {
4442 save_cpu_state(ctx, 0);
4443 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
4445 tcg_gen_exit_tb(0);
4449 /* Branches (before delay slot) */
4450 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4451 int insn_bytes,
4452 int rs, int rt, int32_t offset,
4453 int delayslot_size)
4455 target_ulong btgt = -1;
4456 int blink = 0;
4457 int bcond_compute = 0;
4458 TCGv t0 = tcg_temp_new();
4459 TCGv t1 = tcg_temp_new();
4461 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4462 #ifdef MIPS_DEBUG_DISAS
4463 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4464 TARGET_FMT_lx "\n", ctx->pc);
4465 #endif
4466 generate_exception(ctx, EXCP_RI);
4467 goto out;
4470 /* Load needed operands */
4471 switch (opc) {
4472 case OPC_BEQ:
4473 case OPC_BEQL:
4474 case OPC_BNE:
4475 case OPC_BNEL:
4476 /* Compare two registers */
4477 if (rs != rt) {
4478 gen_load_gpr(t0, rs);
4479 gen_load_gpr(t1, rt);
4480 bcond_compute = 1;
4482 btgt = ctx->pc + insn_bytes + offset;
4483 break;
4484 case OPC_BGEZ:
4485 case OPC_BGEZAL:
4486 case OPC_BGEZALL:
4487 case OPC_BGEZL:
4488 case OPC_BGTZ:
4489 case OPC_BGTZL:
4490 case OPC_BLEZ:
4491 case OPC_BLEZL:
4492 case OPC_BLTZ:
4493 case OPC_BLTZAL:
4494 case OPC_BLTZALL:
4495 case OPC_BLTZL:
4496 /* Compare to zero */
4497 if (rs != 0) {
4498 gen_load_gpr(t0, rs);
4499 bcond_compute = 1;
4501 btgt = ctx->pc + insn_bytes + offset;
4502 break;
4503 case OPC_BPOSGE32:
4504 #if defined(TARGET_MIPS64)
4505 case OPC_BPOSGE64:
4506 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4507 #else
4508 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4509 #endif
4510 bcond_compute = 1;
4511 btgt = ctx->pc + insn_bytes + offset;
4512 break;
4513 case OPC_J:
4514 case OPC_JAL:
4515 case OPC_JALX:
4516 /* Jump to immediate */
4517 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4518 break;
4519 case OPC_JR:
4520 case OPC_JALR:
4521 /* Jump to register */
4522 if (offset != 0 && offset != 16) {
4523 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4524 others are reserved. */
4525 MIPS_INVAL("jump hint");
4526 generate_exception(ctx, EXCP_RI);
4527 goto out;
4529 gen_load_gpr(btarget, rs);
4530 break;
4531 default:
4532 MIPS_INVAL("branch/jump");
4533 generate_exception(ctx, EXCP_RI);
4534 goto out;
4536 if (bcond_compute == 0) {
4537 /* No condition to be computed */
4538 switch (opc) {
4539 case OPC_BEQ: /* rx == rx */
4540 case OPC_BEQL: /* rx == rx likely */
4541 case OPC_BGEZ: /* 0 >= 0 */
4542 case OPC_BGEZL: /* 0 >= 0 likely */
4543 case OPC_BLEZ: /* 0 <= 0 */
4544 case OPC_BLEZL: /* 0 <= 0 likely */
4545 /* Always take */
4546 ctx->hflags |= MIPS_HFLAG_B;
4547 MIPS_DEBUG("balways");
4548 break;
4549 case OPC_BGEZAL: /* 0 >= 0 */
4550 case OPC_BGEZALL: /* 0 >= 0 likely */
4551 /* Always take and link */
4552 blink = 31;
4553 ctx->hflags |= MIPS_HFLAG_B;
4554 MIPS_DEBUG("balways and link");
4555 break;
4556 case OPC_BNE: /* rx != rx */
4557 case OPC_BGTZ: /* 0 > 0 */
4558 case OPC_BLTZ: /* 0 < 0 */
4559 /* Treat as NOP. */
4560 MIPS_DEBUG("bnever (NOP)");
4561 goto out;
4562 case OPC_BLTZAL: /* 0 < 0 */
4563 /* Handle as an unconditional branch to get correct delay
4564 slot checking. */
4565 blink = 31;
4566 btgt = ctx->pc + insn_bytes + delayslot_size;
4567 ctx->hflags |= MIPS_HFLAG_B;
4568 MIPS_DEBUG("bnever and link");
4569 break;
4570 case OPC_BLTZALL: /* 0 < 0 likely */
4571 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4572 /* Skip the instruction in the delay slot */
4573 MIPS_DEBUG("bnever, link and skip");
4574 ctx->pc += 4;
4575 goto out;
4576 case OPC_BNEL: /* rx != rx likely */
4577 case OPC_BGTZL: /* 0 > 0 likely */
4578 case OPC_BLTZL: /* 0 < 0 likely */
4579 /* Skip the instruction in the delay slot */
4580 MIPS_DEBUG("bnever and skip");
4581 ctx->pc += 4;
4582 goto out;
4583 case OPC_J:
4584 ctx->hflags |= MIPS_HFLAG_B;
4585 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
4586 break;
4587 case OPC_JALX:
4588 ctx->hflags |= MIPS_HFLAG_BX;
4589 /* Fallthrough */
4590 case OPC_JAL:
4591 blink = 31;
4592 ctx->hflags |= MIPS_HFLAG_B;
4593 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
4594 break;
4595 case OPC_JR:
4596 ctx->hflags |= MIPS_HFLAG_BR;
4597 MIPS_DEBUG("jr %s", regnames[rs]);
4598 break;
4599 case OPC_JALR:
4600 blink = rt;
4601 ctx->hflags |= MIPS_HFLAG_BR;
4602 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
4603 break;
4604 default:
4605 MIPS_INVAL("branch/jump");
4606 generate_exception(ctx, EXCP_RI);
4607 goto out;
4609 } else {
4610 switch (opc) {
4611 case OPC_BEQ:
4612 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4613 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
4614 regnames[rs], regnames[rt], btgt);
4615 goto not_likely;
4616 case OPC_BEQL:
4617 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4618 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
4619 regnames[rs], regnames[rt], btgt);
4620 goto likely;
4621 case OPC_BNE:
4622 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4623 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
4624 regnames[rs], regnames[rt], btgt);
4625 goto not_likely;
4626 case OPC_BNEL:
4627 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4628 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
4629 regnames[rs], regnames[rt], btgt);
4630 goto likely;
4631 case OPC_BGEZ:
4632 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4633 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4634 goto not_likely;
4635 case OPC_BGEZL:
4636 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4637 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4638 goto likely;
4639 case OPC_BGEZAL:
4640 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4641 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4642 blink = 31;
4643 goto not_likely;
4644 case OPC_BGEZALL:
4645 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4646 blink = 31;
4647 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4648 goto likely;
4649 case OPC_BGTZ:
4650 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4651 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4652 goto not_likely;
4653 case OPC_BGTZL:
4654 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4655 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4656 goto likely;
4657 case OPC_BLEZ:
4658 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4659 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4660 goto not_likely;
4661 case OPC_BLEZL:
4662 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4663 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4664 goto likely;
4665 case OPC_BLTZ:
4666 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4667 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4668 goto not_likely;
4669 case OPC_BLTZL:
4670 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4671 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4672 goto likely;
4673 case OPC_BPOSGE32:
4674 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4675 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
4676 goto not_likely;
4677 #if defined(TARGET_MIPS64)
4678 case OPC_BPOSGE64:
4679 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4680 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
4681 goto not_likely;
4682 #endif
4683 case OPC_BLTZAL:
4684 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4685 blink = 31;
4686 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4687 not_likely:
4688 ctx->hflags |= MIPS_HFLAG_BC;
4689 break;
4690 case OPC_BLTZALL:
4691 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4692 blink = 31;
4693 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4694 likely:
4695 ctx->hflags |= MIPS_HFLAG_BL;
4696 break;
4697 default:
4698 MIPS_INVAL("conditional branch/jump");
4699 generate_exception(ctx, EXCP_RI);
4700 goto out;
4703 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
4704 blink, ctx->hflags, btgt);
4706 ctx->btarget = btgt;
4708 switch (delayslot_size) {
4709 case 2:
4710 ctx->hflags |= MIPS_HFLAG_BDS16;
4711 break;
4712 case 4:
4713 ctx->hflags |= MIPS_HFLAG_BDS32;
4714 break;
4717 if (blink > 0) {
4718 int post_delay = insn_bytes + delayslot_size;
4719 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4721 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4724 out:
4725 if (insn_bytes == 2)
4726 ctx->hflags |= MIPS_HFLAG_B16;
4727 tcg_temp_free(t0);
4728 tcg_temp_free(t1);
4731 /* special3 bitfield operations */
4732 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4733 int rs, int lsb, int msb)
4735 TCGv t0 = tcg_temp_new();
4736 TCGv t1 = tcg_temp_new();
4738 gen_load_gpr(t1, rs);
4739 switch (opc) {
4740 case OPC_EXT:
4741 if (lsb + msb > 31)
4742 goto fail;
4743 tcg_gen_shri_tl(t0, t1, lsb);
4744 if (msb != 31) {
4745 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
4746 } else {
4747 tcg_gen_ext32s_tl(t0, t0);
4749 break;
4750 #if defined(TARGET_MIPS64)
4751 case OPC_DEXTM:
4752 tcg_gen_shri_tl(t0, t1, lsb);
4753 if (msb != 31) {
4754 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
4756 break;
4757 case OPC_DEXTU:
4758 tcg_gen_shri_tl(t0, t1, lsb + 32);
4759 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4760 break;
4761 case OPC_DEXT:
4762 tcg_gen_shri_tl(t0, t1, lsb);
4763 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4764 break;
4765 #endif
4766 case OPC_INS:
4767 if (lsb > msb)
4768 goto fail;
4769 gen_load_gpr(t0, rt);
4770 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4771 tcg_gen_ext32s_tl(t0, t0);
4772 break;
4773 #if defined(TARGET_MIPS64)
4774 case OPC_DINSM:
4775 gen_load_gpr(t0, rt);
4776 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb + 32 - lsb + 1);
4777 break;
4778 case OPC_DINSU:
4779 gen_load_gpr(t0, rt);
4780 tcg_gen_deposit_tl(t0, t0, t1, lsb + 32, msb - lsb + 1);
4781 break;
4782 case OPC_DINS:
4783 gen_load_gpr(t0, rt);
4784 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4785 break;
4786 #endif
4787 default:
4788 fail:
4789 MIPS_INVAL("bitops");
4790 generate_exception(ctx, EXCP_RI);
4791 tcg_temp_free(t0);
4792 tcg_temp_free(t1);
4793 return;
4795 gen_store_gpr(t0, rt);
4796 tcg_temp_free(t0);
4797 tcg_temp_free(t1);
4800 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4802 TCGv t0;
4804 if (rd == 0) {
4805 /* If no destination, treat it as a NOP. */
4806 MIPS_DEBUG("NOP");
4807 return;
4810 t0 = tcg_temp_new();
4811 gen_load_gpr(t0, rt);
4812 switch (op2) {
4813 case OPC_WSBH:
4815 TCGv t1 = tcg_temp_new();
4817 tcg_gen_shri_tl(t1, t0, 8);
4818 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4819 tcg_gen_shli_tl(t0, t0, 8);
4820 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4821 tcg_gen_or_tl(t0, t0, t1);
4822 tcg_temp_free(t1);
4823 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4825 break;
4826 case OPC_SEB:
4827 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4828 break;
4829 case OPC_SEH:
4830 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4831 break;
4832 #if defined(TARGET_MIPS64)
4833 case OPC_DSBH:
4835 TCGv t1 = tcg_temp_new();
4837 tcg_gen_shri_tl(t1, t0, 8);
4838 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4839 tcg_gen_shli_tl(t0, t0, 8);
4840 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4841 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4842 tcg_temp_free(t1);
4844 break;
4845 case OPC_DSHD:
4847 TCGv t1 = tcg_temp_new();
4849 tcg_gen_shri_tl(t1, t0, 16);
4850 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4851 tcg_gen_shli_tl(t0, t0, 16);
4852 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4853 tcg_gen_or_tl(t0, t0, t1);
4854 tcg_gen_shri_tl(t1, t0, 32);
4855 tcg_gen_shli_tl(t0, t0, 32);
4856 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4857 tcg_temp_free(t1);
4859 break;
4860 #endif
4861 default:
4862 MIPS_INVAL("bsfhl");
4863 generate_exception(ctx, EXCP_RI);
4864 tcg_temp_free(t0);
4865 return;
4867 tcg_temp_free(t0);
4870 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4871 int imm2)
4873 TCGv t0;
4874 TCGv t1;
4875 if (rd == 0) {
4876 /* Treat as NOP. */
4877 return;
4879 t0 = tcg_temp_new();
4880 t1 = tcg_temp_new();
4881 gen_load_gpr(t0, rs);
4882 gen_load_gpr(t1, rt);
4883 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4884 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4885 if (opc == OPC_LSA) {
4886 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4889 tcg_temp_free(t1);
4890 tcg_temp_free(t0);
4892 return;
4895 static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
4896 int bp)
4898 TCGv t0;
4899 if (rd == 0) {
4900 /* Treat as NOP. */
4901 return;
4903 t0 = tcg_temp_new();
4904 gen_load_gpr(t0, rt);
4905 if (bp == 0) {
4906 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4907 } else {
4908 TCGv t1 = tcg_temp_new();
4909 gen_load_gpr(t1, rs);
4910 switch (opc) {
4911 case OPC_ALIGN:
4913 TCGv_i64 t2 = tcg_temp_new_i64();
4914 tcg_gen_concat_tl_i64(t2, t1, t0);
4915 tcg_gen_shri_i64(t2, t2, 8 * (4 - bp));
4916 gen_move_low32(cpu_gpr[rd], t2);
4917 tcg_temp_free_i64(t2);
4919 break;
4920 #if defined(TARGET_MIPS64)
4921 case OPC_DALIGN:
4922 tcg_gen_shli_tl(t0, t0, 8 * bp);
4923 tcg_gen_shri_tl(t1, t1, 8 * (8 - bp));
4924 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4925 break;
4926 #endif
4928 tcg_temp_free(t1);
4931 tcg_temp_free(t0);
4934 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4936 TCGv t0;
4937 if (rd == 0) {
4938 /* Treat as NOP. */
4939 return;
4941 t0 = tcg_temp_new();
4942 gen_load_gpr(t0, rt);
4943 switch (opc) {
4944 case OPC_BITSWAP:
4945 gen_helper_bitswap(cpu_gpr[rd], t0);
4946 break;
4947 #if defined(TARGET_MIPS64)
4948 case OPC_DBITSWAP:
4949 gen_helper_dbitswap(cpu_gpr[rd], t0);
4950 break;
4951 #endif
4953 tcg_temp_free(t0);
4956 #ifndef CONFIG_USER_ONLY
4957 /* CP0 (MMU and control) */
4958 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4960 TCGv_i64 t0 = tcg_temp_new_i64();
4961 TCGv_i64 t1 = tcg_temp_new_i64();
4963 tcg_gen_ext_tl_i64(t0, arg);
4964 tcg_gen_ld_i64(t1, cpu_env, off);
4965 #if defined(TARGET_MIPS64)
4966 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4967 #else
4968 tcg_gen_concat32_i64(t1, t1, t0);
4969 #endif
4970 tcg_gen_st_i64(t1, cpu_env, off);
4971 tcg_temp_free_i64(t1);
4972 tcg_temp_free_i64(t0);
4975 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4977 TCGv_i64 t0 = tcg_temp_new_i64();
4978 TCGv_i64 t1 = tcg_temp_new_i64();
4980 tcg_gen_ext_tl_i64(t0, arg);
4981 tcg_gen_ld_i64(t1, cpu_env, off);
4982 tcg_gen_concat32_i64(t1, t1, t0);
4983 tcg_gen_st_i64(t1, cpu_env, off);
4984 tcg_temp_free_i64(t1);
4985 tcg_temp_free_i64(t0);
4988 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
4990 TCGv_i64 t0 = tcg_temp_new_i64();
4992 tcg_gen_ld_i64(t0, cpu_env, off);
4993 #if defined(TARGET_MIPS64)
4994 tcg_gen_shri_i64(t0, t0, 30);
4995 #else
4996 tcg_gen_shri_i64(t0, t0, 32);
4997 #endif
4998 gen_move_low32(arg, t0);
4999 tcg_temp_free_i64(t0);
5002 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5004 TCGv_i64 t0 = tcg_temp_new_i64();
5006 tcg_gen_ld_i64(t0, cpu_env, off);
5007 tcg_gen_shri_i64(t0, t0, 32 + shift);
5008 gen_move_low32(arg, t0);
5009 tcg_temp_free_i64(t0);
5012 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
5014 TCGv_i32 t0 = tcg_temp_new_i32();
5016 tcg_gen_ld_i32(t0, cpu_env, off);
5017 tcg_gen_ext_i32_tl(arg, t0);
5018 tcg_temp_free_i32(t0);
5021 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
5023 tcg_gen_ld_tl(arg, cpu_env, off);
5024 tcg_gen_ext32s_tl(arg, arg);
5027 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
5029 TCGv_i32 t0 = tcg_temp_new_i32();
5031 tcg_gen_trunc_tl_i32(t0, arg);
5032 tcg_gen_st_i32(t0, cpu_env, off);
5033 tcg_temp_free_i32(t0);
5036 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
5038 tcg_gen_ext32s_tl(arg, arg);
5039 tcg_gen_st_tl(arg, cpu_env, off);
5042 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5044 const char *rn = "invalid";
5046 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
5047 goto mfhc0_read_zero;
5050 switch (reg) {
5051 case 2:
5052 switch (sel) {
5053 case 0:
5054 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5055 rn = "EntryLo0";
5056 break;
5057 default:
5058 goto mfhc0_read_zero;
5060 break;
5061 case 3:
5062 switch (sel) {
5063 case 0:
5064 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5065 rn = "EntryLo1";
5066 break;
5067 default:
5068 goto mfhc0_read_zero;
5070 break;
5071 case 17:
5072 switch (sel) {
5073 case 0:
5074 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
5075 ctx->CP0_LLAddr_shift);
5076 rn = "LLAddr";
5077 break;
5078 default:
5079 goto mfhc0_read_zero;
5081 break;
5082 case 28:
5083 switch (sel) {
5084 case 0:
5085 case 2:
5086 case 4:
5087 case 6:
5088 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5089 rn = "TagLo";
5090 break;
5091 default:
5092 goto mfhc0_read_zero;
5094 break;
5095 default:
5096 goto mfhc0_read_zero;
5099 (void)rn; /* avoid a compiler warning */
5100 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5101 return;
5103 mfhc0_read_zero:
5104 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5105 tcg_gen_movi_tl(arg, 0);
5108 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5110 const char *rn = "invalid";
5111 uint64_t mask = ctx->PAMask >> 36;
5113 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
5114 goto mthc0_nop;
5117 switch (reg) {
5118 case 2:
5119 switch (sel) {
5120 case 0:
5121 tcg_gen_andi_tl(arg, arg, mask);
5122 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5123 rn = "EntryLo0";
5124 break;
5125 default:
5126 goto mthc0_nop;
5128 break;
5129 case 3:
5130 switch (sel) {
5131 case 0:
5132 tcg_gen_andi_tl(arg, arg, mask);
5133 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5134 rn = "EntryLo1";
5135 break;
5136 default:
5137 goto mthc0_nop;
5139 break;
5140 case 17:
5141 switch (sel) {
5142 case 0:
5143 /* LLAddr is read-only (the only exception is bit 0 if LLB is
5144 supported); the CP0_LLAddr_rw_bitmask does not seem to be
5145 relevant for modern MIPS cores supporting MTHC0, therefore
5146 treating MTHC0 to LLAddr as NOP. */
5147 rn = "LLAddr";
5148 break;
5149 default:
5150 goto mthc0_nop;
5152 break;
5153 case 28:
5154 switch (sel) {
5155 case 0:
5156 case 2:
5157 case 4:
5158 case 6:
5159 tcg_gen_andi_tl(arg, arg, mask);
5160 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5161 rn = "TagLo";
5162 break;
5163 default:
5164 goto mthc0_nop;
5166 break;
5167 default:
5168 goto mthc0_nop;
5171 (void)rn; /* avoid a compiler warning */
5172 mthc0_nop:
5173 LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
5176 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5178 if (ctx->insn_flags & ISA_MIPS32R6) {
5179 tcg_gen_movi_tl(arg, 0);
5180 } else {
5181 tcg_gen_movi_tl(arg, ~0);
5185 #define CP0_CHECK(c) \
5186 do { \
5187 if (!(c)) { \
5188 goto cp0_unimplemented; \
5190 } while (0)
5192 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5194 const char *rn = "invalid";
5196 if (sel != 0)
5197 check_insn(ctx, ISA_MIPS32);
5199 switch (reg) {
5200 case 0:
5201 switch (sel) {
5202 case 0:
5203 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5204 rn = "Index";
5205 break;
5206 case 1:
5207 CP0_CHECK(ctx->insn_flags & ASE_MT);
5208 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5209 rn = "MVPControl";
5210 break;
5211 case 2:
5212 CP0_CHECK(ctx->insn_flags & ASE_MT);
5213 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5214 rn = "MVPConf0";
5215 break;
5216 case 3:
5217 CP0_CHECK(ctx->insn_flags & ASE_MT);
5218 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5219 rn = "MVPConf1";
5220 break;
5221 default:
5222 goto cp0_unimplemented;
5224 break;
5225 case 1:
5226 switch (sel) {
5227 case 0:
5228 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5229 gen_helper_mfc0_random(arg, cpu_env);
5230 rn = "Random";
5231 break;
5232 case 1:
5233 CP0_CHECK(ctx->insn_flags & ASE_MT);
5234 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5235 rn = "VPEControl";
5236 break;
5237 case 2:
5238 CP0_CHECK(ctx->insn_flags & ASE_MT);
5239 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5240 rn = "VPEConf0";
5241 break;
5242 case 3:
5243 CP0_CHECK(ctx->insn_flags & ASE_MT);
5244 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5245 rn = "VPEConf1";
5246 break;
5247 case 4:
5248 CP0_CHECK(ctx->insn_flags & ASE_MT);
5249 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5250 rn = "YQMask";
5251 break;
5252 case 5:
5253 CP0_CHECK(ctx->insn_flags & ASE_MT);
5254 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5255 rn = "VPESchedule";
5256 break;
5257 case 6:
5258 CP0_CHECK(ctx->insn_flags & ASE_MT);
5259 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5260 rn = "VPEScheFBack";
5261 break;
5262 case 7:
5263 CP0_CHECK(ctx->insn_flags & ASE_MT);
5264 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5265 rn = "VPEOpt";
5266 break;
5267 default:
5268 goto cp0_unimplemented;
5270 break;
5271 case 2:
5272 switch (sel) {
5273 case 0:
5275 TCGv_i64 tmp = tcg_temp_new_i64();
5276 tcg_gen_ld_i64(tmp, cpu_env,
5277 offsetof(CPUMIPSState, CP0_EntryLo0));
5278 #if defined(TARGET_MIPS64)
5279 if (ctx->rxi) {
5280 /* Move RI/XI fields to bits 31:30 */
5281 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5282 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5284 #endif
5285 gen_move_low32(arg, tmp);
5286 tcg_temp_free_i64(tmp);
5288 rn = "EntryLo0";
5289 break;
5290 case 1:
5291 CP0_CHECK(ctx->insn_flags & ASE_MT);
5292 gen_helper_mfc0_tcstatus(arg, cpu_env);
5293 rn = "TCStatus";
5294 break;
5295 case 2:
5296 CP0_CHECK(ctx->insn_flags & ASE_MT);
5297 gen_helper_mfc0_tcbind(arg, cpu_env);
5298 rn = "TCBind";
5299 break;
5300 case 3:
5301 CP0_CHECK(ctx->insn_flags & ASE_MT);
5302 gen_helper_mfc0_tcrestart(arg, cpu_env);
5303 rn = "TCRestart";
5304 break;
5305 case 4:
5306 CP0_CHECK(ctx->insn_flags & ASE_MT);
5307 gen_helper_mfc0_tchalt(arg, cpu_env);
5308 rn = "TCHalt";
5309 break;
5310 case 5:
5311 CP0_CHECK(ctx->insn_flags & ASE_MT);
5312 gen_helper_mfc0_tccontext(arg, cpu_env);
5313 rn = "TCContext";
5314 break;
5315 case 6:
5316 CP0_CHECK(ctx->insn_flags & ASE_MT);
5317 gen_helper_mfc0_tcschedule(arg, cpu_env);
5318 rn = "TCSchedule";
5319 break;
5320 case 7:
5321 CP0_CHECK(ctx->insn_flags & ASE_MT);
5322 gen_helper_mfc0_tcschefback(arg, cpu_env);
5323 rn = "TCScheFBack";
5324 break;
5325 default:
5326 goto cp0_unimplemented;
5328 break;
5329 case 3:
5330 switch (sel) {
5331 case 0:
5333 TCGv_i64 tmp = tcg_temp_new_i64();
5334 tcg_gen_ld_i64(tmp, cpu_env,
5335 offsetof(CPUMIPSState, CP0_EntryLo1));
5336 #if defined(TARGET_MIPS64)
5337 if (ctx->rxi) {
5338 /* Move RI/XI fields to bits 31:30 */
5339 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5340 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5342 #endif
5343 gen_move_low32(arg, tmp);
5344 tcg_temp_free_i64(tmp);
5346 rn = "EntryLo1";
5347 break;
5348 default:
5349 goto cp0_unimplemented;
5351 break;
5352 case 4:
5353 switch (sel) {
5354 case 0:
5355 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5356 tcg_gen_ext32s_tl(arg, arg);
5357 rn = "Context";
5358 break;
5359 case 1:
5360 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5361 rn = "ContextConfig";
5362 goto cp0_unimplemented;
5363 // break;
5364 case 2:
5365 CP0_CHECK(ctx->ulri);
5366 tcg_gen_ld32s_tl(arg, cpu_env,
5367 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5368 rn = "UserLocal";
5369 break;
5370 default:
5371 goto cp0_unimplemented;
5373 break;
5374 case 5:
5375 switch (sel) {
5376 case 0:
5377 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5378 rn = "PageMask";
5379 break;
5380 case 1:
5381 check_insn(ctx, ISA_MIPS32R2);
5382 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5383 rn = "PageGrain";
5384 break;
5385 default:
5386 goto cp0_unimplemented;
5388 break;
5389 case 6:
5390 switch (sel) {
5391 case 0:
5392 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5393 rn = "Wired";
5394 break;
5395 case 1:
5396 check_insn(ctx, ISA_MIPS32R2);
5397 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5398 rn = "SRSConf0";
5399 break;
5400 case 2:
5401 check_insn(ctx, ISA_MIPS32R2);
5402 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5403 rn = "SRSConf1";
5404 break;
5405 case 3:
5406 check_insn(ctx, ISA_MIPS32R2);
5407 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5408 rn = "SRSConf2";
5409 break;
5410 case 4:
5411 check_insn(ctx, ISA_MIPS32R2);
5412 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5413 rn = "SRSConf3";
5414 break;
5415 case 5:
5416 check_insn(ctx, ISA_MIPS32R2);
5417 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5418 rn = "SRSConf4";
5419 break;
5420 default:
5421 goto cp0_unimplemented;
5423 break;
5424 case 7:
5425 switch (sel) {
5426 case 0:
5427 check_insn(ctx, ISA_MIPS32R2);
5428 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5429 rn = "HWREna";
5430 break;
5431 default:
5432 goto cp0_unimplemented;
5434 break;
5435 case 8:
5436 switch (sel) {
5437 case 0:
5438 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5439 tcg_gen_ext32s_tl(arg, arg);
5440 rn = "BadVAddr";
5441 break;
5442 case 1:
5443 CP0_CHECK(ctx->bi);
5444 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5445 rn = "BadInstr";
5446 break;
5447 case 2:
5448 CP0_CHECK(ctx->bp);
5449 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5450 rn = "BadInstrP";
5451 break;
5452 default:
5453 goto cp0_unimplemented;
5455 break;
5456 case 9:
5457 switch (sel) {
5458 case 0:
5459 /* Mark as an IO operation because we read the time. */
5460 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5461 gen_io_start();
5463 gen_helper_mfc0_count(arg, cpu_env);
5464 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5465 gen_io_end();
5467 /* Break the TB to be able to take timer interrupts immediately
5468 after reading count. */
5469 ctx->bstate = BS_STOP;
5470 rn = "Count";
5471 break;
5472 /* 6,7 are implementation dependent */
5473 default:
5474 goto cp0_unimplemented;
5476 break;
5477 case 10:
5478 switch (sel) {
5479 case 0:
5480 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5481 tcg_gen_ext32s_tl(arg, arg);
5482 rn = "EntryHi";
5483 break;
5484 default:
5485 goto cp0_unimplemented;
5487 break;
5488 case 11:
5489 switch (sel) {
5490 case 0:
5491 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5492 rn = "Compare";
5493 break;
5494 /* 6,7 are implementation dependent */
5495 default:
5496 goto cp0_unimplemented;
5498 break;
5499 case 12:
5500 switch (sel) {
5501 case 0:
5502 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5503 rn = "Status";
5504 break;
5505 case 1:
5506 check_insn(ctx, ISA_MIPS32R2);
5507 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5508 rn = "IntCtl";
5509 break;
5510 case 2:
5511 check_insn(ctx, ISA_MIPS32R2);
5512 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5513 rn = "SRSCtl";
5514 break;
5515 case 3:
5516 check_insn(ctx, ISA_MIPS32R2);
5517 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5518 rn = "SRSMap";
5519 break;
5520 default:
5521 goto cp0_unimplemented;
5523 break;
5524 case 13:
5525 switch (sel) {
5526 case 0:
5527 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5528 rn = "Cause";
5529 break;
5530 default:
5531 goto cp0_unimplemented;
5533 break;
5534 case 14:
5535 switch (sel) {
5536 case 0:
5537 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5538 tcg_gen_ext32s_tl(arg, arg);
5539 rn = "EPC";
5540 break;
5541 default:
5542 goto cp0_unimplemented;
5544 break;
5545 case 15:
5546 switch (sel) {
5547 case 0:
5548 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5549 rn = "PRid";
5550 break;
5551 case 1:
5552 check_insn(ctx, ISA_MIPS32R2);
5553 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5554 rn = "EBase";
5555 break;
5556 default:
5557 goto cp0_unimplemented;
5559 break;
5560 case 16:
5561 switch (sel) {
5562 case 0:
5563 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5564 rn = "Config";
5565 break;
5566 case 1:
5567 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5568 rn = "Config1";
5569 break;
5570 case 2:
5571 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5572 rn = "Config2";
5573 break;
5574 case 3:
5575 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5576 rn = "Config3";
5577 break;
5578 case 4:
5579 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5580 rn = "Config4";
5581 break;
5582 case 5:
5583 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5584 rn = "Config5";
5585 break;
5586 /* 6,7 are implementation dependent */
5587 case 6:
5588 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5589 rn = "Config6";
5590 break;
5591 case 7:
5592 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5593 rn = "Config7";
5594 break;
5595 default:
5596 goto cp0_unimplemented;
5598 break;
5599 case 17:
5600 switch (sel) {
5601 case 0:
5602 gen_helper_mfc0_lladdr(arg, cpu_env);
5603 rn = "LLAddr";
5604 break;
5605 default:
5606 goto cp0_unimplemented;
5608 break;
5609 case 18:
5610 switch (sel) {
5611 case 0 ... 7:
5612 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5613 rn = "WatchLo";
5614 break;
5615 default:
5616 goto cp0_unimplemented;
5618 break;
5619 case 19:
5620 switch (sel) {
5621 case 0 ...7:
5622 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5623 rn = "WatchHi";
5624 break;
5625 default:
5626 goto cp0_unimplemented;
5628 break;
5629 case 20:
5630 switch (sel) {
5631 case 0:
5632 #if defined(TARGET_MIPS64)
5633 check_insn(ctx, ISA_MIPS3);
5634 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5635 tcg_gen_ext32s_tl(arg, arg);
5636 rn = "XContext";
5637 break;
5638 #endif
5639 default:
5640 goto cp0_unimplemented;
5642 break;
5643 case 21:
5644 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5645 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5646 switch (sel) {
5647 case 0:
5648 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5649 rn = "Framemask";
5650 break;
5651 default:
5652 goto cp0_unimplemented;
5654 break;
5655 case 22:
5656 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5657 rn = "'Diagnostic"; /* implementation dependent */
5658 break;
5659 case 23:
5660 switch (sel) {
5661 case 0:
5662 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5663 rn = "Debug";
5664 break;
5665 case 1:
5666 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5667 rn = "TraceControl";
5668 // break;
5669 case 2:
5670 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5671 rn = "TraceControl2";
5672 // break;
5673 case 3:
5674 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5675 rn = "UserTraceData";
5676 // break;
5677 case 4:
5678 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5679 rn = "TraceBPC";
5680 // break;
5681 default:
5682 goto cp0_unimplemented;
5684 break;
5685 case 24:
5686 switch (sel) {
5687 case 0:
5688 /* EJTAG support */
5689 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5690 tcg_gen_ext32s_tl(arg, arg);
5691 rn = "DEPC";
5692 break;
5693 default:
5694 goto cp0_unimplemented;
5696 break;
5697 case 25:
5698 switch (sel) {
5699 case 0:
5700 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5701 rn = "Performance0";
5702 break;
5703 case 1:
5704 // gen_helper_mfc0_performance1(arg);
5705 rn = "Performance1";
5706 // break;
5707 case 2:
5708 // gen_helper_mfc0_performance2(arg);
5709 rn = "Performance2";
5710 // break;
5711 case 3:
5712 // gen_helper_mfc0_performance3(arg);
5713 rn = "Performance3";
5714 // break;
5715 case 4:
5716 // gen_helper_mfc0_performance4(arg);
5717 rn = "Performance4";
5718 // break;
5719 case 5:
5720 // gen_helper_mfc0_performance5(arg);
5721 rn = "Performance5";
5722 // break;
5723 case 6:
5724 // gen_helper_mfc0_performance6(arg);
5725 rn = "Performance6";
5726 // break;
5727 case 7:
5728 // gen_helper_mfc0_performance7(arg);
5729 rn = "Performance7";
5730 // break;
5731 default:
5732 goto cp0_unimplemented;
5734 break;
5735 case 26:
5736 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5737 rn = "ECC";
5738 break;
5739 case 27:
5740 switch (sel) {
5741 case 0 ... 3:
5742 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5743 rn = "CacheErr";
5744 break;
5745 default:
5746 goto cp0_unimplemented;
5748 break;
5749 case 28:
5750 switch (sel) {
5751 case 0:
5752 case 2:
5753 case 4:
5754 case 6:
5756 TCGv_i64 tmp = tcg_temp_new_i64();
5757 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5758 gen_move_low32(arg, tmp);
5759 tcg_temp_free_i64(tmp);
5761 rn = "TagLo";
5762 break;
5763 case 1:
5764 case 3:
5765 case 5:
5766 case 7:
5767 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5768 rn = "DataLo";
5769 break;
5770 default:
5771 goto cp0_unimplemented;
5773 break;
5774 case 29:
5775 switch (sel) {
5776 case 0:
5777 case 2:
5778 case 4:
5779 case 6:
5780 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5781 rn = "TagHi";
5782 break;
5783 case 1:
5784 case 3:
5785 case 5:
5786 case 7:
5787 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5788 rn = "DataHi";
5789 break;
5790 default:
5791 goto cp0_unimplemented;
5793 break;
5794 case 30:
5795 switch (sel) {
5796 case 0:
5797 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5798 tcg_gen_ext32s_tl(arg, arg);
5799 rn = "ErrorEPC";
5800 break;
5801 default:
5802 goto cp0_unimplemented;
5804 break;
5805 case 31:
5806 switch (sel) {
5807 case 0:
5808 /* EJTAG support */
5809 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5810 rn = "DESAVE";
5811 break;
5812 case 2 ... 7:
5813 CP0_CHECK(ctx->kscrexist & (1 << sel));
5814 tcg_gen_ld_tl(arg, cpu_env,
5815 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5816 tcg_gen_ext32s_tl(arg, arg);
5817 rn = "KScratch";
5818 break;
5819 default:
5820 goto cp0_unimplemented;
5822 break;
5823 default:
5824 goto cp0_unimplemented;
5826 (void)rn; /* avoid a compiler warning */
5827 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5828 return;
5830 cp0_unimplemented:
5831 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5832 gen_mfc0_unimplemented(ctx, arg);
5835 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5837 const char *rn = "invalid";
5839 if (sel != 0)
5840 check_insn(ctx, ISA_MIPS32);
5842 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5843 gen_io_start();
5846 switch (reg) {
5847 case 0:
5848 switch (sel) {
5849 case 0:
5850 gen_helper_mtc0_index(cpu_env, arg);
5851 rn = "Index";
5852 break;
5853 case 1:
5854 CP0_CHECK(ctx->insn_flags & ASE_MT);
5855 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5856 rn = "MVPControl";
5857 break;
5858 case 2:
5859 CP0_CHECK(ctx->insn_flags & ASE_MT);
5860 /* ignored */
5861 rn = "MVPConf0";
5862 break;
5863 case 3:
5864 CP0_CHECK(ctx->insn_flags & ASE_MT);
5865 /* ignored */
5866 rn = "MVPConf1";
5867 break;
5868 default:
5869 goto cp0_unimplemented;
5871 break;
5872 case 1:
5873 switch (sel) {
5874 case 0:
5875 /* ignored */
5876 rn = "Random";
5877 break;
5878 case 1:
5879 CP0_CHECK(ctx->insn_flags & ASE_MT);
5880 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5881 rn = "VPEControl";
5882 break;
5883 case 2:
5884 CP0_CHECK(ctx->insn_flags & ASE_MT);
5885 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5886 rn = "VPEConf0";
5887 break;
5888 case 3:
5889 CP0_CHECK(ctx->insn_flags & ASE_MT);
5890 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5891 rn = "VPEConf1";
5892 break;
5893 case 4:
5894 CP0_CHECK(ctx->insn_flags & ASE_MT);
5895 gen_helper_mtc0_yqmask(cpu_env, arg);
5896 rn = "YQMask";
5897 break;
5898 case 5:
5899 CP0_CHECK(ctx->insn_flags & ASE_MT);
5900 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5901 rn = "VPESchedule";
5902 break;
5903 case 6:
5904 CP0_CHECK(ctx->insn_flags & ASE_MT);
5905 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5906 rn = "VPEScheFBack";
5907 break;
5908 case 7:
5909 CP0_CHECK(ctx->insn_flags & ASE_MT);
5910 gen_helper_mtc0_vpeopt(cpu_env, arg);
5911 rn = "VPEOpt";
5912 break;
5913 default:
5914 goto cp0_unimplemented;
5916 break;
5917 case 2:
5918 switch (sel) {
5919 case 0:
5920 gen_helper_mtc0_entrylo0(cpu_env, arg);
5921 rn = "EntryLo0";
5922 break;
5923 case 1:
5924 CP0_CHECK(ctx->insn_flags & ASE_MT);
5925 gen_helper_mtc0_tcstatus(cpu_env, arg);
5926 rn = "TCStatus";
5927 break;
5928 case 2:
5929 CP0_CHECK(ctx->insn_flags & ASE_MT);
5930 gen_helper_mtc0_tcbind(cpu_env, arg);
5931 rn = "TCBind";
5932 break;
5933 case 3:
5934 CP0_CHECK(ctx->insn_flags & ASE_MT);
5935 gen_helper_mtc0_tcrestart(cpu_env, arg);
5936 rn = "TCRestart";
5937 break;
5938 case 4:
5939 CP0_CHECK(ctx->insn_flags & ASE_MT);
5940 gen_helper_mtc0_tchalt(cpu_env, arg);
5941 rn = "TCHalt";
5942 break;
5943 case 5:
5944 CP0_CHECK(ctx->insn_flags & ASE_MT);
5945 gen_helper_mtc0_tccontext(cpu_env, arg);
5946 rn = "TCContext";
5947 break;
5948 case 6:
5949 CP0_CHECK(ctx->insn_flags & ASE_MT);
5950 gen_helper_mtc0_tcschedule(cpu_env, arg);
5951 rn = "TCSchedule";
5952 break;
5953 case 7:
5954 CP0_CHECK(ctx->insn_flags & ASE_MT);
5955 gen_helper_mtc0_tcschefback(cpu_env, arg);
5956 rn = "TCScheFBack";
5957 break;
5958 default:
5959 goto cp0_unimplemented;
5961 break;
5962 case 3:
5963 switch (sel) {
5964 case 0:
5965 gen_helper_mtc0_entrylo1(cpu_env, arg);
5966 rn = "EntryLo1";
5967 break;
5968 default:
5969 goto cp0_unimplemented;
5971 break;
5972 case 4:
5973 switch (sel) {
5974 case 0:
5975 gen_helper_mtc0_context(cpu_env, arg);
5976 rn = "Context";
5977 break;
5978 case 1:
5979 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5980 rn = "ContextConfig";
5981 goto cp0_unimplemented;
5982 // break;
5983 case 2:
5984 CP0_CHECK(ctx->ulri);
5985 tcg_gen_st_tl(arg, cpu_env,
5986 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5987 rn = "UserLocal";
5988 break;
5989 default:
5990 goto cp0_unimplemented;
5992 break;
5993 case 5:
5994 switch (sel) {
5995 case 0:
5996 gen_helper_mtc0_pagemask(cpu_env, arg);
5997 rn = "PageMask";
5998 break;
5999 case 1:
6000 check_insn(ctx, ISA_MIPS32R2);
6001 gen_helper_mtc0_pagegrain(cpu_env, arg);
6002 rn = "PageGrain";
6003 ctx->bstate = BS_STOP;
6004 break;
6005 default:
6006 goto cp0_unimplemented;
6008 break;
6009 case 6:
6010 switch (sel) {
6011 case 0:
6012 gen_helper_mtc0_wired(cpu_env, arg);
6013 rn = "Wired";
6014 break;
6015 case 1:
6016 check_insn(ctx, ISA_MIPS32R2);
6017 gen_helper_mtc0_srsconf0(cpu_env, arg);
6018 rn = "SRSConf0";
6019 break;
6020 case 2:
6021 check_insn(ctx, ISA_MIPS32R2);
6022 gen_helper_mtc0_srsconf1(cpu_env, arg);
6023 rn = "SRSConf1";
6024 break;
6025 case 3:
6026 check_insn(ctx, ISA_MIPS32R2);
6027 gen_helper_mtc0_srsconf2(cpu_env, arg);
6028 rn = "SRSConf2";
6029 break;
6030 case 4:
6031 check_insn(ctx, ISA_MIPS32R2);
6032 gen_helper_mtc0_srsconf3(cpu_env, arg);
6033 rn = "SRSConf3";
6034 break;
6035 case 5:
6036 check_insn(ctx, ISA_MIPS32R2);
6037 gen_helper_mtc0_srsconf4(cpu_env, arg);
6038 rn = "SRSConf4";
6039 break;
6040 default:
6041 goto cp0_unimplemented;
6043 break;
6044 case 7:
6045 switch (sel) {
6046 case 0:
6047 check_insn(ctx, ISA_MIPS32R2);
6048 gen_helper_mtc0_hwrena(cpu_env, arg);
6049 ctx->bstate = BS_STOP;
6050 rn = "HWREna";
6051 break;
6052 default:
6053 goto cp0_unimplemented;
6055 break;
6056 case 8:
6057 switch (sel) {
6058 case 0:
6059 /* ignored */
6060 rn = "BadVAddr";
6061 break;
6062 case 1:
6063 /* ignored */
6064 rn = "BadInstr";
6065 break;
6066 case 2:
6067 /* ignored */
6068 rn = "BadInstrP";
6069 break;
6070 default:
6071 goto cp0_unimplemented;
6073 break;
6074 case 9:
6075 switch (sel) {
6076 case 0:
6077 gen_helper_mtc0_count(cpu_env, arg);
6078 rn = "Count";
6079 break;
6080 /* 6,7 are implementation dependent */
6081 default:
6082 goto cp0_unimplemented;
6084 break;
6085 case 10:
6086 switch (sel) {
6087 case 0:
6088 gen_helper_mtc0_entryhi(cpu_env, arg);
6089 rn = "EntryHi";
6090 break;
6091 default:
6092 goto cp0_unimplemented;
6094 break;
6095 case 11:
6096 switch (sel) {
6097 case 0:
6098 gen_helper_mtc0_compare(cpu_env, arg);
6099 rn = "Compare";
6100 break;
6101 /* 6,7 are implementation dependent */
6102 default:
6103 goto cp0_unimplemented;
6105 break;
6106 case 12:
6107 switch (sel) {
6108 case 0:
6109 save_cpu_state(ctx, 1);
6110 gen_helper_mtc0_status(cpu_env, arg);
6111 /* BS_STOP isn't good enough here, hflags may have changed. */
6112 gen_save_pc(ctx->pc + 4);
6113 ctx->bstate = BS_EXCP;
6114 rn = "Status";
6115 break;
6116 case 1:
6117 check_insn(ctx, ISA_MIPS32R2);
6118 gen_helper_mtc0_intctl(cpu_env, arg);
6119 /* Stop translation as we may have switched the execution mode */
6120 ctx->bstate = BS_STOP;
6121 rn = "IntCtl";
6122 break;
6123 case 2:
6124 check_insn(ctx, ISA_MIPS32R2);
6125 gen_helper_mtc0_srsctl(cpu_env, arg);
6126 /* Stop translation as we may have switched the execution mode */
6127 ctx->bstate = BS_STOP;
6128 rn = "SRSCtl";
6129 break;
6130 case 3:
6131 check_insn(ctx, ISA_MIPS32R2);
6132 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6133 /* Stop translation as we may have switched the execution mode */
6134 ctx->bstate = BS_STOP;
6135 rn = "SRSMap";
6136 break;
6137 default:
6138 goto cp0_unimplemented;
6140 break;
6141 case 13:
6142 switch (sel) {
6143 case 0:
6144 save_cpu_state(ctx, 1);
6145 gen_helper_mtc0_cause(cpu_env, arg);
6146 rn = "Cause";
6147 break;
6148 default:
6149 goto cp0_unimplemented;
6151 break;
6152 case 14:
6153 switch (sel) {
6154 case 0:
6155 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
6156 rn = "EPC";
6157 break;
6158 default:
6159 goto cp0_unimplemented;
6161 break;
6162 case 15:
6163 switch (sel) {
6164 case 0:
6165 /* ignored */
6166 rn = "PRid";
6167 break;
6168 case 1:
6169 check_insn(ctx, ISA_MIPS32R2);
6170 gen_helper_mtc0_ebase(cpu_env, arg);
6171 rn = "EBase";
6172 break;
6173 default:
6174 goto cp0_unimplemented;
6176 break;
6177 case 16:
6178 switch (sel) {
6179 case 0:
6180 gen_helper_mtc0_config0(cpu_env, arg);
6181 rn = "Config";
6182 /* Stop translation as we may have switched the execution mode */
6183 ctx->bstate = BS_STOP;
6184 break;
6185 case 1:
6186 /* ignored, read only */
6187 rn = "Config1";
6188 break;
6189 case 2:
6190 gen_helper_mtc0_config2(cpu_env, arg);
6191 rn = "Config2";
6192 /* Stop translation as we may have switched the execution mode */
6193 ctx->bstate = BS_STOP;
6194 break;
6195 case 3:
6196 gen_helper_mtc0_config3(cpu_env, arg);
6197 rn = "Config3";
6198 /* Stop translation as we may have switched the execution mode */
6199 ctx->bstate = BS_STOP;
6200 break;
6201 case 4:
6202 gen_helper_mtc0_config4(cpu_env, arg);
6203 rn = "Config4";
6204 ctx->bstate = BS_STOP;
6205 break;
6206 case 5:
6207 gen_helper_mtc0_config5(cpu_env, arg);
6208 rn = "Config5";
6209 /* Stop translation as we may have switched the execution mode */
6210 ctx->bstate = BS_STOP;
6211 break;
6212 /* 6,7 are implementation dependent */
6213 case 6:
6214 /* ignored */
6215 rn = "Config6";
6216 break;
6217 case 7:
6218 /* ignored */
6219 rn = "Config7";
6220 break;
6221 default:
6222 rn = "Invalid config selector";
6223 goto cp0_unimplemented;
6225 break;
6226 case 17:
6227 switch (sel) {
6228 case 0:
6229 gen_helper_mtc0_lladdr(cpu_env, arg);
6230 rn = "LLAddr";
6231 break;
6232 default:
6233 goto cp0_unimplemented;
6235 break;
6236 case 18:
6237 switch (sel) {
6238 case 0 ... 7:
6239 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6240 rn = "WatchLo";
6241 break;
6242 default:
6243 goto cp0_unimplemented;
6245 break;
6246 case 19:
6247 switch (sel) {
6248 case 0 ... 7:
6249 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6250 rn = "WatchHi";
6251 break;
6252 default:
6253 goto cp0_unimplemented;
6255 break;
6256 case 20:
6257 switch (sel) {
6258 case 0:
6259 #if defined(TARGET_MIPS64)
6260 check_insn(ctx, ISA_MIPS3);
6261 gen_helper_mtc0_xcontext(cpu_env, arg);
6262 rn = "XContext";
6263 break;
6264 #endif
6265 default:
6266 goto cp0_unimplemented;
6268 break;
6269 case 21:
6270 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6271 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6272 switch (sel) {
6273 case 0:
6274 gen_helper_mtc0_framemask(cpu_env, arg);
6275 rn = "Framemask";
6276 break;
6277 default:
6278 goto cp0_unimplemented;
6280 break;
6281 case 22:
6282 /* ignored */
6283 rn = "Diagnostic"; /* implementation dependent */
6284 break;
6285 case 23:
6286 switch (sel) {
6287 case 0:
6288 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6289 /* BS_STOP isn't good enough here, hflags may have changed. */
6290 gen_save_pc(ctx->pc + 4);
6291 ctx->bstate = BS_EXCP;
6292 rn = "Debug";
6293 break;
6294 case 1:
6295 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6296 rn = "TraceControl";
6297 /* Stop translation as we may have switched the execution mode */
6298 ctx->bstate = BS_STOP;
6299 // break;
6300 case 2:
6301 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6302 rn = "TraceControl2";
6303 /* Stop translation as we may have switched the execution mode */
6304 ctx->bstate = BS_STOP;
6305 // break;
6306 case 3:
6307 /* Stop translation as we may have switched the execution mode */
6308 ctx->bstate = BS_STOP;
6309 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6310 rn = "UserTraceData";
6311 /* Stop translation as we may have switched the execution mode */
6312 ctx->bstate = BS_STOP;
6313 // break;
6314 case 4:
6315 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6316 /* Stop translation as we may have switched the execution mode */
6317 ctx->bstate = BS_STOP;
6318 rn = "TraceBPC";
6319 // break;
6320 default:
6321 goto cp0_unimplemented;
6323 break;
6324 case 24:
6325 switch (sel) {
6326 case 0:
6327 /* EJTAG support */
6328 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
6329 rn = "DEPC";
6330 break;
6331 default:
6332 goto cp0_unimplemented;
6334 break;
6335 case 25:
6336 switch (sel) {
6337 case 0:
6338 gen_helper_mtc0_performance0(cpu_env, arg);
6339 rn = "Performance0";
6340 break;
6341 case 1:
6342 // gen_helper_mtc0_performance1(arg);
6343 rn = "Performance1";
6344 // break;
6345 case 2:
6346 // gen_helper_mtc0_performance2(arg);
6347 rn = "Performance2";
6348 // break;
6349 case 3:
6350 // gen_helper_mtc0_performance3(arg);
6351 rn = "Performance3";
6352 // break;
6353 case 4:
6354 // gen_helper_mtc0_performance4(arg);
6355 rn = "Performance4";
6356 // break;
6357 case 5:
6358 // gen_helper_mtc0_performance5(arg);
6359 rn = "Performance5";
6360 // break;
6361 case 6:
6362 // gen_helper_mtc0_performance6(arg);
6363 rn = "Performance6";
6364 // break;
6365 case 7:
6366 // gen_helper_mtc0_performance7(arg);
6367 rn = "Performance7";
6368 // break;
6369 default:
6370 goto cp0_unimplemented;
6372 break;
6373 case 26:
6374 /* ignored */
6375 rn = "ECC";
6376 break;
6377 case 27:
6378 switch (sel) {
6379 case 0 ... 3:
6380 /* ignored */
6381 rn = "CacheErr";
6382 break;
6383 default:
6384 goto cp0_unimplemented;
6386 break;
6387 case 28:
6388 switch (sel) {
6389 case 0:
6390 case 2:
6391 case 4:
6392 case 6:
6393 gen_helper_mtc0_taglo(cpu_env, arg);
6394 rn = "TagLo";
6395 break;
6396 case 1:
6397 case 3:
6398 case 5:
6399 case 7:
6400 gen_helper_mtc0_datalo(cpu_env, arg);
6401 rn = "DataLo";
6402 break;
6403 default:
6404 goto cp0_unimplemented;
6406 break;
6407 case 29:
6408 switch (sel) {
6409 case 0:
6410 case 2:
6411 case 4:
6412 case 6:
6413 gen_helper_mtc0_taghi(cpu_env, arg);
6414 rn = "TagHi";
6415 break;
6416 case 1:
6417 case 3:
6418 case 5:
6419 case 7:
6420 gen_helper_mtc0_datahi(cpu_env, arg);
6421 rn = "DataHi";
6422 break;
6423 default:
6424 rn = "invalid sel";
6425 goto cp0_unimplemented;
6427 break;
6428 case 30:
6429 switch (sel) {
6430 case 0:
6431 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
6432 rn = "ErrorEPC";
6433 break;
6434 default:
6435 goto cp0_unimplemented;
6437 break;
6438 case 31:
6439 switch (sel) {
6440 case 0:
6441 /* EJTAG support */
6442 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6443 rn = "DESAVE";
6444 break;
6445 case 2 ... 7:
6446 CP0_CHECK(ctx->kscrexist & (1 << sel));
6447 tcg_gen_st_tl(arg, cpu_env,
6448 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6449 rn = "KScratch";
6450 break;
6451 default:
6452 goto cp0_unimplemented;
6454 /* Stop translation as we may have switched the execution mode */
6455 ctx->bstate = BS_STOP;
6456 break;
6457 default:
6458 goto cp0_unimplemented;
6460 (void)rn; /* avoid a compiler warning */
6461 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6462 /* For simplicity assume that all writes can cause interrupts. */
6463 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6464 gen_io_end();
6465 ctx->bstate = BS_STOP;
6467 return;
6469 cp0_unimplemented:
6470 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6473 #if defined(TARGET_MIPS64)
6474 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6476 const char *rn = "invalid";
6478 if (sel != 0)
6479 check_insn(ctx, ISA_MIPS64);
6481 switch (reg) {
6482 case 0:
6483 switch (sel) {
6484 case 0:
6485 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6486 rn = "Index";
6487 break;
6488 case 1:
6489 CP0_CHECK(ctx->insn_flags & ASE_MT);
6490 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6491 rn = "MVPControl";
6492 break;
6493 case 2:
6494 CP0_CHECK(ctx->insn_flags & ASE_MT);
6495 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6496 rn = "MVPConf0";
6497 break;
6498 case 3:
6499 CP0_CHECK(ctx->insn_flags & ASE_MT);
6500 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6501 rn = "MVPConf1";
6502 break;
6503 default:
6504 goto cp0_unimplemented;
6506 break;
6507 case 1:
6508 switch (sel) {
6509 case 0:
6510 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6511 gen_helper_mfc0_random(arg, cpu_env);
6512 rn = "Random";
6513 break;
6514 case 1:
6515 CP0_CHECK(ctx->insn_flags & ASE_MT);
6516 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6517 rn = "VPEControl";
6518 break;
6519 case 2:
6520 CP0_CHECK(ctx->insn_flags & ASE_MT);
6521 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6522 rn = "VPEConf0";
6523 break;
6524 case 3:
6525 CP0_CHECK(ctx->insn_flags & ASE_MT);
6526 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6527 rn = "VPEConf1";
6528 break;
6529 case 4:
6530 CP0_CHECK(ctx->insn_flags & ASE_MT);
6531 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6532 rn = "YQMask";
6533 break;
6534 case 5:
6535 CP0_CHECK(ctx->insn_flags & ASE_MT);
6536 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6537 rn = "VPESchedule";
6538 break;
6539 case 6:
6540 CP0_CHECK(ctx->insn_flags & ASE_MT);
6541 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6542 rn = "VPEScheFBack";
6543 break;
6544 case 7:
6545 CP0_CHECK(ctx->insn_flags & ASE_MT);
6546 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6547 rn = "VPEOpt";
6548 break;
6549 default:
6550 goto cp0_unimplemented;
6552 break;
6553 case 2:
6554 switch (sel) {
6555 case 0:
6556 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6557 rn = "EntryLo0";
6558 break;
6559 case 1:
6560 CP0_CHECK(ctx->insn_flags & ASE_MT);
6561 gen_helper_mfc0_tcstatus(arg, cpu_env);
6562 rn = "TCStatus";
6563 break;
6564 case 2:
6565 CP0_CHECK(ctx->insn_flags & ASE_MT);
6566 gen_helper_mfc0_tcbind(arg, cpu_env);
6567 rn = "TCBind";
6568 break;
6569 case 3:
6570 CP0_CHECK(ctx->insn_flags & ASE_MT);
6571 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6572 rn = "TCRestart";
6573 break;
6574 case 4:
6575 CP0_CHECK(ctx->insn_flags & ASE_MT);
6576 gen_helper_dmfc0_tchalt(arg, cpu_env);
6577 rn = "TCHalt";
6578 break;
6579 case 5:
6580 CP0_CHECK(ctx->insn_flags & ASE_MT);
6581 gen_helper_dmfc0_tccontext(arg, cpu_env);
6582 rn = "TCContext";
6583 break;
6584 case 6:
6585 CP0_CHECK(ctx->insn_flags & ASE_MT);
6586 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6587 rn = "TCSchedule";
6588 break;
6589 case 7:
6590 CP0_CHECK(ctx->insn_flags & ASE_MT);
6591 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6592 rn = "TCScheFBack";
6593 break;
6594 default:
6595 goto cp0_unimplemented;
6597 break;
6598 case 3:
6599 switch (sel) {
6600 case 0:
6601 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6602 rn = "EntryLo1";
6603 break;
6604 default:
6605 goto cp0_unimplemented;
6607 break;
6608 case 4:
6609 switch (sel) {
6610 case 0:
6611 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6612 rn = "Context";
6613 break;
6614 case 1:
6615 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6616 rn = "ContextConfig";
6617 goto cp0_unimplemented;
6618 // break;
6619 case 2:
6620 CP0_CHECK(ctx->ulri);
6621 tcg_gen_ld_tl(arg, cpu_env,
6622 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6623 rn = "UserLocal";
6624 break;
6625 default:
6626 goto cp0_unimplemented;
6628 break;
6629 case 5:
6630 switch (sel) {
6631 case 0:
6632 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6633 rn = "PageMask";
6634 break;
6635 case 1:
6636 check_insn(ctx, ISA_MIPS32R2);
6637 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6638 rn = "PageGrain";
6639 break;
6640 default:
6641 goto cp0_unimplemented;
6643 break;
6644 case 6:
6645 switch (sel) {
6646 case 0:
6647 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6648 rn = "Wired";
6649 break;
6650 case 1:
6651 check_insn(ctx, ISA_MIPS32R2);
6652 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6653 rn = "SRSConf0";
6654 break;
6655 case 2:
6656 check_insn(ctx, ISA_MIPS32R2);
6657 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6658 rn = "SRSConf1";
6659 break;
6660 case 3:
6661 check_insn(ctx, ISA_MIPS32R2);
6662 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6663 rn = "SRSConf2";
6664 break;
6665 case 4:
6666 check_insn(ctx, ISA_MIPS32R2);
6667 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6668 rn = "SRSConf3";
6669 break;
6670 case 5:
6671 check_insn(ctx, ISA_MIPS32R2);
6672 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6673 rn = "SRSConf4";
6674 break;
6675 default:
6676 goto cp0_unimplemented;
6678 break;
6679 case 7:
6680 switch (sel) {
6681 case 0:
6682 check_insn(ctx, ISA_MIPS32R2);
6683 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6684 rn = "HWREna";
6685 break;
6686 default:
6687 goto cp0_unimplemented;
6689 break;
6690 case 8:
6691 switch (sel) {
6692 case 0:
6693 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6694 rn = "BadVAddr";
6695 break;
6696 case 1:
6697 CP0_CHECK(ctx->bi);
6698 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6699 rn = "BadInstr";
6700 break;
6701 case 2:
6702 CP0_CHECK(ctx->bp);
6703 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6704 rn = "BadInstrP";
6705 break;
6706 default:
6707 goto cp0_unimplemented;
6709 break;
6710 case 9:
6711 switch (sel) {
6712 case 0:
6713 /* Mark as an IO operation because we read the time. */
6714 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6715 gen_io_start();
6717 gen_helper_mfc0_count(arg, cpu_env);
6718 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6719 gen_io_end();
6721 /* Break the TB to be able to take timer interrupts immediately
6722 after reading count. */
6723 ctx->bstate = BS_STOP;
6724 rn = "Count";
6725 break;
6726 /* 6,7 are implementation dependent */
6727 default:
6728 goto cp0_unimplemented;
6730 break;
6731 case 10:
6732 switch (sel) {
6733 case 0:
6734 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6735 rn = "EntryHi";
6736 break;
6737 default:
6738 goto cp0_unimplemented;
6740 break;
6741 case 11:
6742 switch (sel) {
6743 case 0:
6744 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6745 rn = "Compare";
6746 break;
6747 /* 6,7 are implementation dependent */
6748 default:
6749 goto cp0_unimplemented;
6751 break;
6752 case 12:
6753 switch (sel) {
6754 case 0:
6755 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6756 rn = "Status";
6757 break;
6758 case 1:
6759 check_insn(ctx, ISA_MIPS32R2);
6760 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6761 rn = "IntCtl";
6762 break;
6763 case 2:
6764 check_insn(ctx, ISA_MIPS32R2);
6765 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6766 rn = "SRSCtl";
6767 break;
6768 case 3:
6769 check_insn(ctx, ISA_MIPS32R2);
6770 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6771 rn = "SRSMap";
6772 break;
6773 default:
6774 goto cp0_unimplemented;
6776 break;
6777 case 13:
6778 switch (sel) {
6779 case 0:
6780 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6781 rn = "Cause";
6782 break;
6783 default:
6784 goto cp0_unimplemented;
6786 break;
6787 case 14:
6788 switch (sel) {
6789 case 0:
6790 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6791 rn = "EPC";
6792 break;
6793 default:
6794 goto cp0_unimplemented;
6796 break;
6797 case 15:
6798 switch (sel) {
6799 case 0:
6800 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6801 rn = "PRid";
6802 break;
6803 case 1:
6804 check_insn(ctx, ISA_MIPS32R2);
6805 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6806 rn = "EBase";
6807 break;
6808 default:
6809 goto cp0_unimplemented;
6811 break;
6812 case 16:
6813 switch (sel) {
6814 case 0:
6815 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6816 rn = "Config";
6817 break;
6818 case 1:
6819 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6820 rn = "Config1";
6821 break;
6822 case 2:
6823 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6824 rn = "Config2";
6825 break;
6826 case 3:
6827 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6828 rn = "Config3";
6829 break;
6830 case 4:
6831 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6832 rn = "Config4";
6833 break;
6834 case 5:
6835 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6836 rn = "Config5";
6837 break;
6838 /* 6,7 are implementation dependent */
6839 case 6:
6840 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6841 rn = "Config6";
6842 break;
6843 case 7:
6844 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6845 rn = "Config7";
6846 break;
6847 default:
6848 goto cp0_unimplemented;
6850 break;
6851 case 17:
6852 switch (sel) {
6853 case 0:
6854 gen_helper_dmfc0_lladdr(arg, cpu_env);
6855 rn = "LLAddr";
6856 break;
6857 default:
6858 goto cp0_unimplemented;
6860 break;
6861 case 18:
6862 switch (sel) {
6863 case 0 ... 7:
6864 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6865 rn = "WatchLo";
6866 break;
6867 default:
6868 goto cp0_unimplemented;
6870 break;
6871 case 19:
6872 switch (sel) {
6873 case 0 ... 7:
6874 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6875 rn = "WatchHi";
6876 break;
6877 default:
6878 goto cp0_unimplemented;
6880 break;
6881 case 20:
6882 switch (sel) {
6883 case 0:
6884 check_insn(ctx, ISA_MIPS3);
6885 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6886 rn = "XContext";
6887 break;
6888 default:
6889 goto cp0_unimplemented;
6891 break;
6892 case 21:
6893 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6894 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6895 switch (sel) {
6896 case 0:
6897 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6898 rn = "Framemask";
6899 break;
6900 default:
6901 goto cp0_unimplemented;
6903 break;
6904 case 22:
6905 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6906 rn = "'Diagnostic"; /* implementation dependent */
6907 break;
6908 case 23:
6909 switch (sel) {
6910 case 0:
6911 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6912 rn = "Debug";
6913 break;
6914 case 1:
6915 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6916 rn = "TraceControl";
6917 // break;
6918 case 2:
6919 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6920 rn = "TraceControl2";
6921 // break;
6922 case 3:
6923 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6924 rn = "UserTraceData";
6925 // break;
6926 case 4:
6927 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6928 rn = "TraceBPC";
6929 // break;
6930 default:
6931 goto cp0_unimplemented;
6933 break;
6934 case 24:
6935 switch (sel) {
6936 case 0:
6937 /* EJTAG support */
6938 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6939 rn = "DEPC";
6940 break;
6941 default:
6942 goto cp0_unimplemented;
6944 break;
6945 case 25:
6946 switch (sel) {
6947 case 0:
6948 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6949 rn = "Performance0";
6950 break;
6951 case 1:
6952 // gen_helper_dmfc0_performance1(arg);
6953 rn = "Performance1";
6954 // break;
6955 case 2:
6956 // gen_helper_dmfc0_performance2(arg);
6957 rn = "Performance2";
6958 // break;
6959 case 3:
6960 // gen_helper_dmfc0_performance3(arg);
6961 rn = "Performance3";
6962 // break;
6963 case 4:
6964 // gen_helper_dmfc0_performance4(arg);
6965 rn = "Performance4";
6966 // break;
6967 case 5:
6968 // gen_helper_dmfc0_performance5(arg);
6969 rn = "Performance5";
6970 // break;
6971 case 6:
6972 // gen_helper_dmfc0_performance6(arg);
6973 rn = "Performance6";
6974 // break;
6975 case 7:
6976 // gen_helper_dmfc0_performance7(arg);
6977 rn = "Performance7";
6978 // break;
6979 default:
6980 goto cp0_unimplemented;
6982 break;
6983 case 26:
6984 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6985 rn = "ECC";
6986 break;
6987 case 27:
6988 switch (sel) {
6989 /* ignored */
6990 case 0 ... 3:
6991 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6992 rn = "CacheErr";
6993 break;
6994 default:
6995 goto cp0_unimplemented;
6997 break;
6998 case 28:
6999 switch (sel) {
7000 case 0:
7001 case 2:
7002 case 4:
7003 case 6:
7004 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
7005 rn = "TagLo";
7006 break;
7007 case 1:
7008 case 3:
7009 case 5:
7010 case 7:
7011 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7012 rn = "DataLo";
7013 break;
7014 default:
7015 goto cp0_unimplemented;
7017 break;
7018 case 29:
7019 switch (sel) {
7020 case 0:
7021 case 2:
7022 case 4:
7023 case 6:
7024 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7025 rn = "TagHi";
7026 break;
7027 case 1:
7028 case 3:
7029 case 5:
7030 case 7:
7031 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7032 rn = "DataHi";
7033 break;
7034 default:
7035 goto cp0_unimplemented;
7037 break;
7038 case 30:
7039 switch (sel) {
7040 case 0:
7041 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7042 rn = "ErrorEPC";
7043 break;
7044 default:
7045 goto cp0_unimplemented;
7047 break;
7048 case 31:
7049 switch (sel) {
7050 case 0:
7051 /* EJTAG support */
7052 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7053 rn = "DESAVE";
7054 break;
7055 case 2 ... 7:
7056 CP0_CHECK(ctx->kscrexist & (1 << sel));
7057 tcg_gen_ld_tl(arg, cpu_env,
7058 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7059 rn = "KScratch";
7060 break;
7061 default:
7062 goto cp0_unimplemented;
7064 break;
7065 default:
7066 goto cp0_unimplemented;
7068 (void)rn; /* avoid a compiler warning */
7069 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7070 return;
7072 cp0_unimplemented:
7073 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7074 gen_mfc0_unimplemented(ctx, arg);
7077 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7079 const char *rn = "invalid";
7081 if (sel != 0)
7082 check_insn(ctx, ISA_MIPS64);
7084 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7085 gen_io_start();
7088 switch (reg) {
7089 case 0:
7090 switch (sel) {
7091 case 0:
7092 gen_helper_mtc0_index(cpu_env, arg);
7093 rn = "Index";
7094 break;
7095 case 1:
7096 CP0_CHECK(ctx->insn_flags & ASE_MT);
7097 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7098 rn = "MVPControl";
7099 break;
7100 case 2:
7101 CP0_CHECK(ctx->insn_flags & ASE_MT);
7102 /* ignored */
7103 rn = "MVPConf0";
7104 break;
7105 case 3:
7106 CP0_CHECK(ctx->insn_flags & ASE_MT);
7107 /* ignored */
7108 rn = "MVPConf1";
7109 break;
7110 default:
7111 goto cp0_unimplemented;
7113 break;
7114 case 1:
7115 switch (sel) {
7116 case 0:
7117 /* ignored */
7118 rn = "Random";
7119 break;
7120 case 1:
7121 CP0_CHECK(ctx->insn_flags & ASE_MT);
7122 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7123 rn = "VPEControl";
7124 break;
7125 case 2:
7126 CP0_CHECK(ctx->insn_flags & ASE_MT);
7127 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7128 rn = "VPEConf0";
7129 break;
7130 case 3:
7131 CP0_CHECK(ctx->insn_flags & ASE_MT);
7132 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7133 rn = "VPEConf1";
7134 break;
7135 case 4:
7136 CP0_CHECK(ctx->insn_flags & ASE_MT);
7137 gen_helper_mtc0_yqmask(cpu_env, arg);
7138 rn = "YQMask";
7139 break;
7140 case 5:
7141 CP0_CHECK(ctx->insn_flags & ASE_MT);
7142 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7143 rn = "VPESchedule";
7144 break;
7145 case 6:
7146 CP0_CHECK(ctx->insn_flags & ASE_MT);
7147 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7148 rn = "VPEScheFBack";
7149 break;
7150 case 7:
7151 CP0_CHECK(ctx->insn_flags & ASE_MT);
7152 gen_helper_mtc0_vpeopt(cpu_env, arg);
7153 rn = "VPEOpt";
7154 break;
7155 default:
7156 goto cp0_unimplemented;
7158 break;
7159 case 2:
7160 switch (sel) {
7161 case 0:
7162 gen_helper_dmtc0_entrylo0(cpu_env, arg);
7163 rn = "EntryLo0";
7164 break;
7165 case 1:
7166 CP0_CHECK(ctx->insn_flags & ASE_MT);
7167 gen_helper_mtc0_tcstatus(cpu_env, arg);
7168 rn = "TCStatus";
7169 break;
7170 case 2:
7171 CP0_CHECK(ctx->insn_flags & ASE_MT);
7172 gen_helper_mtc0_tcbind(cpu_env, arg);
7173 rn = "TCBind";
7174 break;
7175 case 3:
7176 CP0_CHECK(ctx->insn_flags & ASE_MT);
7177 gen_helper_mtc0_tcrestart(cpu_env, arg);
7178 rn = "TCRestart";
7179 break;
7180 case 4:
7181 CP0_CHECK(ctx->insn_flags & ASE_MT);
7182 gen_helper_mtc0_tchalt(cpu_env, arg);
7183 rn = "TCHalt";
7184 break;
7185 case 5:
7186 CP0_CHECK(ctx->insn_flags & ASE_MT);
7187 gen_helper_mtc0_tccontext(cpu_env, arg);
7188 rn = "TCContext";
7189 break;
7190 case 6:
7191 CP0_CHECK(ctx->insn_flags & ASE_MT);
7192 gen_helper_mtc0_tcschedule(cpu_env, arg);
7193 rn = "TCSchedule";
7194 break;
7195 case 7:
7196 CP0_CHECK(ctx->insn_flags & ASE_MT);
7197 gen_helper_mtc0_tcschefback(cpu_env, arg);
7198 rn = "TCScheFBack";
7199 break;
7200 default:
7201 goto cp0_unimplemented;
7203 break;
7204 case 3:
7205 switch (sel) {
7206 case 0:
7207 gen_helper_dmtc0_entrylo1(cpu_env, arg);
7208 rn = "EntryLo1";
7209 break;
7210 default:
7211 goto cp0_unimplemented;
7213 break;
7214 case 4:
7215 switch (sel) {
7216 case 0:
7217 gen_helper_mtc0_context(cpu_env, arg);
7218 rn = "Context";
7219 break;
7220 case 1:
7221 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7222 rn = "ContextConfig";
7223 goto cp0_unimplemented;
7224 // break;
7225 case 2:
7226 CP0_CHECK(ctx->ulri);
7227 tcg_gen_st_tl(arg, cpu_env,
7228 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7229 rn = "UserLocal";
7230 break;
7231 default:
7232 goto cp0_unimplemented;
7234 break;
7235 case 5:
7236 switch (sel) {
7237 case 0:
7238 gen_helper_mtc0_pagemask(cpu_env, arg);
7239 rn = "PageMask";
7240 break;
7241 case 1:
7242 check_insn(ctx, ISA_MIPS32R2);
7243 gen_helper_mtc0_pagegrain(cpu_env, arg);
7244 rn = "PageGrain";
7245 break;
7246 default:
7247 goto cp0_unimplemented;
7249 break;
7250 case 6:
7251 switch (sel) {
7252 case 0:
7253 gen_helper_mtc0_wired(cpu_env, arg);
7254 rn = "Wired";
7255 break;
7256 case 1:
7257 check_insn(ctx, ISA_MIPS32R2);
7258 gen_helper_mtc0_srsconf0(cpu_env, arg);
7259 rn = "SRSConf0";
7260 break;
7261 case 2:
7262 check_insn(ctx, ISA_MIPS32R2);
7263 gen_helper_mtc0_srsconf1(cpu_env, arg);
7264 rn = "SRSConf1";
7265 break;
7266 case 3:
7267 check_insn(ctx, ISA_MIPS32R2);
7268 gen_helper_mtc0_srsconf2(cpu_env, arg);
7269 rn = "SRSConf2";
7270 break;
7271 case 4:
7272 check_insn(ctx, ISA_MIPS32R2);
7273 gen_helper_mtc0_srsconf3(cpu_env, arg);
7274 rn = "SRSConf3";
7275 break;
7276 case 5:
7277 check_insn(ctx, ISA_MIPS32R2);
7278 gen_helper_mtc0_srsconf4(cpu_env, arg);
7279 rn = "SRSConf4";
7280 break;
7281 default:
7282 goto cp0_unimplemented;
7284 break;
7285 case 7:
7286 switch (sel) {
7287 case 0:
7288 check_insn(ctx, ISA_MIPS32R2);
7289 gen_helper_mtc0_hwrena(cpu_env, arg);
7290 ctx->bstate = BS_STOP;
7291 rn = "HWREna";
7292 break;
7293 default:
7294 goto cp0_unimplemented;
7296 break;
7297 case 8:
7298 switch (sel) {
7299 case 0:
7300 /* ignored */
7301 rn = "BadVAddr";
7302 break;
7303 case 1:
7304 /* ignored */
7305 rn = "BadInstr";
7306 break;
7307 case 2:
7308 /* ignored */
7309 rn = "BadInstrP";
7310 break;
7311 default:
7312 goto cp0_unimplemented;
7314 break;
7315 case 9:
7316 switch (sel) {
7317 case 0:
7318 gen_helper_mtc0_count(cpu_env, arg);
7319 rn = "Count";
7320 break;
7321 /* 6,7 are implementation dependent */
7322 default:
7323 goto cp0_unimplemented;
7325 /* Stop translation as we may have switched the execution mode */
7326 ctx->bstate = BS_STOP;
7327 break;
7328 case 10:
7329 switch (sel) {
7330 case 0:
7331 gen_helper_mtc0_entryhi(cpu_env, arg);
7332 rn = "EntryHi";
7333 break;
7334 default:
7335 goto cp0_unimplemented;
7337 break;
7338 case 11:
7339 switch (sel) {
7340 case 0:
7341 gen_helper_mtc0_compare(cpu_env, arg);
7342 rn = "Compare";
7343 break;
7344 /* 6,7 are implementation dependent */
7345 default:
7346 goto cp0_unimplemented;
7348 /* Stop translation as we may have switched the execution mode */
7349 ctx->bstate = BS_STOP;
7350 break;
7351 case 12:
7352 switch (sel) {
7353 case 0:
7354 save_cpu_state(ctx, 1);
7355 gen_helper_mtc0_status(cpu_env, arg);
7356 /* BS_STOP isn't good enough here, hflags may have changed. */
7357 gen_save_pc(ctx->pc + 4);
7358 ctx->bstate = BS_EXCP;
7359 rn = "Status";
7360 break;
7361 case 1:
7362 check_insn(ctx, ISA_MIPS32R2);
7363 gen_helper_mtc0_intctl(cpu_env, arg);
7364 /* Stop translation as we may have switched the execution mode */
7365 ctx->bstate = BS_STOP;
7366 rn = "IntCtl";
7367 break;
7368 case 2:
7369 check_insn(ctx, ISA_MIPS32R2);
7370 gen_helper_mtc0_srsctl(cpu_env, arg);
7371 /* Stop translation as we may have switched the execution mode */
7372 ctx->bstate = BS_STOP;
7373 rn = "SRSCtl";
7374 break;
7375 case 3:
7376 check_insn(ctx, ISA_MIPS32R2);
7377 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7378 /* Stop translation as we may have switched the execution mode */
7379 ctx->bstate = BS_STOP;
7380 rn = "SRSMap";
7381 break;
7382 default:
7383 goto cp0_unimplemented;
7385 break;
7386 case 13:
7387 switch (sel) {
7388 case 0:
7389 save_cpu_state(ctx, 1);
7390 /* Mark as an IO operation because we may trigger a software
7391 interrupt. */
7392 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7393 gen_io_start();
7395 gen_helper_mtc0_cause(cpu_env, arg);
7396 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7397 gen_io_end();
7399 /* Stop translation as we may have triggered an intetrupt */
7400 ctx->bstate = BS_STOP;
7401 rn = "Cause";
7402 break;
7403 default:
7404 goto cp0_unimplemented;
7406 break;
7407 case 14:
7408 switch (sel) {
7409 case 0:
7410 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7411 rn = "EPC";
7412 break;
7413 default:
7414 goto cp0_unimplemented;
7416 break;
7417 case 15:
7418 switch (sel) {
7419 case 0:
7420 /* ignored */
7421 rn = "PRid";
7422 break;
7423 case 1:
7424 check_insn(ctx, ISA_MIPS32R2);
7425 gen_helper_mtc0_ebase(cpu_env, arg);
7426 rn = "EBase";
7427 break;
7428 default:
7429 goto cp0_unimplemented;
7431 break;
7432 case 16:
7433 switch (sel) {
7434 case 0:
7435 gen_helper_mtc0_config0(cpu_env, arg);
7436 rn = "Config";
7437 /* Stop translation as we may have switched the execution mode */
7438 ctx->bstate = BS_STOP;
7439 break;
7440 case 1:
7441 /* ignored, read only */
7442 rn = "Config1";
7443 break;
7444 case 2:
7445 gen_helper_mtc0_config2(cpu_env, arg);
7446 rn = "Config2";
7447 /* Stop translation as we may have switched the execution mode */
7448 ctx->bstate = BS_STOP;
7449 break;
7450 case 3:
7451 gen_helper_mtc0_config3(cpu_env, arg);
7452 rn = "Config3";
7453 /* Stop translation as we may have switched the execution mode */
7454 ctx->bstate = BS_STOP;
7455 break;
7456 case 4:
7457 /* currently ignored */
7458 rn = "Config4";
7459 break;
7460 case 5:
7461 gen_helper_mtc0_config5(cpu_env, arg);
7462 rn = "Config5";
7463 /* Stop translation as we may have switched the execution mode */
7464 ctx->bstate = BS_STOP;
7465 break;
7466 /* 6,7 are implementation dependent */
7467 default:
7468 rn = "Invalid config selector";
7469 goto cp0_unimplemented;
7471 break;
7472 case 17:
7473 switch (sel) {
7474 case 0:
7475 gen_helper_mtc0_lladdr(cpu_env, arg);
7476 rn = "LLAddr";
7477 break;
7478 default:
7479 goto cp0_unimplemented;
7481 break;
7482 case 18:
7483 switch (sel) {
7484 case 0 ... 7:
7485 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7486 rn = "WatchLo";
7487 break;
7488 default:
7489 goto cp0_unimplemented;
7491 break;
7492 case 19:
7493 switch (sel) {
7494 case 0 ... 7:
7495 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7496 rn = "WatchHi";
7497 break;
7498 default:
7499 goto cp0_unimplemented;
7501 break;
7502 case 20:
7503 switch (sel) {
7504 case 0:
7505 check_insn(ctx, ISA_MIPS3);
7506 gen_helper_mtc0_xcontext(cpu_env, arg);
7507 rn = "XContext";
7508 break;
7509 default:
7510 goto cp0_unimplemented;
7512 break;
7513 case 21:
7514 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7515 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7516 switch (sel) {
7517 case 0:
7518 gen_helper_mtc0_framemask(cpu_env, arg);
7519 rn = "Framemask";
7520 break;
7521 default:
7522 goto cp0_unimplemented;
7524 break;
7525 case 22:
7526 /* ignored */
7527 rn = "Diagnostic"; /* implementation dependent */
7528 break;
7529 case 23:
7530 switch (sel) {
7531 case 0:
7532 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7533 /* BS_STOP isn't good enough here, hflags may have changed. */
7534 gen_save_pc(ctx->pc + 4);
7535 ctx->bstate = BS_EXCP;
7536 rn = "Debug";
7537 break;
7538 case 1:
7539 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7540 /* Stop translation as we may have switched the execution mode */
7541 ctx->bstate = BS_STOP;
7542 rn = "TraceControl";
7543 // break;
7544 case 2:
7545 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7546 /* Stop translation as we may have switched the execution mode */
7547 ctx->bstate = BS_STOP;
7548 rn = "TraceControl2";
7549 // break;
7550 case 3:
7551 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7552 /* Stop translation as we may have switched the execution mode */
7553 ctx->bstate = BS_STOP;
7554 rn = "UserTraceData";
7555 // break;
7556 case 4:
7557 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7558 /* Stop translation as we may have switched the execution mode */
7559 ctx->bstate = BS_STOP;
7560 rn = "TraceBPC";
7561 // break;
7562 default:
7563 goto cp0_unimplemented;
7565 break;
7566 case 24:
7567 switch (sel) {
7568 case 0:
7569 /* EJTAG support */
7570 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7571 rn = "DEPC";
7572 break;
7573 default:
7574 goto cp0_unimplemented;
7576 break;
7577 case 25:
7578 switch (sel) {
7579 case 0:
7580 gen_helper_mtc0_performance0(cpu_env, arg);
7581 rn = "Performance0";
7582 break;
7583 case 1:
7584 // gen_helper_mtc0_performance1(cpu_env, arg);
7585 rn = "Performance1";
7586 // break;
7587 case 2:
7588 // gen_helper_mtc0_performance2(cpu_env, arg);
7589 rn = "Performance2";
7590 // break;
7591 case 3:
7592 // gen_helper_mtc0_performance3(cpu_env, arg);
7593 rn = "Performance3";
7594 // break;
7595 case 4:
7596 // gen_helper_mtc0_performance4(cpu_env, arg);
7597 rn = "Performance4";
7598 // break;
7599 case 5:
7600 // gen_helper_mtc0_performance5(cpu_env, arg);
7601 rn = "Performance5";
7602 // break;
7603 case 6:
7604 // gen_helper_mtc0_performance6(cpu_env, arg);
7605 rn = "Performance6";
7606 // break;
7607 case 7:
7608 // gen_helper_mtc0_performance7(cpu_env, arg);
7609 rn = "Performance7";
7610 // break;
7611 default:
7612 goto cp0_unimplemented;
7614 break;
7615 case 26:
7616 /* ignored */
7617 rn = "ECC";
7618 break;
7619 case 27:
7620 switch (sel) {
7621 case 0 ... 3:
7622 /* ignored */
7623 rn = "CacheErr";
7624 break;
7625 default:
7626 goto cp0_unimplemented;
7628 break;
7629 case 28:
7630 switch (sel) {
7631 case 0:
7632 case 2:
7633 case 4:
7634 case 6:
7635 gen_helper_mtc0_taglo(cpu_env, arg);
7636 rn = "TagLo";
7637 break;
7638 case 1:
7639 case 3:
7640 case 5:
7641 case 7:
7642 gen_helper_mtc0_datalo(cpu_env, arg);
7643 rn = "DataLo";
7644 break;
7645 default:
7646 goto cp0_unimplemented;
7648 break;
7649 case 29:
7650 switch (sel) {
7651 case 0:
7652 case 2:
7653 case 4:
7654 case 6:
7655 gen_helper_mtc0_taghi(cpu_env, arg);
7656 rn = "TagHi";
7657 break;
7658 case 1:
7659 case 3:
7660 case 5:
7661 case 7:
7662 gen_helper_mtc0_datahi(cpu_env, arg);
7663 rn = "DataHi";
7664 break;
7665 default:
7666 rn = "invalid sel";
7667 goto cp0_unimplemented;
7669 break;
7670 case 30:
7671 switch (sel) {
7672 case 0:
7673 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7674 rn = "ErrorEPC";
7675 break;
7676 default:
7677 goto cp0_unimplemented;
7679 break;
7680 case 31:
7681 switch (sel) {
7682 case 0:
7683 /* EJTAG support */
7684 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7685 rn = "DESAVE";
7686 break;
7687 case 2 ... 7:
7688 CP0_CHECK(ctx->kscrexist & (1 << sel));
7689 tcg_gen_st_tl(arg, cpu_env,
7690 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7691 rn = "KScratch";
7692 break;
7693 default:
7694 goto cp0_unimplemented;
7696 /* Stop translation as we may have switched the execution mode */
7697 ctx->bstate = BS_STOP;
7698 break;
7699 default:
7700 goto cp0_unimplemented;
7702 (void)rn; /* avoid a compiler warning */
7703 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7704 /* For simplicity assume that all writes can cause interrupts. */
7705 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7706 gen_io_end();
7707 ctx->bstate = BS_STOP;
7709 return;
7711 cp0_unimplemented:
7712 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7714 #endif /* TARGET_MIPS64 */
7716 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7717 int u, int sel, int h)
7719 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7720 TCGv t0 = tcg_temp_local_new();
7722 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7723 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7724 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7725 tcg_gen_movi_tl(t0, -1);
7726 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7727 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7728 tcg_gen_movi_tl(t0, -1);
7729 else if (u == 0) {
7730 switch (rt) {
7731 case 1:
7732 switch (sel) {
7733 case 1:
7734 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7735 break;
7736 case 2:
7737 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7738 break;
7739 default:
7740 goto die;
7741 break;
7743 break;
7744 case 2:
7745 switch (sel) {
7746 case 1:
7747 gen_helper_mftc0_tcstatus(t0, cpu_env);
7748 break;
7749 case 2:
7750 gen_helper_mftc0_tcbind(t0, cpu_env);
7751 break;
7752 case 3:
7753 gen_helper_mftc0_tcrestart(t0, cpu_env);
7754 break;
7755 case 4:
7756 gen_helper_mftc0_tchalt(t0, cpu_env);
7757 break;
7758 case 5:
7759 gen_helper_mftc0_tccontext(t0, cpu_env);
7760 break;
7761 case 6:
7762 gen_helper_mftc0_tcschedule(t0, cpu_env);
7763 break;
7764 case 7:
7765 gen_helper_mftc0_tcschefback(t0, cpu_env);
7766 break;
7767 default:
7768 gen_mfc0(ctx, t0, rt, sel);
7769 break;
7771 break;
7772 case 10:
7773 switch (sel) {
7774 case 0:
7775 gen_helper_mftc0_entryhi(t0, cpu_env);
7776 break;
7777 default:
7778 gen_mfc0(ctx, t0, rt, sel);
7779 break;
7781 case 12:
7782 switch (sel) {
7783 case 0:
7784 gen_helper_mftc0_status(t0, cpu_env);
7785 break;
7786 default:
7787 gen_mfc0(ctx, t0, rt, sel);
7788 break;
7790 case 13:
7791 switch (sel) {
7792 case 0:
7793 gen_helper_mftc0_cause(t0, cpu_env);
7794 break;
7795 default:
7796 goto die;
7797 break;
7799 break;
7800 case 14:
7801 switch (sel) {
7802 case 0:
7803 gen_helper_mftc0_epc(t0, cpu_env);
7804 break;
7805 default:
7806 goto die;
7807 break;
7809 break;
7810 case 15:
7811 switch (sel) {
7812 case 1:
7813 gen_helper_mftc0_ebase(t0, cpu_env);
7814 break;
7815 default:
7816 goto die;
7817 break;
7819 break;
7820 case 16:
7821 switch (sel) {
7822 case 0 ... 7:
7823 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7824 break;
7825 default:
7826 goto die;
7827 break;
7829 break;
7830 case 23:
7831 switch (sel) {
7832 case 0:
7833 gen_helper_mftc0_debug(t0, cpu_env);
7834 break;
7835 default:
7836 gen_mfc0(ctx, t0, rt, sel);
7837 break;
7839 break;
7840 default:
7841 gen_mfc0(ctx, t0, rt, sel);
7843 } else switch (sel) {
7844 /* GPR registers. */
7845 case 0:
7846 gen_helper_1e0i(mftgpr, t0, rt);
7847 break;
7848 /* Auxiliary CPU registers */
7849 case 1:
7850 switch (rt) {
7851 case 0:
7852 gen_helper_1e0i(mftlo, t0, 0);
7853 break;
7854 case 1:
7855 gen_helper_1e0i(mfthi, t0, 0);
7856 break;
7857 case 2:
7858 gen_helper_1e0i(mftacx, t0, 0);
7859 break;
7860 case 4:
7861 gen_helper_1e0i(mftlo, t0, 1);
7862 break;
7863 case 5:
7864 gen_helper_1e0i(mfthi, t0, 1);
7865 break;
7866 case 6:
7867 gen_helper_1e0i(mftacx, t0, 1);
7868 break;
7869 case 8:
7870 gen_helper_1e0i(mftlo, t0, 2);
7871 break;
7872 case 9:
7873 gen_helper_1e0i(mfthi, t0, 2);
7874 break;
7875 case 10:
7876 gen_helper_1e0i(mftacx, t0, 2);
7877 break;
7878 case 12:
7879 gen_helper_1e0i(mftlo, t0, 3);
7880 break;
7881 case 13:
7882 gen_helper_1e0i(mfthi, t0, 3);
7883 break;
7884 case 14:
7885 gen_helper_1e0i(mftacx, t0, 3);
7886 break;
7887 case 16:
7888 gen_helper_mftdsp(t0, cpu_env);
7889 break;
7890 default:
7891 goto die;
7893 break;
7894 /* Floating point (COP1). */
7895 case 2:
7896 /* XXX: For now we support only a single FPU context. */
7897 if (h == 0) {
7898 TCGv_i32 fp0 = tcg_temp_new_i32();
7900 gen_load_fpr32(ctx, fp0, rt);
7901 tcg_gen_ext_i32_tl(t0, fp0);
7902 tcg_temp_free_i32(fp0);
7903 } else {
7904 TCGv_i32 fp0 = tcg_temp_new_i32();
7906 gen_load_fpr32h(ctx, fp0, rt);
7907 tcg_gen_ext_i32_tl(t0, fp0);
7908 tcg_temp_free_i32(fp0);
7910 break;
7911 case 3:
7912 /* XXX: For now we support only a single FPU context. */
7913 gen_helper_1e0i(cfc1, t0, rt);
7914 break;
7915 /* COP2: Not implemented. */
7916 case 4:
7917 case 5:
7918 /* fall through */
7919 default:
7920 goto die;
7922 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7923 gen_store_gpr(t0, rd);
7924 tcg_temp_free(t0);
7925 return;
7927 die:
7928 tcg_temp_free(t0);
7929 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7930 generate_exception(ctx, EXCP_RI);
7933 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7934 int u, int sel, int h)
7936 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7937 TCGv t0 = tcg_temp_local_new();
7939 gen_load_gpr(t0, rt);
7940 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7941 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7942 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7943 /* NOP */ ;
7944 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7945 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7946 /* NOP */ ;
7947 else if (u == 0) {
7948 switch (rd) {
7949 case 1:
7950 switch (sel) {
7951 case 1:
7952 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7953 break;
7954 case 2:
7955 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7956 break;
7957 default:
7958 goto die;
7959 break;
7961 break;
7962 case 2:
7963 switch (sel) {
7964 case 1:
7965 gen_helper_mttc0_tcstatus(cpu_env, t0);
7966 break;
7967 case 2:
7968 gen_helper_mttc0_tcbind(cpu_env, t0);
7969 break;
7970 case 3:
7971 gen_helper_mttc0_tcrestart(cpu_env, t0);
7972 break;
7973 case 4:
7974 gen_helper_mttc0_tchalt(cpu_env, t0);
7975 break;
7976 case 5:
7977 gen_helper_mttc0_tccontext(cpu_env, t0);
7978 break;
7979 case 6:
7980 gen_helper_mttc0_tcschedule(cpu_env, t0);
7981 break;
7982 case 7:
7983 gen_helper_mttc0_tcschefback(cpu_env, t0);
7984 break;
7985 default:
7986 gen_mtc0(ctx, t0, rd, sel);
7987 break;
7989 break;
7990 case 10:
7991 switch (sel) {
7992 case 0:
7993 gen_helper_mttc0_entryhi(cpu_env, t0);
7994 break;
7995 default:
7996 gen_mtc0(ctx, t0, rd, sel);
7997 break;
7999 case 12:
8000 switch (sel) {
8001 case 0:
8002 gen_helper_mttc0_status(cpu_env, t0);
8003 break;
8004 default:
8005 gen_mtc0(ctx, t0, rd, sel);
8006 break;
8008 case 13:
8009 switch (sel) {
8010 case 0:
8011 gen_helper_mttc0_cause(cpu_env, t0);
8012 break;
8013 default:
8014 goto die;
8015 break;
8017 break;
8018 case 15:
8019 switch (sel) {
8020 case 1:
8021 gen_helper_mttc0_ebase(cpu_env, t0);
8022 break;
8023 default:
8024 goto die;
8025 break;
8027 break;
8028 case 23:
8029 switch (sel) {
8030 case 0:
8031 gen_helper_mttc0_debug(cpu_env, t0);
8032 break;
8033 default:
8034 gen_mtc0(ctx, t0, rd, sel);
8035 break;
8037 break;
8038 default:
8039 gen_mtc0(ctx, t0, rd, sel);
8041 } else switch (sel) {
8042 /* GPR registers. */
8043 case 0:
8044 gen_helper_0e1i(mttgpr, t0, rd);
8045 break;
8046 /* Auxiliary CPU registers */
8047 case 1:
8048 switch (rd) {
8049 case 0:
8050 gen_helper_0e1i(mttlo, t0, 0);
8051 break;
8052 case 1:
8053 gen_helper_0e1i(mtthi, t0, 0);
8054 break;
8055 case 2:
8056 gen_helper_0e1i(mttacx, t0, 0);
8057 break;
8058 case 4:
8059 gen_helper_0e1i(mttlo, t0, 1);
8060 break;
8061 case 5:
8062 gen_helper_0e1i(mtthi, t0, 1);
8063 break;
8064 case 6:
8065 gen_helper_0e1i(mttacx, t0, 1);
8066 break;
8067 case 8:
8068 gen_helper_0e1i(mttlo, t0, 2);
8069 break;
8070 case 9:
8071 gen_helper_0e1i(mtthi, t0, 2);
8072 break;
8073 case 10:
8074 gen_helper_0e1i(mttacx, t0, 2);
8075 break;
8076 case 12:
8077 gen_helper_0e1i(mttlo, t0, 3);
8078 break;
8079 case 13:
8080 gen_helper_0e1i(mtthi, t0, 3);
8081 break;
8082 case 14:
8083 gen_helper_0e1i(mttacx, t0, 3);
8084 break;
8085 case 16:
8086 gen_helper_mttdsp(cpu_env, t0);
8087 break;
8088 default:
8089 goto die;
8091 break;
8092 /* Floating point (COP1). */
8093 case 2:
8094 /* XXX: For now we support only a single FPU context. */
8095 if (h == 0) {
8096 TCGv_i32 fp0 = tcg_temp_new_i32();
8098 tcg_gen_trunc_tl_i32(fp0, t0);
8099 gen_store_fpr32(ctx, fp0, rd);
8100 tcg_temp_free_i32(fp0);
8101 } else {
8102 TCGv_i32 fp0 = tcg_temp_new_i32();
8104 tcg_gen_trunc_tl_i32(fp0, t0);
8105 gen_store_fpr32h(ctx, fp0, rd);
8106 tcg_temp_free_i32(fp0);
8108 break;
8109 case 3:
8110 /* XXX: For now we support only a single FPU context. */
8111 save_cpu_state(ctx, 1);
8113 TCGv_i32 fs_tmp = tcg_const_i32(rd);
8115 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8116 tcg_temp_free_i32(fs_tmp);
8118 /* Stop translation as we may have changed hflags */
8119 ctx->bstate = BS_STOP;
8120 break;
8121 /* COP2: Not implemented. */
8122 case 4:
8123 case 5:
8124 /* fall through */
8125 default:
8126 goto die;
8128 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8129 tcg_temp_free(t0);
8130 return;
8132 die:
8133 tcg_temp_free(t0);
8134 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8135 generate_exception(ctx, EXCP_RI);
8138 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
8140 const char *opn = "ldst";
8142 check_cp0_enabled(ctx);
8143 switch (opc) {
8144 case OPC_MFC0:
8145 if (rt == 0) {
8146 /* Treat as NOP. */
8147 return;
8149 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8150 opn = "mfc0";
8151 break;
8152 case OPC_MTC0:
8154 TCGv t0 = tcg_temp_new();
8156 gen_load_gpr(t0, rt);
8157 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8158 tcg_temp_free(t0);
8160 opn = "mtc0";
8161 break;
8162 #if defined(TARGET_MIPS64)
8163 case OPC_DMFC0:
8164 check_insn(ctx, ISA_MIPS3);
8165 if (rt == 0) {
8166 /* Treat as NOP. */
8167 return;
8169 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8170 opn = "dmfc0";
8171 break;
8172 case OPC_DMTC0:
8173 check_insn(ctx, ISA_MIPS3);
8175 TCGv t0 = tcg_temp_new();
8177 gen_load_gpr(t0, rt);
8178 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8179 tcg_temp_free(t0);
8181 opn = "dmtc0";
8182 break;
8183 #endif
8184 case OPC_MFHC0:
8185 check_mvh(ctx);
8186 if (rt == 0) {
8187 /* Treat as NOP. */
8188 return;
8190 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8191 opn = "mfhc0";
8192 break;
8193 case OPC_MTHC0:
8194 check_mvh(ctx);
8196 TCGv t0 = tcg_temp_new();
8197 gen_load_gpr(t0, rt);
8198 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8199 tcg_temp_free(t0);
8201 opn = "mthc0";
8202 break;
8203 case OPC_MFTR:
8204 check_insn(ctx, ASE_MT);
8205 if (rd == 0) {
8206 /* Treat as NOP. */
8207 return;
8209 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8210 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8211 opn = "mftr";
8212 break;
8213 case OPC_MTTR:
8214 check_insn(ctx, ASE_MT);
8215 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8216 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8217 opn = "mttr";
8218 break;
8219 case OPC_TLBWI:
8220 opn = "tlbwi";
8221 if (!env->tlb->helper_tlbwi)
8222 goto die;
8223 gen_helper_tlbwi(cpu_env);
8224 break;
8225 case OPC_TLBINV:
8226 opn = "tlbinv";
8227 if (ctx->ie >= 2) {
8228 if (!env->tlb->helper_tlbinv) {
8229 goto die;
8231 gen_helper_tlbinv(cpu_env);
8232 } /* treat as nop if TLBINV not supported */
8233 break;
8234 case OPC_TLBINVF:
8235 opn = "tlbinvf";
8236 if (ctx->ie >= 2) {
8237 if (!env->tlb->helper_tlbinvf) {
8238 goto die;
8240 gen_helper_tlbinvf(cpu_env);
8241 } /* treat as nop if TLBINV not supported */
8242 break;
8243 case OPC_TLBWR:
8244 opn = "tlbwr";
8245 if (!env->tlb->helper_tlbwr)
8246 goto die;
8247 gen_helper_tlbwr(cpu_env);
8248 break;
8249 case OPC_TLBP:
8250 opn = "tlbp";
8251 if (!env->tlb->helper_tlbp)
8252 goto die;
8253 gen_helper_tlbp(cpu_env);
8254 break;
8255 case OPC_TLBR:
8256 opn = "tlbr";
8257 if (!env->tlb->helper_tlbr)
8258 goto die;
8259 gen_helper_tlbr(cpu_env);
8260 break;
8261 case OPC_ERET: /* OPC_ERETNC */
8262 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8263 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8264 MIPS_DEBUG("CTI in delay / forbidden slot");
8265 goto die;
8266 } else {
8267 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8268 if (ctx->opcode & (1 << bit_shift)) {
8269 /* OPC_ERETNC */
8270 opn = "eretnc";
8271 check_insn(ctx, ISA_MIPS32R5);
8272 gen_helper_eretnc(cpu_env);
8273 } else {
8274 /* OPC_ERET */
8275 opn = "eret";
8276 check_insn(ctx, ISA_MIPS2);
8277 gen_helper_eret(cpu_env);
8279 ctx->bstate = BS_EXCP;
8281 break;
8282 case OPC_DERET:
8283 opn = "deret";
8284 check_insn(ctx, ISA_MIPS32);
8285 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8286 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8287 MIPS_DEBUG("CTI in delay / forbidden slot");
8288 goto die;
8290 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8291 MIPS_INVAL(opn);
8292 generate_exception(ctx, EXCP_RI);
8293 } else {
8294 gen_helper_deret(cpu_env);
8295 ctx->bstate = BS_EXCP;
8297 break;
8298 case OPC_WAIT:
8299 opn = "wait";
8300 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8301 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8302 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8303 MIPS_DEBUG("CTI in delay / forbidden slot");
8304 goto die;
8306 /* If we get an exception, we want to restart at next instruction */
8307 ctx->pc += 4;
8308 save_cpu_state(ctx, 1);
8309 ctx->pc -= 4;
8310 gen_helper_wait(cpu_env);
8311 ctx->bstate = BS_EXCP;
8312 break;
8313 default:
8314 die:
8315 MIPS_INVAL(opn);
8316 generate_exception(ctx, EXCP_RI);
8317 return;
8319 (void)opn; /* avoid a compiler warning */
8320 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
8322 #endif /* !CONFIG_USER_ONLY */
8324 /* CP1 Branches (before delay slot) */
8325 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8326 int32_t cc, int32_t offset)
8328 target_ulong btarget;
8329 const char *opn = "cp1 cond branch";
8330 TCGv_i32 t0 = tcg_temp_new_i32();
8332 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8333 MIPS_DEBUG("CTI in delay / forbidden slot");
8334 generate_exception(ctx, EXCP_RI);
8335 goto out;
8338 if (cc != 0)
8339 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8341 btarget = ctx->pc + 4 + offset;
8343 switch (op) {
8344 case OPC_BC1F:
8345 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8346 tcg_gen_not_i32(t0, t0);
8347 tcg_gen_andi_i32(t0, t0, 1);
8348 tcg_gen_extu_i32_tl(bcond, t0);
8349 opn = "bc1f";
8350 goto not_likely;
8351 case OPC_BC1FL:
8352 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8353 tcg_gen_not_i32(t0, t0);
8354 tcg_gen_andi_i32(t0, t0, 1);
8355 tcg_gen_extu_i32_tl(bcond, t0);
8356 opn = "bc1fl";
8357 goto likely;
8358 case OPC_BC1T:
8359 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8360 tcg_gen_andi_i32(t0, t0, 1);
8361 tcg_gen_extu_i32_tl(bcond, t0);
8362 opn = "bc1t";
8363 goto not_likely;
8364 case OPC_BC1TL:
8365 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8366 tcg_gen_andi_i32(t0, t0, 1);
8367 tcg_gen_extu_i32_tl(bcond, t0);
8368 opn = "bc1tl";
8369 likely:
8370 ctx->hflags |= MIPS_HFLAG_BL;
8371 break;
8372 case OPC_BC1FANY2:
8374 TCGv_i32 t1 = tcg_temp_new_i32();
8375 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8376 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8377 tcg_gen_nand_i32(t0, t0, t1);
8378 tcg_temp_free_i32(t1);
8379 tcg_gen_andi_i32(t0, t0, 1);
8380 tcg_gen_extu_i32_tl(bcond, t0);
8382 opn = "bc1any2f";
8383 goto not_likely;
8384 case OPC_BC1TANY2:
8386 TCGv_i32 t1 = tcg_temp_new_i32();
8387 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8388 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8389 tcg_gen_or_i32(t0, t0, t1);
8390 tcg_temp_free_i32(t1);
8391 tcg_gen_andi_i32(t0, t0, 1);
8392 tcg_gen_extu_i32_tl(bcond, t0);
8394 opn = "bc1any2t";
8395 goto not_likely;
8396 case OPC_BC1FANY4:
8398 TCGv_i32 t1 = tcg_temp_new_i32();
8399 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8400 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8401 tcg_gen_and_i32(t0, t0, t1);
8402 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8403 tcg_gen_and_i32(t0, t0, t1);
8404 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8405 tcg_gen_nand_i32(t0, t0, t1);
8406 tcg_temp_free_i32(t1);
8407 tcg_gen_andi_i32(t0, t0, 1);
8408 tcg_gen_extu_i32_tl(bcond, t0);
8410 opn = "bc1any4f";
8411 goto not_likely;
8412 case OPC_BC1TANY4:
8414 TCGv_i32 t1 = tcg_temp_new_i32();
8415 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8416 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8417 tcg_gen_or_i32(t0, t0, t1);
8418 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8419 tcg_gen_or_i32(t0, t0, t1);
8420 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8421 tcg_gen_or_i32(t0, t0, t1);
8422 tcg_temp_free_i32(t1);
8423 tcg_gen_andi_i32(t0, t0, 1);
8424 tcg_gen_extu_i32_tl(bcond, t0);
8426 opn = "bc1any4t";
8427 not_likely:
8428 ctx->hflags |= MIPS_HFLAG_BC;
8429 break;
8430 default:
8431 MIPS_INVAL(opn);
8432 generate_exception (ctx, EXCP_RI);
8433 goto out;
8435 (void)opn; /* avoid a compiler warning */
8436 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8437 ctx->hflags, btarget);
8438 ctx->btarget = btarget;
8439 ctx->hflags |= MIPS_HFLAG_BDS32;
8440 out:
8441 tcg_temp_free_i32(t0);
8444 /* R6 CP1 Branches */
8445 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8446 int32_t ft, int32_t offset,
8447 int delayslot_size)
8449 target_ulong btarget;
8450 const char *opn = "cp1 cond branch";
8451 TCGv_i64 t0 = tcg_temp_new_i64();
8453 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8454 #ifdef MIPS_DEBUG_DISAS
8455 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8456 "\n", ctx->pc);
8457 #endif
8458 generate_exception(ctx, EXCP_RI);
8459 goto out;
8462 gen_load_fpr64(ctx, t0, ft);
8463 tcg_gen_andi_i64(t0, t0, 1);
8465 btarget = addr_add(ctx, ctx->pc + 4, offset);
8467 switch (op) {
8468 case OPC_BC1EQZ:
8469 tcg_gen_xori_i64(t0, t0, 1);
8470 opn = "bc1eqz";
8471 ctx->hflags |= MIPS_HFLAG_BC;
8472 break;
8473 case OPC_BC1NEZ:
8474 /* t0 already set */
8475 opn = "bc1nez";
8476 ctx->hflags |= MIPS_HFLAG_BC;
8477 break;
8478 default:
8479 MIPS_INVAL(opn);
8480 generate_exception(ctx, EXCP_RI);
8481 goto out;
8484 tcg_gen_trunc_i64_tl(bcond, t0);
8486 (void)opn; /* avoid a compiler warning */
8487 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8488 ctx->hflags, btarget);
8489 ctx->btarget = btarget;
8491 switch (delayslot_size) {
8492 case 2:
8493 ctx->hflags |= MIPS_HFLAG_BDS16;
8494 break;
8495 case 4:
8496 ctx->hflags |= MIPS_HFLAG_BDS32;
8497 break;
8500 out:
8501 tcg_temp_free_i64(t0);
8504 /* Coprocessor 1 (FPU) */
8506 #define FOP(func, fmt) (((fmt) << 21) | (func))
8508 enum fopcode {
8509 OPC_ADD_S = FOP(0, FMT_S),
8510 OPC_SUB_S = FOP(1, FMT_S),
8511 OPC_MUL_S = FOP(2, FMT_S),
8512 OPC_DIV_S = FOP(3, FMT_S),
8513 OPC_SQRT_S = FOP(4, FMT_S),
8514 OPC_ABS_S = FOP(5, FMT_S),
8515 OPC_MOV_S = FOP(6, FMT_S),
8516 OPC_NEG_S = FOP(7, FMT_S),
8517 OPC_ROUND_L_S = FOP(8, FMT_S),
8518 OPC_TRUNC_L_S = FOP(9, FMT_S),
8519 OPC_CEIL_L_S = FOP(10, FMT_S),
8520 OPC_FLOOR_L_S = FOP(11, FMT_S),
8521 OPC_ROUND_W_S = FOP(12, FMT_S),
8522 OPC_TRUNC_W_S = FOP(13, FMT_S),
8523 OPC_CEIL_W_S = FOP(14, FMT_S),
8524 OPC_FLOOR_W_S = FOP(15, FMT_S),
8525 OPC_SEL_S = FOP(16, FMT_S),
8526 OPC_MOVCF_S = FOP(17, FMT_S),
8527 OPC_MOVZ_S = FOP(18, FMT_S),
8528 OPC_MOVN_S = FOP(19, FMT_S),
8529 OPC_SELEQZ_S = FOP(20, FMT_S),
8530 OPC_RECIP_S = FOP(21, FMT_S),
8531 OPC_RSQRT_S = FOP(22, FMT_S),
8532 OPC_SELNEZ_S = FOP(23, FMT_S),
8533 OPC_MADDF_S = FOP(24, FMT_S),
8534 OPC_MSUBF_S = FOP(25, FMT_S),
8535 OPC_RINT_S = FOP(26, FMT_S),
8536 OPC_CLASS_S = FOP(27, FMT_S),
8537 OPC_MIN_S = FOP(28, FMT_S),
8538 OPC_RECIP2_S = FOP(28, FMT_S),
8539 OPC_MINA_S = FOP(29, FMT_S),
8540 OPC_RECIP1_S = FOP(29, FMT_S),
8541 OPC_MAX_S = FOP(30, FMT_S),
8542 OPC_RSQRT1_S = FOP(30, FMT_S),
8543 OPC_MAXA_S = FOP(31, FMT_S),
8544 OPC_RSQRT2_S = FOP(31, FMT_S),
8545 OPC_CVT_D_S = FOP(33, FMT_S),
8546 OPC_CVT_W_S = FOP(36, FMT_S),
8547 OPC_CVT_L_S = FOP(37, FMT_S),
8548 OPC_CVT_PS_S = FOP(38, FMT_S),
8549 OPC_CMP_F_S = FOP (48, FMT_S),
8550 OPC_CMP_UN_S = FOP (49, FMT_S),
8551 OPC_CMP_EQ_S = FOP (50, FMT_S),
8552 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8553 OPC_CMP_OLT_S = FOP (52, FMT_S),
8554 OPC_CMP_ULT_S = FOP (53, FMT_S),
8555 OPC_CMP_OLE_S = FOP (54, FMT_S),
8556 OPC_CMP_ULE_S = FOP (55, FMT_S),
8557 OPC_CMP_SF_S = FOP (56, FMT_S),
8558 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8559 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8560 OPC_CMP_NGL_S = FOP (59, FMT_S),
8561 OPC_CMP_LT_S = FOP (60, FMT_S),
8562 OPC_CMP_NGE_S = FOP (61, FMT_S),
8563 OPC_CMP_LE_S = FOP (62, FMT_S),
8564 OPC_CMP_NGT_S = FOP (63, FMT_S),
8566 OPC_ADD_D = FOP(0, FMT_D),
8567 OPC_SUB_D = FOP(1, FMT_D),
8568 OPC_MUL_D = FOP(2, FMT_D),
8569 OPC_DIV_D = FOP(3, FMT_D),
8570 OPC_SQRT_D = FOP(4, FMT_D),
8571 OPC_ABS_D = FOP(5, FMT_D),
8572 OPC_MOV_D = FOP(6, FMT_D),
8573 OPC_NEG_D = FOP(7, FMT_D),
8574 OPC_ROUND_L_D = FOP(8, FMT_D),
8575 OPC_TRUNC_L_D = FOP(9, FMT_D),
8576 OPC_CEIL_L_D = FOP(10, FMT_D),
8577 OPC_FLOOR_L_D = FOP(11, FMT_D),
8578 OPC_ROUND_W_D = FOP(12, FMT_D),
8579 OPC_TRUNC_W_D = FOP(13, FMT_D),
8580 OPC_CEIL_W_D = FOP(14, FMT_D),
8581 OPC_FLOOR_W_D = FOP(15, FMT_D),
8582 OPC_SEL_D = FOP(16, FMT_D),
8583 OPC_MOVCF_D = FOP(17, FMT_D),
8584 OPC_MOVZ_D = FOP(18, FMT_D),
8585 OPC_MOVN_D = FOP(19, FMT_D),
8586 OPC_SELEQZ_D = FOP(20, FMT_D),
8587 OPC_RECIP_D = FOP(21, FMT_D),
8588 OPC_RSQRT_D = FOP(22, FMT_D),
8589 OPC_SELNEZ_D = FOP(23, FMT_D),
8590 OPC_MADDF_D = FOP(24, FMT_D),
8591 OPC_MSUBF_D = FOP(25, FMT_D),
8592 OPC_RINT_D = FOP(26, FMT_D),
8593 OPC_CLASS_D = FOP(27, FMT_D),
8594 OPC_MIN_D = FOP(28, FMT_D),
8595 OPC_RECIP2_D = FOP(28, FMT_D),
8596 OPC_MINA_D = FOP(29, FMT_D),
8597 OPC_RECIP1_D = FOP(29, FMT_D),
8598 OPC_MAX_D = FOP(30, FMT_D),
8599 OPC_RSQRT1_D = FOP(30, FMT_D),
8600 OPC_MAXA_D = FOP(31, FMT_D),
8601 OPC_RSQRT2_D = FOP(31, FMT_D),
8602 OPC_CVT_S_D = FOP(32, FMT_D),
8603 OPC_CVT_W_D = FOP(36, FMT_D),
8604 OPC_CVT_L_D = FOP(37, FMT_D),
8605 OPC_CMP_F_D = FOP (48, FMT_D),
8606 OPC_CMP_UN_D = FOP (49, FMT_D),
8607 OPC_CMP_EQ_D = FOP (50, FMT_D),
8608 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8609 OPC_CMP_OLT_D = FOP (52, FMT_D),
8610 OPC_CMP_ULT_D = FOP (53, FMT_D),
8611 OPC_CMP_OLE_D = FOP (54, FMT_D),
8612 OPC_CMP_ULE_D = FOP (55, FMT_D),
8613 OPC_CMP_SF_D = FOP (56, FMT_D),
8614 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8615 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8616 OPC_CMP_NGL_D = FOP (59, FMT_D),
8617 OPC_CMP_LT_D = FOP (60, FMT_D),
8618 OPC_CMP_NGE_D = FOP (61, FMT_D),
8619 OPC_CMP_LE_D = FOP (62, FMT_D),
8620 OPC_CMP_NGT_D = FOP (63, FMT_D),
8622 OPC_CVT_S_W = FOP(32, FMT_W),
8623 OPC_CVT_D_W = FOP(33, FMT_W),
8624 OPC_CVT_S_L = FOP(32, FMT_L),
8625 OPC_CVT_D_L = FOP(33, FMT_L),
8626 OPC_CVT_PS_PW = FOP(38, FMT_W),
8628 OPC_ADD_PS = FOP(0, FMT_PS),
8629 OPC_SUB_PS = FOP(1, FMT_PS),
8630 OPC_MUL_PS = FOP(2, FMT_PS),
8631 OPC_DIV_PS = FOP(3, FMT_PS),
8632 OPC_ABS_PS = FOP(5, FMT_PS),
8633 OPC_MOV_PS = FOP(6, FMT_PS),
8634 OPC_NEG_PS = FOP(7, FMT_PS),
8635 OPC_MOVCF_PS = FOP(17, FMT_PS),
8636 OPC_MOVZ_PS = FOP(18, FMT_PS),
8637 OPC_MOVN_PS = FOP(19, FMT_PS),
8638 OPC_ADDR_PS = FOP(24, FMT_PS),
8639 OPC_MULR_PS = FOP(26, FMT_PS),
8640 OPC_RECIP2_PS = FOP(28, FMT_PS),
8641 OPC_RECIP1_PS = FOP(29, FMT_PS),
8642 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8643 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8645 OPC_CVT_S_PU = FOP(32, FMT_PS),
8646 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8647 OPC_CVT_S_PL = FOP(40, FMT_PS),
8648 OPC_PLL_PS = FOP(44, FMT_PS),
8649 OPC_PLU_PS = FOP(45, FMT_PS),
8650 OPC_PUL_PS = FOP(46, FMT_PS),
8651 OPC_PUU_PS = FOP(47, FMT_PS),
8652 OPC_CMP_F_PS = FOP (48, FMT_PS),
8653 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8654 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8655 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8656 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8657 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8658 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8659 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8660 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8661 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8662 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8663 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8664 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8665 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8666 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8667 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8670 enum r6_f_cmp_op {
8671 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8672 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8673 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8674 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8675 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8676 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8677 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8678 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8679 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8680 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8681 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8682 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8683 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8684 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8685 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8686 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8687 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8688 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8689 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8690 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8691 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8692 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8694 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8695 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8696 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8697 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8698 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8699 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8700 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8701 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8702 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8703 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8704 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8705 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8706 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8707 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8708 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8709 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8710 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8711 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8712 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8713 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8714 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8715 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8717 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8719 const char *opn = "cp1 move";
8720 TCGv t0 = tcg_temp_new();
8722 switch (opc) {
8723 case OPC_MFC1:
8725 TCGv_i32 fp0 = tcg_temp_new_i32();
8727 gen_load_fpr32(ctx, fp0, fs);
8728 tcg_gen_ext_i32_tl(t0, fp0);
8729 tcg_temp_free_i32(fp0);
8731 gen_store_gpr(t0, rt);
8732 opn = "mfc1";
8733 break;
8734 case OPC_MTC1:
8735 gen_load_gpr(t0, rt);
8737 TCGv_i32 fp0 = tcg_temp_new_i32();
8739 tcg_gen_trunc_tl_i32(fp0, t0);
8740 gen_store_fpr32(ctx, fp0, fs);
8741 tcg_temp_free_i32(fp0);
8743 opn = "mtc1";
8744 break;
8745 case OPC_CFC1:
8746 gen_helper_1e0i(cfc1, t0, fs);
8747 gen_store_gpr(t0, rt);
8748 opn = "cfc1";
8749 break;
8750 case OPC_CTC1:
8751 gen_load_gpr(t0, rt);
8752 save_cpu_state(ctx, 1);
8754 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8756 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8757 tcg_temp_free_i32(fs_tmp);
8759 /* Stop translation as we may have changed hflags */
8760 ctx->bstate = BS_STOP;
8761 opn = "ctc1";
8762 break;
8763 #if defined(TARGET_MIPS64)
8764 case OPC_DMFC1:
8765 gen_load_fpr64(ctx, t0, fs);
8766 gen_store_gpr(t0, rt);
8767 opn = "dmfc1";
8768 break;
8769 case OPC_DMTC1:
8770 gen_load_gpr(t0, rt);
8771 gen_store_fpr64(ctx, t0, fs);
8772 opn = "dmtc1";
8773 break;
8774 #endif
8775 case OPC_MFHC1:
8777 TCGv_i32 fp0 = tcg_temp_new_i32();
8779 gen_load_fpr32h(ctx, fp0, fs);
8780 tcg_gen_ext_i32_tl(t0, fp0);
8781 tcg_temp_free_i32(fp0);
8783 gen_store_gpr(t0, rt);
8784 opn = "mfhc1";
8785 break;
8786 case OPC_MTHC1:
8787 gen_load_gpr(t0, rt);
8789 TCGv_i32 fp0 = tcg_temp_new_i32();
8791 tcg_gen_trunc_tl_i32(fp0, t0);
8792 gen_store_fpr32h(ctx, fp0, fs);
8793 tcg_temp_free_i32(fp0);
8795 opn = "mthc1";
8796 break;
8797 default:
8798 MIPS_INVAL(opn);
8799 generate_exception (ctx, EXCP_RI);
8800 goto out;
8802 (void)opn; /* avoid a compiler warning */
8803 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
8805 out:
8806 tcg_temp_free(t0);
8809 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8811 TCGLabel *l1;
8812 TCGCond cond;
8813 TCGv_i32 t0;
8815 if (rd == 0) {
8816 /* Treat as NOP. */
8817 return;
8820 if (tf)
8821 cond = TCG_COND_EQ;
8822 else
8823 cond = TCG_COND_NE;
8825 l1 = gen_new_label();
8826 t0 = tcg_temp_new_i32();
8827 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8828 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8829 tcg_temp_free_i32(t0);
8830 if (rs == 0) {
8831 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8832 } else {
8833 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8835 gen_set_label(l1);
8838 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
8839 int tf)
8841 int cond;
8842 TCGv_i32 t0 = tcg_temp_new_i32();
8843 TCGLabel *l1 = gen_new_label();
8845 if (tf)
8846 cond = TCG_COND_EQ;
8847 else
8848 cond = TCG_COND_NE;
8850 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8851 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8852 gen_load_fpr32(ctx, t0, fs);
8853 gen_store_fpr32(ctx, t0, fd);
8854 gen_set_label(l1);
8855 tcg_temp_free_i32(t0);
8858 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8860 int cond;
8861 TCGv_i32 t0 = tcg_temp_new_i32();
8862 TCGv_i64 fp0;
8863 TCGLabel *l1 = gen_new_label();
8865 if (tf)
8866 cond = TCG_COND_EQ;
8867 else
8868 cond = TCG_COND_NE;
8870 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8871 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8872 tcg_temp_free_i32(t0);
8873 fp0 = tcg_temp_new_i64();
8874 gen_load_fpr64(ctx, fp0, fs);
8875 gen_store_fpr64(ctx, fp0, fd);
8876 tcg_temp_free_i64(fp0);
8877 gen_set_label(l1);
8880 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8881 int cc, int tf)
8883 int cond;
8884 TCGv_i32 t0 = tcg_temp_new_i32();
8885 TCGLabel *l1 = gen_new_label();
8886 TCGLabel *l2 = gen_new_label();
8888 if (tf)
8889 cond = TCG_COND_EQ;
8890 else
8891 cond = TCG_COND_NE;
8893 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8894 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8895 gen_load_fpr32(ctx, t0, fs);
8896 gen_store_fpr32(ctx, t0, fd);
8897 gen_set_label(l1);
8899 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8900 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8901 gen_load_fpr32h(ctx, t0, fs);
8902 gen_store_fpr32h(ctx, t0, fd);
8903 tcg_temp_free_i32(t0);
8904 gen_set_label(l2);
8907 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8908 int fs)
8910 TCGv_i32 t1 = tcg_const_i32(0);
8911 TCGv_i32 fp0 = tcg_temp_new_i32();
8912 TCGv_i32 fp1 = tcg_temp_new_i32();
8913 TCGv_i32 fp2 = tcg_temp_new_i32();
8914 gen_load_fpr32(ctx, fp0, fd);
8915 gen_load_fpr32(ctx, fp1, ft);
8916 gen_load_fpr32(ctx, fp2, fs);
8918 switch (op1) {
8919 case OPC_SEL_S:
8920 tcg_gen_andi_i32(fp0, fp0, 1);
8921 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8922 break;
8923 case OPC_SELEQZ_S:
8924 tcg_gen_andi_i32(fp1, fp1, 1);
8925 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8926 break;
8927 case OPC_SELNEZ_S:
8928 tcg_gen_andi_i32(fp1, fp1, 1);
8929 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8930 break;
8931 default:
8932 MIPS_INVAL("gen_sel_s");
8933 generate_exception (ctx, EXCP_RI);
8934 break;
8937 gen_store_fpr32(ctx, fp0, fd);
8938 tcg_temp_free_i32(fp2);
8939 tcg_temp_free_i32(fp1);
8940 tcg_temp_free_i32(fp0);
8941 tcg_temp_free_i32(t1);
8944 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8945 int fs)
8947 TCGv_i64 t1 = tcg_const_i64(0);
8948 TCGv_i64 fp0 = tcg_temp_new_i64();
8949 TCGv_i64 fp1 = tcg_temp_new_i64();
8950 TCGv_i64 fp2 = tcg_temp_new_i64();
8951 gen_load_fpr64(ctx, fp0, fd);
8952 gen_load_fpr64(ctx, fp1, ft);
8953 gen_load_fpr64(ctx, fp2, fs);
8955 switch (op1) {
8956 case OPC_SEL_D:
8957 tcg_gen_andi_i64(fp0, fp0, 1);
8958 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8959 break;
8960 case OPC_SELEQZ_D:
8961 tcg_gen_andi_i64(fp1, fp1, 1);
8962 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8963 break;
8964 case OPC_SELNEZ_D:
8965 tcg_gen_andi_i64(fp1, fp1, 1);
8966 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8967 break;
8968 default:
8969 MIPS_INVAL("gen_sel_d");
8970 generate_exception (ctx, EXCP_RI);
8971 break;
8974 gen_store_fpr64(ctx, fp0, fd);
8975 tcg_temp_free_i64(fp2);
8976 tcg_temp_free_i64(fp1);
8977 tcg_temp_free_i64(fp0);
8978 tcg_temp_free_i64(t1);
8981 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8982 int ft, int fs, int fd, int cc)
8984 const char *opn = "farith";
8985 const char *condnames[] = {
8986 "c.f",
8987 "c.un",
8988 "c.eq",
8989 "c.ueq",
8990 "c.olt",
8991 "c.ult",
8992 "c.ole",
8993 "c.ule",
8994 "c.sf",
8995 "c.ngle",
8996 "c.seq",
8997 "c.ngl",
8998 "c.lt",
8999 "c.nge",
9000 "c.le",
9001 "c.ngt",
9003 const char *condnames_abs[] = {
9004 "cabs.f",
9005 "cabs.un",
9006 "cabs.eq",
9007 "cabs.ueq",
9008 "cabs.olt",
9009 "cabs.ult",
9010 "cabs.ole",
9011 "cabs.ule",
9012 "cabs.sf",
9013 "cabs.ngle",
9014 "cabs.seq",
9015 "cabs.ngl",
9016 "cabs.lt",
9017 "cabs.nge",
9018 "cabs.le",
9019 "cabs.ngt",
9021 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
9022 uint32_t func = ctx->opcode & 0x3f;
9023 switch (op1) {
9024 case OPC_ADD_S:
9026 TCGv_i32 fp0 = tcg_temp_new_i32();
9027 TCGv_i32 fp1 = tcg_temp_new_i32();
9029 gen_load_fpr32(ctx, fp0, fs);
9030 gen_load_fpr32(ctx, fp1, ft);
9031 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
9032 tcg_temp_free_i32(fp1);
9033 gen_store_fpr32(ctx, fp0, fd);
9034 tcg_temp_free_i32(fp0);
9036 opn = "add.s";
9037 optype = BINOP;
9038 break;
9039 case OPC_SUB_S:
9041 TCGv_i32 fp0 = tcg_temp_new_i32();
9042 TCGv_i32 fp1 = tcg_temp_new_i32();
9044 gen_load_fpr32(ctx, fp0, fs);
9045 gen_load_fpr32(ctx, fp1, ft);
9046 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
9047 tcg_temp_free_i32(fp1);
9048 gen_store_fpr32(ctx, fp0, fd);
9049 tcg_temp_free_i32(fp0);
9051 opn = "sub.s";
9052 optype = BINOP;
9053 break;
9054 case OPC_MUL_S:
9056 TCGv_i32 fp0 = tcg_temp_new_i32();
9057 TCGv_i32 fp1 = tcg_temp_new_i32();
9059 gen_load_fpr32(ctx, fp0, fs);
9060 gen_load_fpr32(ctx, fp1, ft);
9061 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
9062 tcg_temp_free_i32(fp1);
9063 gen_store_fpr32(ctx, fp0, fd);
9064 tcg_temp_free_i32(fp0);
9066 opn = "mul.s";
9067 optype = BINOP;
9068 break;
9069 case OPC_DIV_S:
9071 TCGv_i32 fp0 = tcg_temp_new_i32();
9072 TCGv_i32 fp1 = tcg_temp_new_i32();
9074 gen_load_fpr32(ctx, fp0, fs);
9075 gen_load_fpr32(ctx, fp1, ft);
9076 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
9077 tcg_temp_free_i32(fp1);
9078 gen_store_fpr32(ctx, fp0, fd);
9079 tcg_temp_free_i32(fp0);
9081 opn = "div.s";
9082 optype = BINOP;
9083 break;
9084 case OPC_SQRT_S:
9086 TCGv_i32 fp0 = tcg_temp_new_i32();
9088 gen_load_fpr32(ctx, fp0, fs);
9089 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
9090 gen_store_fpr32(ctx, fp0, fd);
9091 tcg_temp_free_i32(fp0);
9093 opn = "sqrt.s";
9094 break;
9095 case OPC_ABS_S:
9097 TCGv_i32 fp0 = tcg_temp_new_i32();
9099 gen_load_fpr32(ctx, fp0, fs);
9100 gen_helper_float_abs_s(fp0, fp0);
9101 gen_store_fpr32(ctx, fp0, fd);
9102 tcg_temp_free_i32(fp0);
9104 opn = "abs.s";
9105 break;
9106 case OPC_MOV_S:
9108 TCGv_i32 fp0 = tcg_temp_new_i32();
9110 gen_load_fpr32(ctx, fp0, fs);
9111 gen_store_fpr32(ctx, fp0, fd);
9112 tcg_temp_free_i32(fp0);
9114 opn = "mov.s";
9115 break;
9116 case OPC_NEG_S:
9118 TCGv_i32 fp0 = tcg_temp_new_i32();
9120 gen_load_fpr32(ctx, fp0, fs);
9121 gen_helper_float_chs_s(fp0, fp0);
9122 gen_store_fpr32(ctx, fp0, fd);
9123 tcg_temp_free_i32(fp0);
9125 opn = "neg.s";
9126 break;
9127 case OPC_ROUND_L_S:
9128 check_cp1_64bitmode(ctx);
9130 TCGv_i32 fp32 = tcg_temp_new_i32();
9131 TCGv_i64 fp64 = tcg_temp_new_i64();
9133 gen_load_fpr32(ctx, fp32, fs);
9134 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
9135 tcg_temp_free_i32(fp32);
9136 gen_store_fpr64(ctx, fp64, fd);
9137 tcg_temp_free_i64(fp64);
9139 opn = "round.l.s";
9140 break;
9141 case OPC_TRUNC_L_S:
9142 check_cp1_64bitmode(ctx);
9144 TCGv_i32 fp32 = tcg_temp_new_i32();
9145 TCGv_i64 fp64 = tcg_temp_new_i64();
9147 gen_load_fpr32(ctx, fp32, fs);
9148 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
9149 tcg_temp_free_i32(fp32);
9150 gen_store_fpr64(ctx, fp64, fd);
9151 tcg_temp_free_i64(fp64);
9153 opn = "trunc.l.s";
9154 break;
9155 case OPC_CEIL_L_S:
9156 check_cp1_64bitmode(ctx);
9158 TCGv_i32 fp32 = tcg_temp_new_i32();
9159 TCGv_i64 fp64 = tcg_temp_new_i64();
9161 gen_load_fpr32(ctx, fp32, fs);
9162 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
9163 tcg_temp_free_i32(fp32);
9164 gen_store_fpr64(ctx, fp64, fd);
9165 tcg_temp_free_i64(fp64);
9167 opn = "ceil.l.s";
9168 break;
9169 case OPC_FLOOR_L_S:
9170 check_cp1_64bitmode(ctx);
9172 TCGv_i32 fp32 = tcg_temp_new_i32();
9173 TCGv_i64 fp64 = tcg_temp_new_i64();
9175 gen_load_fpr32(ctx, fp32, fs);
9176 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
9177 tcg_temp_free_i32(fp32);
9178 gen_store_fpr64(ctx, fp64, fd);
9179 tcg_temp_free_i64(fp64);
9181 opn = "floor.l.s";
9182 break;
9183 case OPC_ROUND_W_S:
9185 TCGv_i32 fp0 = tcg_temp_new_i32();
9187 gen_load_fpr32(ctx, fp0, fs);
9188 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
9189 gen_store_fpr32(ctx, fp0, fd);
9190 tcg_temp_free_i32(fp0);
9192 opn = "round.w.s";
9193 break;
9194 case OPC_TRUNC_W_S:
9196 TCGv_i32 fp0 = tcg_temp_new_i32();
9198 gen_load_fpr32(ctx, fp0, fs);
9199 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
9200 gen_store_fpr32(ctx, fp0, fd);
9201 tcg_temp_free_i32(fp0);
9203 opn = "trunc.w.s";
9204 break;
9205 case OPC_CEIL_W_S:
9207 TCGv_i32 fp0 = tcg_temp_new_i32();
9209 gen_load_fpr32(ctx, fp0, fs);
9210 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
9211 gen_store_fpr32(ctx, fp0, fd);
9212 tcg_temp_free_i32(fp0);
9214 opn = "ceil.w.s";
9215 break;
9216 case OPC_FLOOR_W_S:
9218 TCGv_i32 fp0 = tcg_temp_new_i32();
9220 gen_load_fpr32(ctx, fp0, fs);
9221 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
9222 gen_store_fpr32(ctx, fp0, fd);
9223 tcg_temp_free_i32(fp0);
9225 opn = "floor.w.s";
9226 break;
9227 case OPC_SEL_S:
9228 check_insn(ctx, ISA_MIPS32R6);
9229 gen_sel_s(ctx, op1, fd, ft, fs);
9230 opn = "sel.s";
9231 break;
9232 case OPC_SELEQZ_S:
9233 check_insn(ctx, ISA_MIPS32R6);
9234 gen_sel_s(ctx, op1, fd, ft, fs);
9235 opn = "seleqz.s";
9236 break;
9237 case OPC_SELNEZ_S:
9238 check_insn(ctx, ISA_MIPS32R6);
9239 gen_sel_s(ctx, op1, fd, ft, fs);
9240 opn = "selnez.s";
9241 break;
9242 case OPC_MOVCF_S:
9243 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9244 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9245 opn = "movcf.s";
9246 break;
9247 case OPC_MOVZ_S:
9248 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9250 TCGLabel *l1 = gen_new_label();
9251 TCGv_i32 fp0;
9253 if (ft != 0) {
9254 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9256 fp0 = tcg_temp_new_i32();
9257 gen_load_fpr32(ctx, fp0, fs);
9258 gen_store_fpr32(ctx, fp0, fd);
9259 tcg_temp_free_i32(fp0);
9260 gen_set_label(l1);
9262 opn = "movz.s";
9263 break;
9264 case OPC_MOVN_S:
9265 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9267 TCGLabel *l1 = gen_new_label();
9268 TCGv_i32 fp0;
9270 if (ft != 0) {
9271 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9272 fp0 = tcg_temp_new_i32();
9273 gen_load_fpr32(ctx, fp0, fs);
9274 gen_store_fpr32(ctx, fp0, fd);
9275 tcg_temp_free_i32(fp0);
9276 gen_set_label(l1);
9279 opn = "movn.s";
9280 break;
9281 case OPC_RECIP_S:
9282 check_cop1x(ctx);
9284 TCGv_i32 fp0 = tcg_temp_new_i32();
9286 gen_load_fpr32(ctx, fp0, fs);
9287 gen_helper_float_recip_s(fp0, cpu_env, fp0);
9288 gen_store_fpr32(ctx, fp0, fd);
9289 tcg_temp_free_i32(fp0);
9291 opn = "recip.s";
9292 break;
9293 case OPC_RSQRT_S:
9294 check_cop1x(ctx);
9296 TCGv_i32 fp0 = tcg_temp_new_i32();
9298 gen_load_fpr32(ctx, fp0, fs);
9299 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
9300 gen_store_fpr32(ctx, fp0, fd);
9301 tcg_temp_free_i32(fp0);
9303 opn = "rsqrt.s";
9304 break;
9305 case OPC_MADDF_S:
9306 check_insn(ctx, ISA_MIPS32R6);
9308 TCGv_i32 fp0 = tcg_temp_new_i32();
9309 TCGv_i32 fp1 = tcg_temp_new_i32();
9310 TCGv_i32 fp2 = tcg_temp_new_i32();
9311 gen_load_fpr32(ctx, fp0, fs);
9312 gen_load_fpr32(ctx, fp1, ft);
9313 gen_load_fpr32(ctx, fp2, fd);
9314 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
9315 gen_store_fpr32(ctx, fp2, fd);
9316 tcg_temp_free_i32(fp2);
9317 tcg_temp_free_i32(fp1);
9318 tcg_temp_free_i32(fp0);
9319 opn = "maddf.s";
9321 break;
9322 case OPC_MSUBF_S:
9323 check_insn(ctx, ISA_MIPS32R6);
9325 TCGv_i32 fp0 = tcg_temp_new_i32();
9326 TCGv_i32 fp1 = tcg_temp_new_i32();
9327 TCGv_i32 fp2 = tcg_temp_new_i32();
9328 gen_load_fpr32(ctx, fp0, fs);
9329 gen_load_fpr32(ctx, fp1, ft);
9330 gen_load_fpr32(ctx, fp2, fd);
9331 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9332 gen_store_fpr32(ctx, fp2, fd);
9333 tcg_temp_free_i32(fp2);
9334 tcg_temp_free_i32(fp1);
9335 tcg_temp_free_i32(fp0);
9336 opn = "msubf.s";
9338 break;
9339 case OPC_RINT_S:
9340 check_insn(ctx, ISA_MIPS32R6);
9342 TCGv_i32 fp0 = tcg_temp_new_i32();
9343 gen_load_fpr32(ctx, fp0, fs);
9344 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9345 gen_store_fpr32(ctx, fp0, fd);
9346 tcg_temp_free_i32(fp0);
9347 opn = "rint.s";
9349 break;
9350 case OPC_CLASS_S:
9351 check_insn(ctx, ISA_MIPS32R6);
9353 TCGv_i32 fp0 = tcg_temp_new_i32();
9354 gen_load_fpr32(ctx, fp0, fs);
9355 gen_helper_float_class_s(fp0, fp0);
9356 gen_store_fpr32(ctx, fp0, fd);
9357 tcg_temp_free_i32(fp0);
9358 opn = "class.s";
9360 break;
9361 case OPC_MIN_S: /* OPC_RECIP2_S */
9362 if (ctx->insn_flags & ISA_MIPS32R6) {
9363 /* OPC_MIN_S */
9364 TCGv_i32 fp0 = tcg_temp_new_i32();
9365 TCGv_i32 fp1 = tcg_temp_new_i32();
9366 TCGv_i32 fp2 = tcg_temp_new_i32();
9367 gen_load_fpr32(ctx, fp0, fs);
9368 gen_load_fpr32(ctx, fp1, ft);
9369 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9370 gen_store_fpr32(ctx, fp2, fd);
9371 tcg_temp_free_i32(fp2);
9372 tcg_temp_free_i32(fp1);
9373 tcg_temp_free_i32(fp0);
9374 opn = "min.s";
9375 } else {
9376 /* OPC_RECIP2_S */
9377 check_cp1_64bitmode(ctx);
9379 TCGv_i32 fp0 = tcg_temp_new_i32();
9380 TCGv_i32 fp1 = tcg_temp_new_i32();
9382 gen_load_fpr32(ctx, fp0, fs);
9383 gen_load_fpr32(ctx, fp1, ft);
9384 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9385 tcg_temp_free_i32(fp1);
9386 gen_store_fpr32(ctx, fp0, fd);
9387 tcg_temp_free_i32(fp0);
9389 opn = "recip2.s";
9391 break;
9392 case OPC_MINA_S: /* OPC_RECIP1_S */
9393 if (ctx->insn_flags & ISA_MIPS32R6) {
9394 /* OPC_MINA_S */
9395 TCGv_i32 fp0 = tcg_temp_new_i32();
9396 TCGv_i32 fp1 = tcg_temp_new_i32();
9397 TCGv_i32 fp2 = tcg_temp_new_i32();
9398 gen_load_fpr32(ctx, fp0, fs);
9399 gen_load_fpr32(ctx, fp1, ft);
9400 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9401 gen_store_fpr32(ctx, fp2, fd);
9402 tcg_temp_free_i32(fp2);
9403 tcg_temp_free_i32(fp1);
9404 tcg_temp_free_i32(fp0);
9405 opn = "mina.s";
9406 } else {
9407 /* OPC_RECIP1_S */
9408 check_cp1_64bitmode(ctx);
9410 TCGv_i32 fp0 = tcg_temp_new_i32();
9412 gen_load_fpr32(ctx, fp0, fs);
9413 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9414 gen_store_fpr32(ctx, fp0, fd);
9415 tcg_temp_free_i32(fp0);
9417 opn = "recip1.s";
9419 break;
9420 case OPC_MAX_S: /* OPC_RSQRT1_S */
9421 if (ctx->insn_flags & ISA_MIPS32R6) {
9422 /* OPC_MAX_S */
9423 TCGv_i32 fp0 = tcg_temp_new_i32();
9424 TCGv_i32 fp1 = tcg_temp_new_i32();
9425 gen_load_fpr32(ctx, fp0, fs);
9426 gen_load_fpr32(ctx, fp1, ft);
9427 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9428 gen_store_fpr32(ctx, fp1, fd);
9429 tcg_temp_free_i32(fp1);
9430 tcg_temp_free_i32(fp0);
9431 opn = "max.s";
9432 } else {
9433 /* OPC_RSQRT1_S */
9434 check_cp1_64bitmode(ctx);
9436 TCGv_i32 fp0 = tcg_temp_new_i32();
9438 gen_load_fpr32(ctx, fp0, fs);
9439 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9440 gen_store_fpr32(ctx, fp0, fd);
9441 tcg_temp_free_i32(fp0);
9443 opn = "rsqrt1.s";
9445 break;
9446 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9447 if (ctx->insn_flags & ISA_MIPS32R6) {
9448 /* OPC_MAXA_S */
9449 TCGv_i32 fp0 = tcg_temp_new_i32();
9450 TCGv_i32 fp1 = tcg_temp_new_i32();
9451 gen_load_fpr32(ctx, fp0, fs);
9452 gen_load_fpr32(ctx, fp1, ft);
9453 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9454 gen_store_fpr32(ctx, fp1, fd);
9455 tcg_temp_free_i32(fp1);
9456 tcg_temp_free_i32(fp0);
9457 opn = "maxa.s";
9458 } else {
9459 /* OPC_RSQRT2_S */
9460 check_cp1_64bitmode(ctx);
9462 TCGv_i32 fp0 = tcg_temp_new_i32();
9463 TCGv_i32 fp1 = tcg_temp_new_i32();
9465 gen_load_fpr32(ctx, fp0, fs);
9466 gen_load_fpr32(ctx, fp1, ft);
9467 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9468 tcg_temp_free_i32(fp1);
9469 gen_store_fpr32(ctx, fp0, fd);
9470 tcg_temp_free_i32(fp0);
9472 opn = "rsqrt2.s";
9474 break;
9475 case OPC_CVT_D_S:
9476 check_cp1_registers(ctx, fd);
9478 TCGv_i32 fp32 = tcg_temp_new_i32();
9479 TCGv_i64 fp64 = tcg_temp_new_i64();
9481 gen_load_fpr32(ctx, fp32, fs);
9482 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9483 tcg_temp_free_i32(fp32);
9484 gen_store_fpr64(ctx, fp64, fd);
9485 tcg_temp_free_i64(fp64);
9487 opn = "cvt.d.s";
9488 break;
9489 case OPC_CVT_W_S:
9491 TCGv_i32 fp0 = tcg_temp_new_i32();
9493 gen_load_fpr32(ctx, fp0, fs);
9494 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
9495 gen_store_fpr32(ctx, fp0, fd);
9496 tcg_temp_free_i32(fp0);
9498 opn = "cvt.w.s";
9499 break;
9500 case OPC_CVT_L_S:
9501 check_cp1_64bitmode(ctx);
9503 TCGv_i32 fp32 = tcg_temp_new_i32();
9504 TCGv_i64 fp64 = tcg_temp_new_i64();
9506 gen_load_fpr32(ctx, fp32, fs);
9507 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
9508 tcg_temp_free_i32(fp32);
9509 gen_store_fpr64(ctx, fp64, fd);
9510 tcg_temp_free_i64(fp64);
9512 opn = "cvt.l.s";
9513 break;
9514 case OPC_CVT_PS_S:
9515 check_ps(ctx);
9517 TCGv_i64 fp64 = tcg_temp_new_i64();
9518 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9519 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9521 gen_load_fpr32(ctx, fp32_0, fs);
9522 gen_load_fpr32(ctx, fp32_1, ft);
9523 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9524 tcg_temp_free_i32(fp32_1);
9525 tcg_temp_free_i32(fp32_0);
9526 gen_store_fpr64(ctx, fp64, fd);
9527 tcg_temp_free_i64(fp64);
9529 opn = "cvt.ps.s";
9530 break;
9531 case OPC_CMP_F_S:
9532 case OPC_CMP_UN_S:
9533 case OPC_CMP_EQ_S:
9534 case OPC_CMP_UEQ_S:
9535 case OPC_CMP_OLT_S:
9536 case OPC_CMP_ULT_S:
9537 case OPC_CMP_OLE_S:
9538 case OPC_CMP_ULE_S:
9539 case OPC_CMP_SF_S:
9540 case OPC_CMP_NGLE_S:
9541 case OPC_CMP_SEQ_S:
9542 case OPC_CMP_NGL_S:
9543 case OPC_CMP_LT_S:
9544 case OPC_CMP_NGE_S:
9545 case OPC_CMP_LE_S:
9546 case OPC_CMP_NGT_S:
9547 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9548 if (ctx->opcode & (1 << 6)) {
9549 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9550 opn = condnames_abs[func-48];
9551 } else {
9552 gen_cmp_s(ctx, func-48, ft, fs, cc);
9553 opn = condnames[func-48];
9555 break;
9556 case OPC_ADD_D:
9557 check_cp1_registers(ctx, fs | ft | fd);
9559 TCGv_i64 fp0 = tcg_temp_new_i64();
9560 TCGv_i64 fp1 = tcg_temp_new_i64();
9562 gen_load_fpr64(ctx, fp0, fs);
9563 gen_load_fpr64(ctx, fp1, ft);
9564 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9565 tcg_temp_free_i64(fp1);
9566 gen_store_fpr64(ctx, fp0, fd);
9567 tcg_temp_free_i64(fp0);
9569 opn = "add.d";
9570 optype = BINOP;
9571 break;
9572 case OPC_SUB_D:
9573 check_cp1_registers(ctx, fs | ft | fd);
9575 TCGv_i64 fp0 = tcg_temp_new_i64();
9576 TCGv_i64 fp1 = tcg_temp_new_i64();
9578 gen_load_fpr64(ctx, fp0, fs);
9579 gen_load_fpr64(ctx, fp1, ft);
9580 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9581 tcg_temp_free_i64(fp1);
9582 gen_store_fpr64(ctx, fp0, fd);
9583 tcg_temp_free_i64(fp0);
9585 opn = "sub.d";
9586 optype = BINOP;
9587 break;
9588 case OPC_MUL_D:
9589 check_cp1_registers(ctx, fs | ft | fd);
9591 TCGv_i64 fp0 = tcg_temp_new_i64();
9592 TCGv_i64 fp1 = tcg_temp_new_i64();
9594 gen_load_fpr64(ctx, fp0, fs);
9595 gen_load_fpr64(ctx, fp1, ft);
9596 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9597 tcg_temp_free_i64(fp1);
9598 gen_store_fpr64(ctx, fp0, fd);
9599 tcg_temp_free_i64(fp0);
9601 opn = "mul.d";
9602 optype = BINOP;
9603 break;
9604 case OPC_DIV_D:
9605 check_cp1_registers(ctx, fs | ft | fd);
9607 TCGv_i64 fp0 = tcg_temp_new_i64();
9608 TCGv_i64 fp1 = tcg_temp_new_i64();
9610 gen_load_fpr64(ctx, fp0, fs);
9611 gen_load_fpr64(ctx, fp1, ft);
9612 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9613 tcg_temp_free_i64(fp1);
9614 gen_store_fpr64(ctx, fp0, fd);
9615 tcg_temp_free_i64(fp0);
9617 opn = "div.d";
9618 optype = BINOP;
9619 break;
9620 case OPC_SQRT_D:
9621 check_cp1_registers(ctx, fs | fd);
9623 TCGv_i64 fp0 = tcg_temp_new_i64();
9625 gen_load_fpr64(ctx, fp0, fs);
9626 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9627 gen_store_fpr64(ctx, fp0, fd);
9628 tcg_temp_free_i64(fp0);
9630 opn = "sqrt.d";
9631 break;
9632 case OPC_ABS_D:
9633 check_cp1_registers(ctx, fs | fd);
9635 TCGv_i64 fp0 = tcg_temp_new_i64();
9637 gen_load_fpr64(ctx, fp0, fs);
9638 gen_helper_float_abs_d(fp0, fp0);
9639 gen_store_fpr64(ctx, fp0, fd);
9640 tcg_temp_free_i64(fp0);
9642 opn = "abs.d";
9643 break;
9644 case OPC_MOV_D:
9645 check_cp1_registers(ctx, fs | fd);
9647 TCGv_i64 fp0 = tcg_temp_new_i64();
9649 gen_load_fpr64(ctx, fp0, fs);
9650 gen_store_fpr64(ctx, fp0, fd);
9651 tcg_temp_free_i64(fp0);
9653 opn = "mov.d";
9654 break;
9655 case OPC_NEG_D:
9656 check_cp1_registers(ctx, fs | fd);
9658 TCGv_i64 fp0 = tcg_temp_new_i64();
9660 gen_load_fpr64(ctx, fp0, fs);
9661 gen_helper_float_chs_d(fp0, fp0);
9662 gen_store_fpr64(ctx, fp0, fd);
9663 tcg_temp_free_i64(fp0);
9665 opn = "neg.d";
9666 break;
9667 case OPC_ROUND_L_D:
9668 check_cp1_64bitmode(ctx);
9670 TCGv_i64 fp0 = tcg_temp_new_i64();
9672 gen_load_fpr64(ctx, fp0, fs);
9673 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
9674 gen_store_fpr64(ctx, fp0, fd);
9675 tcg_temp_free_i64(fp0);
9677 opn = "round.l.d";
9678 break;
9679 case OPC_TRUNC_L_D:
9680 check_cp1_64bitmode(ctx);
9682 TCGv_i64 fp0 = tcg_temp_new_i64();
9684 gen_load_fpr64(ctx, fp0, fs);
9685 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
9686 gen_store_fpr64(ctx, fp0, fd);
9687 tcg_temp_free_i64(fp0);
9689 opn = "trunc.l.d";
9690 break;
9691 case OPC_CEIL_L_D:
9692 check_cp1_64bitmode(ctx);
9694 TCGv_i64 fp0 = tcg_temp_new_i64();
9696 gen_load_fpr64(ctx, fp0, fs);
9697 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
9698 gen_store_fpr64(ctx, fp0, fd);
9699 tcg_temp_free_i64(fp0);
9701 opn = "ceil.l.d";
9702 break;
9703 case OPC_FLOOR_L_D:
9704 check_cp1_64bitmode(ctx);
9706 TCGv_i64 fp0 = tcg_temp_new_i64();
9708 gen_load_fpr64(ctx, fp0, fs);
9709 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
9710 gen_store_fpr64(ctx, fp0, fd);
9711 tcg_temp_free_i64(fp0);
9713 opn = "floor.l.d";
9714 break;
9715 case OPC_ROUND_W_D:
9716 check_cp1_registers(ctx, fs);
9718 TCGv_i32 fp32 = tcg_temp_new_i32();
9719 TCGv_i64 fp64 = tcg_temp_new_i64();
9721 gen_load_fpr64(ctx, fp64, fs);
9722 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
9723 tcg_temp_free_i64(fp64);
9724 gen_store_fpr32(ctx, fp32, fd);
9725 tcg_temp_free_i32(fp32);
9727 opn = "round.w.d";
9728 break;
9729 case OPC_TRUNC_W_D:
9730 check_cp1_registers(ctx, fs);
9732 TCGv_i32 fp32 = tcg_temp_new_i32();
9733 TCGv_i64 fp64 = tcg_temp_new_i64();
9735 gen_load_fpr64(ctx, fp64, fs);
9736 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
9737 tcg_temp_free_i64(fp64);
9738 gen_store_fpr32(ctx, fp32, fd);
9739 tcg_temp_free_i32(fp32);
9741 opn = "trunc.w.d";
9742 break;
9743 case OPC_CEIL_W_D:
9744 check_cp1_registers(ctx, fs);
9746 TCGv_i32 fp32 = tcg_temp_new_i32();
9747 TCGv_i64 fp64 = tcg_temp_new_i64();
9749 gen_load_fpr64(ctx, fp64, fs);
9750 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
9751 tcg_temp_free_i64(fp64);
9752 gen_store_fpr32(ctx, fp32, fd);
9753 tcg_temp_free_i32(fp32);
9755 opn = "ceil.w.d";
9756 break;
9757 case OPC_FLOOR_W_D:
9758 check_cp1_registers(ctx, fs);
9760 TCGv_i32 fp32 = tcg_temp_new_i32();
9761 TCGv_i64 fp64 = tcg_temp_new_i64();
9763 gen_load_fpr64(ctx, fp64, fs);
9764 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
9765 tcg_temp_free_i64(fp64);
9766 gen_store_fpr32(ctx, fp32, fd);
9767 tcg_temp_free_i32(fp32);
9769 opn = "floor.w.d";
9770 break;
9771 case OPC_SEL_D:
9772 check_insn(ctx, ISA_MIPS32R6);
9773 gen_sel_d(ctx, op1, fd, ft, fs);
9774 opn = "sel.d";
9775 break;
9776 case OPC_SELEQZ_D:
9777 check_insn(ctx, ISA_MIPS32R6);
9778 gen_sel_d(ctx, op1, fd, ft, fs);
9779 opn = "seleqz.d";
9780 break;
9781 case OPC_SELNEZ_D:
9782 check_insn(ctx, ISA_MIPS32R6);
9783 gen_sel_d(ctx, op1, fd, ft, fs);
9784 opn = "selnez.d";
9785 break;
9786 case OPC_MOVCF_D:
9787 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9788 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9789 opn = "movcf.d";
9790 break;
9791 case OPC_MOVZ_D:
9792 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9794 TCGLabel *l1 = gen_new_label();
9795 TCGv_i64 fp0;
9797 if (ft != 0) {
9798 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9800 fp0 = tcg_temp_new_i64();
9801 gen_load_fpr64(ctx, fp0, fs);
9802 gen_store_fpr64(ctx, fp0, fd);
9803 tcg_temp_free_i64(fp0);
9804 gen_set_label(l1);
9806 opn = "movz.d";
9807 break;
9808 case OPC_MOVN_D:
9809 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9811 TCGLabel *l1 = gen_new_label();
9812 TCGv_i64 fp0;
9814 if (ft != 0) {
9815 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9816 fp0 = tcg_temp_new_i64();
9817 gen_load_fpr64(ctx, fp0, fs);
9818 gen_store_fpr64(ctx, fp0, fd);
9819 tcg_temp_free_i64(fp0);
9820 gen_set_label(l1);
9823 opn = "movn.d";
9824 break;
9825 case OPC_RECIP_D:
9826 check_cp1_64bitmode(ctx);
9828 TCGv_i64 fp0 = tcg_temp_new_i64();
9830 gen_load_fpr64(ctx, fp0, fs);
9831 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9832 gen_store_fpr64(ctx, fp0, fd);
9833 tcg_temp_free_i64(fp0);
9835 opn = "recip.d";
9836 break;
9837 case OPC_RSQRT_D:
9838 check_cp1_64bitmode(ctx);
9840 TCGv_i64 fp0 = tcg_temp_new_i64();
9842 gen_load_fpr64(ctx, fp0, fs);
9843 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9844 gen_store_fpr64(ctx, fp0, fd);
9845 tcg_temp_free_i64(fp0);
9847 opn = "rsqrt.d";
9848 break;
9849 case OPC_MADDF_D:
9850 check_insn(ctx, ISA_MIPS32R6);
9852 TCGv_i64 fp0 = tcg_temp_new_i64();
9853 TCGv_i64 fp1 = tcg_temp_new_i64();
9854 TCGv_i64 fp2 = tcg_temp_new_i64();
9855 gen_load_fpr64(ctx, fp0, fs);
9856 gen_load_fpr64(ctx, fp1, ft);
9857 gen_load_fpr64(ctx, fp2, fd);
9858 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9859 gen_store_fpr64(ctx, fp2, fd);
9860 tcg_temp_free_i64(fp2);
9861 tcg_temp_free_i64(fp1);
9862 tcg_temp_free_i64(fp0);
9863 opn = "maddf.d";
9865 break;
9866 case OPC_MSUBF_D:
9867 check_insn(ctx, ISA_MIPS32R6);
9869 TCGv_i64 fp0 = tcg_temp_new_i64();
9870 TCGv_i64 fp1 = tcg_temp_new_i64();
9871 TCGv_i64 fp2 = tcg_temp_new_i64();
9872 gen_load_fpr64(ctx, fp0, fs);
9873 gen_load_fpr64(ctx, fp1, ft);
9874 gen_load_fpr64(ctx, fp2, fd);
9875 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9876 gen_store_fpr64(ctx, fp2, fd);
9877 tcg_temp_free_i64(fp2);
9878 tcg_temp_free_i64(fp1);
9879 tcg_temp_free_i64(fp0);
9880 opn = "msubf.d";
9882 break;
9883 case OPC_RINT_D:
9884 check_insn(ctx, ISA_MIPS32R6);
9886 TCGv_i64 fp0 = tcg_temp_new_i64();
9887 gen_load_fpr64(ctx, fp0, fs);
9888 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9889 gen_store_fpr64(ctx, fp0, fd);
9890 tcg_temp_free_i64(fp0);
9891 opn = "rint.d";
9893 break;
9894 case OPC_CLASS_D:
9895 check_insn(ctx, ISA_MIPS32R6);
9897 TCGv_i64 fp0 = tcg_temp_new_i64();
9898 gen_load_fpr64(ctx, fp0, fs);
9899 gen_helper_float_class_d(fp0, fp0);
9900 gen_store_fpr64(ctx, fp0, fd);
9901 tcg_temp_free_i64(fp0);
9902 opn = "class.d";
9904 break;
9905 case OPC_MIN_D: /* OPC_RECIP2_D */
9906 if (ctx->insn_flags & ISA_MIPS32R6) {
9907 /* OPC_MIN_D */
9908 TCGv_i64 fp0 = tcg_temp_new_i64();
9909 TCGv_i64 fp1 = tcg_temp_new_i64();
9910 gen_load_fpr64(ctx, fp0, fs);
9911 gen_load_fpr64(ctx, fp1, ft);
9912 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9913 gen_store_fpr64(ctx, fp1, fd);
9914 tcg_temp_free_i64(fp1);
9915 tcg_temp_free_i64(fp0);
9916 opn = "min.d";
9917 } else {
9918 /* OPC_RECIP2_D */
9919 check_cp1_64bitmode(ctx);
9921 TCGv_i64 fp0 = tcg_temp_new_i64();
9922 TCGv_i64 fp1 = tcg_temp_new_i64();
9924 gen_load_fpr64(ctx, fp0, fs);
9925 gen_load_fpr64(ctx, fp1, ft);
9926 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9927 tcg_temp_free_i64(fp1);
9928 gen_store_fpr64(ctx, fp0, fd);
9929 tcg_temp_free_i64(fp0);
9931 opn = "recip2.d";
9933 break;
9934 case OPC_MINA_D: /* OPC_RECIP1_D */
9935 if (ctx->insn_flags & ISA_MIPS32R6) {
9936 /* OPC_MINA_D */
9937 TCGv_i64 fp0 = tcg_temp_new_i64();
9938 TCGv_i64 fp1 = tcg_temp_new_i64();
9939 gen_load_fpr64(ctx, fp0, fs);
9940 gen_load_fpr64(ctx, fp1, ft);
9941 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9942 gen_store_fpr64(ctx, fp1, fd);
9943 tcg_temp_free_i64(fp1);
9944 tcg_temp_free_i64(fp0);
9945 opn = "mina.d";
9946 } else {
9947 /* OPC_RECIP1_D */
9948 check_cp1_64bitmode(ctx);
9950 TCGv_i64 fp0 = tcg_temp_new_i64();
9952 gen_load_fpr64(ctx, fp0, fs);
9953 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9954 gen_store_fpr64(ctx, fp0, fd);
9955 tcg_temp_free_i64(fp0);
9957 opn = "recip1.d";
9959 break;
9960 case OPC_MAX_D: /* OPC_RSQRT1_D */
9961 if (ctx->insn_flags & ISA_MIPS32R6) {
9962 /* OPC_MAX_D */
9963 TCGv_i64 fp0 = tcg_temp_new_i64();
9964 TCGv_i64 fp1 = tcg_temp_new_i64();
9965 gen_load_fpr64(ctx, fp0, fs);
9966 gen_load_fpr64(ctx, fp1, ft);
9967 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9968 gen_store_fpr64(ctx, fp1, fd);
9969 tcg_temp_free_i64(fp1);
9970 tcg_temp_free_i64(fp0);
9971 opn = "max.d";
9972 } else {
9973 /* OPC_RSQRT1_D */
9974 check_cp1_64bitmode(ctx);
9976 TCGv_i64 fp0 = tcg_temp_new_i64();
9978 gen_load_fpr64(ctx, fp0, fs);
9979 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9980 gen_store_fpr64(ctx, fp0, fd);
9981 tcg_temp_free_i64(fp0);
9983 opn = "rsqrt1.d";
9985 break;
9986 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9987 if (ctx->insn_flags & ISA_MIPS32R6) {
9988 /* OPC_MAXA_D */
9989 TCGv_i64 fp0 = tcg_temp_new_i64();
9990 TCGv_i64 fp1 = tcg_temp_new_i64();
9991 gen_load_fpr64(ctx, fp0, fs);
9992 gen_load_fpr64(ctx, fp1, ft);
9993 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9994 gen_store_fpr64(ctx, fp1, fd);
9995 tcg_temp_free_i64(fp1);
9996 tcg_temp_free_i64(fp0);
9997 opn = "maxa.d";
9998 } else {
9999 /* OPC_RSQRT2_D */
10000 check_cp1_64bitmode(ctx);
10002 TCGv_i64 fp0 = tcg_temp_new_i64();
10003 TCGv_i64 fp1 = tcg_temp_new_i64();
10005 gen_load_fpr64(ctx, fp0, fs);
10006 gen_load_fpr64(ctx, fp1, ft);
10007 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
10008 tcg_temp_free_i64(fp1);
10009 gen_store_fpr64(ctx, fp0, fd);
10010 tcg_temp_free_i64(fp0);
10012 opn = "rsqrt2.d";
10014 break;
10015 case OPC_CMP_F_D:
10016 case OPC_CMP_UN_D:
10017 case OPC_CMP_EQ_D:
10018 case OPC_CMP_UEQ_D:
10019 case OPC_CMP_OLT_D:
10020 case OPC_CMP_ULT_D:
10021 case OPC_CMP_OLE_D:
10022 case OPC_CMP_ULE_D:
10023 case OPC_CMP_SF_D:
10024 case OPC_CMP_NGLE_D:
10025 case OPC_CMP_SEQ_D:
10026 case OPC_CMP_NGL_D:
10027 case OPC_CMP_LT_D:
10028 case OPC_CMP_NGE_D:
10029 case OPC_CMP_LE_D:
10030 case OPC_CMP_NGT_D:
10031 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10032 if (ctx->opcode & (1 << 6)) {
10033 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
10034 opn = condnames_abs[func-48];
10035 } else {
10036 gen_cmp_d(ctx, func-48, ft, fs, cc);
10037 opn = condnames[func-48];
10039 break;
10040 case OPC_CVT_S_D:
10041 check_cp1_registers(ctx, fs);
10043 TCGv_i32 fp32 = tcg_temp_new_i32();
10044 TCGv_i64 fp64 = tcg_temp_new_i64();
10046 gen_load_fpr64(ctx, fp64, fs);
10047 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
10048 tcg_temp_free_i64(fp64);
10049 gen_store_fpr32(ctx, fp32, fd);
10050 tcg_temp_free_i32(fp32);
10052 opn = "cvt.s.d";
10053 break;
10054 case OPC_CVT_W_D:
10055 check_cp1_registers(ctx, fs);
10057 TCGv_i32 fp32 = tcg_temp_new_i32();
10058 TCGv_i64 fp64 = tcg_temp_new_i64();
10060 gen_load_fpr64(ctx, fp64, fs);
10061 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
10062 tcg_temp_free_i64(fp64);
10063 gen_store_fpr32(ctx, fp32, fd);
10064 tcg_temp_free_i32(fp32);
10066 opn = "cvt.w.d";
10067 break;
10068 case OPC_CVT_L_D:
10069 check_cp1_64bitmode(ctx);
10071 TCGv_i64 fp0 = tcg_temp_new_i64();
10073 gen_load_fpr64(ctx, fp0, fs);
10074 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
10075 gen_store_fpr64(ctx, fp0, fd);
10076 tcg_temp_free_i64(fp0);
10078 opn = "cvt.l.d";
10079 break;
10080 case OPC_CVT_S_W:
10082 TCGv_i32 fp0 = tcg_temp_new_i32();
10084 gen_load_fpr32(ctx, fp0, fs);
10085 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
10086 gen_store_fpr32(ctx, fp0, fd);
10087 tcg_temp_free_i32(fp0);
10089 opn = "cvt.s.w";
10090 break;
10091 case OPC_CVT_D_W:
10092 check_cp1_registers(ctx, fd);
10094 TCGv_i32 fp32 = tcg_temp_new_i32();
10095 TCGv_i64 fp64 = tcg_temp_new_i64();
10097 gen_load_fpr32(ctx, fp32, fs);
10098 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
10099 tcg_temp_free_i32(fp32);
10100 gen_store_fpr64(ctx, fp64, fd);
10101 tcg_temp_free_i64(fp64);
10103 opn = "cvt.d.w";
10104 break;
10105 case OPC_CVT_S_L:
10106 check_cp1_64bitmode(ctx);
10108 TCGv_i32 fp32 = tcg_temp_new_i32();
10109 TCGv_i64 fp64 = tcg_temp_new_i64();
10111 gen_load_fpr64(ctx, fp64, fs);
10112 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
10113 tcg_temp_free_i64(fp64);
10114 gen_store_fpr32(ctx, fp32, fd);
10115 tcg_temp_free_i32(fp32);
10117 opn = "cvt.s.l";
10118 break;
10119 case OPC_CVT_D_L:
10120 check_cp1_64bitmode(ctx);
10122 TCGv_i64 fp0 = tcg_temp_new_i64();
10124 gen_load_fpr64(ctx, fp0, fs);
10125 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
10126 gen_store_fpr64(ctx, fp0, fd);
10127 tcg_temp_free_i64(fp0);
10129 opn = "cvt.d.l";
10130 break;
10131 case OPC_CVT_PS_PW:
10132 check_ps(ctx);
10134 TCGv_i64 fp0 = tcg_temp_new_i64();
10136 gen_load_fpr64(ctx, fp0, fs);
10137 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
10138 gen_store_fpr64(ctx, fp0, fd);
10139 tcg_temp_free_i64(fp0);
10141 opn = "cvt.ps.pw";
10142 break;
10143 case OPC_ADD_PS:
10144 check_ps(ctx);
10146 TCGv_i64 fp0 = tcg_temp_new_i64();
10147 TCGv_i64 fp1 = tcg_temp_new_i64();
10149 gen_load_fpr64(ctx, fp0, fs);
10150 gen_load_fpr64(ctx, fp1, ft);
10151 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
10152 tcg_temp_free_i64(fp1);
10153 gen_store_fpr64(ctx, fp0, fd);
10154 tcg_temp_free_i64(fp0);
10156 opn = "add.ps";
10157 break;
10158 case OPC_SUB_PS:
10159 check_ps(ctx);
10161 TCGv_i64 fp0 = tcg_temp_new_i64();
10162 TCGv_i64 fp1 = tcg_temp_new_i64();
10164 gen_load_fpr64(ctx, fp0, fs);
10165 gen_load_fpr64(ctx, fp1, ft);
10166 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
10167 tcg_temp_free_i64(fp1);
10168 gen_store_fpr64(ctx, fp0, fd);
10169 tcg_temp_free_i64(fp0);
10171 opn = "sub.ps";
10172 break;
10173 case OPC_MUL_PS:
10174 check_ps(ctx);
10176 TCGv_i64 fp0 = tcg_temp_new_i64();
10177 TCGv_i64 fp1 = tcg_temp_new_i64();
10179 gen_load_fpr64(ctx, fp0, fs);
10180 gen_load_fpr64(ctx, fp1, ft);
10181 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
10182 tcg_temp_free_i64(fp1);
10183 gen_store_fpr64(ctx, fp0, fd);
10184 tcg_temp_free_i64(fp0);
10186 opn = "mul.ps";
10187 break;
10188 case OPC_ABS_PS:
10189 check_ps(ctx);
10191 TCGv_i64 fp0 = tcg_temp_new_i64();
10193 gen_load_fpr64(ctx, fp0, fs);
10194 gen_helper_float_abs_ps(fp0, fp0);
10195 gen_store_fpr64(ctx, fp0, fd);
10196 tcg_temp_free_i64(fp0);
10198 opn = "abs.ps";
10199 break;
10200 case OPC_MOV_PS:
10201 check_ps(ctx);
10203 TCGv_i64 fp0 = tcg_temp_new_i64();
10205 gen_load_fpr64(ctx, fp0, fs);
10206 gen_store_fpr64(ctx, fp0, fd);
10207 tcg_temp_free_i64(fp0);
10209 opn = "mov.ps";
10210 break;
10211 case OPC_NEG_PS:
10212 check_ps(ctx);
10214 TCGv_i64 fp0 = tcg_temp_new_i64();
10216 gen_load_fpr64(ctx, fp0, fs);
10217 gen_helper_float_chs_ps(fp0, fp0);
10218 gen_store_fpr64(ctx, fp0, fd);
10219 tcg_temp_free_i64(fp0);
10221 opn = "neg.ps";
10222 break;
10223 case OPC_MOVCF_PS:
10224 check_ps(ctx);
10225 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10226 opn = "movcf.ps";
10227 break;
10228 case OPC_MOVZ_PS:
10229 check_ps(ctx);
10231 TCGLabel *l1 = gen_new_label();
10232 TCGv_i64 fp0;
10234 if (ft != 0)
10235 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10236 fp0 = tcg_temp_new_i64();
10237 gen_load_fpr64(ctx, fp0, fs);
10238 gen_store_fpr64(ctx, fp0, fd);
10239 tcg_temp_free_i64(fp0);
10240 gen_set_label(l1);
10242 opn = "movz.ps";
10243 break;
10244 case OPC_MOVN_PS:
10245 check_ps(ctx);
10247 TCGLabel *l1 = gen_new_label();
10248 TCGv_i64 fp0;
10250 if (ft != 0) {
10251 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10252 fp0 = tcg_temp_new_i64();
10253 gen_load_fpr64(ctx, fp0, fs);
10254 gen_store_fpr64(ctx, fp0, fd);
10255 tcg_temp_free_i64(fp0);
10256 gen_set_label(l1);
10259 opn = "movn.ps";
10260 break;
10261 case OPC_ADDR_PS:
10262 check_ps(ctx);
10264 TCGv_i64 fp0 = tcg_temp_new_i64();
10265 TCGv_i64 fp1 = tcg_temp_new_i64();
10267 gen_load_fpr64(ctx, fp0, ft);
10268 gen_load_fpr64(ctx, fp1, fs);
10269 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
10270 tcg_temp_free_i64(fp1);
10271 gen_store_fpr64(ctx, fp0, fd);
10272 tcg_temp_free_i64(fp0);
10274 opn = "addr.ps";
10275 break;
10276 case OPC_MULR_PS:
10277 check_ps(ctx);
10279 TCGv_i64 fp0 = tcg_temp_new_i64();
10280 TCGv_i64 fp1 = tcg_temp_new_i64();
10282 gen_load_fpr64(ctx, fp0, ft);
10283 gen_load_fpr64(ctx, fp1, fs);
10284 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
10285 tcg_temp_free_i64(fp1);
10286 gen_store_fpr64(ctx, fp0, fd);
10287 tcg_temp_free_i64(fp0);
10289 opn = "mulr.ps";
10290 break;
10291 case OPC_RECIP2_PS:
10292 check_ps(ctx);
10294 TCGv_i64 fp0 = tcg_temp_new_i64();
10295 TCGv_i64 fp1 = tcg_temp_new_i64();
10297 gen_load_fpr64(ctx, fp0, fs);
10298 gen_load_fpr64(ctx, fp1, ft);
10299 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
10300 tcg_temp_free_i64(fp1);
10301 gen_store_fpr64(ctx, fp0, fd);
10302 tcg_temp_free_i64(fp0);
10304 opn = "recip2.ps";
10305 break;
10306 case OPC_RECIP1_PS:
10307 check_ps(ctx);
10309 TCGv_i64 fp0 = tcg_temp_new_i64();
10311 gen_load_fpr64(ctx, fp0, fs);
10312 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
10313 gen_store_fpr64(ctx, fp0, fd);
10314 tcg_temp_free_i64(fp0);
10316 opn = "recip1.ps";
10317 break;
10318 case OPC_RSQRT1_PS:
10319 check_ps(ctx);
10321 TCGv_i64 fp0 = tcg_temp_new_i64();
10323 gen_load_fpr64(ctx, fp0, fs);
10324 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
10325 gen_store_fpr64(ctx, fp0, fd);
10326 tcg_temp_free_i64(fp0);
10328 opn = "rsqrt1.ps";
10329 break;
10330 case OPC_RSQRT2_PS:
10331 check_ps(ctx);
10333 TCGv_i64 fp0 = tcg_temp_new_i64();
10334 TCGv_i64 fp1 = tcg_temp_new_i64();
10336 gen_load_fpr64(ctx, fp0, fs);
10337 gen_load_fpr64(ctx, fp1, ft);
10338 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
10339 tcg_temp_free_i64(fp1);
10340 gen_store_fpr64(ctx, fp0, fd);
10341 tcg_temp_free_i64(fp0);
10343 opn = "rsqrt2.ps";
10344 break;
10345 case OPC_CVT_S_PU:
10346 check_cp1_64bitmode(ctx);
10348 TCGv_i32 fp0 = tcg_temp_new_i32();
10350 gen_load_fpr32h(ctx, fp0, fs);
10351 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
10352 gen_store_fpr32(ctx, fp0, fd);
10353 tcg_temp_free_i32(fp0);
10355 opn = "cvt.s.pu";
10356 break;
10357 case OPC_CVT_PW_PS:
10358 check_ps(ctx);
10360 TCGv_i64 fp0 = tcg_temp_new_i64();
10362 gen_load_fpr64(ctx, fp0, fs);
10363 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
10364 gen_store_fpr64(ctx, fp0, fd);
10365 tcg_temp_free_i64(fp0);
10367 opn = "cvt.pw.ps";
10368 break;
10369 case OPC_CVT_S_PL:
10370 check_cp1_64bitmode(ctx);
10372 TCGv_i32 fp0 = tcg_temp_new_i32();
10374 gen_load_fpr32(ctx, fp0, fs);
10375 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10376 gen_store_fpr32(ctx, fp0, fd);
10377 tcg_temp_free_i32(fp0);
10379 opn = "cvt.s.pl";
10380 break;
10381 case OPC_PLL_PS:
10382 check_ps(ctx);
10384 TCGv_i32 fp0 = tcg_temp_new_i32();
10385 TCGv_i32 fp1 = tcg_temp_new_i32();
10387 gen_load_fpr32(ctx, fp0, fs);
10388 gen_load_fpr32(ctx, fp1, ft);
10389 gen_store_fpr32h(ctx, fp0, fd);
10390 gen_store_fpr32(ctx, fp1, fd);
10391 tcg_temp_free_i32(fp0);
10392 tcg_temp_free_i32(fp1);
10394 opn = "pll.ps";
10395 break;
10396 case OPC_PLU_PS:
10397 check_ps(ctx);
10399 TCGv_i32 fp0 = tcg_temp_new_i32();
10400 TCGv_i32 fp1 = tcg_temp_new_i32();
10402 gen_load_fpr32(ctx, fp0, fs);
10403 gen_load_fpr32h(ctx, fp1, ft);
10404 gen_store_fpr32(ctx, fp1, fd);
10405 gen_store_fpr32h(ctx, fp0, fd);
10406 tcg_temp_free_i32(fp0);
10407 tcg_temp_free_i32(fp1);
10409 opn = "plu.ps";
10410 break;
10411 case OPC_PUL_PS:
10412 check_ps(ctx);
10414 TCGv_i32 fp0 = tcg_temp_new_i32();
10415 TCGv_i32 fp1 = tcg_temp_new_i32();
10417 gen_load_fpr32h(ctx, fp0, fs);
10418 gen_load_fpr32(ctx, fp1, ft);
10419 gen_store_fpr32(ctx, fp1, fd);
10420 gen_store_fpr32h(ctx, fp0, fd);
10421 tcg_temp_free_i32(fp0);
10422 tcg_temp_free_i32(fp1);
10424 opn = "pul.ps";
10425 break;
10426 case OPC_PUU_PS:
10427 check_ps(ctx);
10429 TCGv_i32 fp0 = tcg_temp_new_i32();
10430 TCGv_i32 fp1 = tcg_temp_new_i32();
10432 gen_load_fpr32h(ctx, fp0, fs);
10433 gen_load_fpr32h(ctx, fp1, ft);
10434 gen_store_fpr32(ctx, fp1, fd);
10435 gen_store_fpr32h(ctx, fp0, fd);
10436 tcg_temp_free_i32(fp0);
10437 tcg_temp_free_i32(fp1);
10439 opn = "puu.ps";
10440 break;
10441 case OPC_CMP_F_PS:
10442 case OPC_CMP_UN_PS:
10443 case OPC_CMP_EQ_PS:
10444 case OPC_CMP_UEQ_PS:
10445 case OPC_CMP_OLT_PS:
10446 case OPC_CMP_ULT_PS:
10447 case OPC_CMP_OLE_PS:
10448 case OPC_CMP_ULE_PS:
10449 case OPC_CMP_SF_PS:
10450 case OPC_CMP_NGLE_PS:
10451 case OPC_CMP_SEQ_PS:
10452 case OPC_CMP_NGL_PS:
10453 case OPC_CMP_LT_PS:
10454 case OPC_CMP_NGE_PS:
10455 case OPC_CMP_LE_PS:
10456 case OPC_CMP_NGT_PS:
10457 if (ctx->opcode & (1 << 6)) {
10458 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10459 opn = condnames_abs[func-48];
10460 } else {
10461 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10462 opn = condnames[func-48];
10464 break;
10465 default:
10466 MIPS_INVAL(opn);
10467 generate_exception (ctx, EXCP_RI);
10468 return;
10470 (void)opn; /* avoid a compiler warning */
10471 switch (optype) {
10472 case BINOP:
10473 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
10474 break;
10475 case CMPOP:
10476 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
10477 break;
10478 default:
10479 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
10480 break;
10484 /* Coprocessor 3 (FPU) */
10485 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10486 int fd, int fs, int base, int index)
10488 const char *opn = "extended float load/store";
10489 int store = 0;
10490 TCGv t0 = tcg_temp_new();
10492 if (base == 0) {
10493 gen_load_gpr(t0, index);
10494 } else if (index == 0) {
10495 gen_load_gpr(t0, base);
10496 } else {
10497 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10499 /* Don't do NOP if destination is zero: we must perform the actual
10500 memory access. */
10501 switch (opc) {
10502 case OPC_LWXC1:
10503 check_cop1x(ctx);
10505 TCGv_i32 fp0 = tcg_temp_new_i32();
10507 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10508 tcg_gen_trunc_tl_i32(fp0, t0);
10509 gen_store_fpr32(ctx, fp0, fd);
10510 tcg_temp_free_i32(fp0);
10512 opn = "lwxc1";
10513 break;
10514 case OPC_LDXC1:
10515 check_cop1x(ctx);
10516 check_cp1_registers(ctx, fd);
10518 TCGv_i64 fp0 = tcg_temp_new_i64();
10519 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10520 gen_store_fpr64(ctx, fp0, fd);
10521 tcg_temp_free_i64(fp0);
10523 opn = "ldxc1";
10524 break;
10525 case OPC_LUXC1:
10526 check_cp1_64bitmode(ctx);
10527 tcg_gen_andi_tl(t0, t0, ~0x7);
10529 TCGv_i64 fp0 = tcg_temp_new_i64();
10531 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10532 gen_store_fpr64(ctx, fp0, fd);
10533 tcg_temp_free_i64(fp0);
10535 opn = "luxc1";
10536 break;
10537 case OPC_SWXC1:
10538 check_cop1x(ctx);
10540 TCGv_i32 fp0 = tcg_temp_new_i32();
10541 gen_load_fpr32(ctx, fp0, fs);
10542 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10543 tcg_temp_free_i32(fp0);
10545 opn = "swxc1";
10546 store = 1;
10547 break;
10548 case OPC_SDXC1:
10549 check_cop1x(ctx);
10550 check_cp1_registers(ctx, fs);
10552 TCGv_i64 fp0 = tcg_temp_new_i64();
10553 gen_load_fpr64(ctx, fp0, fs);
10554 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10555 tcg_temp_free_i64(fp0);
10557 opn = "sdxc1";
10558 store = 1;
10559 break;
10560 case OPC_SUXC1:
10561 check_cp1_64bitmode(ctx);
10562 tcg_gen_andi_tl(t0, t0, ~0x7);
10564 TCGv_i64 fp0 = tcg_temp_new_i64();
10565 gen_load_fpr64(ctx, fp0, fs);
10566 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10567 tcg_temp_free_i64(fp0);
10569 opn = "suxc1";
10570 store = 1;
10571 break;
10573 tcg_temp_free(t0);
10574 (void)opn; (void)store; /* avoid compiler warnings */
10575 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
10576 regnames[index], regnames[base]);
10579 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10580 int fd, int fr, int fs, int ft)
10582 const char *opn = "flt3_arith";
10584 switch (opc) {
10585 case OPC_ALNV_PS:
10586 check_ps(ctx);
10588 TCGv t0 = tcg_temp_local_new();
10589 TCGv_i32 fp = tcg_temp_new_i32();
10590 TCGv_i32 fph = tcg_temp_new_i32();
10591 TCGLabel *l1 = gen_new_label();
10592 TCGLabel *l2 = gen_new_label();
10594 gen_load_gpr(t0, fr);
10595 tcg_gen_andi_tl(t0, t0, 0x7);
10597 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10598 gen_load_fpr32(ctx, fp, fs);
10599 gen_load_fpr32h(ctx, fph, fs);
10600 gen_store_fpr32(ctx, fp, fd);
10601 gen_store_fpr32h(ctx, fph, fd);
10602 tcg_gen_br(l2);
10603 gen_set_label(l1);
10604 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10605 tcg_temp_free(t0);
10606 #ifdef TARGET_WORDS_BIGENDIAN
10607 gen_load_fpr32(ctx, fp, fs);
10608 gen_load_fpr32h(ctx, fph, ft);
10609 gen_store_fpr32h(ctx, fp, fd);
10610 gen_store_fpr32(ctx, fph, fd);
10611 #else
10612 gen_load_fpr32h(ctx, fph, fs);
10613 gen_load_fpr32(ctx, fp, ft);
10614 gen_store_fpr32(ctx, fph, fd);
10615 gen_store_fpr32h(ctx, fp, fd);
10616 #endif
10617 gen_set_label(l2);
10618 tcg_temp_free_i32(fp);
10619 tcg_temp_free_i32(fph);
10621 opn = "alnv.ps";
10622 break;
10623 case OPC_MADD_S:
10624 check_cop1x(ctx);
10626 TCGv_i32 fp0 = tcg_temp_new_i32();
10627 TCGv_i32 fp1 = tcg_temp_new_i32();
10628 TCGv_i32 fp2 = tcg_temp_new_i32();
10630 gen_load_fpr32(ctx, fp0, fs);
10631 gen_load_fpr32(ctx, fp1, ft);
10632 gen_load_fpr32(ctx, fp2, fr);
10633 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10634 tcg_temp_free_i32(fp0);
10635 tcg_temp_free_i32(fp1);
10636 gen_store_fpr32(ctx, fp2, fd);
10637 tcg_temp_free_i32(fp2);
10639 opn = "madd.s";
10640 break;
10641 case OPC_MADD_D:
10642 check_cop1x(ctx);
10643 check_cp1_registers(ctx, fd | fs | ft | fr);
10645 TCGv_i64 fp0 = tcg_temp_new_i64();
10646 TCGv_i64 fp1 = tcg_temp_new_i64();
10647 TCGv_i64 fp2 = tcg_temp_new_i64();
10649 gen_load_fpr64(ctx, fp0, fs);
10650 gen_load_fpr64(ctx, fp1, ft);
10651 gen_load_fpr64(ctx, fp2, fr);
10652 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10653 tcg_temp_free_i64(fp0);
10654 tcg_temp_free_i64(fp1);
10655 gen_store_fpr64(ctx, fp2, fd);
10656 tcg_temp_free_i64(fp2);
10658 opn = "madd.d";
10659 break;
10660 case OPC_MADD_PS:
10661 check_ps(ctx);
10663 TCGv_i64 fp0 = tcg_temp_new_i64();
10664 TCGv_i64 fp1 = tcg_temp_new_i64();
10665 TCGv_i64 fp2 = tcg_temp_new_i64();
10667 gen_load_fpr64(ctx, fp0, fs);
10668 gen_load_fpr64(ctx, fp1, ft);
10669 gen_load_fpr64(ctx, fp2, fr);
10670 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10671 tcg_temp_free_i64(fp0);
10672 tcg_temp_free_i64(fp1);
10673 gen_store_fpr64(ctx, fp2, fd);
10674 tcg_temp_free_i64(fp2);
10676 opn = "madd.ps";
10677 break;
10678 case OPC_MSUB_S:
10679 check_cop1x(ctx);
10681 TCGv_i32 fp0 = tcg_temp_new_i32();
10682 TCGv_i32 fp1 = tcg_temp_new_i32();
10683 TCGv_i32 fp2 = tcg_temp_new_i32();
10685 gen_load_fpr32(ctx, fp0, fs);
10686 gen_load_fpr32(ctx, fp1, ft);
10687 gen_load_fpr32(ctx, fp2, fr);
10688 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10689 tcg_temp_free_i32(fp0);
10690 tcg_temp_free_i32(fp1);
10691 gen_store_fpr32(ctx, fp2, fd);
10692 tcg_temp_free_i32(fp2);
10694 opn = "msub.s";
10695 break;
10696 case OPC_MSUB_D:
10697 check_cop1x(ctx);
10698 check_cp1_registers(ctx, fd | fs | ft | fr);
10700 TCGv_i64 fp0 = tcg_temp_new_i64();
10701 TCGv_i64 fp1 = tcg_temp_new_i64();
10702 TCGv_i64 fp2 = tcg_temp_new_i64();
10704 gen_load_fpr64(ctx, fp0, fs);
10705 gen_load_fpr64(ctx, fp1, ft);
10706 gen_load_fpr64(ctx, fp2, fr);
10707 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10708 tcg_temp_free_i64(fp0);
10709 tcg_temp_free_i64(fp1);
10710 gen_store_fpr64(ctx, fp2, fd);
10711 tcg_temp_free_i64(fp2);
10713 opn = "msub.d";
10714 break;
10715 case OPC_MSUB_PS:
10716 check_ps(ctx);
10718 TCGv_i64 fp0 = tcg_temp_new_i64();
10719 TCGv_i64 fp1 = tcg_temp_new_i64();
10720 TCGv_i64 fp2 = tcg_temp_new_i64();
10722 gen_load_fpr64(ctx, fp0, fs);
10723 gen_load_fpr64(ctx, fp1, ft);
10724 gen_load_fpr64(ctx, fp2, fr);
10725 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10726 tcg_temp_free_i64(fp0);
10727 tcg_temp_free_i64(fp1);
10728 gen_store_fpr64(ctx, fp2, fd);
10729 tcg_temp_free_i64(fp2);
10731 opn = "msub.ps";
10732 break;
10733 case OPC_NMADD_S:
10734 check_cop1x(ctx);
10736 TCGv_i32 fp0 = tcg_temp_new_i32();
10737 TCGv_i32 fp1 = tcg_temp_new_i32();
10738 TCGv_i32 fp2 = tcg_temp_new_i32();
10740 gen_load_fpr32(ctx, fp0, fs);
10741 gen_load_fpr32(ctx, fp1, ft);
10742 gen_load_fpr32(ctx, fp2, fr);
10743 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10744 tcg_temp_free_i32(fp0);
10745 tcg_temp_free_i32(fp1);
10746 gen_store_fpr32(ctx, fp2, fd);
10747 tcg_temp_free_i32(fp2);
10749 opn = "nmadd.s";
10750 break;
10751 case OPC_NMADD_D:
10752 check_cop1x(ctx);
10753 check_cp1_registers(ctx, fd | fs | ft | fr);
10755 TCGv_i64 fp0 = tcg_temp_new_i64();
10756 TCGv_i64 fp1 = tcg_temp_new_i64();
10757 TCGv_i64 fp2 = tcg_temp_new_i64();
10759 gen_load_fpr64(ctx, fp0, fs);
10760 gen_load_fpr64(ctx, fp1, ft);
10761 gen_load_fpr64(ctx, fp2, fr);
10762 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10763 tcg_temp_free_i64(fp0);
10764 tcg_temp_free_i64(fp1);
10765 gen_store_fpr64(ctx, fp2, fd);
10766 tcg_temp_free_i64(fp2);
10768 opn = "nmadd.d";
10769 break;
10770 case OPC_NMADD_PS:
10771 check_ps(ctx);
10773 TCGv_i64 fp0 = tcg_temp_new_i64();
10774 TCGv_i64 fp1 = tcg_temp_new_i64();
10775 TCGv_i64 fp2 = tcg_temp_new_i64();
10777 gen_load_fpr64(ctx, fp0, fs);
10778 gen_load_fpr64(ctx, fp1, ft);
10779 gen_load_fpr64(ctx, fp2, fr);
10780 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10781 tcg_temp_free_i64(fp0);
10782 tcg_temp_free_i64(fp1);
10783 gen_store_fpr64(ctx, fp2, fd);
10784 tcg_temp_free_i64(fp2);
10786 opn = "nmadd.ps";
10787 break;
10788 case OPC_NMSUB_S:
10789 check_cop1x(ctx);
10791 TCGv_i32 fp0 = tcg_temp_new_i32();
10792 TCGv_i32 fp1 = tcg_temp_new_i32();
10793 TCGv_i32 fp2 = tcg_temp_new_i32();
10795 gen_load_fpr32(ctx, fp0, fs);
10796 gen_load_fpr32(ctx, fp1, ft);
10797 gen_load_fpr32(ctx, fp2, fr);
10798 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10799 tcg_temp_free_i32(fp0);
10800 tcg_temp_free_i32(fp1);
10801 gen_store_fpr32(ctx, fp2, fd);
10802 tcg_temp_free_i32(fp2);
10804 opn = "nmsub.s";
10805 break;
10806 case OPC_NMSUB_D:
10807 check_cop1x(ctx);
10808 check_cp1_registers(ctx, fd | fs | ft | fr);
10810 TCGv_i64 fp0 = tcg_temp_new_i64();
10811 TCGv_i64 fp1 = tcg_temp_new_i64();
10812 TCGv_i64 fp2 = tcg_temp_new_i64();
10814 gen_load_fpr64(ctx, fp0, fs);
10815 gen_load_fpr64(ctx, fp1, ft);
10816 gen_load_fpr64(ctx, fp2, fr);
10817 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10818 tcg_temp_free_i64(fp0);
10819 tcg_temp_free_i64(fp1);
10820 gen_store_fpr64(ctx, fp2, fd);
10821 tcg_temp_free_i64(fp2);
10823 opn = "nmsub.d";
10824 break;
10825 case OPC_NMSUB_PS:
10826 check_ps(ctx);
10828 TCGv_i64 fp0 = tcg_temp_new_i64();
10829 TCGv_i64 fp1 = tcg_temp_new_i64();
10830 TCGv_i64 fp2 = tcg_temp_new_i64();
10832 gen_load_fpr64(ctx, fp0, fs);
10833 gen_load_fpr64(ctx, fp1, ft);
10834 gen_load_fpr64(ctx, fp2, fr);
10835 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10836 tcg_temp_free_i64(fp0);
10837 tcg_temp_free_i64(fp1);
10838 gen_store_fpr64(ctx, fp2, fd);
10839 tcg_temp_free_i64(fp2);
10841 opn = "nmsub.ps";
10842 break;
10843 default:
10844 MIPS_INVAL(opn);
10845 generate_exception (ctx, EXCP_RI);
10846 return;
10848 (void)opn; /* avoid a compiler warning */
10849 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
10850 fregnames[fs], fregnames[ft]);
10853 static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
10855 TCGv t0;
10857 #if !defined(CONFIG_USER_ONLY)
10858 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10859 Therefore only check the ISA in system mode. */
10860 check_insn(ctx, ISA_MIPS32R2);
10861 #endif
10862 t0 = tcg_temp_new();
10864 switch (rd) {
10865 case 0:
10866 save_cpu_state(ctx, 1);
10867 gen_helper_rdhwr_cpunum(t0, cpu_env);
10868 gen_store_gpr(t0, rt);
10869 break;
10870 case 1:
10871 save_cpu_state(ctx, 1);
10872 gen_helper_rdhwr_synci_step(t0, cpu_env);
10873 gen_store_gpr(t0, rt);
10874 break;
10875 case 2:
10876 save_cpu_state(ctx, 1);
10877 gen_helper_rdhwr_cc(t0, cpu_env);
10878 gen_store_gpr(t0, rt);
10879 break;
10880 case 3:
10881 save_cpu_state(ctx, 1);
10882 gen_helper_rdhwr_ccres(t0, cpu_env);
10883 gen_store_gpr(t0, rt);
10884 break;
10885 case 29:
10886 #if defined(CONFIG_USER_ONLY)
10887 tcg_gen_ld_tl(t0, cpu_env,
10888 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10889 gen_store_gpr(t0, rt);
10890 break;
10891 #else
10892 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10893 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10894 tcg_gen_ld_tl(t0, cpu_env,
10895 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10896 gen_store_gpr(t0, rt);
10897 } else {
10898 generate_exception(ctx, EXCP_RI);
10900 break;
10901 #endif
10902 default: /* Invalid */
10903 MIPS_INVAL("rdhwr");
10904 generate_exception(ctx, EXCP_RI);
10905 break;
10907 tcg_temp_free(t0);
10910 static inline void clear_branch_hflags(DisasContext *ctx)
10912 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10913 if (ctx->bstate == BS_NONE) {
10914 save_cpu_state(ctx, 0);
10915 } else {
10916 /* it is not safe to save ctx->hflags as hflags may be changed
10917 in execution time by the instruction in delay / forbidden slot. */
10918 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10922 static void gen_branch(DisasContext *ctx, int insn_bytes)
10924 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10925 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10926 /* Branches completion */
10927 clear_branch_hflags(ctx);
10928 ctx->bstate = BS_BRANCH;
10929 /* FIXME: Need to clear can_do_io. */
10930 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10931 case MIPS_HFLAG_FBNSLOT:
10932 MIPS_DEBUG("forbidden slot");
10933 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10934 break;
10935 case MIPS_HFLAG_B:
10936 /* unconditional branch */
10937 MIPS_DEBUG("unconditional branch");
10938 if (proc_hflags & MIPS_HFLAG_BX) {
10939 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10941 gen_goto_tb(ctx, 0, ctx->btarget);
10942 break;
10943 case MIPS_HFLAG_BL:
10944 /* blikely taken case */
10945 MIPS_DEBUG("blikely branch taken");
10946 gen_goto_tb(ctx, 0, ctx->btarget);
10947 break;
10948 case MIPS_HFLAG_BC:
10949 /* Conditional branch */
10950 MIPS_DEBUG("conditional branch");
10952 TCGLabel *l1 = gen_new_label();
10954 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10955 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10956 gen_set_label(l1);
10957 gen_goto_tb(ctx, 0, ctx->btarget);
10959 break;
10960 case MIPS_HFLAG_BR:
10961 /* unconditional branch to register */
10962 MIPS_DEBUG("branch to register");
10963 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10964 TCGv t0 = tcg_temp_new();
10965 TCGv_i32 t1 = tcg_temp_new_i32();
10967 tcg_gen_andi_tl(t0, btarget, 0x1);
10968 tcg_gen_trunc_tl_i32(t1, t0);
10969 tcg_temp_free(t0);
10970 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10971 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10972 tcg_gen_or_i32(hflags, hflags, t1);
10973 tcg_temp_free_i32(t1);
10975 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10976 } else {
10977 tcg_gen_mov_tl(cpu_PC, btarget);
10979 if (ctx->singlestep_enabled) {
10980 save_cpu_state(ctx, 0);
10981 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
10983 tcg_gen_exit_tb(0);
10984 break;
10985 default:
10986 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
10987 abort();
10992 /* Compact Branches */
10993 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
10994 int rs, int rt, int32_t offset)
10996 int bcond_compute = 0;
10997 TCGv t0 = tcg_temp_new();
10998 TCGv t1 = tcg_temp_new();
10999 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
11001 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11002 #ifdef MIPS_DEBUG_DISAS
11003 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11004 "\n", ctx->pc);
11005 #endif
11006 generate_exception(ctx, EXCP_RI);
11007 goto out;
11010 /* Load needed operands and calculate btarget */
11011 switch (opc) {
11012 /* compact branch */
11013 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11014 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11015 gen_load_gpr(t0, rs);
11016 gen_load_gpr(t1, rt);
11017 bcond_compute = 1;
11018 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11019 if (rs <= rt && rs == 0) {
11020 /* OPC_BEQZALC, OPC_BNEZALC */
11021 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11023 break;
11024 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11025 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11026 gen_load_gpr(t0, rs);
11027 gen_load_gpr(t1, rt);
11028 bcond_compute = 1;
11029 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11030 break;
11031 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11032 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11033 if (rs == 0 || rs == rt) {
11034 /* OPC_BLEZALC, OPC_BGEZALC */
11035 /* OPC_BGTZALC, OPC_BLTZALC */
11036 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11038 gen_load_gpr(t0, rs);
11039 gen_load_gpr(t1, rt);
11040 bcond_compute = 1;
11041 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11042 break;
11043 case OPC_BC:
11044 case OPC_BALC:
11045 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11046 break;
11047 case OPC_BEQZC:
11048 case OPC_BNEZC:
11049 if (rs != 0) {
11050 /* OPC_BEQZC, OPC_BNEZC */
11051 gen_load_gpr(t0, rs);
11052 bcond_compute = 1;
11053 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11054 } else {
11055 /* OPC_JIC, OPC_JIALC */
11056 TCGv tbase = tcg_temp_new();
11057 TCGv toffset = tcg_temp_new();
11059 gen_load_gpr(tbase, rt);
11060 tcg_gen_movi_tl(toffset, offset);
11061 gen_op_addr_add(ctx, btarget, tbase, toffset);
11062 tcg_temp_free(tbase);
11063 tcg_temp_free(toffset);
11065 break;
11066 default:
11067 MIPS_INVAL("Compact branch/jump");
11068 generate_exception(ctx, EXCP_RI);
11069 goto out;
11072 if (bcond_compute == 0) {
11073 /* Uncoditional compact branch */
11074 switch (opc) {
11075 case OPC_JIALC:
11076 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11077 /* Fallthrough */
11078 case OPC_JIC:
11079 ctx->hflags |= MIPS_HFLAG_BR;
11080 break;
11081 case OPC_BALC:
11082 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11083 /* Fallthrough */
11084 case OPC_BC:
11085 ctx->hflags |= MIPS_HFLAG_B;
11086 break;
11087 default:
11088 MIPS_INVAL("Compact branch/jump");
11089 generate_exception(ctx, EXCP_RI);
11090 goto out;
11093 /* Generating branch here as compact branches don't have delay slot */
11094 gen_branch(ctx, 4);
11095 } else {
11096 /* Conditional compact branch */
11097 TCGLabel *fs = gen_new_label();
11098 save_cpu_state(ctx, 0);
11100 switch (opc) {
11101 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11102 if (rs == 0 && rt != 0) {
11103 /* OPC_BLEZALC */
11104 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11105 } else if (rs != 0 && rt != 0 && rs == rt) {
11106 /* OPC_BGEZALC */
11107 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11108 } else {
11109 /* OPC_BGEUC */
11110 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
11112 break;
11113 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11114 if (rs == 0 && rt != 0) {
11115 /* OPC_BGTZALC */
11116 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11117 } else if (rs != 0 && rt != 0 && rs == rt) {
11118 /* OPC_BLTZALC */
11119 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11120 } else {
11121 /* OPC_BLTUC */
11122 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
11124 break;
11125 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11126 if (rs == 0 && rt != 0) {
11127 /* OPC_BLEZC */
11128 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11129 } else if (rs != 0 && rt != 0 && rs == rt) {
11130 /* OPC_BGEZC */
11131 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11132 } else {
11133 /* OPC_BGEC */
11134 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
11136 break;
11137 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11138 if (rs == 0 && rt != 0) {
11139 /* OPC_BGTZC */
11140 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11141 } else if (rs != 0 && rt != 0 && rs == rt) {
11142 /* OPC_BLTZC */
11143 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11144 } else {
11145 /* OPC_BLTC */
11146 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
11148 break;
11149 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11150 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11151 if (rs >= rt) {
11152 /* OPC_BOVC, OPC_BNVC */
11153 TCGv t2 = tcg_temp_new();
11154 TCGv t3 = tcg_temp_new();
11155 TCGv t4 = tcg_temp_new();
11156 TCGv input_overflow = tcg_temp_new();
11158 gen_load_gpr(t0, rs);
11159 gen_load_gpr(t1, rt);
11160 tcg_gen_ext32s_tl(t2, t0);
11161 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
11162 tcg_gen_ext32s_tl(t3, t1);
11163 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
11164 tcg_gen_or_tl(input_overflow, input_overflow, t4);
11166 tcg_gen_add_tl(t4, t2, t3);
11167 tcg_gen_ext32s_tl(t4, t4);
11168 tcg_gen_xor_tl(t2, t2, t3);
11169 tcg_gen_xor_tl(t3, t4, t3);
11170 tcg_gen_andc_tl(t2, t3, t2);
11171 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
11172 tcg_gen_or_tl(t4, t4, input_overflow);
11173 if (opc == OPC_BOVC) {
11174 /* OPC_BOVC */
11175 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
11176 } else {
11177 /* OPC_BNVC */
11178 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
11180 tcg_temp_free(input_overflow);
11181 tcg_temp_free(t4);
11182 tcg_temp_free(t3);
11183 tcg_temp_free(t2);
11184 } else if (rs < rt && rs == 0) {
11185 /* OPC_BEQZALC, OPC_BNEZALC */
11186 if (opc == OPC_BEQZALC) {
11187 /* OPC_BEQZALC */
11188 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
11189 } else {
11190 /* OPC_BNEZALC */
11191 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
11193 } else {
11194 /* OPC_BEQC, OPC_BNEC */
11195 if (opc == OPC_BEQC) {
11196 /* OPC_BEQC */
11197 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
11198 } else {
11199 /* OPC_BNEC */
11200 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
11203 break;
11204 case OPC_BEQZC:
11205 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
11206 break;
11207 case OPC_BNEZC:
11208 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
11209 break;
11210 default:
11211 MIPS_INVAL("Compact conditional branch/jump");
11212 generate_exception(ctx, EXCP_RI);
11213 goto out;
11216 /* Generating branch here as compact branches don't have delay slot */
11217 gen_goto_tb(ctx, 1, ctx->btarget);
11218 gen_set_label(fs);
11220 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
11221 MIPS_DEBUG("Compact conditional branch");
11224 out:
11225 tcg_temp_free(t0);
11226 tcg_temp_free(t1);
11229 /* ISA extensions (ASEs) */
11230 /* MIPS16 extension to MIPS32 */
11232 /* MIPS16 major opcodes */
11233 enum {
11234 M16_OPC_ADDIUSP = 0x00,
11235 M16_OPC_ADDIUPC = 0x01,
11236 M16_OPC_B = 0x02,
11237 M16_OPC_JAL = 0x03,
11238 M16_OPC_BEQZ = 0x04,
11239 M16_OPC_BNEQZ = 0x05,
11240 M16_OPC_SHIFT = 0x06,
11241 M16_OPC_LD = 0x07,
11242 M16_OPC_RRIA = 0x08,
11243 M16_OPC_ADDIU8 = 0x09,
11244 M16_OPC_SLTI = 0x0a,
11245 M16_OPC_SLTIU = 0x0b,
11246 M16_OPC_I8 = 0x0c,
11247 M16_OPC_LI = 0x0d,
11248 M16_OPC_CMPI = 0x0e,
11249 M16_OPC_SD = 0x0f,
11250 M16_OPC_LB = 0x10,
11251 M16_OPC_LH = 0x11,
11252 M16_OPC_LWSP = 0x12,
11253 M16_OPC_LW = 0x13,
11254 M16_OPC_LBU = 0x14,
11255 M16_OPC_LHU = 0x15,
11256 M16_OPC_LWPC = 0x16,
11257 M16_OPC_LWU = 0x17,
11258 M16_OPC_SB = 0x18,
11259 M16_OPC_SH = 0x19,
11260 M16_OPC_SWSP = 0x1a,
11261 M16_OPC_SW = 0x1b,
11262 M16_OPC_RRR = 0x1c,
11263 M16_OPC_RR = 0x1d,
11264 M16_OPC_EXTEND = 0x1e,
11265 M16_OPC_I64 = 0x1f
11268 /* I8 funct field */
11269 enum {
11270 I8_BTEQZ = 0x0,
11271 I8_BTNEZ = 0x1,
11272 I8_SWRASP = 0x2,
11273 I8_ADJSP = 0x3,
11274 I8_SVRS = 0x4,
11275 I8_MOV32R = 0x5,
11276 I8_MOVR32 = 0x7
11279 /* RRR f field */
11280 enum {
11281 RRR_DADDU = 0x0,
11282 RRR_ADDU = 0x1,
11283 RRR_DSUBU = 0x2,
11284 RRR_SUBU = 0x3
11287 /* RR funct field */
11288 enum {
11289 RR_JR = 0x00,
11290 RR_SDBBP = 0x01,
11291 RR_SLT = 0x02,
11292 RR_SLTU = 0x03,
11293 RR_SLLV = 0x04,
11294 RR_BREAK = 0x05,
11295 RR_SRLV = 0x06,
11296 RR_SRAV = 0x07,
11297 RR_DSRL = 0x08,
11298 RR_CMP = 0x0a,
11299 RR_NEG = 0x0b,
11300 RR_AND = 0x0c,
11301 RR_OR = 0x0d,
11302 RR_XOR = 0x0e,
11303 RR_NOT = 0x0f,
11304 RR_MFHI = 0x10,
11305 RR_CNVT = 0x11,
11306 RR_MFLO = 0x12,
11307 RR_DSRA = 0x13,
11308 RR_DSLLV = 0x14,
11309 RR_DSRLV = 0x16,
11310 RR_DSRAV = 0x17,
11311 RR_MULT = 0x18,
11312 RR_MULTU = 0x19,
11313 RR_DIV = 0x1a,
11314 RR_DIVU = 0x1b,
11315 RR_DMULT = 0x1c,
11316 RR_DMULTU = 0x1d,
11317 RR_DDIV = 0x1e,
11318 RR_DDIVU = 0x1f
11321 /* I64 funct field */
11322 enum {
11323 I64_LDSP = 0x0,
11324 I64_SDSP = 0x1,
11325 I64_SDRASP = 0x2,
11326 I64_DADJSP = 0x3,
11327 I64_LDPC = 0x4,
11328 I64_DADDIU5 = 0x5,
11329 I64_DADDIUPC = 0x6,
11330 I64_DADDIUSP = 0x7
11333 /* RR ry field for CNVT */
11334 enum {
11335 RR_RY_CNVT_ZEB = 0x0,
11336 RR_RY_CNVT_ZEH = 0x1,
11337 RR_RY_CNVT_ZEW = 0x2,
11338 RR_RY_CNVT_SEB = 0x4,
11339 RR_RY_CNVT_SEH = 0x5,
11340 RR_RY_CNVT_SEW = 0x6,
11343 static int xlat (int r)
11345 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11347 return map[r];
11350 static void gen_mips16_save (DisasContext *ctx,
11351 int xsregs, int aregs,
11352 int do_ra, int do_s0, int do_s1,
11353 int framesize)
11355 TCGv t0 = tcg_temp_new();
11356 TCGv t1 = tcg_temp_new();
11357 TCGv t2 = tcg_temp_new();
11358 int args, astatic;
11360 switch (aregs) {
11361 case 0:
11362 case 1:
11363 case 2:
11364 case 3:
11365 case 11:
11366 args = 0;
11367 break;
11368 case 4:
11369 case 5:
11370 case 6:
11371 case 7:
11372 args = 1;
11373 break;
11374 case 8:
11375 case 9:
11376 case 10:
11377 args = 2;
11378 break;
11379 case 12:
11380 case 13:
11381 args = 3;
11382 break;
11383 case 14:
11384 args = 4;
11385 break;
11386 default:
11387 generate_exception(ctx, EXCP_RI);
11388 return;
11391 switch (args) {
11392 case 4:
11393 gen_base_offset_addr(ctx, t0, 29, 12);
11394 gen_load_gpr(t1, 7);
11395 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11396 /* Fall through */
11397 case 3:
11398 gen_base_offset_addr(ctx, t0, 29, 8);
11399 gen_load_gpr(t1, 6);
11400 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11401 /* Fall through */
11402 case 2:
11403 gen_base_offset_addr(ctx, t0, 29, 4);
11404 gen_load_gpr(t1, 5);
11405 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11406 /* Fall through */
11407 case 1:
11408 gen_base_offset_addr(ctx, t0, 29, 0);
11409 gen_load_gpr(t1, 4);
11410 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11413 gen_load_gpr(t0, 29);
11415 #define DECR_AND_STORE(reg) do { \
11416 tcg_gen_movi_tl(t2, -4); \
11417 gen_op_addr_add(ctx, t0, t0, t2); \
11418 gen_load_gpr(t1, reg); \
11419 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
11420 } while (0)
11422 if (do_ra) {
11423 DECR_AND_STORE(31);
11426 switch (xsregs) {
11427 case 7:
11428 DECR_AND_STORE(30);
11429 /* Fall through */
11430 case 6:
11431 DECR_AND_STORE(23);
11432 /* Fall through */
11433 case 5:
11434 DECR_AND_STORE(22);
11435 /* Fall through */
11436 case 4:
11437 DECR_AND_STORE(21);
11438 /* Fall through */
11439 case 3:
11440 DECR_AND_STORE(20);
11441 /* Fall through */
11442 case 2:
11443 DECR_AND_STORE(19);
11444 /* Fall through */
11445 case 1:
11446 DECR_AND_STORE(18);
11449 if (do_s1) {
11450 DECR_AND_STORE(17);
11452 if (do_s0) {
11453 DECR_AND_STORE(16);
11456 switch (aregs) {
11457 case 0:
11458 case 4:
11459 case 8:
11460 case 12:
11461 case 14:
11462 astatic = 0;
11463 break;
11464 case 1:
11465 case 5:
11466 case 9:
11467 case 13:
11468 astatic = 1;
11469 break;
11470 case 2:
11471 case 6:
11472 case 10:
11473 astatic = 2;
11474 break;
11475 case 3:
11476 case 7:
11477 astatic = 3;
11478 break;
11479 case 11:
11480 astatic = 4;
11481 break;
11482 default:
11483 generate_exception(ctx, EXCP_RI);
11484 return;
11487 if (astatic > 0) {
11488 DECR_AND_STORE(7);
11489 if (astatic > 1) {
11490 DECR_AND_STORE(6);
11491 if (astatic > 2) {
11492 DECR_AND_STORE(5);
11493 if (astatic > 3) {
11494 DECR_AND_STORE(4);
11499 #undef DECR_AND_STORE
11501 tcg_gen_movi_tl(t2, -framesize);
11502 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11503 tcg_temp_free(t0);
11504 tcg_temp_free(t1);
11505 tcg_temp_free(t2);
11508 static void gen_mips16_restore (DisasContext *ctx,
11509 int xsregs, int aregs,
11510 int do_ra, int do_s0, int do_s1,
11511 int framesize)
11513 int astatic;
11514 TCGv t0 = tcg_temp_new();
11515 TCGv t1 = tcg_temp_new();
11516 TCGv t2 = tcg_temp_new();
11518 tcg_gen_movi_tl(t2, framesize);
11519 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11521 #define DECR_AND_LOAD(reg) do { \
11522 tcg_gen_movi_tl(t2, -4); \
11523 gen_op_addr_add(ctx, t0, t0, t2); \
11524 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11525 gen_store_gpr(t1, reg); \
11526 } while (0)
11528 if (do_ra) {
11529 DECR_AND_LOAD(31);
11532 switch (xsregs) {
11533 case 7:
11534 DECR_AND_LOAD(30);
11535 /* Fall through */
11536 case 6:
11537 DECR_AND_LOAD(23);
11538 /* Fall through */
11539 case 5:
11540 DECR_AND_LOAD(22);
11541 /* Fall through */
11542 case 4:
11543 DECR_AND_LOAD(21);
11544 /* Fall through */
11545 case 3:
11546 DECR_AND_LOAD(20);
11547 /* Fall through */
11548 case 2:
11549 DECR_AND_LOAD(19);
11550 /* Fall through */
11551 case 1:
11552 DECR_AND_LOAD(18);
11555 if (do_s1) {
11556 DECR_AND_LOAD(17);
11558 if (do_s0) {
11559 DECR_AND_LOAD(16);
11562 switch (aregs) {
11563 case 0:
11564 case 4:
11565 case 8:
11566 case 12:
11567 case 14:
11568 astatic = 0;
11569 break;
11570 case 1:
11571 case 5:
11572 case 9:
11573 case 13:
11574 astatic = 1;
11575 break;
11576 case 2:
11577 case 6:
11578 case 10:
11579 astatic = 2;
11580 break;
11581 case 3:
11582 case 7:
11583 astatic = 3;
11584 break;
11585 case 11:
11586 astatic = 4;
11587 break;
11588 default:
11589 generate_exception(ctx, EXCP_RI);
11590 return;
11593 if (astatic > 0) {
11594 DECR_AND_LOAD(7);
11595 if (astatic > 1) {
11596 DECR_AND_LOAD(6);
11597 if (astatic > 2) {
11598 DECR_AND_LOAD(5);
11599 if (astatic > 3) {
11600 DECR_AND_LOAD(4);
11605 #undef DECR_AND_LOAD
11607 tcg_gen_movi_tl(t2, framesize);
11608 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11609 tcg_temp_free(t0);
11610 tcg_temp_free(t1);
11611 tcg_temp_free(t2);
11614 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11615 int is_64_bit, int extended)
11617 TCGv t0;
11619 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11620 generate_exception(ctx, EXCP_RI);
11621 return;
11624 t0 = tcg_temp_new();
11626 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11627 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11628 if (!is_64_bit) {
11629 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11632 tcg_temp_free(t0);
11635 #if defined(TARGET_MIPS64)
11636 static void decode_i64_mips16 (DisasContext *ctx,
11637 int ry, int funct, int16_t offset,
11638 int extended)
11640 switch (funct) {
11641 case I64_LDSP:
11642 check_insn(ctx, ISA_MIPS3);
11643 check_mips_64(ctx);
11644 offset = extended ? offset : offset << 3;
11645 gen_ld(ctx, OPC_LD, ry, 29, offset);
11646 break;
11647 case I64_SDSP:
11648 check_insn(ctx, ISA_MIPS3);
11649 check_mips_64(ctx);
11650 offset = extended ? offset : offset << 3;
11651 gen_st(ctx, OPC_SD, ry, 29, offset);
11652 break;
11653 case I64_SDRASP:
11654 check_insn(ctx, ISA_MIPS3);
11655 check_mips_64(ctx);
11656 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11657 gen_st(ctx, OPC_SD, 31, 29, offset);
11658 break;
11659 case I64_DADJSP:
11660 check_insn(ctx, ISA_MIPS3);
11661 check_mips_64(ctx);
11662 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11663 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11664 break;
11665 case I64_LDPC:
11666 check_insn(ctx, ISA_MIPS3);
11667 check_mips_64(ctx);
11668 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11669 generate_exception(ctx, EXCP_RI);
11670 } else {
11671 offset = extended ? offset : offset << 3;
11672 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11674 break;
11675 case I64_DADDIU5:
11676 check_insn(ctx, ISA_MIPS3);
11677 check_mips_64(ctx);
11678 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11679 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11680 break;
11681 case I64_DADDIUPC:
11682 check_insn(ctx, ISA_MIPS3);
11683 check_mips_64(ctx);
11684 offset = extended ? offset : offset << 2;
11685 gen_addiupc(ctx, ry, offset, 1, extended);
11686 break;
11687 case I64_DADDIUSP:
11688 check_insn(ctx, ISA_MIPS3);
11689 check_mips_64(ctx);
11690 offset = extended ? offset : offset << 2;
11691 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11692 break;
11695 #endif
11697 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11699 int extend = cpu_lduw_code(env, ctx->pc + 2);
11700 int op, rx, ry, funct, sa;
11701 int16_t imm, offset;
11703 ctx->opcode = (ctx->opcode << 16) | extend;
11704 op = (ctx->opcode >> 11) & 0x1f;
11705 sa = (ctx->opcode >> 22) & 0x1f;
11706 funct = (ctx->opcode >> 8) & 0x7;
11707 rx = xlat((ctx->opcode >> 8) & 0x7);
11708 ry = xlat((ctx->opcode >> 5) & 0x7);
11709 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11710 | ((ctx->opcode >> 21) & 0x3f) << 5
11711 | (ctx->opcode & 0x1f));
11713 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11714 counterparts. */
11715 switch (op) {
11716 case M16_OPC_ADDIUSP:
11717 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11718 break;
11719 case M16_OPC_ADDIUPC:
11720 gen_addiupc(ctx, rx, imm, 0, 1);
11721 break;
11722 case M16_OPC_B:
11723 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11724 /* No delay slot, so just process as a normal instruction */
11725 break;
11726 case M16_OPC_BEQZ:
11727 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11728 /* No delay slot, so just process as a normal instruction */
11729 break;
11730 case M16_OPC_BNEQZ:
11731 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11732 /* No delay slot, so just process as a normal instruction */
11733 break;
11734 case M16_OPC_SHIFT:
11735 switch (ctx->opcode & 0x3) {
11736 case 0x0:
11737 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11738 break;
11739 case 0x1:
11740 #if defined(TARGET_MIPS64)
11741 check_mips_64(ctx);
11742 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11743 #else
11744 generate_exception(ctx, EXCP_RI);
11745 #endif
11746 break;
11747 case 0x2:
11748 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11749 break;
11750 case 0x3:
11751 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11752 break;
11754 break;
11755 #if defined(TARGET_MIPS64)
11756 case M16_OPC_LD:
11757 check_insn(ctx, ISA_MIPS3);
11758 check_mips_64(ctx);
11759 gen_ld(ctx, OPC_LD, ry, rx, offset);
11760 break;
11761 #endif
11762 case M16_OPC_RRIA:
11763 imm = ctx->opcode & 0xf;
11764 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11765 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11766 imm = (int16_t) (imm << 1) >> 1;
11767 if ((ctx->opcode >> 4) & 0x1) {
11768 #if defined(TARGET_MIPS64)
11769 check_mips_64(ctx);
11770 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11771 #else
11772 generate_exception(ctx, EXCP_RI);
11773 #endif
11774 } else {
11775 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11777 break;
11778 case M16_OPC_ADDIU8:
11779 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11780 break;
11781 case M16_OPC_SLTI:
11782 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11783 break;
11784 case M16_OPC_SLTIU:
11785 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11786 break;
11787 case M16_OPC_I8:
11788 switch (funct) {
11789 case I8_BTEQZ:
11790 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11791 break;
11792 case I8_BTNEZ:
11793 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11794 break;
11795 case I8_SWRASP:
11796 gen_st(ctx, OPC_SW, 31, 29, imm);
11797 break;
11798 case I8_ADJSP:
11799 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11800 break;
11801 case I8_SVRS:
11802 check_insn(ctx, ISA_MIPS32);
11804 int xsregs = (ctx->opcode >> 24) & 0x7;
11805 int aregs = (ctx->opcode >> 16) & 0xf;
11806 int do_ra = (ctx->opcode >> 6) & 0x1;
11807 int do_s0 = (ctx->opcode >> 5) & 0x1;
11808 int do_s1 = (ctx->opcode >> 4) & 0x1;
11809 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11810 | (ctx->opcode & 0xf)) << 3;
11812 if (ctx->opcode & (1 << 7)) {
11813 gen_mips16_save(ctx, xsregs, aregs,
11814 do_ra, do_s0, do_s1,
11815 framesize);
11816 } else {
11817 gen_mips16_restore(ctx, xsregs, aregs,
11818 do_ra, do_s0, do_s1,
11819 framesize);
11822 break;
11823 default:
11824 generate_exception(ctx, EXCP_RI);
11825 break;
11827 break;
11828 case M16_OPC_LI:
11829 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11830 break;
11831 case M16_OPC_CMPI:
11832 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11833 break;
11834 #if defined(TARGET_MIPS64)
11835 case M16_OPC_SD:
11836 check_insn(ctx, ISA_MIPS3);
11837 check_mips_64(ctx);
11838 gen_st(ctx, OPC_SD, ry, rx, offset);
11839 break;
11840 #endif
11841 case M16_OPC_LB:
11842 gen_ld(ctx, OPC_LB, ry, rx, offset);
11843 break;
11844 case M16_OPC_LH:
11845 gen_ld(ctx, OPC_LH, ry, rx, offset);
11846 break;
11847 case M16_OPC_LWSP:
11848 gen_ld(ctx, OPC_LW, rx, 29, offset);
11849 break;
11850 case M16_OPC_LW:
11851 gen_ld(ctx, OPC_LW, ry, rx, offset);
11852 break;
11853 case M16_OPC_LBU:
11854 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11855 break;
11856 case M16_OPC_LHU:
11857 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11858 break;
11859 case M16_OPC_LWPC:
11860 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11861 break;
11862 #if defined(TARGET_MIPS64)
11863 case M16_OPC_LWU:
11864 check_insn(ctx, ISA_MIPS3);
11865 check_mips_64(ctx);
11866 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11867 break;
11868 #endif
11869 case M16_OPC_SB:
11870 gen_st(ctx, OPC_SB, ry, rx, offset);
11871 break;
11872 case M16_OPC_SH:
11873 gen_st(ctx, OPC_SH, ry, rx, offset);
11874 break;
11875 case M16_OPC_SWSP:
11876 gen_st(ctx, OPC_SW, rx, 29, offset);
11877 break;
11878 case M16_OPC_SW:
11879 gen_st(ctx, OPC_SW, ry, rx, offset);
11880 break;
11881 #if defined(TARGET_MIPS64)
11882 case M16_OPC_I64:
11883 decode_i64_mips16(ctx, ry, funct, offset, 1);
11884 break;
11885 #endif
11886 default:
11887 generate_exception(ctx, EXCP_RI);
11888 break;
11891 return 4;
11894 static inline bool is_uhi(int sdbbp_code)
11896 #ifdef CONFIG_USER_ONLY
11897 return false;
11898 #else
11899 return semihosting_enabled() && sdbbp_code == 1;
11900 #endif
11903 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11905 int rx, ry;
11906 int sa;
11907 int op, cnvt_op, op1, offset;
11908 int funct;
11909 int n_bytes;
11911 op = (ctx->opcode >> 11) & 0x1f;
11912 sa = (ctx->opcode >> 2) & 0x7;
11913 sa = sa == 0 ? 8 : sa;
11914 rx = xlat((ctx->opcode >> 8) & 0x7);
11915 cnvt_op = (ctx->opcode >> 5) & 0x7;
11916 ry = xlat((ctx->opcode >> 5) & 0x7);
11917 op1 = offset = ctx->opcode & 0x1f;
11919 n_bytes = 2;
11921 switch (op) {
11922 case M16_OPC_ADDIUSP:
11924 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11926 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11928 break;
11929 case M16_OPC_ADDIUPC:
11930 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11931 break;
11932 case M16_OPC_B:
11933 offset = (ctx->opcode & 0x7ff) << 1;
11934 offset = (int16_t)(offset << 4) >> 4;
11935 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11936 /* No delay slot, so just process as a normal instruction */
11937 break;
11938 case M16_OPC_JAL:
11939 offset = cpu_lduw_code(env, ctx->pc + 2);
11940 offset = (((ctx->opcode & 0x1f) << 21)
11941 | ((ctx->opcode >> 5) & 0x1f) << 16
11942 | offset) << 2;
11943 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11944 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11945 n_bytes = 4;
11946 break;
11947 case M16_OPC_BEQZ:
11948 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11949 ((int8_t)ctx->opcode) << 1, 0);
11950 /* No delay slot, so just process as a normal instruction */
11951 break;
11952 case M16_OPC_BNEQZ:
11953 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11954 ((int8_t)ctx->opcode) << 1, 0);
11955 /* No delay slot, so just process as a normal instruction */
11956 break;
11957 case M16_OPC_SHIFT:
11958 switch (ctx->opcode & 0x3) {
11959 case 0x0:
11960 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11961 break;
11962 case 0x1:
11963 #if defined(TARGET_MIPS64)
11964 check_insn(ctx, ISA_MIPS3);
11965 check_mips_64(ctx);
11966 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11967 #else
11968 generate_exception(ctx, EXCP_RI);
11969 #endif
11970 break;
11971 case 0x2:
11972 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11973 break;
11974 case 0x3:
11975 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11976 break;
11978 break;
11979 #if defined(TARGET_MIPS64)
11980 case M16_OPC_LD:
11981 check_insn(ctx, ISA_MIPS3);
11982 check_mips_64(ctx);
11983 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
11984 break;
11985 #endif
11986 case M16_OPC_RRIA:
11988 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
11990 if ((ctx->opcode >> 4) & 1) {
11991 #if defined(TARGET_MIPS64)
11992 check_insn(ctx, ISA_MIPS3);
11993 check_mips_64(ctx);
11994 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11995 #else
11996 generate_exception(ctx, EXCP_RI);
11997 #endif
11998 } else {
11999 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12002 break;
12003 case M16_OPC_ADDIU8:
12005 int16_t imm = (int8_t) ctx->opcode;
12007 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12009 break;
12010 case M16_OPC_SLTI:
12012 int16_t imm = (uint8_t) ctx->opcode;
12013 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12015 break;
12016 case M16_OPC_SLTIU:
12018 int16_t imm = (uint8_t) ctx->opcode;
12019 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12021 break;
12022 case M16_OPC_I8:
12024 int reg32;
12026 funct = (ctx->opcode >> 8) & 0x7;
12027 switch (funct) {
12028 case I8_BTEQZ:
12029 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
12030 ((int8_t)ctx->opcode) << 1, 0);
12031 break;
12032 case I8_BTNEZ:
12033 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
12034 ((int8_t)ctx->opcode) << 1, 0);
12035 break;
12036 case I8_SWRASP:
12037 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
12038 break;
12039 case I8_ADJSP:
12040 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
12041 ((int8_t)ctx->opcode) << 3);
12042 break;
12043 case I8_SVRS:
12044 check_insn(ctx, ISA_MIPS32);
12046 int do_ra = ctx->opcode & (1 << 6);
12047 int do_s0 = ctx->opcode & (1 << 5);
12048 int do_s1 = ctx->opcode & (1 << 4);
12049 int framesize = ctx->opcode & 0xf;
12051 if (framesize == 0) {
12052 framesize = 128;
12053 } else {
12054 framesize = framesize << 3;
12057 if (ctx->opcode & (1 << 7)) {
12058 gen_mips16_save(ctx, 0, 0,
12059 do_ra, do_s0, do_s1, framesize);
12060 } else {
12061 gen_mips16_restore(ctx, 0, 0,
12062 do_ra, do_s0, do_s1, framesize);
12065 break;
12066 case I8_MOV32R:
12068 int rz = xlat(ctx->opcode & 0x7);
12070 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
12071 ((ctx->opcode >> 5) & 0x7);
12072 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
12074 break;
12075 case I8_MOVR32:
12076 reg32 = ctx->opcode & 0x1f;
12077 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
12078 break;
12079 default:
12080 generate_exception(ctx, EXCP_RI);
12081 break;
12084 break;
12085 case M16_OPC_LI:
12087 int16_t imm = (uint8_t) ctx->opcode;
12089 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
12091 break;
12092 case M16_OPC_CMPI:
12094 int16_t imm = (uint8_t) ctx->opcode;
12095 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
12097 break;
12098 #if defined(TARGET_MIPS64)
12099 case M16_OPC_SD:
12100 check_insn(ctx, ISA_MIPS3);
12101 check_mips_64(ctx);
12102 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
12103 break;
12104 #endif
12105 case M16_OPC_LB:
12106 gen_ld(ctx, OPC_LB, ry, rx, offset);
12107 break;
12108 case M16_OPC_LH:
12109 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
12110 break;
12111 case M16_OPC_LWSP:
12112 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12113 break;
12114 case M16_OPC_LW:
12115 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
12116 break;
12117 case M16_OPC_LBU:
12118 gen_ld(ctx, OPC_LBU, ry, rx, offset);
12119 break;
12120 case M16_OPC_LHU:
12121 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
12122 break;
12123 case M16_OPC_LWPC:
12124 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
12125 break;
12126 #if defined (TARGET_MIPS64)
12127 case M16_OPC_LWU:
12128 check_insn(ctx, ISA_MIPS3);
12129 check_mips_64(ctx);
12130 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
12131 break;
12132 #endif
12133 case M16_OPC_SB:
12134 gen_st(ctx, OPC_SB, ry, rx, offset);
12135 break;
12136 case M16_OPC_SH:
12137 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
12138 break;
12139 case M16_OPC_SWSP:
12140 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12141 break;
12142 case M16_OPC_SW:
12143 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
12144 break;
12145 case M16_OPC_RRR:
12147 int rz = xlat((ctx->opcode >> 2) & 0x7);
12148 int mips32_op;
12150 switch (ctx->opcode & 0x3) {
12151 case RRR_ADDU:
12152 mips32_op = OPC_ADDU;
12153 break;
12154 case RRR_SUBU:
12155 mips32_op = OPC_SUBU;
12156 break;
12157 #if defined(TARGET_MIPS64)
12158 case RRR_DADDU:
12159 mips32_op = OPC_DADDU;
12160 check_insn(ctx, ISA_MIPS3);
12161 check_mips_64(ctx);
12162 break;
12163 case RRR_DSUBU:
12164 mips32_op = OPC_DSUBU;
12165 check_insn(ctx, ISA_MIPS3);
12166 check_mips_64(ctx);
12167 break;
12168 #endif
12169 default:
12170 generate_exception(ctx, EXCP_RI);
12171 goto done;
12174 gen_arith(ctx, mips32_op, rz, rx, ry);
12175 done:
12178 break;
12179 case M16_OPC_RR:
12180 switch (op1) {
12181 case RR_JR:
12183 int nd = (ctx->opcode >> 7) & 0x1;
12184 int link = (ctx->opcode >> 6) & 0x1;
12185 int ra = (ctx->opcode >> 5) & 0x1;
12187 if (nd) {
12188 check_insn(ctx, ISA_MIPS32);
12191 if (link) {
12192 op = OPC_JALR;
12193 } else {
12194 op = OPC_JR;
12197 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
12198 (nd ? 0 : 2));
12200 break;
12201 case RR_SDBBP:
12202 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
12203 gen_helper_do_semihosting(cpu_env);
12204 } else {
12205 /* XXX: not clear which exception should be raised
12206 * when in debug mode...
12208 check_insn(ctx, ISA_MIPS32);
12209 generate_exception(ctx, EXCP_DBp);
12211 break;
12212 case RR_SLT:
12213 gen_slt(ctx, OPC_SLT, 24, rx, ry);
12214 break;
12215 case RR_SLTU:
12216 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
12217 break;
12218 case RR_BREAK:
12219 generate_exception(ctx, EXCP_BREAK);
12220 break;
12221 case RR_SLLV:
12222 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
12223 break;
12224 case RR_SRLV:
12225 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
12226 break;
12227 case RR_SRAV:
12228 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
12229 break;
12230 #if defined (TARGET_MIPS64)
12231 case RR_DSRL:
12232 check_insn(ctx, ISA_MIPS3);
12233 check_mips_64(ctx);
12234 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
12235 break;
12236 #endif
12237 case RR_CMP:
12238 gen_logic(ctx, OPC_XOR, 24, rx, ry);
12239 break;
12240 case RR_NEG:
12241 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
12242 break;
12243 case RR_AND:
12244 gen_logic(ctx, OPC_AND, rx, rx, ry);
12245 break;
12246 case RR_OR:
12247 gen_logic(ctx, OPC_OR, rx, rx, ry);
12248 break;
12249 case RR_XOR:
12250 gen_logic(ctx, OPC_XOR, rx, rx, ry);
12251 break;
12252 case RR_NOT:
12253 gen_logic(ctx, OPC_NOR, rx, ry, 0);
12254 break;
12255 case RR_MFHI:
12256 gen_HILO(ctx, OPC_MFHI, 0, rx);
12257 break;
12258 case RR_CNVT:
12259 check_insn(ctx, ISA_MIPS32);
12260 switch (cnvt_op) {
12261 case RR_RY_CNVT_ZEB:
12262 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12263 break;
12264 case RR_RY_CNVT_ZEH:
12265 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12266 break;
12267 case RR_RY_CNVT_SEB:
12268 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12269 break;
12270 case RR_RY_CNVT_SEH:
12271 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12272 break;
12273 #if defined (TARGET_MIPS64)
12274 case RR_RY_CNVT_ZEW:
12275 check_insn(ctx, ISA_MIPS64);
12276 check_mips_64(ctx);
12277 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12278 break;
12279 case RR_RY_CNVT_SEW:
12280 check_insn(ctx, ISA_MIPS64);
12281 check_mips_64(ctx);
12282 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12283 break;
12284 #endif
12285 default:
12286 generate_exception(ctx, EXCP_RI);
12287 break;
12289 break;
12290 case RR_MFLO:
12291 gen_HILO(ctx, OPC_MFLO, 0, rx);
12292 break;
12293 #if defined (TARGET_MIPS64)
12294 case RR_DSRA:
12295 check_insn(ctx, ISA_MIPS3);
12296 check_mips_64(ctx);
12297 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
12298 break;
12299 case RR_DSLLV:
12300 check_insn(ctx, ISA_MIPS3);
12301 check_mips_64(ctx);
12302 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
12303 break;
12304 case RR_DSRLV:
12305 check_insn(ctx, ISA_MIPS3);
12306 check_mips_64(ctx);
12307 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
12308 break;
12309 case RR_DSRAV:
12310 check_insn(ctx, ISA_MIPS3);
12311 check_mips_64(ctx);
12312 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
12313 break;
12314 #endif
12315 case RR_MULT:
12316 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
12317 break;
12318 case RR_MULTU:
12319 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
12320 break;
12321 case RR_DIV:
12322 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
12323 break;
12324 case RR_DIVU:
12325 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
12326 break;
12327 #if defined (TARGET_MIPS64)
12328 case RR_DMULT:
12329 check_insn(ctx, ISA_MIPS3);
12330 check_mips_64(ctx);
12331 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
12332 break;
12333 case RR_DMULTU:
12334 check_insn(ctx, ISA_MIPS3);
12335 check_mips_64(ctx);
12336 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
12337 break;
12338 case RR_DDIV:
12339 check_insn(ctx, ISA_MIPS3);
12340 check_mips_64(ctx);
12341 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
12342 break;
12343 case RR_DDIVU:
12344 check_insn(ctx, ISA_MIPS3);
12345 check_mips_64(ctx);
12346 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
12347 break;
12348 #endif
12349 default:
12350 generate_exception(ctx, EXCP_RI);
12351 break;
12353 break;
12354 case M16_OPC_EXTEND:
12355 decode_extended_mips16_opc(env, ctx);
12356 n_bytes = 4;
12357 break;
12358 #if defined(TARGET_MIPS64)
12359 case M16_OPC_I64:
12360 funct = (ctx->opcode >> 8) & 0x7;
12361 decode_i64_mips16(ctx, ry, funct, offset, 0);
12362 break;
12363 #endif
12364 default:
12365 generate_exception(ctx, EXCP_RI);
12366 break;
12369 return n_bytes;
12372 /* microMIPS extension to MIPS32/MIPS64 */
12375 * microMIPS32/microMIPS64 major opcodes
12377 * 1. MIPS Architecture for Programmers Volume II-B:
12378 * The microMIPS32 Instruction Set (Revision 3.05)
12380 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12382 * 2. MIPS Architecture For Programmers Volume II-A:
12383 * The MIPS64 Instruction Set (Revision 3.51)
12386 enum {
12387 POOL32A = 0x00,
12388 POOL16A = 0x01,
12389 LBU16 = 0x02,
12390 MOVE16 = 0x03,
12391 ADDI32 = 0x04,
12392 R6_LUI = 0x04,
12393 AUI = 0x04,
12394 LBU32 = 0x05,
12395 SB32 = 0x06,
12396 LB32 = 0x07,
12398 POOL32B = 0x08,
12399 POOL16B = 0x09,
12400 LHU16 = 0x0a,
12401 ANDI16 = 0x0b,
12402 ADDIU32 = 0x0c,
12403 LHU32 = 0x0d,
12404 SH32 = 0x0e,
12405 LH32 = 0x0f,
12407 POOL32I = 0x10,
12408 POOL16C = 0x11,
12409 LWSP16 = 0x12,
12410 POOL16D = 0x13,
12411 ORI32 = 0x14,
12412 POOL32F = 0x15,
12413 POOL32S = 0x16, /* MIPS64 */
12414 DADDIU32 = 0x17, /* MIPS64 */
12416 POOL32C = 0x18,
12417 LWGP16 = 0x19,
12418 LW16 = 0x1a,
12419 POOL16E = 0x1b,
12420 XORI32 = 0x1c,
12421 JALS32 = 0x1d,
12422 BOVC = 0x1d,
12423 BEQC = 0x1d,
12424 BEQZALC = 0x1d,
12425 ADDIUPC = 0x1e,
12426 PCREL = 0x1e,
12427 BNVC = 0x1f,
12428 BNEC = 0x1f,
12429 BNEZALC = 0x1f,
12431 R6_BEQZC = 0x20,
12432 JIC = 0x20,
12433 POOL16F = 0x21,
12434 SB16 = 0x22,
12435 BEQZ16 = 0x23,
12436 BEQZC16 = 0x23,
12437 SLTI32 = 0x24,
12438 BEQ32 = 0x25,
12439 BC = 0x25,
12440 SWC132 = 0x26,
12441 LWC132 = 0x27,
12443 /* 0x29 is reserved */
12444 RES_29 = 0x29,
12445 R6_BNEZC = 0x28,
12446 JIALC = 0x28,
12447 SH16 = 0x2a,
12448 BNEZ16 = 0x2b,
12449 BNEZC16 = 0x2b,
12450 SLTIU32 = 0x2c,
12451 BNE32 = 0x2d,
12452 BALC = 0x2d,
12453 SDC132 = 0x2e,
12454 LDC132 = 0x2f,
12456 /* 0x31 is reserved */
12457 RES_31 = 0x31,
12458 BLEZALC = 0x30,
12459 BGEZALC = 0x30,
12460 BGEUC = 0x30,
12461 SWSP16 = 0x32,
12462 B16 = 0x33,
12463 BC16 = 0x33,
12464 ANDI32 = 0x34,
12465 J32 = 0x35,
12466 BGTZC = 0x35,
12467 BLTZC = 0x35,
12468 BLTC = 0x35,
12469 SD32 = 0x36, /* MIPS64 */
12470 LD32 = 0x37, /* MIPS64 */
12472 /* 0x39 is reserved */
12473 RES_39 = 0x39,
12474 BGTZALC = 0x38,
12475 BLTZALC = 0x38,
12476 BLTUC = 0x38,
12477 SW16 = 0x3a,
12478 LI16 = 0x3b,
12479 JALX32 = 0x3c,
12480 JAL32 = 0x3d,
12481 BLEZC = 0x3d,
12482 BGEZC = 0x3d,
12483 BGEC = 0x3d,
12484 SW32 = 0x3e,
12485 LW32 = 0x3f
12488 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12489 enum {
12490 ADDIUPC_00 = 0x00,
12491 ADDIUPC_07 = 0x07,
12492 AUIPC = 0x1e,
12493 ALUIPC = 0x1f,
12494 LWPC_08 = 0x08,
12495 LWPC_0F = 0x0F,
12498 /* POOL32A encoding of minor opcode field */
12500 enum {
12501 /* These opcodes are distinguished only by bits 9..6; those bits are
12502 * what are recorded below. */
12503 SLL32 = 0x0,
12504 SRL32 = 0x1,
12505 SRA = 0x2,
12506 ROTR = 0x3,
12507 SELEQZ = 0x5,
12508 SELNEZ = 0x6,
12510 SLLV = 0x0,
12511 SRLV = 0x1,
12512 SRAV = 0x2,
12513 ROTRV = 0x3,
12514 ADD = 0x4,
12515 ADDU32 = 0x5,
12516 SUB = 0x6,
12517 SUBU32 = 0x7,
12518 MUL = 0x8,
12519 AND = 0x9,
12520 OR32 = 0xa,
12521 NOR = 0xb,
12522 XOR32 = 0xc,
12523 SLT = 0xd,
12524 SLTU = 0xe,
12526 MOVN = 0x0,
12527 R6_MUL = 0x0,
12528 MOVZ = 0x1,
12529 MUH = 0x1,
12530 MULU = 0x2,
12531 MUHU = 0x3,
12532 LWXS = 0x4,
12533 R6_DIV = 0x4,
12534 MOD = 0x5,
12535 R6_DIVU = 0x6,
12536 MODU = 0x7,
12538 /* The following can be distinguished by their lower 6 bits. */
12539 INS = 0x0c,
12540 LSA = 0x0f,
12541 ALIGN = 0x1f,
12542 EXT = 0x2c,
12543 POOL32AXF = 0x3c
12546 /* POOL32AXF encoding of minor opcode field extension */
12549 * 1. MIPS Architecture for Programmers Volume II-B:
12550 * The microMIPS32 Instruction Set (Revision 3.05)
12552 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12554 * 2. MIPS Architecture for Programmers VolumeIV-e:
12555 * The MIPS DSP Application-Specific Extension
12556 * to the microMIPS32 Architecture (Revision 2.34)
12558 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12561 enum {
12562 /* bits 11..6 */
12563 TEQ = 0x00,
12564 TGE = 0x08,
12565 TGEU = 0x10,
12566 TLT = 0x20,
12567 TLTU = 0x28,
12568 TNE = 0x30,
12570 MFC0 = 0x03,
12571 MTC0 = 0x0b,
12573 /* begin of microMIPS32 DSP */
12575 /* bits 13..12 for 0x01 */
12576 MFHI_ACC = 0x0,
12577 MFLO_ACC = 0x1,
12578 MTHI_ACC = 0x2,
12579 MTLO_ACC = 0x3,
12581 /* bits 13..12 for 0x2a */
12582 MADD_ACC = 0x0,
12583 MADDU_ACC = 0x1,
12584 MSUB_ACC = 0x2,
12585 MSUBU_ACC = 0x3,
12587 /* bits 13..12 for 0x32 */
12588 MULT_ACC = 0x0,
12589 MULTU_ACC = 0x1,
12591 /* end of microMIPS32 DSP */
12593 /* bits 15..12 for 0x2c */
12594 BITSWAP = 0x0,
12595 SEB = 0x2,
12596 SEH = 0x3,
12597 CLO = 0x4,
12598 CLZ = 0x5,
12599 RDHWR = 0x6,
12600 WSBH = 0x7,
12601 MULT = 0x8,
12602 MULTU = 0x9,
12603 DIV = 0xa,
12604 DIVU = 0xb,
12605 MADD = 0xc,
12606 MADDU = 0xd,
12607 MSUB = 0xe,
12608 MSUBU = 0xf,
12610 /* bits 15..12 for 0x34 */
12611 MFC2 = 0x4,
12612 MTC2 = 0x5,
12613 MFHC2 = 0x8,
12614 MTHC2 = 0x9,
12615 CFC2 = 0xc,
12616 CTC2 = 0xd,
12618 /* bits 15..12 for 0x3c */
12619 JALR = 0x0,
12620 JR = 0x0, /* alias */
12621 JALRC = 0x0,
12622 JRC = 0x0,
12623 JALR_HB = 0x1,
12624 JALRC_HB = 0x1,
12625 JALRS = 0x4,
12626 JALRS_HB = 0x5,
12628 /* bits 15..12 for 0x05 */
12629 RDPGPR = 0xe,
12630 WRPGPR = 0xf,
12632 /* bits 15..12 for 0x0d */
12633 TLBP = 0x0,
12634 TLBR = 0x1,
12635 TLBWI = 0x2,
12636 TLBWR = 0x3,
12637 TLBINV = 0x4,
12638 TLBINVF = 0x5,
12639 WAIT = 0x9,
12640 IRET = 0xd,
12641 DERET = 0xe,
12642 ERET = 0xf,
12644 /* bits 15..12 for 0x15 */
12645 DMT = 0x0,
12646 DVPE = 0x1,
12647 EMT = 0x2,
12648 EVPE = 0x3,
12650 /* bits 15..12 for 0x1d */
12651 DI = 0x4,
12652 EI = 0x5,
12654 /* bits 15..12 for 0x2d */
12655 SYNC = 0x6,
12656 SYSCALL = 0x8,
12657 SDBBP = 0xd,
12659 /* bits 15..12 for 0x35 */
12660 MFHI32 = 0x0,
12661 MFLO32 = 0x1,
12662 MTHI32 = 0x2,
12663 MTLO32 = 0x3,
12666 /* POOL32B encoding of minor opcode field (bits 15..12) */
12668 enum {
12669 LWC2 = 0x0,
12670 LWP = 0x1,
12671 LDP = 0x4,
12672 LWM32 = 0x5,
12673 CACHE = 0x6,
12674 LDM = 0x7,
12675 SWC2 = 0x8,
12676 SWP = 0x9,
12677 SDP = 0xc,
12678 SWM32 = 0xd,
12679 SDM = 0xf
12682 /* POOL32C encoding of minor opcode field (bits 15..12) */
12684 enum {
12685 LWL = 0x0,
12686 SWL = 0x8,
12687 LWR = 0x1,
12688 SWR = 0x9,
12689 PREF = 0x2,
12690 /* 0xa is reserved */
12691 LL = 0x3,
12692 SC = 0xb,
12693 LDL = 0x4,
12694 SDL = 0xc,
12695 LDR = 0x5,
12696 SDR = 0xd,
12697 /* 0x6 is reserved */
12698 LWU = 0xe,
12699 LLD = 0x7,
12700 SCD = 0xf
12703 /* POOL32F encoding of minor opcode field (bits 5..0) */
12705 enum {
12706 /* These are the bit 7..6 values */
12707 ADD_FMT = 0x0,
12709 SUB_FMT = 0x1,
12711 MUL_FMT = 0x2,
12713 DIV_FMT = 0x3,
12715 /* These are the bit 8..6 values */
12716 MOVN_FMT = 0x0,
12717 RSQRT2_FMT = 0x0,
12718 MOVF_FMT = 0x0,
12719 RINT_FMT = 0x0,
12720 SELNEZ_FMT = 0x0,
12722 MOVZ_FMT = 0x1,
12723 LWXC1 = 0x1,
12724 MOVT_FMT = 0x1,
12725 CLASS_FMT = 0x1,
12726 SELEQZ_FMT = 0x1,
12728 PLL_PS = 0x2,
12729 SWXC1 = 0x2,
12730 SEL_FMT = 0x2,
12732 PLU_PS = 0x3,
12733 LDXC1 = 0x3,
12735 MOVN_FMT_04 = 0x4,
12736 PUL_PS = 0x4,
12737 SDXC1 = 0x4,
12738 RECIP2_FMT = 0x4,
12740 MOVZ_FMT_05 = 0x05,
12741 PUU_PS = 0x5,
12742 LUXC1 = 0x5,
12744 CVT_PS_S = 0x6,
12745 SUXC1 = 0x6,
12746 ADDR_PS = 0x6,
12747 PREFX = 0x6,
12748 MADDF_FMT = 0x6,
12750 MULR_PS = 0x7,
12751 MSUBF_FMT = 0x7,
12753 MADD_S = 0x01,
12754 MADD_D = 0x09,
12755 MADD_PS = 0x11,
12756 ALNV_PS = 0x19,
12757 MSUB_S = 0x21,
12758 MSUB_D = 0x29,
12759 MSUB_PS = 0x31,
12761 NMADD_S = 0x02,
12762 NMADD_D = 0x0a,
12763 NMADD_PS = 0x12,
12764 NMSUB_S = 0x22,
12765 NMSUB_D = 0x2a,
12766 NMSUB_PS = 0x32,
12768 MIN_FMT = 0x3,
12769 MAX_FMT = 0xb,
12770 MINA_FMT = 0x23,
12771 MAXA_FMT = 0x2b,
12772 POOL32FXF = 0x3b,
12774 CABS_COND_FMT = 0x1c, /* MIPS3D */
12775 C_COND_FMT = 0x3c,
12777 CMP_CONDN_S = 0x5,
12778 CMP_CONDN_D = 0x15
12781 /* POOL32Fxf encoding of minor opcode extension field */
12783 enum {
12784 CVT_L = 0x04,
12785 RSQRT_FMT = 0x08,
12786 FLOOR_L = 0x0c,
12787 CVT_PW_PS = 0x1c,
12788 CVT_W = 0x24,
12789 SQRT_FMT = 0x28,
12790 FLOOR_W = 0x2c,
12791 CVT_PS_PW = 0x3c,
12792 CFC1 = 0x40,
12793 RECIP_FMT = 0x48,
12794 CEIL_L = 0x4c,
12795 CTC1 = 0x60,
12796 CEIL_W = 0x6c,
12797 MFC1 = 0x80,
12798 CVT_S_PL = 0x84,
12799 TRUNC_L = 0x8c,
12800 MTC1 = 0xa0,
12801 CVT_S_PU = 0xa4,
12802 TRUNC_W = 0xac,
12803 MFHC1 = 0xc0,
12804 ROUND_L = 0xcc,
12805 MTHC1 = 0xe0,
12806 ROUND_W = 0xec,
12808 MOV_FMT = 0x01,
12809 MOVF = 0x05,
12810 ABS_FMT = 0x0d,
12811 RSQRT1_FMT = 0x1d,
12812 MOVT = 0x25,
12813 NEG_FMT = 0x2d,
12814 CVT_D = 0x4d,
12815 RECIP1_FMT = 0x5d,
12816 CVT_S = 0x6d
12819 /* POOL32I encoding of minor opcode field (bits 25..21) */
12821 enum {
12822 BLTZ = 0x00,
12823 BLTZAL = 0x01,
12824 BGEZ = 0x02,
12825 BGEZAL = 0x03,
12826 BLEZ = 0x04,
12827 BNEZC = 0x05,
12828 BGTZ = 0x06,
12829 BEQZC = 0x07,
12830 TLTI = 0x08,
12831 BC1EQZC = 0x08,
12832 TGEI = 0x09,
12833 BC1NEZC = 0x09,
12834 TLTIU = 0x0a,
12835 BC2EQZC = 0x0a,
12836 TGEIU = 0x0b,
12837 BC2NEZC = 0x0a,
12838 TNEI = 0x0c,
12839 R6_SYNCI = 0x0c,
12840 LUI = 0x0d,
12841 TEQI = 0x0e,
12842 SYNCI = 0x10,
12843 BLTZALS = 0x11,
12844 BGEZALS = 0x13,
12845 BC2F = 0x14,
12846 BC2T = 0x15,
12847 BPOSGE64 = 0x1a,
12848 BPOSGE32 = 0x1b,
12849 /* These overlap and are distinguished by bit16 of the instruction */
12850 BC1F = 0x1c,
12851 BC1T = 0x1d,
12852 BC1ANY2F = 0x1c,
12853 BC1ANY2T = 0x1d,
12854 BC1ANY4F = 0x1e,
12855 BC1ANY4T = 0x1f
12858 /* POOL16A encoding of minor opcode field */
12860 enum {
12861 ADDU16 = 0x0,
12862 SUBU16 = 0x1
12865 /* POOL16B encoding of minor opcode field */
12867 enum {
12868 SLL16 = 0x0,
12869 SRL16 = 0x1
12872 /* POOL16C encoding of minor opcode field */
12874 enum {
12875 NOT16 = 0x00,
12876 XOR16 = 0x04,
12877 AND16 = 0x08,
12878 OR16 = 0x0c,
12879 LWM16 = 0x10,
12880 SWM16 = 0x14,
12881 JR16 = 0x18,
12882 JRC16 = 0x1a,
12883 JALR16 = 0x1c,
12884 JALR16S = 0x1e,
12885 MFHI16 = 0x20,
12886 MFLO16 = 0x24,
12887 BREAK16 = 0x28,
12888 SDBBP16 = 0x2c,
12889 JRADDIUSP = 0x30
12892 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
12894 enum {
12895 R6_NOT16 = 0x00,
12896 R6_AND16 = 0x01,
12897 R6_LWM16 = 0x02,
12898 R6_JRC16 = 0x03,
12899 MOVEP = 0x04,
12900 MOVEP_07 = 0x07,
12901 R6_XOR16 = 0x08,
12902 R6_OR16 = 0x09,
12903 R6_SWM16 = 0x0a,
12904 JALRC16 = 0x0b,
12905 MOVEP_0C = 0x0c,
12906 MOVEP_0F = 0x0f,
12907 JRCADDIUSP = 0x13,
12908 R6_BREAK16 = 0x1b,
12909 R6_SDBBP16 = 0x3b
12912 /* POOL16D encoding of minor opcode field */
12914 enum {
12915 ADDIUS5 = 0x0,
12916 ADDIUSP = 0x1
12919 /* POOL16E encoding of minor opcode field */
12921 enum {
12922 ADDIUR2 = 0x0,
12923 ADDIUR1SP = 0x1
12926 static int mmreg (int r)
12928 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12930 return map[r];
12933 /* Used for 16-bit store instructions. */
12934 static int mmreg2 (int r)
12936 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12938 return map[r];
12941 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12942 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12943 #define uMIPS_RS2(op) uMIPS_RS(op)
12944 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12945 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12946 #define uMIPS_RS5(op) (op & 0x1f)
12948 /* Signed immediate */
12949 #define SIMM(op, start, width) \
12950 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12951 << (32-width)) \
12952 >> (32-width))
12953 /* Zero-extended immediate */
12954 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12956 static void gen_addiur1sp(DisasContext *ctx)
12958 int rd = mmreg(uMIPS_RD(ctx->opcode));
12960 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12963 static void gen_addiur2(DisasContext *ctx)
12965 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12966 int rd = mmreg(uMIPS_RD(ctx->opcode));
12967 int rs = mmreg(uMIPS_RS(ctx->opcode));
12969 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12972 static void gen_addiusp(DisasContext *ctx)
12974 int encoded = ZIMM(ctx->opcode, 1, 9);
12975 int decoded;
12977 if (encoded <= 1) {
12978 decoded = 256 + encoded;
12979 } else if (encoded <= 255) {
12980 decoded = encoded;
12981 } else if (encoded <= 509) {
12982 decoded = encoded - 512;
12983 } else {
12984 decoded = encoded - 768;
12987 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
12990 static void gen_addius5(DisasContext *ctx)
12992 int imm = SIMM(ctx->opcode, 1, 4);
12993 int rd = (ctx->opcode >> 5) & 0x1f;
12995 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
12998 static void gen_andi16(DisasContext *ctx)
13000 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
13001 31, 32, 63, 64, 255, 32768, 65535 };
13002 int rd = mmreg(uMIPS_RD(ctx->opcode));
13003 int rs = mmreg(uMIPS_RS(ctx->opcode));
13004 int encoded = ZIMM(ctx->opcode, 0, 4);
13006 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
13009 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
13010 int base, int16_t offset)
13012 const char *opn = "ldst_multiple";
13013 TCGv t0, t1;
13014 TCGv_i32 t2;
13016 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13017 generate_exception(ctx, EXCP_RI);
13018 return;
13021 t0 = tcg_temp_new();
13023 gen_base_offset_addr(ctx, t0, base, offset);
13025 t1 = tcg_const_tl(reglist);
13026 t2 = tcg_const_i32(ctx->mem_idx);
13028 save_cpu_state(ctx, 1);
13029 switch (opc) {
13030 case LWM32:
13031 gen_helper_lwm(cpu_env, t0, t1, t2);
13032 opn = "lwm";
13033 break;
13034 case SWM32:
13035 gen_helper_swm(cpu_env, t0, t1, t2);
13036 opn = "swm";
13037 break;
13038 #ifdef TARGET_MIPS64
13039 case LDM:
13040 gen_helper_ldm(cpu_env, t0, t1, t2);
13041 opn = "ldm";
13042 break;
13043 case SDM:
13044 gen_helper_sdm(cpu_env, t0, t1, t2);
13045 opn = "sdm";
13046 break;
13047 #endif
13049 (void)opn;
13050 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
13051 tcg_temp_free(t0);
13052 tcg_temp_free(t1);
13053 tcg_temp_free_i32(t2);
13057 static void gen_pool16c_insn(DisasContext *ctx)
13059 int rd = mmreg((ctx->opcode >> 3) & 0x7);
13060 int rs = mmreg(ctx->opcode & 0x7);
13062 switch (((ctx->opcode) >> 4) & 0x3f) {
13063 case NOT16 + 0:
13064 case NOT16 + 1:
13065 case NOT16 + 2:
13066 case NOT16 + 3:
13067 gen_logic(ctx, OPC_NOR, rd, rs, 0);
13068 break;
13069 case XOR16 + 0:
13070 case XOR16 + 1:
13071 case XOR16 + 2:
13072 case XOR16 + 3:
13073 gen_logic(ctx, OPC_XOR, rd, rd, rs);
13074 break;
13075 case AND16 + 0:
13076 case AND16 + 1:
13077 case AND16 + 2:
13078 case AND16 + 3:
13079 gen_logic(ctx, OPC_AND, rd, rd, rs);
13080 break;
13081 case OR16 + 0:
13082 case OR16 + 1:
13083 case OR16 + 2:
13084 case OR16 + 3:
13085 gen_logic(ctx, OPC_OR, rd, rd, rs);
13086 break;
13087 case LWM16 + 0:
13088 case LWM16 + 1:
13089 case LWM16 + 2:
13090 case LWM16 + 3:
13092 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13093 int offset = ZIMM(ctx->opcode, 0, 4);
13095 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
13096 29, offset << 2);
13098 break;
13099 case SWM16 + 0:
13100 case SWM16 + 1:
13101 case SWM16 + 2:
13102 case SWM16 + 3:
13104 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13105 int offset = ZIMM(ctx->opcode, 0, 4);
13107 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
13108 29, offset << 2);
13110 break;
13111 case JR16 + 0:
13112 case JR16 + 1:
13114 int reg = ctx->opcode & 0x1f;
13116 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
13118 break;
13119 case JRC16 + 0:
13120 case JRC16 + 1:
13122 int reg = ctx->opcode & 0x1f;
13123 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
13124 /* Let normal delay slot handling in our caller take us
13125 to the branch target. */
13127 break;
13128 case JALR16 + 0:
13129 case JALR16 + 1:
13130 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
13131 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13132 break;
13133 case JALR16S + 0:
13134 case JALR16S + 1:
13135 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
13136 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13137 break;
13138 case MFHI16 + 0:
13139 case MFHI16 + 1:
13140 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
13141 break;
13142 case MFLO16 + 0:
13143 case MFLO16 + 1:
13144 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
13145 break;
13146 case BREAK16:
13147 generate_exception(ctx, EXCP_BREAK);
13148 break;
13149 case SDBBP16:
13150 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
13151 gen_helper_do_semihosting(cpu_env);
13152 } else {
13153 /* XXX: not clear which exception should be raised
13154 * when in debug mode...
13156 check_insn(ctx, ISA_MIPS32);
13157 generate_exception(ctx, EXCP_DBp);
13159 break;
13160 case JRADDIUSP + 0:
13161 case JRADDIUSP + 1:
13163 int imm = ZIMM(ctx->opcode, 0, 5);
13164 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13165 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13166 /* Let normal delay slot handling in our caller take us
13167 to the branch target. */
13169 break;
13170 default:
13171 generate_exception(ctx, EXCP_RI);
13172 break;
13176 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
13177 int enc_rs)
13179 int rd, rs, re, rt;
13180 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
13181 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
13182 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
13183 rd = rd_enc[enc_dest];
13184 re = re_enc[enc_dest];
13185 rs = rs_rt_enc[enc_rs];
13186 rt = rs_rt_enc[enc_rt];
13187 if (rs) {
13188 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
13189 } else {
13190 tcg_gen_movi_tl(cpu_gpr[rd], 0);
13192 if (rt) {
13193 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
13194 } else {
13195 tcg_gen_movi_tl(cpu_gpr[re], 0);
13199 static void gen_pool16c_r6_insn(DisasContext *ctx)
13201 int rt = mmreg((ctx->opcode >> 7) & 0x7);
13202 int rs = mmreg((ctx->opcode >> 4) & 0x7);
13204 switch (ctx->opcode & 0xf) {
13205 case R6_NOT16:
13206 gen_logic(ctx, OPC_NOR, rt, rs, 0);
13207 break;
13208 case R6_AND16:
13209 gen_logic(ctx, OPC_AND, rt, rt, rs);
13210 break;
13211 case R6_LWM16:
13213 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13214 int offset = extract32(ctx->opcode, 4, 4);
13215 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
13217 break;
13218 case R6_JRC16: /* JRCADDIUSP */
13219 if ((ctx->opcode >> 4) & 1) {
13220 /* JRCADDIUSP */
13221 int imm = extract32(ctx->opcode, 5, 5);
13222 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13223 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13224 } else {
13225 /* JRC16 */
13226 int rs = extract32(ctx->opcode, 5, 5);
13227 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
13229 break;
13230 case MOVEP ... MOVEP_07:
13231 case MOVEP_0C ... MOVEP_0F:
13233 int enc_dest = uMIPS_RD(ctx->opcode);
13234 int enc_rt = uMIPS_RS2(ctx->opcode);
13235 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
13236 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
13238 break;
13239 case R6_XOR16:
13240 gen_logic(ctx, OPC_XOR, rt, rt, rs);
13241 break;
13242 case R6_OR16:
13243 gen_logic(ctx, OPC_OR, rt, rt, rs);
13244 break;
13245 case R6_SWM16:
13247 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13248 int offset = extract32(ctx->opcode, 4, 4);
13249 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
13251 break;
13252 case JALRC16: /* BREAK16, SDBBP16 */
13253 switch (ctx->opcode & 0x3f) {
13254 case JALRC16:
13255 case JALRC16 + 0x20:
13256 /* JALRC16 */
13257 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
13258 31, 0, 0);
13259 break;
13260 case R6_BREAK16:
13261 /* BREAK16 */
13262 generate_exception(ctx, EXCP_BREAK);
13263 break;
13264 case R6_SDBBP16:
13265 /* SDBBP16 */
13266 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13267 generate_exception(ctx, EXCP_RI);
13268 } else {
13269 generate_exception(ctx, EXCP_DBp);
13271 break;
13273 break;
13274 default:
13275 generate_exception(ctx, EXCP_RI);
13276 break;
13280 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
13282 TCGv t0 = tcg_temp_new();
13283 TCGv t1 = tcg_temp_new();
13285 gen_load_gpr(t0, base);
13287 if (index != 0) {
13288 gen_load_gpr(t1, index);
13289 tcg_gen_shli_tl(t1, t1, 2);
13290 gen_op_addr_add(ctx, t0, t1, t0);
13293 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13294 gen_store_gpr(t1, rd);
13296 tcg_temp_free(t0);
13297 tcg_temp_free(t1);
13300 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
13301 int base, int16_t offset)
13303 const char *opn = "ldst_pair";
13304 TCGv t0, t1;
13306 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
13307 generate_exception(ctx, EXCP_RI);
13308 return;
13311 t0 = tcg_temp_new();
13312 t1 = tcg_temp_new();
13314 gen_base_offset_addr(ctx, t0, base, offset);
13316 switch (opc) {
13317 case LWP:
13318 if (rd == base) {
13319 generate_exception(ctx, EXCP_RI);
13320 return;
13322 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13323 gen_store_gpr(t1, rd);
13324 tcg_gen_movi_tl(t1, 4);
13325 gen_op_addr_add(ctx, t0, t0, t1);
13326 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13327 gen_store_gpr(t1, rd+1);
13328 opn = "lwp";
13329 break;
13330 case SWP:
13331 gen_load_gpr(t1, rd);
13332 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13333 tcg_gen_movi_tl(t1, 4);
13334 gen_op_addr_add(ctx, t0, t0, t1);
13335 gen_load_gpr(t1, rd+1);
13336 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13337 opn = "swp";
13338 break;
13339 #ifdef TARGET_MIPS64
13340 case LDP:
13341 if (rd == base) {
13342 generate_exception(ctx, EXCP_RI);
13343 return;
13345 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13346 gen_store_gpr(t1, rd);
13347 tcg_gen_movi_tl(t1, 8);
13348 gen_op_addr_add(ctx, t0, t0, t1);
13349 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13350 gen_store_gpr(t1, rd+1);
13351 opn = "ldp";
13352 break;
13353 case SDP:
13354 gen_load_gpr(t1, rd);
13355 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13356 tcg_gen_movi_tl(t1, 8);
13357 gen_op_addr_add(ctx, t0, t0, t1);
13358 gen_load_gpr(t1, rd+1);
13359 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13360 opn = "sdp";
13361 break;
13362 #endif
13364 (void)opn; /* avoid a compiler warning */
13365 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
13366 tcg_temp_free(t0);
13367 tcg_temp_free(t1);
13370 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
13372 int extension = (ctx->opcode >> 6) & 0x3f;
13373 int minor = (ctx->opcode >> 12) & 0xf;
13374 uint32_t mips32_op;
13376 switch (extension) {
13377 case TEQ:
13378 mips32_op = OPC_TEQ;
13379 goto do_trap;
13380 case TGE:
13381 mips32_op = OPC_TGE;
13382 goto do_trap;
13383 case TGEU:
13384 mips32_op = OPC_TGEU;
13385 goto do_trap;
13386 case TLT:
13387 mips32_op = OPC_TLT;
13388 goto do_trap;
13389 case TLTU:
13390 mips32_op = OPC_TLTU;
13391 goto do_trap;
13392 case TNE:
13393 mips32_op = OPC_TNE;
13394 do_trap:
13395 gen_trap(ctx, mips32_op, rs, rt, -1);
13396 break;
13397 #ifndef CONFIG_USER_ONLY
13398 case MFC0:
13399 case MFC0 + 32:
13400 check_cp0_enabled(ctx);
13401 if (rt == 0) {
13402 /* Treat as NOP. */
13403 break;
13405 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
13406 break;
13407 case MTC0:
13408 case MTC0 + 32:
13409 check_cp0_enabled(ctx);
13411 TCGv t0 = tcg_temp_new();
13413 gen_load_gpr(t0, rt);
13414 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
13415 tcg_temp_free(t0);
13417 break;
13418 #endif
13419 case 0x2a:
13420 switch (minor & 3) {
13421 case MADD_ACC:
13422 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
13423 break;
13424 case MADDU_ACC:
13425 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
13426 break;
13427 case MSUB_ACC:
13428 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
13429 break;
13430 case MSUBU_ACC:
13431 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
13432 break;
13433 default:
13434 goto pool32axf_invalid;
13436 break;
13437 case 0x32:
13438 switch (minor & 3) {
13439 case MULT_ACC:
13440 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
13441 break;
13442 case MULTU_ACC:
13443 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
13444 break;
13445 default:
13446 goto pool32axf_invalid;
13448 break;
13449 case 0x2c:
13450 switch (minor) {
13451 case BITSWAP:
13452 check_insn(ctx, ISA_MIPS32R6);
13453 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
13454 break;
13455 case SEB:
13456 gen_bshfl(ctx, OPC_SEB, rs, rt);
13457 break;
13458 case SEH:
13459 gen_bshfl(ctx, OPC_SEH, rs, rt);
13460 break;
13461 case CLO:
13462 mips32_op = OPC_CLO;
13463 goto do_cl;
13464 case CLZ:
13465 mips32_op = OPC_CLZ;
13466 do_cl:
13467 check_insn(ctx, ISA_MIPS32);
13468 gen_cl(ctx, mips32_op, rt, rs);
13469 break;
13470 case RDHWR:
13471 gen_rdhwr(ctx, rt, rs);
13472 break;
13473 case WSBH:
13474 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13475 break;
13476 case MULT:
13477 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13478 mips32_op = OPC_MULT;
13479 goto do_mul;
13480 case MULTU:
13481 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13482 mips32_op = OPC_MULTU;
13483 goto do_mul;
13484 case DIV:
13485 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13486 mips32_op = OPC_DIV;
13487 goto do_div;
13488 case DIVU:
13489 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13490 mips32_op = OPC_DIVU;
13491 goto do_div;
13492 do_div:
13493 check_insn(ctx, ISA_MIPS32);
13494 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13495 break;
13496 case MADD:
13497 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13498 mips32_op = OPC_MADD;
13499 goto do_mul;
13500 case MADDU:
13501 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13502 mips32_op = OPC_MADDU;
13503 goto do_mul;
13504 case MSUB:
13505 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13506 mips32_op = OPC_MSUB;
13507 goto do_mul;
13508 case MSUBU:
13509 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13510 mips32_op = OPC_MSUBU;
13511 do_mul:
13512 check_insn(ctx, ISA_MIPS32);
13513 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13514 break;
13515 default:
13516 goto pool32axf_invalid;
13518 break;
13519 case 0x34:
13520 switch (minor) {
13521 case MFC2:
13522 case MTC2:
13523 case MFHC2:
13524 case MTHC2:
13525 case CFC2:
13526 case CTC2:
13527 generate_exception_err(ctx, EXCP_CpU, 2);
13528 break;
13529 default:
13530 goto pool32axf_invalid;
13532 break;
13533 case 0x3c:
13534 switch (minor) {
13535 case JALR: /* JALRC */
13536 case JALR_HB: /* JALRC_HB */
13537 if (ctx->insn_flags & ISA_MIPS32R6) {
13538 /* JALRC, JALRC_HB */
13539 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13540 } else {
13541 /* JALR, JALR_HB */
13542 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13543 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13545 break;
13546 case JALRS:
13547 case JALRS_HB:
13548 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13549 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13550 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13551 break;
13552 default:
13553 goto pool32axf_invalid;
13555 break;
13556 case 0x05:
13557 switch (minor) {
13558 case RDPGPR:
13559 check_cp0_enabled(ctx);
13560 check_insn(ctx, ISA_MIPS32R2);
13561 gen_load_srsgpr(rs, rt);
13562 break;
13563 case WRPGPR:
13564 check_cp0_enabled(ctx);
13565 check_insn(ctx, ISA_MIPS32R2);
13566 gen_store_srsgpr(rs, rt);
13567 break;
13568 default:
13569 goto pool32axf_invalid;
13571 break;
13572 #ifndef CONFIG_USER_ONLY
13573 case 0x0d:
13574 switch (minor) {
13575 case TLBP:
13576 mips32_op = OPC_TLBP;
13577 goto do_cp0;
13578 case TLBR:
13579 mips32_op = OPC_TLBR;
13580 goto do_cp0;
13581 case TLBWI:
13582 mips32_op = OPC_TLBWI;
13583 goto do_cp0;
13584 case TLBWR:
13585 mips32_op = OPC_TLBWR;
13586 goto do_cp0;
13587 case TLBINV:
13588 mips32_op = OPC_TLBINV;
13589 goto do_cp0;
13590 case TLBINVF:
13591 mips32_op = OPC_TLBINVF;
13592 goto do_cp0;
13593 case WAIT:
13594 mips32_op = OPC_WAIT;
13595 goto do_cp0;
13596 case DERET:
13597 mips32_op = OPC_DERET;
13598 goto do_cp0;
13599 case ERET:
13600 mips32_op = OPC_ERET;
13601 do_cp0:
13602 gen_cp0(env, ctx, mips32_op, rt, rs);
13603 break;
13604 default:
13605 goto pool32axf_invalid;
13607 break;
13608 case 0x1d:
13609 switch (minor) {
13610 case DI:
13611 check_cp0_enabled(ctx);
13613 TCGv t0 = tcg_temp_new();
13615 save_cpu_state(ctx, 1);
13616 gen_helper_di(t0, cpu_env);
13617 gen_store_gpr(t0, rs);
13618 /* Stop translation as we may have switched the execution mode */
13619 ctx->bstate = BS_STOP;
13620 tcg_temp_free(t0);
13622 break;
13623 case EI:
13624 check_cp0_enabled(ctx);
13626 TCGv t0 = tcg_temp_new();
13628 save_cpu_state(ctx, 1);
13629 gen_helper_ei(t0, cpu_env);
13630 gen_store_gpr(t0, rs);
13631 /* Stop translation as we may have switched the execution mode */
13632 ctx->bstate = BS_STOP;
13633 tcg_temp_free(t0);
13635 break;
13636 default:
13637 goto pool32axf_invalid;
13639 break;
13640 #endif
13641 case 0x2d:
13642 switch (minor) {
13643 case SYNC:
13644 /* NOP */
13645 break;
13646 case SYSCALL:
13647 generate_exception(ctx, EXCP_SYSCALL);
13648 ctx->bstate = BS_STOP;
13649 break;
13650 case SDBBP:
13651 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
13652 gen_helper_do_semihosting(cpu_env);
13653 } else {
13654 check_insn(ctx, ISA_MIPS32);
13655 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13656 generate_exception(ctx, EXCP_RI);
13657 } else {
13658 generate_exception(ctx, EXCP_DBp);
13661 break;
13662 default:
13663 goto pool32axf_invalid;
13665 break;
13666 case 0x01:
13667 switch (minor & 3) {
13668 case MFHI_ACC:
13669 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
13670 break;
13671 case MFLO_ACC:
13672 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
13673 break;
13674 case MTHI_ACC:
13675 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
13676 break;
13677 case MTLO_ACC:
13678 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
13679 break;
13680 default:
13681 goto pool32axf_invalid;
13683 break;
13684 case 0x35:
13685 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13686 switch (minor) {
13687 case MFHI32:
13688 gen_HILO(ctx, OPC_MFHI, 0, rs);
13689 break;
13690 case MFLO32:
13691 gen_HILO(ctx, OPC_MFLO, 0, rs);
13692 break;
13693 case MTHI32:
13694 gen_HILO(ctx, OPC_MTHI, 0, rs);
13695 break;
13696 case MTLO32:
13697 gen_HILO(ctx, OPC_MTLO, 0, rs);
13698 break;
13699 default:
13700 goto pool32axf_invalid;
13702 break;
13703 default:
13704 pool32axf_invalid:
13705 MIPS_INVAL("pool32axf");
13706 generate_exception(ctx, EXCP_RI);
13707 break;
13711 /* Values for microMIPS fmt field. Variable-width, depending on which
13712 formats the instruction supports. */
13714 enum {
13715 FMT_SD_S = 0,
13716 FMT_SD_D = 1,
13718 FMT_SDPS_S = 0,
13719 FMT_SDPS_D = 1,
13720 FMT_SDPS_PS = 2,
13722 FMT_SWL_S = 0,
13723 FMT_SWL_W = 1,
13724 FMT_SWL_L = 2,
13726 FMT_DWL_D = 0,
13727 FMT_DWL_W = 1,
13728 FMT_DWL_L = 2
13731 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
13733 int extension = (ctx->opcode >> 6) & 0x3ff;
13734 uint32_t mips32_op;
13736 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
13737 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
13738 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
13740 switch (extension) {
13741 case FLOAT_1BIT_FMT(CFC1, 0):
13742 mips32_op = OPC_CFC1;
13743 goto do_cp1;
13744 case FLOAT_1BIT_FMT(CTC1, 0):
13745 mips32_op = OPC_CTC1;
13746 goto do_cp1;
13747 case FLOAT_1BIT_FMT(MFC1, 0):
13748 mips32_op = OPC_MFC1;
13749 goto do_cp1;
13750 case FLOAT_1BIT_FMT(MTC1, 0):
13751 mips32_op = OPC_MTC1;
13752 goto do_cp1;
13753 case FLOAT_1BIT_FMT(MFHC1, 0):
13754 mips32_op = OPC_MFHC1;
13755 goto do_cp1;
13756 case FLOAT_1BIT_FMT(MTHC1, 0):
13757 mips32_op = OPC_MTHC1;
13758 do_cp1:
13759 gen_cp1(ctx, mips32_op, rt, rs);
13760 break;
13762 /* Reciprocal square root */
13763 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
13764 mips32_op = OPC_RSQRT_S;
13765 goto do_unaryfp;
13766 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
13767 mips32_op = OPC_RSQRT_D;
13768 goto do_unaryfp;
13770 /* Square root */
13771 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
13772 mips32_op = OPC_SQRT_S;
13773 goto do_unaryfp;
13774 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
13775 mips32_op = OPC_SQRT_D;
13776 goto do_unaryfp;
13778 /* Reciprocal */
13779 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
13780 mips32_op = OPC_RECIP_S;
13781 goto do_unaryfp;
13782 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
13783 mips32_op = OPC_RECIP_D;
13784 goto do_unaryfp;
13786 /* Floor */
13787 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
13788 mips32_op = OPC_FLOOR_L_S;
13789 goto do_unaryfp;
13790 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
13791 mips32_op = OPC_FLOOR_L_D;
13792 goto do_unaryfp;
13793 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
13794 mips32_op = OPC_FLOOR_W_S;
13795 goto do_unaryfp;
13796 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
13797 mips32_op = OPC_FLOOR_W_D;
13798 goto do_unaryfp;
13800 /* Ceiling */
13801 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
13802 mips32_op = OPC_CEIL_L_S;
13803 goto do_unaryfp;
13804 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
13805 mips32_op = OPC_CEIL_L_D;
13806 goto do_unaryfp;
13807 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
13808 mips32_op = OPC_CEIL_W_S;
13809 goto do_unaryfp;
13810 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
13811 mips32_op = OPC_CEIL_W_D;
13812 goto do_unaryfp;
13814 /* Truncation */
13815 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
13816 mips32_op = OPC_TRUNC_L_S;
13817 goto do_unaryfp;
13818 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
13819 mips32_op = OPC_TRUNC_L_D;
13820 goto do_unaryfp;
13821 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
13822 mips32_op = OPC_TRUNC_W_S;
13823 goto do_unaryfp;
13824 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
13825 mips32_op = OPC_TRUNC_W_D;
13826 goto do_unaryfp;
13828 /* Round */
13829 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
13830 mips32_op = OPC_ROUND_L_S;
13831 goto do_unaryfp;
13832 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
13833 mips32_op = OPC_ROUND_L_D;
13834 goto do_unaryfp;
13835 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
13836 mips32_op = OPC_ROUND_W_S;
13837 goto do_unaryfp;
13838 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
13839 mips32_op = OPC_ROUND_W_D;
13840 goto do_unaryfp;
13842 /* Integer to floating-point conversion */
13843 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
13844 mips32_op = OPC_CVT_L_S;
13845 goto do_unaryfp;
13846 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
13847 mips32_op = OPC_CVT_L_D;
13848 goto do_unaryfp;
13849 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
13850 mips32_op = OPC_CVT_W_S;
13851 goto do_unaryfp;
13852 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
13853 mips32_op = OPC_CVT_W_D;
13854 goto do_unaryfp;
13856 /* Paired-foo conversions */
13857 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
13858 mips32_op = OPC_CVT_S_PL;
13859 goto do_unaryfp;
13860 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13861 mips32_op = OPC_CVT_S_PU;
13862 goto do_unaryfp;
13863 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13864 mips32_op = OPC_CVT_PW_PS;
13865 goto do_unaryfp;
13866 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13867 mips32_op = OPC_CVT_PS_PW;
13868 goto do_unaryfp;
13870 /* Floating-point moves */
13871 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13872 mips32_op = OPC_MOV_S;
13873 goto do_unaryfp;
13874 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13875 mips32_op = OPC_MOV_D;
13876 goto do_unaryfp;
13877 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13878 mips32_op = OPC_MOV_PS;
13879 goto do_unaryfp;
13881 /* Absolute value */
13882 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13883 mips32_op = OPC_ABS_S;
13884 goto do_unaryfp;
13885 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13886 mips32_op = OPC_ABS_D;
13887 goto do_unaryfp;
13888 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13889 mips32_op = OPC_ABS_PS;
13890 goto do_unaryfp;
13892 /* Negation */
13893 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13894 mips32_op = OPC_NEG_S;
13895 goto do_unaryfp;
13896 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13897 mips32_op = OPC_NEG_D;
13898 goto do_unaryfp;
13899 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13900 mips32_op = OPC_NEG_PS;
13901 goto do_unaryfp;
13903 /* Reciprocal square root step */
13904 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13905 mips32_op = OPC_RSQRT1_S;
13906 goto do_unaryfp;
13907 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13908 mips32_op = OPC_RSQRT1_D;
13909 goto do_unaryfp;
13910 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13911 mips32_op = OPC_RSQRT1_PS;
13912 goto do_unaryfp;
13914 /* Reciprocal step */
13915 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13916 mips32_op = OPC_RECIP1_S;
13917 goto do_unaryfp;
13918 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13919 mips32_op = OPC_RECIP1_S;
13920 goto do_unaryfp;
13921 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13922 mips32_op = OPC_RECIP1_PS;
13923 goto do_unaryfp;
13925 /* Conversions from double */
13926 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13927 mips32_op = OPC_CVT_D_S;
13928 goto do_unaryfp;
13929 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13930 mips32_op = OPC_CVT_D_W;
13931 goto do_unaryfp;
13932 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13933 mips32_op = OPC_CVT_D_L;
13934 goto do_unaryfp;
13936 /* Conversions from single */
13937 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13938 mips32_op = OPC_CVT_S_D;
13939 goto do_unaryfp;
13940 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13941 mips32_op = OPC_CVT_S_W;
13942 goto do_unaryfp;
13943 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13944 mips32_op = OPC_CVT_S_L;
13945 do_unaryfp:
13946 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13947 break;
13949 /* Conditional moves on floating-point codes */
13950 case COND_FLOAT_MOV(MOVT, 0):
13951 case COND_FLOAT_MOV(MOVT, 1):
13952 case COND_FLOAT_MOV(MOVT, 2):
13953 case COND_FLOAT_MOV(MOVT, 3):
13954 case COND_FLOAT_MOV(MOVT, 4):
13955 case COND_FLOAT_MOV(MOVT, 5):
13956 case COND_FLOAT_MOV(MOVT, 6):
13957 case COND_FLOAT_MOV(MOVT, 7):
13958 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13959 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13960 break;
13961 case COND_FLOAT_MOV(MOVF, 0):
13962 case COND_FLOAT_MOV(MOVF, 1):
13963 case COND_FLOAT_MOV(MOVF, 2):
13964 case COND_FLOAT_MOV(MOVF, 3):
13965 case COND_FLOAT_MOV(MOVF, 4):
13966 case COND_FLOAT_MOV(MOVF, 5):
13967 case COND_FLOAT_MOV(MOVF, 6):
13968 case COND_FLOAT_MOV(MOVF, 7):
13969 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13970 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13971 break;
13972 default:
13973 MIPS_INVAL("pool32fxf");
13974 generate_exception(ctx, EXCP_RI);
13975 break;
13979 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
13981 int32_t offset;
13982 uint16_t insn;
13983 int rt, rs, rd, rr;
13984 int16_t imm;
13985 uint32_t op, minor, mips32_op;
13986 uint32_t cond, fmt, cc;
13988 insn = cpu_lduw_code(env, ctx->pc + 2);
13989 ctx->opcode = (ctx->opcode << 16) | insn;
13991 rt = (ctx->opcode >> 21) & 0x1f;
13992 rs = (ctx->opcode >> 16) & 0x1f;
13993 rd = (ctx->opcode >> 11) & 0x1f;
13994 rr = (ctx->opcode >> 6) & 0x1f;
13995 imm = (int16_t) ctx->opcode;
13997 op = (ctx->opcode >> 26) & 0x3f;
13998 switch (op) {
13999 case POOL32A:
14000 minor = ctx->opcode & 0x3f;
14001 switch (minor) {
14002 case 0x00:
14003 minor = (ctx->opcode >> 6) & 0xf;
14004 switch (minor) {
14005 case SLL32:
14006 mips32_op = OPC_SLL;
14007 goto do_shifti;
14008 case SRA:
14009 mips32_op = OPC_SRA;
14010 goto do_shifti;
14011 case SRL32:
14012 mips32_op = OPC_SRL;
14013 goto do_shifti;
14014 case ROTR:
14015 mips32_op = OPC_ROTR;
14016 do_shifti:
14017 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
14018 break;
14019 case SELEQZ:
14020 check_insn(ctx, ISA_MIPS32R6);
14021 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
14022 break;
14023 case SELNEZ:
14024 check_insn(ctx, ISA_MIPS32R6);
14025 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
14026 break;
14027 default:
14028 goto pool32a_invalid;
14030 break;
14031 case 0x10:
14032 minor = (ctx->opcode >> 6) & 0xf;
14033 switch (minor) {
14034 /* Arithmetic */
14035 case ADD:
14036 mips32_op = OPC_ADD;
14037 goto do_arith;
14038 case ADDU32:
14039 mips32_op = OPC_ADDU;
14040 goto do_arith;
14041 case SUB:
14042 mips32_op = OPC_SUB;
14043 goto do_arith;
14044 case SUBU32:
14045 mips32_op = OPC_SUBU;
14046 goto do_arith;
14047 case MUL:
14048 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14049 mips32_op = OPC_MUL;
14050 do_arith:
14051 gen_arith(ctx, mips32_op, rd, rs, rt);
14052 break;
14053 /* Shifts */
14054 case SLLV:
14055 mips32_op = OPC_SLLV;
14056 goto do_shift;
14057 case SRLV:
14058 mips32_op = OPC_SRLV;
14059 goto do_shift;
14060 case SRAV:
14061 mips32_op = OPC_SRAV;
14062 goto do_shift;
14063 case ROTRV:
14064 mips32_op = OPC_ROTRV;
14065 do_shift:
14066 gen_shift(ctx, mips32_op, rd, rs, rt);
14067 break;
14068 /* Logical operations */
14069 case AND:
14070 mips32_op = OPC_AND;
14071 goto do_logic;
14072 case OR32:
14073 mips32_op = OPC_OR;
14074 goto do_logic;
14075 case NOR:
14076 mips32_op = OPC_NOR;
14077 goto do_logic;
14078 case XOR32:
14079 mips32_op = OPC_XOR;
14080 do_logic:
14081 gen_logic(ctx, mips32_op, rd, rs, rt);
14082 break;
14083 /* Set less than */
14084 case SLT:
14085 mips32_op = OPC_SLT;
14086 goto do_slt;
14087 case SLTU:
14088 mips32_op = OPC_SLTU;
14089 do_slt:
14090 gen_slt(ctx, mips32_op, rd, rs, rt);
14091 break;
14092 default:
14093 goto pool32a_invalid;
14095 break;
14096 case 0x18:
14097 minor = (ctx->opcode >> 6) & 0xf;
14098 switch (minor) {
14099 /* Conditional moves */
14100 case MOVN: /* MUL */
14101 if (ctx->insn_flags & ISA_MIPS32R6) {
14102 /* MUL */
14103 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
14104 } else {
14105 /* MOVN */
14106 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
14108 break;
14109 case MOVZ: /* MUH */
14110 if (ctx->insn_flags & ISA_MIPS32R6) {
14111 /* MUH */
14112 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
14113 } else {
14114 /* MOVZ */
14115 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
14117 break;
14118 case MULU:
14119 check_insn(ctx, ISA_MIPS32R6);
14120 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
14121 break;
14122 case MUHU:
14123 check_insn(ctx, ISA_MIPS32R6);
14124 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
14125 break;
14126 case LWXS: /* DIV */
14127 if (ctx->insn_flags & ISA_MIPS32R6) {
14128 /* DIV */
14129 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
14130 } else {
14131 /* LWXS */
14132 gen_ldxs(ctx, rs, rt, rd);
14134 break;
14135 case MOD:
14136 check_insn(ctx, ISA_MIPS32R6);
14137 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
14138 break;
14139 case R6_DIVU:
14140 check_insn(ctx, ISA_MIPS32R6);
14141 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
14142 break;
14143 case MODU:
14144 check_insn(ctx, ISA_MIPS32R6);
14145 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
14146 break;
14147 default:
14148 goto pool32a_invalid;
14150 break;
14151 case INS:
14152 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
14153 return;
14154 case LSA:
14155 check_insn(ctx, ISA_MIPS32R6);
14156 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
14157 extract32(ctx->opcode, 9, 2));
14158 break;
14159 case ALIGN:
14160 check_insn(ctx, ISA_MIPS32R6);
14161 gen_align(ctx, OPC_ALIGN, rd, rs, rt,
14162 extract32(ctx->opcode, 9, 2));
14163 break;
14164 case EXT:
14165 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
14166 return;
14167 case POOL32AXF:
14168 gen_pool32axf(env, ctx, rt, rs);
14169 break;
14170 case 0x07:
14171 generate_exception(ctx, EXCP_BREAK);
14172 break;
14173 default:
14174 pool32a_invalid:
14175 MIPS_INVAL("pool32a");
14176 generate_exception(ctx, EXCP_RI);
14177 break;
14179 break;
14180 case POOL32B:
14181 minor = (ctx->opcode >> 12) & 0xf;
14182 switch (minor) {
14183 case CACHE:
14184 check_cp0_enabled(ctx);
14185 /* Treat as no-op. */
14186 break;
14187 case LWC2:
14188 case SWC2:
14189 /* COP2: Not implemented. */
14190 generate_exception_err(ctx, EXCP_CpU, 2);
14191 break;
14192 #ifdef TARGET_MIPS64
14193 case LDP:
14194 case SDP:
14195 check_insn(ctx, ISA_MIPS3);
14196 check_mips_64(ctx);
14197 /* Fallthrough */
14198 #endif
14199 case LWP:
14200 case SWP:
14201 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14202 break;
14203 #ifdef TARGET_MIPS64
14204 case LDM:
14205 case SDM:
14206 check_insn(ctx, ISA_MIPS3);
14207 check_mips_64(ctx);
14208 /* Fallthrough */
14209 #endif
14210 case LWM32:
14211 case SWM32:
14212 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14213 break;
14214 default:
14215 MIPS_INVAL("pool32b");
14216 generate_exception(ctx, EXCP_RI);
14217 break;
14219 break;
14220 case POOL32F:
14221 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14222 minor = ctx->opcode & 0x3f;
14223 check_cp1_enabled(ctx);
14224 switch (minor) {
14225 case ALNV_PS:
14226 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14227 mips32_op = OPC_ALNV_PS;
14228 goto do_madd;
14229 case MADD_S:
14230 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14231 mips32_op = OPC_MADD_S;
14232 goto do_madd;
14233 case MADD_D:
14234 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14235 mips32_op = OPC_MADD_D;
14236 goto do_madd;
14237 case MADD_PS:
14238 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14239 mips32_op = OPC_MADD_PS;
14240 goto do_madd;
14241 case MSUB_S:
14242 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14243 mips32_op = OPC_MSUB_S;
14244 goto do_madd;
14245 case MSUB_D:
14246 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14247 mips32_op = OPC_MSUB_D;
14248 goto do_madd;
14249 case MSUB_PS:
14250 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14251 mips32_op = OPC_MSUB_PS;
14252 goto do_madd;
14253 case NMADD_S:
14254 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14255 mips32_op = OPC_NMADD_S;
14256 goto do_madd;
14257 case NMADD_D:
14258 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14259 mips32_op = OPC_NMADD_D;
14260 goto do_madd;
14261 case NMADD_PS:
14262 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14263 mips32_op = OPC_NMADD_PS;
14264 goto do_madd;
14265 case NMSUB_S:
14266 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14267 mips32_op = OPC_NMSUB_S;
14268 goto do_madd;
14269 case NMSUB_D:
14270 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14271 mips32_op = OPC_NMSUB_D;
14272 goto do_madd;
14273 case NMSUB_PS:
14274 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14275 mips32_op = OPC_NMSUB_PS;
14276 do_madd:
14277 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
14278 break;
14279 case CABS_COND_FMT:
14280 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14281 cond = (ctx->opcode >> 6) & 0xf;
14282 cc = (ctx->opcode >> 13) & 0x7;
14283 fmt = (ctx->opcode >> 10) & 0x3;
14284 switch (fmt) {
14285 case 0x0:
14286 gen_cmpabs_s(ctx, cond, rt, rs, cc);
14287 break;
14288 case 0x1:
14289 gen_cmpabs_d(ctx, cond, rt, rs, cc);
14290 break;
14291 case 0x2:
14292 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
14293 break;
14294 default:
14295 goto pool32f_invalid;
14297 break;
14298 case C_COND_FMT:
14299 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14300 cond = (ctx->opcode >> 6) & 0xf;
14301 cc = (ctx->opcode >> 13) & 0x7;
14302 fmt = (ctx->opcode >> 10) & 0x3;
14303 switch (fmt) {
14304 case 0x0:
14305 gen_cmp_s(ctx, cond, rt, rs, cc);
14306 break;
14307 case 0x1:
14308 gen_cmp_d(ctx, cond, rt, rs, cc);
14309 break;
14310 case 0x2:
14311 gen_cmp_ps(ctx, cond, rt, rs, cc);
14312 break;
14313 default:
14314 goto pool32f_invalid;
14316 break;
14317 case CMP_CONDN_S:
14318 check_insn(ctx, ISA_MIPS32R6);
14319 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14320 break;
14321 case CMP_CONDN_D:
14322 check_insn(ctx, ISA_MIPS32R6);
14323 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14324 break;
14325 case POOL32FXF:
14326 gen_pool32fxf(ctx, rt, rs);
14327 break;
14328 case 0x00:
14329 /* PLL foo */
14330 switch ((ctx->opcode >> 6) & 0x7) {
14331 case PLL_PS:
14332 mips32_op = OPC_PLL_PS;
14333 goto do_ps;
14334 case PLU_PS:
14335 mips32_op = OPC_PLU_PS;
14336 goto do_ps;
14337 case PUL_PS:
14338 mips32_op = OPC_PUL_PS;
14339 goto do_ps;
14340 case PUU_PS:
14341 mips32_op = OPC_PUU_PS;
14342 goto do_ps;
14343 case CVT_PS_S:
14344 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14345 mips32_op = OPC_CVT_PS_S;
14346 do_ps:
14347 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14348 break;
14349 default:
14350 goto pool32f_invalid;
14352 break;
14353 case MIN_FMT:
14354 check_insn(ctx, ISA_MIPS32R6);
14355 switch ((ctx->opcode >> 9) & 0x3) {
14356 case FMT_SDPS_S:
14357 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
14358 break;
14359 case FMT_SDPS_D:
14360 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
14361 break;
14362 default:
14363 goto pool32f_invalid;
14365 break;
14366 case 0x08:
14367 /* [LS][WDU]XC1 */
14368 switch ((ctx->opcode >> 6) & 0x7) {
14369 case LWXC1:
14370 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14371 mips32_op = OPC_LWXC1;
14372 goto do_ldst_cp1;
14373 case SWXC1:
14374 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14375 mips32_op = OPC_SWXC1;
14376 goto do_ldst_cp1;
14377 case LDXC1:
14378 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14379 mips32_op = OPC_LDXC1;
14380 goto do_ldst_cp1;
14381 case SDXC1:
14382 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14383 mips32_op = OPC_SDXC1;
14384 goto do_ldst_cp1;
14385 case LUXC1:
14386 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14387 mips32_op = OPC_LUXC1;
14388 goto do_ldst_cp1;
14389 case SUXC1:
14390 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14391 mips32_op = OPC_SUXC1;
14392 do_ldst_cp1:
14393 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
14394 break;
14395 default:
14396 goto pool32f_invalid;
14398 break;
14399 case MAX_FMT:
14400 check_insn(ctx, ISA_MIPS32R6);
14401 switch ((ctx->opcode >> 9) & 0x3) {
14402 case FMT_SDPS_S:
14403 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
14404 break;
14405 case FMT_SDPS_D:
14406 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
14407 break;
14408 default:
14409 goto pool32f_invalid;
14411 break;
14412 case 0x18:
14413 /* 3D insns */
14414 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14415 fmt = (ctx->opcode >> 9) & 0x3;
14416 switch ((ctx->opcode >> 6) & 0x7) {
14417 case RSQRT2_FMT:
14418 switch (fmt) {
14419 case FMT_SDPS_S:
14420 mips32_op = OPC_RSQRT2_S;
14421 goto do_3d;
14422 case FMT_SDPS_D:
14423 mips32_op = OPC_RSQRT2_D;
14424 goto do_3d;
14425 case FMT_SDPS_PS:
14426 mips32_op = OPC_RSQRT2_PS;
14427 goto do_3d;
14428 default:
14429 goto pool32f_invalid;
14431 break;
14432 case RECIP2_FMT:
14433 switch (fmt) {
14434 case FMT_SDPS_S:
14435 mips32_op = OPC_RECIP2_S;
14436 goto do_3d;
14437 case FMT_SDPS_D:
14438 mips32_op = OPC_RECIP2_D;
14439 goto do_3d;
14440 case FMT_SDPS_PS:
14441 mips32_op = OPC_RECIP2_PS;
14442 goto do_3d;
14443 default:
14444 goto pool32f_invalid;
14446 break;
14447 case ADDR_PS:
14448 mips32_op = OPC_ADDR_PS;
14449 goto do_3d;
14450 case MULR_PS:
14451 mips32_op = OPC_MULR_PS;
14452 do_3d:
14453 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14454 break;
14455 default:
14456 goto pool32f_invalid;
14458 break;
14459 case 0x20:
14460 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
14461 cc = (ctx->opcode >> 13) & 0x7;
14462 fmt = (ctx->opcode >> 9) & 0x3;
14463 switch ((ctx->opcode >> 6) & 0x7) {
14464 case MOVF_FMT: /* RINT_FMT */
14465 if (ctx->insn_flags & ISA_MIPS32R6) {
14466 /* RINT_FMT */
14467 switch (fmt) {
14468 case FMT_SDPS_S:
14469 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14470 break;
14471 case FMT_SDPS_D:
14472 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14473 break;
14474 default:
14475 goto pool32f_invalid;
14477 } else {
14478 /* MOVF_FMT */
14479 switch (fmt) {
14480 case FMT_SDPS_S:
14481 gen_movcf_s(ctx, rs, rt, cc, 0);
14482 break;
14483 case FMT_SDPS_D:
14484 gen_movcf_d(ctx, rs, rt, cc, 0);
14485 break;
14486 case FMT_SDPS_PS:
14487 check_ps(ctx);
14488 gen_movcf_ps(ctx, rs, rt, cc, 0);
14489 break;
14490 default:
14491 goto pool32f_invalid;
14494 break;
14495 case MOVT_FMT: /* CLASS_FMT */
14496 if (ctx->insn_flags & ISA_MIPS32R6) {
14497 /* CLASS_FMT */
14498 switch (fmt) {
14499 case FMT_SDPS_S:
14500 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14501 break;
14502 case FMT_SDPS_D:
14503 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14504 break;
14505 default:
14506 goto pool32f_invalid;
14508 } else {
14509 /* MOVT_FMT */
14510 switch (fmt) {
14511 case FMT_SDPS_S:
14512 gen_movcf_s(ctx, rs, rt, cc, 1);
14513 break;
14514 case FMT_SDPS_D:
14515 gen_movcf_d(ctx, rs, rt, cc, 1);
14516 break;
14517 case FMT_SDPS_PS:
14518 check_ps(ctx);
14519 gen_movcf_ps(ctx, rs, rt, cc, 1);
14520 break;
14521 default:
14522 goto pool32f_invalid;
14525 break;
14526 case PREFX:
14527 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14528 break;
14529 default:
14530 goto pool32f_invalid;
14532 break;
14533 #define FINSN_3ARG_SDPS(prfx) \
14534 switch ((ctx->opcode >> 8) & 0x3) { \
14535 case FMT_SDPS_S: \
14536 mips32_op = OPC_##prfx##_S; \
14537 goto do_fpop; \
14538 case FMT_SDPS_D: \
14539 mips32_op = OPC_##prfx##_D; \
14540 goto do_fpop; \
14541 case FMT_SDPS_PS: \
14542 check_ps(ctx); \
14543 mips32_op = OPC_##prfx##_PS; \
14544 goto do_fpop; \
14545 default: \
14546 goto pool32f_invalid; \
14548 case MINA_FMT:
14549 check_insn(ctx, ISA_MIPS32R6);
14550 switch ((ctx->opcode >> 9) & 0x3) {
14551 case FMT_SDPS_S:
14552 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14553 break;
14554 case FMT_SDPS_D:
14555 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14556 break;
14557 default:
14558 goto pool32f_invalid;
14560 break;
14561 case MAXA_FMT:
14562 check_insn(ctx, ISA_MIPS32R6);
14563 switch ((ctx->opcode >> 9) & 0x3) {
14564 case FMT_SDPS_S:
14565 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14566 break;
14567 case FMT_SDPS_D:
14568 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14569 break;
14570 default:
14571 goto pool32f_invalid;
14573 break;
14574 case 0x30:
14575 /* regular FP ops */
14576 switch ((ctx->opcode >> 6) & 0x3) {
14577 case ADD_FMT:
14578 FINSN_3ARG_SDPS(ADD);
14579 break;
14580 case SUB_FMT:
14581 FINSN_3ARG_SDPS(SUB);
14582 break;
14583 case MUL_FMT:
14584 FINSN_3ARG_SDPS(MUL);
14585 break;
14586 case DIV_FMT:
14587 fmt = (ctx->opcode >> 8) & 0x3;
14588 if (fmt == 1) {
14589 mips32_op = OPC_DIV_D;
14590 } else if (fmt == 0) {
14591 mips32_op = OPC_DIV_S;
14592 } else {
14593 goto pool32f_invalid;
14595 goto do_fpop;
14596 default:
14597 goto pool32f_invalid;
14599 break;
14600 case 0x38:
14601 /* cmovs */
14602 switch ((ctx->opcode >> 6) & 0x7) {
14603 case MOVN_FMT: /* SELNEZ_FMT */
14604 if (ctx->insn_flags & ISA_MIPS32R6) {
14605 /* SELNEZ_FMT */
14606 switch ((ctx->opcode >> 9) & 0x3) {
14607 case FMT_SDPS_S:
14608 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14609 break;
14610 case FMT_SDPS_D:
14611 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
14612 break;
14613 default:
14614 goto pool32f_invalid;
14616 } else {
14617 /* MOVN_FMT */
14618 FINSN_3ARG_SDPS(MOVN);
14620 break;
14621 case MOVN_FMT_04:
14622 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14623 FINSN_3ARG_SDPS(MOVN);
14624 break;
14625 case MOVZ_FMT: /* SELEQZ_FMT */
14626 if (ctx->insn_flags & ISA_MIPS32R6) {
14627 /* SELEQZ_FMT */
14628 switch ((ctx->opcode >> 9) & 0x3) {
14629 case FMT_SDPS_S:
14630 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
14631 break;
14632 case FMT_SDPS_D:
14633 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
14634 break;
14635 default:
14636 goto pool32f_invalid;
14638 } else {
14639 /* MOVZ_FMT */
14640 FINSN_3ARG_SDPS(MOVZ);
14642 break;
14643 case MOVZ_FMT_05:
14644 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14645 FINSN_3ARG_SDPS(MOVZ);
14646 break;
14647 case SEL_FMT:
14648 check_insn(ctx, ISA_MIPS32R6);
14649 switch ((ctx->opcode >> 9) & 0x3) {
14650 case FMT_SDPS_S:
14651 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
14652 break;
14653 case FMT_SDPS_D:
14654 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
14655 break;
14656 default:
14657 goto pool32f_invalid;
14659 break;
14660 case MADDF_FMT:
14661 check_insn(ctx, ISA_MIPS32R6);
14662 switch ((ctx->opcode >> 9) & 0x3) {
14663 case FMT_SDPS_S:
14664 mips32_op = OPC_MADDF_S;
14665 goto do_fpop;
14666 case FMT_SDPS_D:
14667 mips32_op = OPC_MADDF_D;
14668 goto do_fpop;
14669 default:
14670 goto pool32f_invalid;
14672 break;
14673 case MSUBF_FMT:
14674 check_insn(ctx, ISA_MIPS32R6);
14675 switch ((ctx->opcode >> 9) & 0x3) {
14676 case FMT_SDPS_S:
14677 mips32_op = OPC_MSUBF_S;
14678 goto do_fpop;
14679 case FMT_SDPS_D:
14680 mips32_op = OPC_MSUBF_D;
14681 goto do_fpop;
14682 default:
14683 goto pool32f_invalid;
14685 break;
14686 default:
14687 goto pool32f_invalid;
14689 break;
14690 do_fpop:
14691 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14692 break;
14693 default:
14694 pool32f_invalid:
14695 MIPS_INVAL("pool32f");
14696 generate_exception(ctx, EXCP_RI);
14697 break;
14699 } else {
14700 generate_exception_err(ctx, EXCP_CpU, 1);
14702 break;
14703 case POOL32I:
14704 minor = (ctx->opcode >> 21) & 0x1f;
14705 switch (minor) {
14706 case BLTZ:
14707 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14708 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
14709 break;
14710 case BLTZAL:
14711 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14712 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
14713 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14714 break;
14715 case BLTZALS:
14716 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14717 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
14718 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14719 break;
14720 case BGEZ:
14721 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14722 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
14723 break;
14724 case BGEZAL:
14725 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14726 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
14727 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14728 break;
14729 case BGEZALS:
14730 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14731 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
14732 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14733 break;
14734 case BLEZ:
14735 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14736 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
14737 break;
14738 case BGTZ:
14739 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14740 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
14741 break;
14743 /* Traps */
14744 case TLTI: /* BC1EQZC */
14745 if (ctx->insn_flags & ISA_MIPS32R6) {
14746 /* BC1EQZC */
14747 check_cp1_enabled(ctx);
14748 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
14749 } else {
14750 /* TLTI */
14751 mips32_op = OPC_TLTI;
14752 goto do_trapi;
14754 break;
14755 case TGEI: /* BC1NEZC */
14756 if (ctx->insn_flags & ISA_MIPS32R6) {
14757 /* BC1NEZC */
14758 check_cp1_enabled(ctx);
14759 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
14760 } else {
14761 /* TGEI */
14762 mips32_op = OPC_TGEI;
14763 goto do_trapi;
14765 break;
14766 case TLTIU:
14767 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14768 mips32_op = OPC_TLTIU;
14769 goto do_trapi;
14770 case TGEIU:
14771 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14772 mips32_op = OPC_TGEIU;
14773 goto do_trapi;
14774 case TNEI: /* SYNCI */
14775 if (ctx->insn_flags & ISA_MIPS32R6) {
14776 /* SYNCI */
14777 /* Break the TB to be able to sync copied instructions
14778 immediately */
14779 ctx->bstate = BS_STOP;
14780 } else {
14781 /* TNEI */
14782 mips32_op = OPC_TNEI;
14783 goto do_trapi;
14785 break;
14786 case TEQI:
14787 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14788 mips32_op = OPC_TEQI;
14789 do_trapi:
14790 gen_trap(ctx, mips32_op, rs, -1, imm);
14791 break;
14793 case BNEZC:
14794 case BEQZC:
14795 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14796 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
14797 4, rs, 0, imm << 1, 0);
14798 /* Compact branches don't have a delay slot, so just let
14799 the normal delay slot handling take us to the branch
14800 target. */
14801 break;
14802 case LUI:
14803 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14804 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
14805 break;
14806 case SYNCI:
14807 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14808 /* Break the TB to be able to sync copied instructions
14809 immediately */
14810 ctx->bstate = BS_STOP;
14811 break;
14812 case BC2F:
14813 case BC2T:
14814 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14815 /* COP2: Not implemented. */
14816 generate_exception_err(ctx, EXCP_CpU, 2);
14817 break;
14818 case BC1F:
14819 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14820 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
14821 goto do_cp1branch;
14822 case BC1T:
14823 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14824 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
14825 goto do_cp1branch;
14826 case BC1ANY4F:
14827 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14828 mips32_op = OPC_BC1FANY4;
14829 goto do_cp1mips3d;
14830 case BC1ANY4T:
14831 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14832 mips32_op = OPC_BC1TANY4;
14833 do_cp1mips3d:
14834 check_cop1x(ctx);
14835 check_insn(ctx, ASE_MIPS3D);
14836 /* Fall through */
14837 do_cp1branch:
14838 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14839 check_cp1_enabled(ctx);
14840 gen_compute_branch1(ctx, mips32_op,
14841 (ctx->opcode >> 18) & 0x7, imm << 1);
14842 } else {
14843 generate_exception_err(ctx, EXCP_CpU, 1);
14845 break;
14846 case BPOSGE64:
14847 case BPOSGE32:
14848 /* MIPS DSP: not implemented */
14849 /* Fall through */
14850 default:
14851 MIPS_INVAL("pool32i");
14852 generate_exception(ctx, EXCP_RI);
14853 break;
14855 break;
14856 case POOL32C:
14857 minor = (ctx->opcode >> 12) & 0xf;
14858 offset = sextract32(ctx->opcode, 0,
14859 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
14860 switch (minor) {
14861 case LWL:
14862 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14863 mips32_op = OPC_LWL;
14864 goto do_ld_lr;
14865 case SWL:
14866 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14867 mips32_op = OPC_SWL;
14868 goto do_st_lr;
14869 case LWR:
14870 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14871 mips32_op = OPC_LWR;
14872 goto do_ld_lr;
14873 case SWR:
14874 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14875 mips32_op = OPC_SWR;
14876 goto do_st_lr;
14877 #if defined(TARGET_MIPS64)
14878 case LDL:
14879 check_insn(ctx, ISA_MIPS3);
14880 check_mips_64(ctx);
14881 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14882 mips32_op = OPC_LDL;
14883 goto do_ld_lr;
14884 case SDL:
14885 check_insn(ctx, ISA_MIPS3);
14886 check_mips_64(ctx);
14887 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14888 mips32_op = OPC_SDL;
14889 goto do_st_lr;
14890 case LDR:
14891 check_insn(ctx, ISA_MIPS3);
14892 check_mips_64(ctx);
14893 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14894 mips32_op = OPC_LDR;
14895 goto do_ld_lr;
14896 case SDR:
14897 check_insn(ctx, ISA_MIPS3);
14898 check_mips_64(ctx);
14899 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14900 mips32_op = OPC_SDR;
14901 goto do_st_lr;
14902 case LWU:
14903 check_insn(ctx, ISA_MIPS3);
14904 check_mips_64(ctx);
14905 mips32_op = OPC_LWU;
14906 goto do_ld_lr;
14907 case LLD:
14908 check_insn(ctx, ISA_MIPS3);
14909 check_mips_64(ctx);
14910 mips32_op = OPC_LLD;
14911 goto do_ld_lr;
14912 #endif
14913 case LL:
14914 mips32_op = OPC_LL;
14915 goto do_ld_lr;
14916 do_ld_lr:
14917 gen_ld(ctx, mips32_op, rt, rs, offset);
14918 break;
14919 do_st_lr:
14920 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
14921 break;
14922 case SC:
14923 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
14924 break;
14925 #if defined(TARGET_MIPS64)
14926 case SCD:
14927 check_insn(ctx, ISA_MIPS3);
14928 check_mips_64(ctx);
14929 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
14930 break;
14931 #endif
14932 case PREF:
14933 /* Treat as no-op */
14934 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
14935 /* hint codes 24-31 are reserved and signal RI */
14936 generate_exception(ctx, EXCP_RI);
14938 break;
14939 default:
14940 MIPS_INVAL("pool32c");
14941 generate_exception(ctx, EXCP_RI);
14942 break;
14944 break;
14945 case ADDI32: /* AUI, LUI */
14946 if (ctx->insn_flags & ISA_MIPS32R6) {
14947 /* AUI, LUI */
14948 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
14949 } else {
14950 /* ADDI32 */
14951 mips32_op = OPC_ADDI;
14952 goto do_addi;
14954 break;
14955 case ADDIU32:
14956 mips32_op = OPC_ADDIU;
14957 do_addi:
14958 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
14959 break;
14961 /* Logical operations */
14962 case ORI32:
14963 mips32_op = OPC_ORI;
14964 goto do_logici;
14965 case XORI32:
14966 mips32_op = OPC_XORI;
14967 goto do_logici;
14968 case ANDI32:
14969 mips32_op = OPC_ANDI;
14970 do_logici:
14971 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
14972 break;
14974 /* Set less than immediate */
14975 case SLTI32:
14976 mips32_op = OPC_SLTI;
14977 goto do_slti;
14978 case SLTIU32:
14979 mips32_op = OPC_SLTIU;
14980 do_slti:
14981 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
14982 break;
14983 case JALX32:
14984 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14985 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14986 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
14987 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14988 break;
14989 case JALS32: /* BOVC, BEQC, BEQZALC */
14990 if (ctx->insn_flags & ISA_MIPS32R6) {
14991 if (rs >= rt) {
14992 /* BOVC */
14993 mips32_op = OPC_BOVC;
14994 } else if (rs < rt && rs == 0) {
14995 /* BEQZALC */
14996 mips32_op = OPC_BEQZALC;
14997 } else {
14998 /* BEQC */
14999 mips32_op = OPC_BEQC;
15001 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15002 } else {
15003 /* JALS32 */
15004 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
15005 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
15006 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15008 break;
15009 case BEQ32: /* BC */
15010 if (ctx->insn_flags & ISA_MIPS32R6) {
15011 /* BC */
15012 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
15013 sextract32(ctx->opcode << 1, 0, 27));
15014 } else {
15015 /* BEQ32 */
15016 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
15018 break;
15019 case BNE32: /* BALC */
15020 if (ctx->insn_flags & ISA_MIPS32R6) {
15021 /* BALC */
15022 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
15023 sextract32(ctx->opcode << 1, 0, 27));
15024 } else {
15025 /* BNE32 */
15026 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
15028 break;
15029 case J32: /* BGTZC, BLTZC, BLTC */
15030 if (ctx->insn_flags & ISA_MIPS32R6) {
15031 if (rs == 0 && rt != 0) {
15032 /* BGTZC */
15033 mips32_op = OPC_BGTZC;
15034 } else if (rs != 0 && rt != 0 && rs == rt) {
15035 /* BLTZC */
15036 mips32_op = OPC_BLTZC;
15037 } else {
15038 /* BLTC */
15039 mips32_op = OPC_BLTC;
15041 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15042 } else {
15043 /* J32 */
15044 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
15045 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15047 break;
15048 case JAL32: /* BLEZC, BGEZC, BGEC */
15049 if (ctx->insn_flags & ISA_MIPS32R6) {
15050 if (rs == 0 && rt != 0) {
15051 /* BLEZC */
15052 mips32_op = OPC_BLEZC;
15053 } else if (rs != 0 && rt != 0 && rs == rt) {
15054 /* BGEZC */
15055 mips32_op = OPC_BGEZC;
15056 } else {
15057 /* BGEC */
15058 mips32_op = OPC_BGEC;
15060 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15061 } else {
15062 /* JAL32 */
15063 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
15064 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15065 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15067 break;
15068 /* Floating point (COP1) */
15069 case LWC132:
15070 mips32_op = OPC_LWC1;
15071 goto do_cop1;
15072 case LDC132:
15073 mips32_op = OPC_LDC1;
15074 goto do_cop1;
15075 case SWC132:
15076 mips32_op = OPC_SWC1;
15077 goto do_cop1;
15078 case SDC132:
15079 mips32_op = OPC_SDC1;
15080 do_cop1:
15081 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
15082 break;
15083 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15084 if (ctx->insn_flags & ISA_MIPS32R6) {
15085 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15086 switch ((ctx->opcode >> 16) & 0x1f) {
15087 case ADDIUPC_00 ... ADDIUPC_07:
15088 gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
15089 break;
15090 case AUIPC:
15091 gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
15092 break;
15093 case ALUIPC:
15094 gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
15095 break;
15096 case LWPC_08 ... LWPC_0F:
15097 gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
15098 break;
15099 default:
15100 generate_exception(ctx, EXCP_RI);
15101 break;
15103 } else {
15104 /* ADDIUPC */
15105 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
15106 int offset = SIMM(ctx->opcode, 0, 23) << 2;
15108 gen_addiupc(ctx, reg, offset, 0, 0);
15110 break;
15111 case BNVC: /* BNEC, BNEZALC */
15112 check_insn(ctx, ISA_MIPS32R6);
15113 if (rs >= rt) {
15114 /* BNVC */
15115 mips32_op = OPC_BNVC;
15116 } else if (rs < rt && rs == 0) {
15117 /* BNEZALC */
15118 mips32_op = OPC_BNEZALC;
15119 } else {
15120 /* BNEC */
15121 mips32_op = OPC_BNEC;
15123 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15124 break;
15125 case R6_BNEZC: /* JIALC */
15126 check_insn(ctx, ISA_MIPS32R6);
15127 if (rt != 0) {
15128 /* BNEZC */
15129 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
15130 sextract32(ctx->opcode << 1, 0, 22));
15131 } else {
15132 /* JIALC */
15133 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
15135 break;
15136 case R6_BEQZC: /* JIC */
15137 check_insn(ctx, ISA_MIPS32R6);
15138 if (rt != 0) {
15139 /* BEQZC */
15140 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
15141 sextract32(ctx->opcode << 1, 0, 22));
15142 } else {
15143 /* JIC */
15144 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
15146 break;
15147 case BLEZALC: /* BGEZALC, BGEUC */
15148 check_insn(ctx, ISA_MIPS32R6);
15149 if (rs == 0 && rt != 0) {
15150 /* BLEZALC */
15151 mips32_op = OPC_BLEZALC;
15152 } else if (rs != 0 && rt != 0 && rs == rt) {
15153 /* BGEZALC */
15154 mips32_op = OPC_BGEZALC;
15155 } else {
15156 /* BGEUC */
15157 mips32_op = OPC_BGEUC;
15159 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15160 break;
15161 case BGTZALC: /* BLTZALC, BLTUC */
15162 check_insn(ctx, ISA_MIPS32R6);
15163 if (rs == 0 && rt != 0) {
15164 /* BGTZALC */
15165 mips32_op = OPC_BGTZALC;
15166 } else if (rs != 0 && rt != 0 && rs == rt) {
15167 /* BLTZALC */
15168 mips32_op = OPC_BLTZALC;
15169 } else {
15170 /* BLTUC */
15171 mips32_op = OPC_BLTUC;
15173 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15174 break;
15175 /* Loads and stores */
15176 case LB32:
15177 mips32_op = OPC_LB;
15178 goto do_ld;
15179 case LBU32:
15180 mips32_op = OPC_LBU;
15181 goto do_ld;
15182 case LH32:
15183 mips32_op = OPC_LH;
15184 goto do_ld;
15185 case LHU32:
15186 mips32_op = OPC_LHU;
15187 goto do_ld;
15188 case LW32:
15189 mips32_op = OPC_LW;
15190 goto do_ld;
15191 #ifdef TARGET_MIPS64
15192 case LD32:
15193 check_insn(ctx, ISA_MIPS3);
15194 check_mips_64(ctx);
15195 mips32_op = OPC_LD;
15196 goto do_ld;
15197 case SD32:
15198 check_insn(ctx, ISA_MIPS3);
15199 check_mips_64(ctx);
15200 mips32_op = OPC_SD;
15201 goto do_st;
15202 #endif
15203 case SB32:
15204 mips32_op = OPC_SB;
15205 goto do_st;
15206 case SH32:
15207 mips32_op = OPC_SH;
15208 goto do_st;
15209 case SW32:
15210 mips32_op = OPC_SW;
15211 goto do_st;
15212 do_ld:
15213 gen_ld(ctx, mips32_op, rt, rs, imm);
15214 break;
15215 do_st:
15216 gen_st(ctx, mips32_op, rt, rs, imm);
15217 break;
15218 default:
15219 generate_exception(ctx, EXCP_RI);
15220 break;
15224 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
15226 uint32_t op;
15228 /* make sure instructions are on a halfword boundary */
15229 if (ctx->pc & 0x1) {
15230 env->CP0_BadVAddr = ctx->pc;
15231 generate_exception(ctx, EXCP_AdEL);
15232 ctx->bstate = BS_STOP;
15233 return 2;
15236 op = (ctx->opcode >> 10) & 0x3f;
15237 /* Enforce properly-sized instructions in a delay slot */
15238 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
15239 switch (op & 0x7) { /* MSB-3..MSB-5 */
15240 case 0:
15241 /* POOL32A, POOL32B, POOL32I, POOL32C */
15242 case 4:
15243 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
15244 case 5:
15245 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
15246 case 6:
15247 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
15248 case 7:
15249 /* LB32, LH32, LWC132, LDC132, LW32 */
15250 if (ctx->hflags & MIPS_HFLAG_BDS16) {
15251 generate_exception(ctx, EXCP_RI);
15252 /* Just stop translation; the user is confused. */
15253 ctx->bstate = BS_STOP;
15254 return 2;
15256 break;
15257 case 1:
15258 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
15259 case 2:
15260 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
15261 case 3:
15262 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
15263 if (ctx->hflags & MIPS_HFLAG_BDS32) {
15264 generate_exception(ctx, EXCP_RI);
15265 /* Just stop translation; the user is confused. */
15266 ctx->bstate = BS_STOP;
15267 return 2;
15269 break;
15273 switch (op) {
15274 case POOL16A:
15276 int rd = mmreg(uMIPS_RD(ctx->opcode));
15277 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
15278 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
15279 uint32_t opc = 0;
15281 switch (ctx->opcode & 0x1) {
15282 case ADDU16:
15283 opc = OPC_ADDU;
15284 break;
15285 case SUBU16:
15286 opc = OPC_SUBU;
15287 break;
15289 if (ctx->insn_flags & ISA_MIPS32R6) {
15290 /* In the Release 6 the register number location in
15291 * the instruction encoding has changed.
15293 gen_arith(ctx, opc, rs1, rd, rs2);
15294 } else {
15295 gen_arith(ctx, opc, rd, rs1, rs2);
15298 break;
15299 case POOL16B:
15301 int rd = mmreg(uMIPS_RD(ctx->opcode));
15302 int rs = mmreg(uMIPS_RS(ctx->opcode));
15303 int amount = (ctx->opcode >> 1) & 0x7;
15304 uint32_t opc = 0;
15305 amount = amount == 0 ? 8 : amount;
15307 switch (ctx->opcode & 0x1) {
15308 case SLL16:
15309 opc = OPC_SLL;
15310 break;
15311 case SRL16:
15312 opc = OPC_SRL;
15313 break;
15316 gen_shift_imm(ctx, opc, rd, rs, amount);
15318 break;
15319 case POOL16C:
15320 if (ctx->insn_flags & ISA_MIPS32R6) {
15321 gen_pool16c_r6_insn(ctx);
15322 } else {
15323 gen_pool16c_insn(ctx);
15325 break;
15326 case LWGP16:
15328 int rd = mmreg(uMIPS_RD(ctx->opcode));
15329 int rb = 28; /* GP */
15330 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
15332 gen_ld(ctx, OPC_LW, rd, rb, offset);
15334 break;
15335 case POOL16F:
15336 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15337 if (ctx->opcode & 1) {
15338 generate_exception(ctx, EXCP_RI);
15339 } else {
15340 /* MOVEP */
15341 int enc_dest = uMIPS_RD(ctx->opcode);
15342 int enc_rt = uMIPS_RS2(ctx->opcode);
15343 int enc_rs = uMIPS_RS1(ctx->opcode);
15344 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15346 break;
15347 case LBU16:
15349 int rd = mmreg(uMIPS_RD(ctx->opcode));
15350 int rb = mmreg(uMIPS_RS(ctx->opcode));
15351 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15352 offset = (offset == 0xf ? -1 : offset);
15354 gen_ld(ctx, OPC_LBU, rd, rb, offset);
15356 break;
15357 case LHU16:
15359 int rd = mmreg(uMIPS_RD(ctx->opcode));
15360 int rb = mmreg(uMIPS_RS(ctx->opcode));
15361 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15363 gen_ld(ctx, OPC_LHU, rd, rb, offset);
15365 break;
15366 case LWSP16:
15368 int rd = (ctx->opcode >> 5) & 0x1f;
15369 int rb = 29; /* SP */
15370 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15372 gen_ld(ctx, OPC_LW, rd, rb, offset);
15374 break;
15375 case LW16:
15377 int rd = mmreg(uMIPS_RD(ctx->opcode));
15378 int rb = mmreg(uMIPS_RS(ctx->opcode));
15379 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15381 gen_ld(ctx, OPC_LW, rd, rb, offset);
15383 break;
15384 case SB16:
15386 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15387 int rb = mmreg(uMIPS_RS(ctx->opcode));
15388 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15390 gen_st(ctx, OPC_SB, rd, rb, offset);
15392 break;
15393 case SH16:
15395 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15396 int rb = mmreg(uMIPS_RS(ctx->opcode));
15397 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15399 gen_st(ctx, OPC_SH, rd, rb, offset);
15401 break;
15402 case SWSP16:
15404 int rd = (ctx->opcode >> 5) & 0x1f;
15405 int rb = 29; /* SP */
15406 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15408 gen_st(ctx, OPC_SW, rd, rb, offset);
15410 break;
15411 case SW16:
15413 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15414 int rb = mmreg(uMIPS_RS(ctx->opcode));
15415 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15417 gen_st(ctx, OPC_SW, rd, rb, offset);
15419 break;
15420 case MOVE16:
15422 int rd = uMIPS_RD5(ctx->opcode);
15423 int rs = uMIPS_RS5(ctx->opcode);
15425 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
15427 break;
15428 case ANDI16:
15429 gen_andi16(ctx);
15430 break;
15431 case POOL16D:
15432 switch (ctx->opcode & 0x1) {
15433 case ADDIUS5:
15434 gen_addius5(ctx);
15435 break;
15436 case ADDIUSP:
15437 gen_addiusp(ctx);
15438 break;
15440 break;
15441 case POOL16E:
15442 switch (ctx->opcode & 0x1) {
15443 case ADDIUR2:
15444 gen_addiur2(ctx);
15445 break;
15446 case ADDIUR1SP:
15447 gen_addiur1sp(ctx);
15448 break;
15450 break;
15451 case B16: /* BC16 */
15452 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
15453 sextract32(ctx->opcode, 0, 10) << 1,
15454 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15455 break;
15456 case BNEZ16: /* BNEZC16 */
15457 case BEQZ16: /* BEQZC16 */
15458 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
15459 mmreg(uMIPS_RD(ctx->opcode)),
15460 0, sextract32(ctx->opcode, 0, 7) << 1,
15461 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15463 break;
15464 case LI16:
15466 int reg = mmreg(uMIPS_RD(ctx->opcode));
15467 int imm = ZIMM(ctx->opcode, 0, 7);
15469 imm = (imm == 0x7f ? -1 : imm);
15470 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15472 break;
15473 case RES_29:
15474 case RES_31:
15475 case RES_39:
15476 generate_exception(ctx, EXCP_RI);
15477 break;
15478 default:
15479 decode_micromips32_opc(env, ctx);
15480 return 4;
15483 return 2;
15486 /* SmartMIPS extension to MIPS32 */
15488 #if defined(TARGET_MIPS64)
15490 /* MDMX extension to MIPS64 */
15492 #endif
15494 /* MIPSDSP functions. */
15495 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
15496 int rd, int base, int offset)
15498 const char *opn = "ldx";
15499 TCGv t0;
15501 check_dsp(ctx);
15502 t0 = tcg_temp_new();
15504 if (base == 0) {
15505 gen_load_gpr(t0, offset);
15506 } else if (offset == 0) {
15507 gen_load_gpr(t0, base);
15508 } else {
15509 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
15512 switch (opc) {
15513 case OPC_LBUX:
15514 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
15515 gen_store_gpr(t0, rd);
15516 opn = "lbux";
15517 break;
15518 case OPC_LHX:
15519 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
15520 gen_store_gpr(t0, rd);
15521 opn = "lhx";
15522 break;
15523 case OPC_LWX:
15524 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
15525 gen_store_gpr(t0, rd);
15526 opn = "lwx";
15527 break;
15528 #if defined(TARGET_MIPS64)
15529 case OPC_LDX:
15530 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
15531 gen_store_gpr(t0, rd);
15532 opn = "ldx";
15533 break;
15534 #endif
15536 (void)opn; /* avoid a compiler warning */
15537 MIPS_DEBUG("%s %s, %s(%s)", opn,
15538 regnames[rd], regnames[offset], regnames[base]);
15539 tcg_temp_free(t0);
15542 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
15543 int ret, int v1, int v2)
15545 const char *opn = "mipsdsp arith";
15546 TCGv v1_t;
15547 TCGv v2_t;
15549 if (ret == 0) {
15550 /* Treat as NOP. */
15551 MIPS_DEBUG("NOP");
15552 return;
15555 v1_t = tcg_temp_new();
15556 v2_t = tcg_temp_new();
15558 gen_load_gpr(v1_t, v1);
15559 gen_load_gpr(v2_t, v2);
15561 switch (op1) {
15562 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
15563 case OPC_MULT_G_2E:
15564 check_dspr2(ctx);
15565 switch (op2) {
15566 case OPC_ADDUH_QB:
15567 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
15568 break;
15569 case OPC_ADDUH_R_QB:
15570 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15571 break;
15572 case OPC_ADDQH_PH:
15573 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
15574 break;
15575 case OPC_ADDQH_R_PH:
15576 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15577 break;
15578 case OPC_ADDQH_W:
15579 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
15580 break;
15581 case OPC_ADDQH_R_W:
15582 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15583 break;
15584 case OPC_SUBUH_QB:
15585 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
15586 break;
15587 case OPC_SUBUH_R_QB:
15588 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15589 break;
15590 case OPC_SUBQH_PH:
15591 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
15592 break;
15593 case OPC_SUBQH_R_PH:
15594 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15595 break;
15596 case OPC_SUBQH_W:
15597 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
15598 break;
15599 case OPC_SUBQH_R_W:
15600 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15601 break;
15603 break;
15604 case OPC_ABSQ_S_PH_DSP:
15605 switch (op2) {
15606 case OPC_ABSQ_S_QB:
15607 check_dspr2(ctx);
15608 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
15609 break;
15610 case OPC_ABSQ_S_PH:
15611 check_dsp(ctx);
15612 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
15613 break;
15614 case OPC_ABSQ_S_W:
15615 check_dsp(ctx);
15616 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
15617 break;
15618 case OPC_PRECEQ_W_PHL:
15619 check_dsp(ctx);
15620 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
15621 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15622 break;
15623 case OPC_PRECEQ_W_PHR:
15624 check_dsp(ctx);
15625 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
15626 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
15627 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15628 break;
15629 case OPC_PRECEQU_PH_QBL:
15630 check_dsp(ctx);
15631 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
15632 break;
15633 case OPC_PRECEQU_PH_QBR:
15634 check_dsp(ctx);
15635 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
15636 break;
15637 case OPC_PRECEQU_PH_QBLA:
15638 check_dsp(ctx);
15639 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
15640 break;
15641 case OPC_PRECEQU_PH_QBRA:
15642 check_dsp(ctx);
15643 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
15644 break;
15645 case OPC_PRECEU_PH_QBL:
15646 check_dsp(ctx);
15647 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
15648 break;
15649 case OPC_PRECEU_PH_QBR:
15650 check_dsp(ctx);
15651 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
15652 break;
15653 case OPC_PRECEU_PH_QBLA:
15654 check_dsp(ctx);
15655 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
15656 break;
15657 case OPC_PRECEU_PH_QBRA:
15658 check_dsp(ctx);
15659 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
15660 break;
15662 break;
15663 case OPC_ADDU_QB_DSP:
15664 switch (op2) {
15665 case OPC_ADDQ_PH:
15666 check_dsp(ctx);
15667 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15668 break;
15669 case OPC_ADDQ_S_PH:
15670 check_dsp(ctx);
15671 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15672 break;
15673 case OPC_ADDQ_S_W:
15674 check_dsp(ctx);
15675 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15676 break;
15677 case OPC_ADDU_QB:
15678 check_dsp(ctx);
15679 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15680 break;
15681 case OPC_ADDU_S_QB:
15682 check_dsp(ctx);
15683 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15684 break;
15685 case OPC_ADDU_PH:
15686 check_dspr2(ctx);
15687 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15688 break;
15689 case OPC_ADDU_S_PH:
15690 check_dspr2(ctx);
15691 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15692 break;
15693 case OPC_SUBQ_PH:
15694 check_dsp(ctx);
15695 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15696 break;
15697 case OPC_SUBQ_S_PH:
15698 check_dsp(ctx);
15699 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15700 break;
15701 case OPC_SUBQ_S_W:
15702 check_dsp(ctx);
15703 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15704 break;
15705 case OPC_SUBU_QB:
15706 check_dsp(ctx);
15707 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15708 break;
15709 case OPC_SUBU_S_QB:
15710 check_dsp(ctx);
15711 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15712 break;
15713 case OPC_SUBU_PH:
15714 check_dspr2(ctx);
15715 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15716 break;
15717 case OPC_SUBU_S_PH:
15718 check_dspr2(ctx);
15719 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15720 break;
15721 case OPC_ADDSC:
15722 check_dsp(ctx);
15723 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15724 break;
15725 case OPC_ADDWC:
15726 check_dsp(ctx);
15727 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15728 break;
15729 case OPC_MODSUB:
15730 check_dsp(ctx);
15731 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
15732 break;
15733 case OPC_RADDU_W_QB:
15734 check_dsp(ctx);
15735 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
15736 break;
15738 break;
15739 case OPC_CMPU_EQ_QB_DSP:
15740 switch (op2) {
15741 case OPC_PRECR_QB_PH:
15742 check_dspr2(ctx);
15743 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15744 break;
15745 case OPC_PRECRQ_QB_PH:
15746 check_dsp(ctx);
15747 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15748 break;
15749 case OPC_PRECR_SRA_PH_W:
15750 check_dspr2(ctx);
15752 TCGv_i32 sa_t = tcg_const_i32(v2);
15753 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
15754 cpu_gpr[ret]);
15755 tcg_temp_free_i32(sa_t);
15756 break;
15758 case OPC_PRECR_SRA_R_PH_W:
15759 check_dspr2(ctx);
15761 TCGv_i32 sa_t = tcg_const_i32(v2);
15762 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
15763 cpu_gpr[ret]);
15764 tcg_temp_free_i32(sa_t);
15765 break;
15767 case OPC_PRECRQ_PH_W:
15768 check_dsp(ctx);
15769 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
15770 break;
15771 case OPC_PRECRQ_RS_PH_W:
15772 check_dsp(ctx);
15773 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15774 break;
15775 case OPC_PRECRQU_S_QB_PH:
15776 check_dsp(ctx);
15777 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15778 break;
15780 break;
15781 #ifdef TARGET_MIPS64
15782 case OPC_ABSQ_S_QH_DSP:
15783 switch (op2) {
15784 case OPC_PRECEQ_L_PWL:
15785 check_dsp(ctx);
15786 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
15787 break;
15788 case OPC_PRECEQ_L_PWR:
15789 check_dsp(ctx);
15790 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
15791 break;
15792 case OPC_PRECEQ_PW_QHL:
15793 check_dsp(ctx);
15794 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
15795 break;
15796 case OPC_PRECEQ_PW_QHR:
15797 check_dsp(ctx);
15798 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
15799 break;
15800 case OPC_PRECEQ_PW_QHLA:
15801 check_dsp(ctx);
15802 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
15803 break;
15804 case OPC_PRECEQ_PW_QHRA:
15805 check_dsp(ctx);
15806 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
15807 break;
15808 case OPC_PRECEQU_QH_OBL:
15809 check_dsp(ctx);
15810 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
15811 break;
15812 case OPC_PRECEQU_QH_OBR:
15813 check_dsp(ctx);
15814 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
15815 break;
15816 case OPC_PRECEQU_QH_OBLA:
15817 check_dsp(ctx);
15818 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
15819 break;
15820 case OPC_PRECEQU_QH_OBRA:
15821 check_dsp(ctx);
15822 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
15823 break;
15824 case OPC_PRECEU_QH_OBL:
15825 check_dsp(ctx);
15826 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
15827 break;
15828 case OPC_PRECEU_QH_OBR:
15829 check_dsp(ctx);
15830 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
15831 break;
15832 case OPC_PRECEU_QH_OBLA:
15833 check_dsp(ctx);
15834 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
15835 break;
15836 case OPC_PRECEU_QH_OBRA:
15837 check_dsp(ctx);
15838 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
15839 break;
15840 case OPC_ABSQ_S_OB:
15841 check_dspr2(ctx);
15842 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
15843 break;
15844 case OPC_ABSQ_S_PW:
15845 check_dsp(ctx);
15846 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
15847 break;
15848 case OPC_ABSQ_S_QH:
15849 check_dsp(ctx);
15850 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
15851 break;
15853 break;
15854 case OPC_ADDU_OB_DSP:
15855 switch (op2) {
15856 case OPC_RADDU_L_OB:
15857 check_dsp(ctx);
15858 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
15859 break;
15860 case OPC_SUBQ_PW:
15861 check_dsp(ctx);
15862 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15863 break;
15864 case OPC_SUBQ_S_PW:
15865 check_dsp(ctx);
15866 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15867 break;
15868 case OPC_SUBQ_QH:
15869 check_dsp(ctx);
15870 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15871 break;
15872 case OPC_SUBQ_S_QH:
15873 check_dsp(ctx);
15874 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15875 break;
15876 case OPC_SUBU_OB:
15877 check_dsp(ctx);
15878 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15879 break;
15880 case OPC_SUBU_S_OB:
15881 check_dsp(ctx);
15882 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15883 break;
15884 case OPC_SUBU_QH:
15885 check_dspr2(ctx);
15886 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15887 break;
15888 case OPC_SUBU_S_QH:
15889 check_dspr2(ctx);
15890 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15891 break;
15892 case OPC_SUBUH_OB:
15893 check_dspr2(ctx);
15894 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
15895 break;
15896 case OPC_SUBUH_R_OB:
15897 check_dspr2(ctx);
15898 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15899 break;
15900 case OPC_ADDQ_PW:
15901 check_dsp(ctx);
15902 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15903 break;
15904 case OPC_ADDQ_S_PW:
15905 check_dsp(ctx);
15906 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15907 break;
15908 case OPC_ADDQ_QH:
15909 check_dsp(ctx);
15910 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15911 break;
15912 case OPC_ADDQ_S_QH:
15913 check_dsp(ctx);
15914 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15915 break;
15916 case OPC_ADDU_OB:
15917 check_dsp(ctx);
15918 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15919 break;
15920 case OPC_ADDU_S_OB:
15921 check_dsp(ctx);
15922 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15923 break;
15924 case OPC_ADDU_QH:
15925 check_dspr2(ctx);
15926 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15927 break;
15928 case OPC_ADDU_S_QH:
15929 check_dspr2(ctx);
15930 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15931 break;
15932 case OPC_ADDUH_OB:
15933 check_dspr2(ctx);
15934 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
15935 break;
15936 case OPC_ADDUH_R_OB:
15937 check_dspr2(ctx);
15938 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15939 break;
15941 break;
15942 case OPC_CMPU_EQ_OB_DSP:
15943 switch (op2) {
15944 case OPC_PRECR_OB_QH:
15945 check_dspr2(ctx);
15946 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15947 break;
15948 case OPC_PRECR_SRA_QH_PW:
15949 check_dspr2(ctx);
15951 TCGv_i32 ret_t = tcg_const_i32(ret);
15952 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
15953 tcg_temp_free_i32(ret_t);
15954 break;
15956 case OPC_PRECR_SRA_R_QH_PW:
15957 check_dspr2(ctx);
15959 TCGv_i32 sa_v = tcg_const_i32(ret);
15960 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
15961 tcg_temp_free_i32(sa_v);
15962 break;
15964 case OPC_PRECRQ_OB_QH:
15965 check_dsp(ctx);
15966 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15967 break;
15968 case OPC_PRECRQ_PW_L:
15969 check_dsp(ctx);
15970 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
15971 break;
15972 case OPC_PRECRQ_QH_PW:
15973 check_dsp(ctx);
15974 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
15975 break;
15976 case OPC_PRECRQ_RS_QH_PW:
15977 check_dsp(ctx);
15978 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15979 break;
15980 case OPC_PRECRQU_S_OB_QH:
15981 check_dsp(ctx);
15982 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15983 break;
15985 break;
15986 #endif
15989 tcg_temp_free(v1_t);
15990 tcg_temp_free(v2_t);
15992 (void)opn; /* avoid a compiler warning */
15993 MIPS_DEBUG("%s", opn);
15996 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
15997 int ret, int v1, int v2)
15999 uint32_t op2;
16000 const char *opn = "mipsdsp shift";
16001 TCGv t0;
16002 TCGv v1_t;
16003 TCGv v2_t;
16005 if (ret == 0) {
16006 /* Treat as NOP. */
16007 MIPS_DEBUG("NOP");
16008 return;
16011 t0 = tcg_temp_new();
16012 v1_t = tcg_temp_new();
16013 v2_t = tcg_temp_new();
16015 tcg_gen_movi_tl(t0, v1);
16016 gen_load_gpr(v1_t, v1);
16017 gen_load_gpr(v2_t, v2);
16019 switch (opc) {
16020 case OPC_SHLL_QB_DSP:
16022 op2 = MASK_SHLL_QB(ctx->opcode);
16023 switch (op2) {
16024 case OPC_SHLL_QB:
16025 check_dsp(ctx);
16026 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
16027 break;
16028 case OPC_SHLLV_QB:
16029 check_dsp(ctx);
16030 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16031 break;
16032 case OPC_SHLL_PH:
16033 check_dsp(ctx);
16034 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
16035 break;
16036 case OPC_SHLLV_PH:
16037 check_dsp(ctx);
16038 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16039 break;
16040 case OPC_SHLL_S_PH:
16041 check_dsp(ctx);
16042 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
16043 break;
16044 case OPC_SHLLV_S_PH:
16045 check_dsp(ctx);
16046 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16047 break;
16048 case OPC_SHLL_S_W:
16049 check_dsp(ctx);
16050 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
16051 break;
16052 case OPC_SHLLV_S_W:
16053 check_dsp(ctx);
16054 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16055 break;
16056 case OPC_SHRL_QB:
16057 check_dsp(ctx);
16058 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
16059 break;
16060 case OPC_SHRLV_QB:
16061 check_dsp(ctx);
16062 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
16063 break;
16064 case OPC_SHRL_PH:
16065 check_dspr2(ctx);
16066 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
16067 break;
16068 case OPC_SHRLV_PH:
16069 check_dspr2(ctx);
16070 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
16071 break;
16072 case OPC_SHRA_QB:
16073 check_dspr2(ctx);
16074 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
16075 break;
16076 case OPC_SHRA_R_QB:
16077 check_dspr2(ctx);
16078 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
16079 break;
16080 case OPC_SHRAV_QB:
16081 check_dspr2(ctx);
16082 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
16083 break;
16084 case OPC_SHRAV_R_QB:
16085 check_dspr2(ctx);
16086 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
16087 break;
16088 case OPC_SHRA_PH:
16089 check_dsp(ctx);
16090 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
16091 break;
16092 case OPC_SHRA_R_PH:
16093 check_dsp(ctx);
16094 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
16095 break;
16096 case OPC_SHRAV_PH:
16097 check_dsp(ctx);
16098 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
16099 break;
16100 case OPC_SHRAV_R_PH:
16101 check_dsp(ctx);
16102 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
16103 break;
16104 case OPC_SHRA_R_W:
16105 check_dsp(ctx);
16106 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
16107 break;
16108 case OPC_SHRAV_R_W:
16109 check_dsp(ctx);
16110 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
16111 break;
16112 default: /* Invalid */
16113 MIPS_INVAL("MASK SHLL.QB");
16114 generate_exception(ctx, EXCP_RI);
16115 break;
16117 break;
16119 #ifdef TARGET_MIPS64
16120 case OPC_SHLL_OB_DSP:
16121 op2 = MASK_SHLL_OB(ctx->opcode);
16122 switch (op2) {
16123 case OPC_SHLL_PW:
16124 check_dsp(ctx);
16125 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
16126 break;
16127 case OPC_SHLLV_PW:
16128 check_dsp(ctx);
16129 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16130 break;
16131 case OPC_SHLL_S_PW:
16132 check_dsp(ctx);
16133 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
16134 break;
16135 case OPC_SHLLV_S_PW:
16136 check_dsp(ctx);
16137 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16138 break;
16139 case OPC_SHLL_OB:
16140 check_dsp(ctx);
16141 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
16142 break;
16143 case OPC_SHLLV_OB:
16144 check_dsp(ctx);
16145 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16146 break;
16147 case OPC_SHLL_QH:
16148 check_dsp(ctx);
16149 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
16150 break;
16151 case OPC_SHLLV_QH:
16152 check_dsp(ctx);
16153 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16154 break;
16155 case OPC_SHLL_S_QH:
16156 check_dsp(ctx);
16157 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
16158 break;
16159 case OPC_SHLLV_S_QH:
16160 check_dsp(ctx);
16161 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16162 break;
16163 case OPC_SHRA_OB:
16164 check_dspr2(ctx);
16165 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
16166 break;
16167 case OPC_SHRAV_OB:
16168 check_dspr2(ctx);
16169 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
16170 break;
16171 case OPC_SHRA_R_OB:
16172 check_dspr2(ctx);
16173 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
16174 break;
16175 case OPC_SHRAV_R_OB:
16176 check_dspr2(ctx);
16177 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
16178 break;
16179 case OPC_SHRA_PW:
16180 check_dsp(ctx);
16181 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
16182 break;
16183 case OPC_SHRAV_PW:
16184 check_dsp(ctx);
16185 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
16186 break;
16187 case OPC_SHRA_R_PW:
16188 check_dsp(ctx);
16189 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
16190 break;
16191 case OPC_SHRAV_R_PW:
16192 check_dsp(ctx);
16193 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
16194 break;
16195 case OPC_SHRA_QH:
16196 check_dsp(ctx);
16197 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
16198 break;
16199 case OPC_SHRAV_QH:
16200 check_dsp(ctx);
16201 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
16202 break;
16203 case OPC_SHRA_R_QH:
16204 check_dsp(ctx);
16205 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
16206 break;
16207 case OPC_SHRAV_R_QH:
16208 check_dsp(ctx);
16209 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
16210 break;
16211 case OPC_SHRL_OB:
16212 check_dsp(ctx);
16213 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
16214 break;
16215 case OPC_SHRLV_OB:
16216 check_dsp(ctx);
16217 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
16218 break;
16219 case OPC_SHRL_QH:
16220 check_dspr2(ctx);
16221 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
16222 break;
16223 case OPC_SHRLV_QH:
16224 check_dspr2(ctx);
16225 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
16226 break;
16227 default: /* Invalid */
16228 MIPS_INVAL("MASK SHLL.OB");
16229 generate_exception(ctx, EXCP_RI);
16230 break;
16232 break;
16233 #endif
16236 tcg_temp_free(t0);
16237 tcg_temp_free(v1_t);
16238 tcg_temp_free(v2_t);
16239 (void)opn; /* avoid a compiler warning */
16240 MIPS_DEBUG("%s", opn);
16243 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
16244 int ret, int v1, int v2, int check_ret)
16246 const char *opn = "mipsdsp multiply";
16247 TCGv_i32 t0;
16248 TCGv v1_t;
16249 TCGv v2_t;
16251 if ((ret == 0) && (check_ret == 1)) {
16252 /* Treat as NOP. */
16253 MIPS_DEBUG("NOP");
16254 return;
16257 t0 = tcg_temp_new_i32();
16258 v1_t = tcg_temp_new();
16259 v2_t = tcg_temp_new();
16261 tcg_gen_movi_i32(t0, ret);
16262 gen_load_gpr(v1_t, v1);
16263 gen_load_gpr(v2_t, v2);
16265 switch (op1) {
16266 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
16267 * the same mask and op1. */
16268 case OPC_MULT_G_2E:
16269 check_dspr2(ctx);
16270 switch (op2) {
16271 case OPC_MUL_PH:
16272 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16273 break;
16274 case OPC_MUL_S_PH:
16275 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16276 break;
16277 case OPC_MULQ_S_W:
16278 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16279 break;
16280 case OPC_MULQ_RS_W:
16281 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16282 break;
16284 break;
16285 case OPC_DPA_W_PH_DSP:
16286 switch (op2) {
16287 case OPC_DPAU_H_QBL:
16288 check_dsp(ctx);
16289 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
16290 break;
16291 case OPC_DPAU_H_QBR:
16292 check_dsp(ctx);
16293 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
16294 break;
16295 case OPC_DPSU_H_QBL:
16296 check_dsp(ctx);
16297 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
16298 break;
16299 case OPC_DPSU_H_QBR:
16300 check_dsp(ctx);
16301 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
16302 break;
16303 case OPC_DPA_W_PH:
16304 check_dspr2(ctx);
16305 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
16306 break;
16307 case OPC_DPAX_W_PH:
16308 check_dspr2(ctx);
16309 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
16310 break;
16311 case OPC_DPAQ_S_W_PH:
16312 check_dsp(ctx);
16313 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16314 break;
16315 case OPC_DPAQX_S_W_PH:
16316 check_dspr2(ctx);
16317 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16318 break;
16319 case OPC_DPAQX_SA_W_PH:
16320 check_dspr2(ctx);
16321 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16322 break;
16323 case OPC_DPS_W_PH:
16324 check_dspr2(ctx);
16325 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
16326 break;
16327 case OPC_DPSX_W_PH:
16328 check_dspr2(ctx);
16329 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
16330 break;
16331 case OPC_DPSQ_S_W_PH:
16332 check_dsp(ctx);
16333 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16334 break;
16335 case OPC_DPSQX_S_W_PH:
16336 check_dspr2(ctx);
16337 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16338 break;
16339 case OPC_DPSQX_SA_W_PH:
16340 check_dspr2(ctx);
16341 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16342 break;
16343 case OPC_MULSAQ_S_W_PH:
16344 check_dsp(ctx);
16345 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16346 break;
16347 case OPC_DPAQ_SA_L_W:
16348 check_dsp(ctx);
16349 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16350 break;
16351 case OPC_DPSQ_SA_L_W:
16352 check_dsp(ctx);
16353 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16354 break;
16355 case OPC_MAQ_S_W_PHL:
16356 check_dsp(ctx);
16357 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
16358 break;
16359 case OPC_MAQ_S_W_PHR:
16360 check_dsp(ctx);
16361 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
16362 break;
16363 case OPC_MAQ_SA_W_PHL:
16364 check_dsp(ctx);
16365 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
16366 break;
16367 case OPC_MAQ_SA_W_PHR:
16368 check_dsp(ctx);
16369 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
16370 break;
16371 case OPC_MULSA_W_PH:
16372 check_dspr2(ctx);
16373 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
16374 break;
16376 break;
16377 #ifdef TARGET_MIPS64
16378 case OPC_DPAQ_W_QH_DSP:
16380 int ac = ret & 0x03;
16381 tcg_gen_movi_i32(t0, ac);
16383 switch (op2) {
16384 case OPC_DMADD:
16385 check_dsp(ctx);
16386 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
16387 break;
16388 case OPC_DMADDU:
16389 check_dsp(ctx);
16390 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
16391 break;
16392 case OPC_DMSUB:
16393 check_dsp(ctx);
16394 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
16395 break;
16396 case OPC_DMSUBU:
16397 check_dsp(ctx);
16398 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
16399 break;
16400 case OPC_DPA_W_QH:
16401 check_dspr2(ctx);
16402 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
16403 break;
16404 case OPC_DPAQ_S_W_QH:
16405 check_dsp(ctx);
16406 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16407 break;
16408 case OPC_DPAQ_SA_L_PW:
16409 check_dsp(ctx);
16410 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16411 break;
16412 case OPC_DPAU_H_OBL:
16413 check_dsp(ctx);
16414 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
16415 break;
16416 case OPC_DPAU_H_OBR:
16417 check_dsp(ctx);
16418 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
16419 break;
16420 case OPC_DPS_W_QH:
16421 check_dspr2(ctx);
16422 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
16423 break;
16424 case OPC_DPSQ_S_W_QH:
16425 check_dsp(ctx);
16426 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16427 break;
16428 case OPC_DPSQ_SA_L_PW:
16429 check_dsp(ctx);
16430 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16431 break;
16432 case OPC_DPSU_H_OBL:
16433 check_dsp(ctx);
16434 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
16435 break;
16436 case OPC_DPSU_H_OBR:
16437 check_dsp(ctx);
16438 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
16439 break;
16440 case OPC_MAQ_S_L_PWL:
16441 check_dsp(ctx);
16442 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
16443 break;
16444 case OPC_MAQ_S_L_PWR:
16445 check_dsp(ctx);
16446 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
16447 break;
16448 case OPC_MAQ_S_W_QHLL:
16449 check_dsp(ctx);
16450 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
16451 break;
16452 case OPC_MAQ_SA_W_QHLL:
16453 check_dsp(ctx);
16454 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
16455 break;
16456 case OPC_MAQ_S_W_QHLR:
16457 check_dsp(ctx);
16458 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
16459 break;
16460 case OPC_MAQ_SA_W_QHLR:
16461 check_dsp(ctx);
16462 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
16463 break;
16464 case OPC_MAQ_S_W_QHRL:
16465 check_dsp(ctx);
16466 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
16467 break;
16468 case OPC_MAQ_SA_W_QHRL:
16469 check_dsp(ctx);
16470 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
16471 break;
16472 case OPC_MAQ_S_W_QHRR:
16473 check_dsp(ctx);
16474 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
16475 break;
16476 case OPC_MAQ_SA_W_QHRR:
16477 check_dsp(ctx);
16478 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
16479 break;
16480 case OPC_MULSAQ_S_L_PW:
16481 check_dsp(ctx);
16482 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
16483 break;
16484 case OPC_MULSAQ_S_W_QH:
16485 check_dsp(ctx);
16486 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16487 break;
16490 break;
16491 #endif
16492 case OPC_ADDU_QB_DSP:
16493 switch (op2) {
16494 case OPC_MULEU_S_PH_QBL:
16495 check_dsp(ctx);
16496 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16497 break;
16498 case OPC_MULEU_S_PH_QBR:
16499 check_dsp(ctx);
16500 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16501 break;
16502 case OPC_MULQ_RS_PH:
16503 check_dsp(ctx);
16504 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16505 break;
16506 case OPC_MULEQ_S_W_PHL:
16507 check_dsp(ctx);
16508 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16509 break;
16510 case OPC_MULEQ_S_W_PHR:
16511 check_dsp(ctx);
16512 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16513 break;
16514 case OPC_MULQ_S_PH:
16515 check_dspr2(ctx);
16516 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16517 break;
16519 break;
16520 #ifdef TARGET_MIPS64
16521 case OPC_ADDU_OB_DSP:
16522 switch (op2) {
16523 case OPC_MULEQ_S_PW_QHL:
16524 check_dsp(ctx);
16525 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16526 break;
16527 case OPC_MULEQ_S_PW_QHR:
16528 check_dsp(ctx);
16529 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16530 break;
16531 case OPC_MULEU_S_QH_OBL:
16532 check_dsp(ctx);
16533 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16534 break;
16535 case OPC_MULEU_S_QH_OBR:
16536 check_dsp(ctx);
16537 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16538 break;
16539 case OPC_MULQ_RS_QH:
16540 check_dsp(ctx);
16541 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16542 break;
16544 break;
16545 #endif
16548 tcg_temp_free_i32(t0);
16549 tcg_temp_free(v1_t);
16550 tcg_temp_free(v2_t);
16552 (void)opn; /* avoid a compiler warning */
16553 MIPS_DEBUG("%s", opn);
16557 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16558 int ret, int val)
16560 const char *opn = "mipsdsp Bit/ Manipulation";
16561 int16_t imm;
16562 TCGv t0;
16563 TCGv val_t;
16565 if (ret == 0) {
16566 /* Treat as NOP. */
16567 MIPS_DEBUG("NOP");
16568 return;
16571 t0 = tcg_temp_new();
16572 val_t = tcg_temp_new();
16573 gen_load_gpr(val_t, val);
16575 switch (op1) {
16576 case OPC_ABSQ_S_PH_DSP:
16577 switch (op2) {
16578 case OPC_BITREV:
16579 check_dsp(ctx);
16580 gen_helper_bitrev(cpu_gpr[ret], val_t);
16581 break;
16582 case OPC_REPL_QB:
16583 check_dsp(ctx);
16585 target_long result;
16586 imm = (ctx->opcode >> 16) & 0xFF;
16587 result = (uint32_t)imm << 24 |
16588 (uint32_t)imm << 16 |
16589 (uint32_t)imm << 8 |
16590 (uint32_t)imm;
16591 result = (int32_t)result;
16592 tcg_gen_movi_tl(cpu_gpr[ret], result);
16594 break;
16595 case OPC_REPLV_QB:
16596 check_dsp(ctx);
16597 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16598 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16599 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16600 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16601 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16602 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16603 break;
16604 case OPC_REPL_PH:
16605 check_dsp(ctx);
16607 imm = (ctx->opcode >> 16) & 0x03FF;
16608 imm = (int16_t)(imm << 6) >> 6;
16609 tcg_gen_movi_tl(cpu_gpr[ret], \
16610 (target_long)((int32_t)imm << 16 | \
16611 (uint16_t)imm));
16613 break;
16614 case OPC_REPLV_PH:
16615 check_dsp(ctx);
16616 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16617 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16618 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16619 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16620 break;
16622 break;
16623 #ifdef TARGET_MIPS64
16624 case OPC_ABSQ_S_QH_DSP:
16625 switch (op2) {
16626 case OPC_REPL_OB:
16627 check_dsp(ctx);
16629 target_long temp;
16631 imm = (ctx->opcode >> 16) & 0xFF;
16632 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
16633 temp = (temp << 16) | temp;
16634 temp = (temp << 32) | temp;
16635 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16636 break;
16638 case OPC_REPL_PW:
16639 check_dsp(ctx);
16641 target_long temp;
16643 imm = (ctx->opcode >> 16) & 0x03FF;
16644 imm = (int16_t)(imm << 6) >> 6;
16645 temp = ((target_long)imm << 32) \
16646 | ((target_long)imm & 0xFFFFFFFF);
16647 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16648 break;
16650 case OPC_REPL_QH:
16651 check_dsp(ctx);
16653 target_long temp;
16655 imm = (ctx->opcode >> 16) & 0x03FF;
16656 imm = (int16_t)(imm << 6) >> 6;
16658 temp = ((uint64_t)(uint16_t)imm << 48) |
16659 ((uint64_t)(uint16_t)imm << 32) |
16660 ((uint64_t)(uint16_t)imm << 16) |
16661 (uint64_t)(uint16_t)imm;
16662 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16663 break;
16665 case OPC_REPLV_OB:
16666 check_dsp(ctx);
16667 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16668 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16669 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16670 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16671 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16672 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16673 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16674 break;
16675 case OPC_REPLV_PW:
16676 check_dsp(ctx);
16677 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
16678 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16679 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16680 break;
16681 case OPC_REPLV_QH:
16682 check_dsp(ctx);
16683 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16684 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16685 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16686 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16687 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16688 break;
16690 break;
16691 #endif
16693 tcg_temp_free(t0);
16694 tcg_temp_free(val_t);
16696 (void)opn; /* avoid a compiler warning */
16697 MIPS_DEBUG("%s", opn);
16700 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
16701 uint32_t op1, uint32_t op2,
16702 int ret, int v1, int v2, int check_ret)
16704 const char *opn = "mipsdsp add compare pick";
16705 TCGv t1;
16706 TCGv v1_t;
16707 TCGv v2_t;
16709 if ((ret == 0) && (check_ret == 1)) {
16710 /* Treat as NOP. */
16711 MIPS_DEBUG("NOP");
16712 return;
16715 t1 = tcg_temp_new();
16716 v1_t = tcg_temp_new();
16717 v2_t = tcg_temp_new();
16719 gen_load_gpr(v1_t, v1);
16720 gen_load_gpr(v2_t, v2);
16722 switch (op1) {
16723 case OPC_CMPU_EQ_QB_DSP:
16724 switch (op2) {
16725 case OPC_CMPU_EQ_QB:
16726 check_dsp(ctx);
16727 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
16728 break;
16729 case OPC_CMPU_LT_QB:
16730 check_dsp(ctx);
16731 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
16732 break;
16733 case OPC_CMPU_LE_QB:
16734 check_dsp(ctx);
16735 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
16736 break;
16737 case OPC_CMPGU_EQ_QB:
16738 check_dsp(ctx);
16739 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
16740 break;
16741 case OPC_CMPGU_LT_QB:
16742 check_dsp(ctx);
16743 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
16744 break;
16745 case OPC_CMPGU_LE_QB:
16746 check_dsp(ctx);
16747 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
16748 break;
16749 case OPC_CMPGDU_EQ_QB:
16750 check_dspr2(ctx);
16751 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
16752 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16753 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16754 tcg_gen_shli_tl(t1, t1, 24);
16755 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16756 break;
16757 case OPC_CMPGDU_LT_QB:
16758 check_dspr2(ctx);
16759 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
16760 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16761 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16762 tcg_gen_shli_tl(t1, t1, 24);
16763 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16764 break;
16765 case OPC_CMPGDU_LE_QB:
16766 check_dspr2(ctx);
16767 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
16768 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16769 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16770 tcg_gen_shli_tl(t1, t1, 24);
16771 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16772 break;
16773 case OPC_CMP_EQ_PH:
16774 check_dsp(ctx);
16775 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
16776 break;
16777 case OPC_CMP_LT_PH:
16778 check_dsp(ctx);
16779 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
16780 break;
16781 case OPC_CMP_LE_PH:
16782 check_dsp(ctx);
16783 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
16784 break;
16785 case OPC_PICK_QB:
16786 check_dsp(ctx);
16787 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16788 break;
16789 case OPC_PICK_PH:
16790 check_dsp(ctx);
16791 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16792 break;
16793 case OPC_PACKRL_PH:
16794 check_dsp(ctx);
16795 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
16796 break;
16798 break;
16799 #ifdef TARGET_MIPS64
16800 case OPC_CMPU_EQ_OB_DSP:
16801 switch (op2) {
16802 case OPC_CMP_EQ_PW:
16803 check_dsp(ctx);
16804 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
16805 break;
16806 case OPC_CMP_LT_PW:
16807 check_dsp(ctx);
16808 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
16809 break;
16810 case OPC_CMP_LE_PW:
16811 check_dsp(ctx);
16812 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
16813 break;
16814 case OPC_CMP_EQ_QH:
16815 check_dsp(ctx);
16816 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
16817 break;
16818 case OPC_CMP_LT_QH:
16819 check_dsp(ctx);
16820 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
16821 break;
16822 case OPC_CMP_LE_QH:
16823 check_dsp(ctx);
16824 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
16825 break;
16826 case OPC_CMPGDU_EQ_OB:
16827 check_dspr2(ctx);
16828 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16829 break;
16830 case OPC_CMPGDU_LT_OB:
16831 check_dspr2(ctx);
16832 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16833 break;
16834 case OPC_CMPGDU_LE_OB:
16835 check_dspr2(ctx);
16836 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16837 break;
16838 case OPC_CMPGU_EQ_OB:
16839 check_dsp(ctx);
16840 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
16841 break;
16842 case OPC_CMPGU_LT_OB:
16843 check_dsp(ctx);
16844 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
16845 break;
16846 case OPC_CMPGU_LE_OB:
16847 check_dsp(ctx);
16848 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
16849 break;
16850 case OPC_CMPU_EQ_OB:
16851 check_dsp(ctx);
16852 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
16853 break;
16854 case OPC_CMPU_LT_OB:
16855 check_dsp(ctx);
16856 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
16857 break;
16858 case OPC_CMPU_LE_OB:
16859 check_dsp(ctx);
16860 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
16861 break;
16862 case OPC_PACKRL_PW:
16863 check_dsp(ctx);
16864 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
16865 break;
16866 case OPC_PICK_OB:
16867 check_dsp(ctx);
16868 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16869 break;
16870 case OPC_PICK_PW:
16871 check_dsp(ctx);
16872 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16873 break;
16874 case OPC_PICK_QH:
16875 check_dsp(ctx);
16876 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16877 break;
16879 break;
16880 #endif
16883 tcg_temp_free(t1);
16884 tcg_temp_free(v1_t);
16885 tcg_temp_free(v2_t);
16887 (void)opn; /* avoid a compiler warning */
16888 MIPS_DEBUG("%s", opn);
16891 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
16892 uint32_t op1, int rt, int rs, int sa)
16894 const char *opn = "mipsdsp append/dappend";
16895 TCGv t0;
16897 check_dspr2(ctx);
16899 if (rt == 0) {
16900 /* Treat as NOP. */
16901 MIPS_DEBUG("NOP");
16902 return;
16905 t0 = tcg_temp_new();
16906 gen_load_gpr(t0, rs);
16908 switch (op1) {
16909 case OPC_APPEND_DSP:
16910 switch (MASK_APPEND(ctx->opcode)) {
16911 case OPC_APPEND:
16912 if (sa != 0) {
16913 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
16915 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16916 break;
16917 case OPC_PREPEND:
16918 if (sa != 0) {
16919 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
16920 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16921 tcg_gen_shli_tl(t0, t0, 32 - sa);
16922 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16924 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16925 break;
16926 case OPC_BALIGN:
16927 sa &= 3;
16928 if (sa != 0 && sa != 2) {
16929 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16930 tcg_gen_ext32u_tl(t0, t0);
16931 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
16932 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16934 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16935 break;
16936 default: /* Invalid */
16937 MIPS_INVAL("MASK APPEND");
16938 generate_exception(ctx, EXCP_RI);
16939 break;
16941 break;
16942 #ifdef TARGET_MIPS64
16943 case OPC_DAPPEND_DSP:
16944 switch (MASK_DAPPEND(ctx->opcode)) {
16945 case OPC_DAPPEND:
16946 if (sa != 0) {
16947 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
16949 break;
16950 case OPC_PREPENDD:
16951 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
16952 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
16953 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
16954 break;
16955 case OPC_PREPENDW:
16956 if (sa != 0) {
16957 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16958 tcg_gen_shli_tl(t0, t0, 64 - sa);
16959 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16961 break;
16962 case OPC_DBALIGN:
16963 sa &= 7;
16964 if (sa != 0 && sa != 2 && sa != 4) {
16965 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16966 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
16967 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16969 break;
16970 default: /* Invalid */
16971 MIPS_INVAL("MASK DAPPEND");
16972 generate_exception(ctx, EXCP_RI);
16973 break;
16975 break;
16976 #endif
16978 tcg_temp_free(t0);
16979 (void)opn; /* avoid a compiler warning */
16980 MIPS_DEBUG("%s", opn);
16983 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16984 int ret, int v1, int v2, int check_ret)
16987 const char *opn = "mipsdsp accumulator";
16988 TCGv t0;
16989 TCGv t1;
16990 TCGv v1_t;
16991 TCGv v2_t;
16992 int16_t imm;
16994 if ((ret == 0) && (check_ret == 1)) {
16995 /* Treat as NOP. */
16996 MIPS_DEBUG("NOP");
16997 return;
17000 t0 = tcg_temp_new();
17001 t1 = tcg_temp_new();
17002 v1_t = tcg_temp_new();
17003 v2_t = tcg_temp_new();
17005 gen_load_gpr(v1_t, v1);
17006 gen_load_gpr(v2_t, v2);
17008 switch (op1) {
17009 case OPC_EXTR_W_DSP:
17010 check_dsp(ctx);
17011 switch (op2) {
17012 case OPC_EXTR_W:
17013 tcg_gen_movi_tl(t0, v2);
17014 tcg_gen_movi_tl(t1, v1);
17015 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
17016 break;
17017 case OPC_EXTR_R_W:
17018 tcg_gen_movi_tl(t0, v2);
17019 tcg_gen_movi_tl(t1, v1);
17020 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
17021 break;
17022 case OPC_EXTR_RS_W:
17023 tcg_gen_movi_tl(t0, v2);
17024 tcg_gen_movi_tl(t1, v1);
17025 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
17026 break;
17027 case OPC_EXTR_S_H:
17028 tcg_gen_movi_tl(t0, v2);
17029 tcg_gen_movi_tl(t1, v1);
17030 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17031 break;
17032 case OPC_EXTRV_S_H:
17033 tcg_gen_movi_tl(t0, v2);
17034 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
17035 break;
17036 case OPC_EXTRV_W:
17037 tcg_gen_movi_tl(t0, v2);
17038 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17039 break;
17040 case OPC_EXTRV_R_W:
17041 tcg_gen_movi_tl(t0, v2);
17042 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17043 break;
17044 case OPC_EXTRV_RS_W:
17045 tcg_gen_movi_tl(t0, v2);
17046 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17047 break;
17048 case OPC_EXTP:
17049 tcg_gen_movi_tl(t0, v2);
17050 tcg_gen_movi_tl(t1, v1);
17051 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
17052 break;
17053 case OPC_EXTPV:
17054 tcg_gen_movi_tl(t0, v2);
17055 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
17056 break;
17057 case OPC_EXTPDP:
17058 tcg_gen_movi_tl(t0, v2);
17059 tcg_gen_movi_tl(t1, v1);
17060 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
17061 break;
17062 case OPC_EXTPDPV:
17063 tcg_gen_movi_tl(t0, v2);
17064 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
17065 break;
17066 case OPC_SHILO:
17067 imm = (ctx->opcode >> 20) & 0x3F;
17068 tcg_gen_movi_tl(t0, ret);
17069 tcg_gen_movi_tl(t1, imm);
17070 gen_helper_shilo(t0, t1, cpu_env);
17071 break;
17072 case OPC_SHILOV:
17073 tcg_gen_movi_tl(t0, ret);
17074 gen_helper_shilo(t0, v1_t, cpu_env);
17075 break;
17076 case OPC_MTHLIP:
17077 tcg_gen_movi_tl(t0, ret);
17078 gen_helper_mthlip(t0, v1_t, cpu_env);
17079 break;
17080 case OPC_WRDSP:
17081 imm = (ctx->opcode >> 11) & 0x3FF;
17082 tcg_gen_movi_tl(t0, imm);
17083 gen_helper_wrdsp(v1_t, t0, cpu_env);
17084 break;
17085 case OPC_RDDSP:
17086 imm = (ctx->opcode >> 16) & 0x03FF;
17087 tcg_gen_movi_tl(t0, imm);
17088 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
17089 break;
17091 break;
17092 #ifdef TARGET_MIPS64
17093 case OPC_DEXTR_W_DSP:
17094 check_dsp(ctx);
17095 switch (op2) {
17096 case OPC_DMTHLIP:
17097 tcg_gen_movi_tl(t0, ret);
17098 gen_helper_dmthlip(v1_t, t0, cpu_env);
17099 break;
17100 case OPC_DSHILO:
17102 int shift = (ctx->opcode >> 19) & 0x7F;
17103 int ac = (ctx->opcode >> 11) & 0x03;
17104 tcg_gen_movi_tl(t0, shift);
17105 tcg_gen_movi_tl(t1, ac);
17106 gen_helper_dshilo(t0, t1, cpu_env);
17107 break;
17109 case OPC_DSHILOV:
17111 int ac = (ctx->opcode >> 11) & 0x03;
17112 tcg_gen_movi_tl(t0, ac);
17113 gen_helper_dshilo(v1_t, t0, cpu_env);
17114 break;
17116 case OPC_DEXTP:
17117 tcg_gen_movi_tl(t0, v2);
17118 tcg_gen_movi_tl(t1, v1);
17120 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
17121 break;
17122 case OPC_DEXTPV:
17123 tcg_gen_movi_tl(t0, v2);
17124 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
17125 break;
17126 case OPC_DEXTPDP:
17127 tcg_gen_movi_tl(t0, v2);
17128 tcg_gen_movi_tl(t1, v1);
17129 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
17130 break;
17131 case OPC_DEXTPDPV:
17132 tcg_gen_movi_tl(t0, v2);
17133 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
17134 break;
17135 case OPC_DEXTR_L:
17136 tcg_gen_movi_tl(t0, v2);
17137 tcg_gen_movi_tl(t1, v1);
17138 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
17139 break;
17140 case OPC_DEXTR_R_L:
17141 tcg_gen_movi_tl(t0, v2);
17142 tcg_gen_movi_tl(t1, v1);
17143 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
17144 break;
17145 case OPC_DEXTR_RS_L:
17146 tcg_gen_movi_tl(t0, v2);
17147 tcg_gen_movi_tl(t1, v1);
17148 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
17149 break;
17150 case OPC_DEXTR_W:
17151 tcg_gen_movi_tl(t0, v2);
17152 tcg_gen_movi_tl(t1, v1);
17153 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
17154 break;
17155 case OPC_DEXTR_R_W:
17156 tcg_gen_movi_tl(t0, v2);
17157 tcg_gen_movi_tl(t1, v1);
17158 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
17159 break;
17160 case OPC_DEXTR_RS_W:
17161 tcg_gen_movi_tl(t0, v2);
17162 tcg_gen_movi_tl(t1, v1);
17163 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
17164 break;
17165 case OPC_DEXTR_S_H:
17166 tcg_gen_movi_tl(t0, v2);
17167 tcg_gen_movi_tl(t1, v1);
17168 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17169 break;
17170 case OPC_DEXTRV_S_H:
17171 tcg_gen_movi_tl(t0, v2);
17172 tcg_gen_movi_tl(t1, v1);
17173 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17174 break;
17175 case OPC_DEXTRV_L:
17176 tcg_gen_movi_tl(t0, v2);
17177 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17178 break;
17179 case OPC_DEXTRV_R_L:
17180 tcg_gen_movi_tl(t0, v2);
17181 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17182 break;
17183 case OPC_DEXTRV_RS_L:
17184 tcg_gen_movi_tl(t0, v2);
17185 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17186 break;
17187 case OPC_DEXTRV_W:
17188 tcg_gen_movi_tl(t0, v2);
17189 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17190 break;
17191 case OPC_DEXTRV_R_W:
17192 tcg_gen_movi_tl(t0, v2);
17193 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17194 break;
17195 case OPC_DEXTRV_RS_W:
17196 tcg_gen_movi_tl(t0, v2);
17197 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17198 break;
17200 break;
17201 #endif
17204 tcg_temp_free(t0);
17205 tcg_temp_free(t1);
17206 tcg_temp_free(v1_t);
17207 tcg_temp_free(v2_t);
17209 (void)opn; /* avoid a compiler warning */
17210 MIPS_DEBUG("%s", opn);
17213 /* End MIPSDSP functions. */
17215 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
17217 int rs, rt, rd, sa;
17218 uint32_t op1, op2;
17220 rs = (ctx->opcode >> 21) & 0x1f;
17221 rt = (ctx->opcode >> 16) & 0x1f;
17222 rd = (ctx->opcode >> 11) & 0x1f;
17223 sa = (ctx->opcode >> 6) & 0x1f;
17225 op1 = MASK_SPECIAL(ctx->opcode);
17226 switch (op1) {
17227 case OPC_LSA:
17228 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
17229 break;
17230 case OPC_MULT ... OPC_DIVU:
17231 op2 = MASK_R6_MULDIV(ctx->opcode);
17232 switch (op2) {
17233 case R6_OPC_MUL:
17234 case R6_OPC_MUH:
17235 case R6_OPC_MULU:
17236 case R6_OPC_MUHU:
17237 case R6_OPC_DIV:
17238 case R6_OPC_MOD:
17239 case R6_OPC_DIVU:
17240 case R6_OPC_MODU:
17241 gen_r6_muldiv(ctx, op2, rd, rs, rt);
17242 break;
17243 default:
17244 MIPS_INVAL("special_r6 muldiv");
17245 generate_exception(ctx, EXCP_RI);
17246 break;
17248 break;
17249 case OPC_SELEQZ:
17250 case OPC_SELNEZ:
17251 gen_cond_move(ctx, op1, rd, rs, rt);
17252 break;
17253 case R6_OPC_CLO:
17254 case R6_OPC_CLZ:
17255 if (rt == 0 && sa == 1) {
17256 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17257 We need additionally to check other fields */
17258 gen_cl(ctx, op1, rd, rs);
17259 } else {
17260 generate_exception(ctx, EXCP_RI);
17262 break;
17263 case R6_OPC_SDBBP:
17264 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17265 gen_helper_do_semihosting(cpu_env);
17266 } else {
17267 if (ctx->hflags & MIPS_HFLAG_SBRI) {
17268 generate_exception(ctx, EXCP_RI);
17269 } else {
17270 generate_exception(ctx, EXCP_DBp);
17273 break;
17274 #if defined(TARGET_MIPS64)
17275 case OPC_DLSA:
17276 check_mips_64(ctx);
17277 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
17278 break;
17279 case R6_OPC_DCLO:
17280 case R6_OPC_DCLZ:
17281 if (rt == 0 && sa == 1) {
17282 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17283 We need additionally to check other fields */
17284 check_mips_64(ctx);
17285 gen_cl(ctx, op1, rd, rs);
17286 } else {
17287 generate_exception(ctx, EXCP_RI);
17289 break;
17290 case OPC_DMULT ... OPC_DDIVU:
17291 op2 = MASK_R6_MULDIV(ctx->opcode);
17292 switch (op2) {
17293 case R6_OPC_DMUL:
17294 case R6_OPC_DMUH:
17295 case R6_OPC_DMULU:
17296 case R6_OPC_DMUHU:
17297 case R6_OPC_DDIV:
17298 case R6_OPC_DMOD:
17299 case R6_OPC_DDIVU:
17300 case R6_OPC_DMODU:
17301 check_mips_64(ctx);
17302 gen_r6_muldiv(ctx, op2, rd, rs, rt);
17303 break;
17304 default:
17305 MIPS_INVAL("special_r6 muldiv");
17306 generate_exception(ctx, EXCP_RI);
17307 break;
17309 break;
17310 #endif
17311 default: /* Invalid */
17312 MIPS_INVAL("special_r6");
17313 generate_exception(ctx, EXCP_RI);
17314 break;
17318 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
17320 int rs, rt, rd, sa;
17321 uint32_t op1;
17323 rs = (ctx->opcode >> 21) & 0x1f;
17324 rt = (ctx->opcode >> 16) & 0x1f;
17325 rd = (ctx->opcode >> 11) & 0x1f;
17326 sa = (ctx->opcode >> 6) & 0x1f;
17328 op1 = MASK_SPECIAL(ctx->opcode);
17329 switch (op1) {
17330 case OPC_MOVN: /* Conditional move */
17331 case OPC_MOVZ:
17332 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
17333 INSN_LOONGSON2E | INSN_LOONGSON2F);
17334 gen_cond_move(ctx, op1, rd, rs, rt);
17335 break;
17336 case OPC_MFHI: /* Move from HI/LO */
17337 case OPC_MFLO:
17338 gen_HILO(ctx, op1, rs & 3, rd);
17339 break;
17340 case OPC_MTHI:
17341 case OPC_MTLO: /* Move to HI/LO */
17342 gen_HILO(ctx, op1, rd & 3, rs);
17343 break;
17344 case OPC_MOVCI:
17345 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
17346 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17347 check_cp1_enabled(ctx);
17348 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
17349 (ctx->opcode >> 16) & 1);
17350 } else {
17351 generate_exception_err(ctx, EXCP_CpU, 1);
17353 break;
17354 case OPC_MULT:
17355 case OPC_MULTU:
17356 if (sa) {
17357 check_insn(ctx, INSN_VR54XX);
17358 op1 = MASK_MUL_VR54XX(ctx->opcode);
17359 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
17360 } else {
17361 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17363 break;
17364 case OPC_DIV:
17365 case OPC_DIVU:
17366 gen_muldiv(ctx, op1, 0, rs, rt);
17367 break;
17368 #if defined(TARGET_MIPS64)
17369 case OPC_DMULT ... OPC_DDIVU:
17370 check_insn(ctx, ISA_MIPS3);
17371 check_mips_64(ctx);
17372 gen_muldiv(ctx, op1, 0, rs, rt);
17373 break;
17374 #endif
17375 case OPC_JR:
17376 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17377 break;
17378 case OPC_SPIM:
17379 #ifdef MIPS_STRICT_STANDARD
17380 MIPS_INVAL("SPIM");
17381 generate_exception(ctx, EXCP_RI);
17382 #else
17383 /* Implemented as RI exception for now. */
17384 MIPS_INVAL("spim (unofficial)");
17385 generate_exception(ctx, EXCP_RI);
17386 #endif
17387 break;
17388 default: /* Invalid */
17389 MIPS_INVAL("special_legacy");
17390 generate_exception(ctx, EXCP_RI);
17391 break;
17395 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
17397 int rs, rt, rd, sa;
17398 uint32_t op1;
17400 rs = (ctx->opcode >> 21) & 0x1f;
17401 rt = (ctx->opcode >> 16) & 0x1f;
17402 rd = (ctx->opcode >> 11) & 0x1f;
17403 sa = (ctx->opcode >> 6) & 0x1f;
17405 op1 = MASK_SPECIAL(ctx->opcode);
17406 switch (op1) {
17407 case OPC_SLL: /* Shift with immediate */
17408 if (sa == 5 && rd == 0 &&
17409 rs == 0 && rt == 0) { /* PAUSE */
17410 if ((ctx->insn_flags & ISA_MIPS32R6) &&
17411 (ctx->hflags & MIPS_HFLAG_BMASK)) {
17412 MIPS_DEBUG("CTI in delay / forbidden slot");
17413 generate_exception(ctx, EXCP_RI);
17414 break;
17417 /* Fallthrough */
17418 case OPC_SRA:
17419 gen_shift_imm(ctx, op1, rd, rt, sa);
17420 break;
17421 case OPC_SRL:
17422 switch ((ctx->opcode >> 21) & 0x1f) {
17423 case 1:
17424 /* rotr is decoded as srl on non-R2 CPUs */
17425 if (ctx->insn_flags & ISA_MIPS32R2) {
17426 op1 = OPC_ROTR;
17428 /* Fallthrough */
17429 case 0:
17430 gen_shift_imm(ctx, op1, rd, rt, sa);
17431 break;
17432 default:
17433 generate_exception(ctx, EXCP_RI);
17434 break;
17436 break;
17437 case OPC_ADD ... OPC_SUBU:
17438 gen_arith(ctx, op1, rd, rs, rt);
17439 break;
17440 case OPC_SLLV: /* Shifts */
17441 case OPC_SRAV:
17442 gen_shift(ctx, op1, rd, rs, rt);
17443 break;
17444 case OPC_SRLV:
17445 switch ((ctx->opcode >> 6) & 0x1f) {
17446 case 1:
17447 /* rotrv is decoded as srlv on non-R2 CPUs */
17448 if (ctx->insn_flags & ISA_MIPS32R2) {
17449 op1 = OPC_ROTRV;
17451 /* Fallthrough */
17452 case 0:
17453 gen_shift(ctx, op1, rd, rs, rt);
17454 break;
17455 default:
17456 generate_exception(ctx, EXCP_RI);
17457 break;
17459 break;
17460 case OPC_SLT: /* Set on less than */
17461 case OPC_SLTU:
17462 gen_slt(ctx, op1, rd, rs, rt);
17463 break;
17464 case OPC_AND: /* Logic*/
17465 case OPC_OR:
17466 case OPC_NOR:
17467 case OPC_XOR:
17468 gen_logic(ctx, op1, rd, rs, rt);
17469 break;
17470 case OPC_JALR:
17471 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17472 break;
17473 case OPC_TGE ... OPC_TEQ: /* Traps */
17474 case OPC_TNE:
17475 check_insn(ctx, ISA_MIPS2);
17476 gen_trap(ctx, op1, rs, rt, -1);
17477 break;
17478 case OPC_LSA: /* OPC_PMON */
17479 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17480 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17481 decode_opc_special_r6(env, ctx);
17482 } else {
17483 /* Pmon entry point, also R4010 selsl */
17484 #ifdef MIPS_STRICT_STANDARD
17485 MIPS_INVAL("PMON / selsl");
17486 generate_exception(ctx, EXCP_RI);
17487 #else
17488 gen_helper_0e0i(pmon, sa);
17489 #endif
17491 break;
17492 case OPC_SYSCALL:
17493 generate_exception(ctx, EXCP_SYSCALL);
17494 ctx->bstate = BS_STOP;
17495 break;
17496 case OPC_BREAK:
17497 generate_exception(ctx, EXCP_BREAK);
17498 break;
17499 case OPC_SYNC:
17500 check_insn(ctx, ISA_MIPS2);
17501 /* Treat as NOP. */
17502 break;
17504 #if defined(TARGET_MIPS64)
17505 /* MIPS64 specific opcodes */
17506 case OPC_DSLL:
17507 case OPC_DSRA:
17508 case OPC_DSLL32:
17509 case OPC_DSRA32:
17510 check_insn(ctx, ISA_MIPS3);
17511 check_mips_64(ctx);
17512 gen_shift_imm(ctx, op1, rd, rt, sa);
17513 break;
17514 case OPC_DSRL:
17515 switch ((ctx->opcode >> 21) & 0x1f) {
17516 case 1:
17517 /* drotr is decoded as dsrl on non-R2 CPUs */
17518 if (ctx->insn_flags & ISA_MIPS32R2) {
17519 op1 = OPC_DROTR;
17521 /* Fallthrough */
17522 case 0:
17523 check_insn(ctx, ISA_MIPS3);
17524 check_mips_64(ctx);
17525 gen_shift_imm(ctx, op1, rd, rt, sa);
17526 break;
17527 default:
17528 generate_exception(ctx, EXCP_RI);
17529 break;
17531 break;
17532 case OPC_DSRL32:
17533 switch ((ctx->opcode >> 21) & 0x1f) {
17534 case 1:
17535 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
17536 if (ctx->insn_flags & ISA_MIPS32R2) {
17537 op1 = OPC_DROTR32;
17539 /* Fallthrough */
17540 case 0:
17541 check_insn(ctx, ISA_MIPS3);
17542 check_mips_64(ctx);
17543 gen_shift_imm(ctx, op1, rd, rt, sa);
17544 break;
17545 default:
17546 generate_exception(ctx, EXCP_RI);
17547 break;
17549 break;
17550 case OPC_DADD ... OPC_DSUBU:
17551 check_insn(ctx, ISA_MIPS3);
17552 check_mips_64(ctx);
17553 gen_arith(ctx, op1, rd, rs, rt);
17554 break;
17555 case OPC_DSLLV:
17556 case OPC_DSRAV:
17557 check_insn(ctx, ISA_MIPS3);
17558 check_mips_64(ctx);
17559 gen_shift(ctx, op1, rd, rs, rt);
17560 break;
17561 case OPC_DSRLV:
17562 switch ((ctx->opcode >> 6) & 0x1f) {
17563 case 1:
17564 /* drotrv is decoded as dsrlv on non-R2 CPUs */
17565 if (ctx->insn_flags & ISA_MIPS32R2) {
17566 op1 = OPC_DROTRV;
17568 /* Fallthrough */
17569 case 0:
17570 check_insn(ctx, ISA_MIPS3);
17571 check_mips_64(ctx);
17572 gen_shift(ctx, op1, rd, rs, rt);
17573 break;
17574 default:
17575 generate_exception(ctx, EXCP_RI);
17576 break;
17578 break;
17579 case OPC_DLSA:
17580 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17581 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17582 decode_opc_special_r6(env, ctx);
17584 break;
17585 #endif
17586 default:
17587 if (ctx->insn_flags & ISA_MIPS32R6) {
17588 decode_opc_special_r6(env, ctx);
17589 } else {
17590 decode_opc_special_legacy(env, ctx);
17595 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
17597 int rs, rt, rd;
17598 uint32_t op1;
17600 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17602 rs = (ctx->opcode >> 21) & 0x1f;
17603 rt = (ctx->opcode >> 16) & 0x1f;
17604 rd = (ctx->opcode >> 11) & 0x1f;
17606 op1 = MASK_SPECIAL2(ctx->opcode);
17607 switch (op1) {
17608 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
17609 case OPC_MSUB ... OPC_MSUBU:
17610 check_insn(ctx, ISA_MIPS32);
17611 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17612 break;
17613 case OPC_MUL:
17614 gen_arith(ctx, op1, rd, rs, rt);
17615 break;
17616 case OPC_DIV_G_2F:
17617 case OPC_DIVU_G_2F:
17618 case OPC_MULT_G_2F:
17619 case OPC_MULTU_G_2F:
17620 case OPC_MOD_G_2F:
17621 case OPC_MODU_G_2F:
17622 check_insn(ctx, INSN_LOONGSON2F);
17623 gen_loongson_integer(ctx, op1, rd, rs, rt);
17624 break;
17625 case OPC_CLO:
17626 case OPC_CLZ:
17627 check_insn(ctx, ISA_MIPS32);
17628 gen_cl(ctx, op1, rd, rs);
17629 break;
17630 case OPC_SDBBP:
17631 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17632 gen_helper_do_semihosting(cpu_env);
17633 } else {
17634 /* XXX: not clear which exception should be raised
17635 * when in debug mode...
17637 check_insn(ctx, ISA_MIPS32);
17638 generate_exception(ctx, EXCP_DBp);
17640 break;
17641 #if defined(TARGET_MIPS64)
17642 case OPC_DCLO:
17643 case OPC_DCLZ:
17644 check_insn(ctx, ISA_MIPS64);
17645 check_mips_64(ctx);
17646 gen_cl(ctx, op1, rd, rs);
17647 break;
17648 case OPC_DMULT_G_2F:
17649 case OPC_DMULTU_G_2F:
17650 case OPC_DDIV_G_2F:
17651 case OPC_DDIVU_G_2F:
17652 case OPC_DMOD_G_2F:
17653 case OPC_DMODU_G_2F:
17654 check_insn(ctx, INSN_LOONGSON2F);
17655 gen_loongson_integer(ctx, op1, rd, rs, rt);
17656 break;
17657 #endif
17658 default: /* Invalid */
17659 MIPS_INVAL("special2_legacy");
17660 generate_exception(ctx, EXCP_RI);
17661 break;
17665 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
17667 int rs, rt, rd, sa;
17668 uint32_t op1, op2;
17669 int16_t imm;
17671 rs = (ctx->opcode >> 21) & 0x1f;
17672 rt = (ctx->opcode >> 16) & 0x1f;
17673 rd = (ctx->opcode >> 11) & 0x1f;
17674 sa = (ctx->opcode >> 6) & 0x1f;
17675 imm = (int16_t)ctx->opcode >> 7;
17677 op1 = MASK_SPECIAL3(ctx->opcode);
17678 switch (op1) {
17679 case R6_OPC_PREF:
17680 if (rt >= 24) {
17681 /* hint codes 24-31 are reserved and signal RI */
17682 generate_exception(ctx, EXCP_RI);
17684 /* Treat as NOP. */
17685 break;
17686 case R6_OPC_CACHE:
17687 /* Treat as NOP. */
17688 break;
17689 case R6_OPC_SC:
17690 gen_st_cond(ctx, op1, rt, rs, imm);
17691 break;
17692 case R6_OPC_LL:
17693 gen_ld(ctx, op1, rt, rs, imm);
17694 break;
17695 case OPC_BSHFL:
17697 if (rd == 0) {
17698 /* Treat as NOP. */
17699 break;
17701 op2 = MASK_BSHFL(ctx->opcode);
17702 switch (op2) {
17703 case OPC_ALIGN ... OPC_ALIGN_END:
17704 gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3);
17705 break;
17706 case OPC_BITSWAP:
17707 gen_bitswap(ctx, op2, rd, rt);
17708 break;
17711 break;
17712 #if defined(TARGET_MIPS64)
17713 case R6_OPC_SCD:
17714 gen_st_cond(ctx, op1, rt, rs, imm);
17715 break;
17716 case R6_OPC_LLD:
17717 gen_ld(ctx, op1, rt, rs, imm);
17718 break;
17719 case OPC_DBSHFL:
17720 check_mips_64(ctx);
17722 if (rd == 0) {
17723 /* Treat as NOP. */
17724 break;
17726 op2 = MASK_DBSHFL(ctx->opcode);
17727 switch (op2) {
17728 case OPC_DALIGN ... OPC_DALIGN_END:
17729 gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7);
17730 break;
17731 case OPC_DBITSWAP:
17732 gen_bitswap(ctx, op2, rd, rt);
17733 break;
17737 break;
17738 #endif
17739 default: /* Invalid */
17740 MIPS_INVAL("special3_r6");
17741 generate_exception(ctx, EXCP_RI);
17742 break;
17746 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
17748 int rs, rt, rd;
17749 uint32_t op1, op2;
17751 rs = (ctx->opcode >> 21) & 0x1f;
17752 rt = (ctx->opcode >> 16) & 0x1f;
17753 rd = (ctx->opcode >> 11) & 0x1f;
17755 op1 = MASK_SPECIAL3(ctx->opcode);
17756 switch (op1) {
17757 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
17758 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
17759 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
17760 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
17761 * the same mask and op1. */
17762 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
17763 op2 = MASK_ADDUH_QB(ctx->opcode);
17764 switch (op2) {
17765 case OPC_ADDUH_QB:
17766 case OPC_ADDUH_R_QB:
17767 case OPC_ADDQH_PH:
17768 case OPC_ADDQH_R_PH:
17769 case OPC_ADDQH_W:
17770 case OPC_ADDQH_R_W:
17771 case OPC_SUBUH_QB:
17772 case OPC_SUBUH_R_QB:
17773 case OPC_SUBQH_PH:
17774 case OPC_SUBQH_R_PH:
17775 case OPC_SUBQH_W:
17776 case OPC_SUBQH_R_W:
17777 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17778 break;
17779 case OPC_MUL_PH:
17780 case OPC_MUL_S_PH:
17781 case OPC_MULQ_S_W:
17782 case OPC_MULQ_RS_W:
17783 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17784 break;
17785 default:
17786 MIPS_INVAL("MASK ADDUH.QB");
17787 generate_exception(ctx, EXCP_RI);
17788 break;
17790 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
17791 gen_loongson_integer(ctx, op1, rd, rs, rt);
17792 } else {
17793 generate_exception(ctx, EXCP_RI);
17795 break;
17796 case OPC_LX_DSP:
17797 op2 = MASK_LX(ctx->opcode);
17798 switch (op2) {
17799 #if defined(TARGET_MIPS64)
17800 case OPC_LDX:
17801 #endif
17802 case OPC_LBUX:
17803 case OPC_LHX:
17804 case OPC_LWX:
17805 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
17806 break;
17807 default: /* Invalid */
17808 MIPS_INVAL("MASK LX");
17809 generate_exception(ctx, EXCP_RI);
17810 break;
17812 break;
17813 case OPC_ABSQ_S_PH_DSP:
17814 op2 = MASK_ABSQ_S_PH(ctx->opcode);
17815 switch (op2) {
17816 case OPC_ABSQ_S_QB:
17817 case OPC_ABSQ_S_PH:
17818 case OPC_ABSQ_S_W:
17819 case OPC_PRECEQ_W_PHL:
17820 case OPC_PRECEQ_W_PHR:
17821 case OPC_PRECEQU_PH_QBL:
17822 case OPC_PRECEQU_PH_QBR:
17823 case OPC_PRECEQU_PH_QBLA:
17824 case OPC_PRECEQU_PH_QBRA:
17825 case OPC_PRECEU_PH_QBL:
17826 case OPC_PRECEU_PH_QBR:
17827 case OPC_PRECEU_PH_QBLA:
17828 case OPC_PRECEU_PH_QBRA:
17829 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17830 break;
17831 case OPC_BITREV:
17832 case OPC_REPL_QB:
17833 case OPC_REPLV_QB:
17834 case OPC_REPL_PH:
17835 case OPC_REPLV_PH:
17836 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17837 break;
17838 default:
17839 MIPS_INVAL("MASK ABSQ_S.PH");
17840 generate_exception(ctx, EXCP_RI);
17841 break;
17843 break;
17844 case OPC_ADDU_QB_DSP:
17845 op2 = MASK_ADDU_QB(ctx->opcode);
17846 switch (op2) {
17847 case OPC_ADDQ_PH:
17848 case OPC_ADDQ_S_PH:
17849 case OPC_ADDQ_S_W:
17850 case OPC_ADDU_QB:
17851 case OPC_ADDU_S_QB:
17852 case OPC_ADDU_PH:
17853 case OPC_ADDU_S_PH:
17854 case OPC_SUBQ_PH:
17855 case OPC_SUBQ_S_PH:
17856 case OPC_SUBQ_S_W:
17857 case OPC_SUBU_QB:
17858 case OPC_SUBU_S_QB:
17859 case OPC_SUBU_PH:
17860 case OPC_SUBU_S_PH:
17861 case OPC_ADDSC:
17862 case OPC_ADDWC:
17863 case OPC_MODSUB:
17864 case OPC_RADDU_W_QB:
17865 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17866 break;
17867 case OPC_MULEU_S_PH_QBL:
17868 case OPC_MULEU_S_PH_QBR:
17869 case OPC_MULQ_RS_PH:
17870 case OPC_MULEQ_S_W_PHL:
17871 case OPC_MULEQ_S_W_PHR:
17872 case OPC_MULQ_S_PH:
17873 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17874 break;
17875 default: /* Invalid */
17876 MIPS_INVAL("MASK ADDU.QB");
17877 generate_exception(ctx, EXCP_RI);
17878 break;
17881 break;
17882 case OPC_CMPU_EQ_QB_DSP:
17883 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
17884 switch (op2) {
17885 case OPC_PRECR_SRA_PH_W:
17886 case OPC_PRECR_SRA_R_PH_W:
17887 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17888 break;
17889 case OPC_PRECR_QB_PH:
17890 case OPC_PRECRQ_QB_PH:
17891 case OPC_PRECRQ_PH_W:
17892 case OPC_PRECRQ_RS_PH_W:
17893 case OPC_PRECRQU_S_QB_PH:
17894 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17895 break;
17896 case OPC_CMPU_EQ_QB:
17897 case OPC_CMPU_LT_QB:
17898 case OPC_CMPU_LE_QB:
17899 case OPC_CMP_EQ_PH:
17900 case OPC_CMP_LT_PH:
17901 case OPC_CMP_LE_PH:
17902 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17903 break;
17904 case OPC_CMPGU_EQ_QB:
17905 case OPC_CMPGU_LT_QB:
17906 case OPC_CMPGU_LE_QB:
17907 case OPC_CMPGDU_EQ_QB:
17908 case OPC_CMPGDU_LT_QB:
17909 case OPC_CMPGDU_LE_QB:
17910 case OPC_PICK_QB:
17911 case OPC_PICK_PH:
17912 case OPC_PACKRL_PH:
17913 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17914 break;
17915 default: /* Invalid */
17916 MIPS_INVAL("MASK CMPU.EQ.QB");
17917 generate_exception(ctx, EXCP_RI);
17918 break;
17920 break;
17921 case OPC_SHLL_QB_DSP:
17922 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17923 break;
17924 case OPC_DPA_W_PH_DSP:
17925 op2 = MASK_DPA_W_PH(ctx->opcode);
17926 switch (op2) {
17927 case OPC_DPAU_H_QBL:
17928 case OPC_DPAU_H_QBR:
17929 case OPC_DPSU_H_QBL:
17930 case OPC_DPSU_H_QBR:
17931 case OPC_DPA_W_PH:
17932 case OPC_DPAX_W_PH:
17933 case OPC_DPAQ_S_W_PH:
17934 case OPC_DPAQX_S_W_PH:
17935 case OPC_DPAQX_SA_W_PH:
17936 case OPC_DPS_W_PH:
17937 case OPC_DPSX_W_PH:
17938 case OPC_DPSQ_S_W_PH:
17939 case OPC_DPSQX_S_W_PH:
17940 case OPC_DPSQX_SA_W_PH:
17941 case OPC_MULSAQ_S_W_PH:
17942 case OPC_DPAQ_SA_L_W:
17943 case OPC_DPSQ_SA_L_W:
17944 case OPC_MAQ_S_W_PHL:
17945 case OPC_MAQ_S_W_PHR:
17946 case OPC_MAQ_SA_W_PHL:
17947 case OPC_MAQ_SA_W_PHR:
17948 case OPC_MULSA_W_PH:
17949 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17950 break;
17951 default: /* Invalid */
17952 MIPS_INVAL("MASK DPAW.PH");
17953 generate_exception(ctx, EXCP_RI);
17954 break;
17956 break;
17957 case OPC_INSV_DSP:
17958 op2 = MASK_INSV(ctx->opcode);
17959 switch (op2) {
17960 case OPC_INSV:
17961 check_dsp(ctx);
17963 TCGv t0, t1;
17965 if (rt == 0) {
17966 MIPS_DEBUG("NOP");
17967 break;
17970 t0 = tcg_temp_new();
17971 t1 = tcg_temp_new();
17973 gen_load_gpr(t0, rt);
17974 gen_load_gpr(t1, rs);
17976 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
17978 tcg_temp_free(t0);
17979 tcg_temp_free(t1);
17980 break;
17982 default: /* Invalid */
17983 MIPS_INVAL("MASK INSV");
17984 generate_exception(ctx, EXCP_RI);
17985 break;
17987 break;
17988 case OPC_APPEND_DSP:
17989 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17990 break;
17991 case OPC_EXTR_W_DSP:
17992 op2 = MASK_EXTR_W(ctx->opcode);
17993 switch (op2) {
17994 case OPC_EXTR_W:
17995 case OPC_EXTR_R_W:
17996 case OPC_EXTR_RS_W:
17997 case OPC_EXTR_S_H:
17998 case OPC_EXTRV_S_H:
17999 case OPC_EXTRV_W:
18000 case OPC_EXTRV_R_W:
18001 case OPC_EXTRV_RS_W:
18002 case OPC_EXTP:
18003 case OPC_EXTPV:
18004 case OPC_EXTPDP:
18005 case OPC_EXTPDPV:
18006 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
18007 break;
18008 case OPC_RDDSP:
18009 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
18010 break;
18011 case OPC_SHILO:
18012 case OPC_SHILOV:
18013 case OPC_MTHLIP:
18014 case OPC_WRDSP:
18015 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
18016 break;
18017 default: /* Invalid */
18018 MIPS_INVAL("MASK EXTR.W");
18019 generate_exception(ctx, EXCP_RI);
18020 break;
18022 break;
18023 #if defined(TARGET_MIPS64)
18024 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
18025 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
18026 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
18027 check_insn(ctx, INSN_LOONGSON2E);
18028 gen_loongson_integer(ctx, op1, rd, rs, rt);
18029 break;
18030 case OPC_ABSQ_S_QH_DSP:
18031 op2 = MASK_ABSQ_S_QH(ctx->opcode);
18032 switch (op2) {
18033 case OPC_PRECEQ_L_PWL:
18034 case OPC_PRECEQ_L_PWR:
18035 case OPC_PRECEQ_PW_QHL:
18036 case OPC_PRECEQ_PW_QHR:
18037 case OPC_PRECEQ_PW_QHLA:
18038 case OPC_PRECEQ_PW_QHRA:
18039 case OPC_PRECEQU_QH_OBL:
18040 case OPC_PRECEQU_QH_OBR:
18041 case OPC_PRECEQU_QH_OBLA:
18042 case OPC_PRECEQU_QH_OBRA:
18043 case OPC_PRECEU_QH_OBL:
18044 case OPC_PRECEU_QH_OBR:
18045 case OPC_PRECEU_QH_OBLA:
18046 case OPC_PRECEU_QH_OBRA:
18047 case OPC_ABSQ_S_OB:
18048 case OPC_ABSQ_S_PW:
18049 case OPC_ABSQ_S_QH:
18050 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18051 break;
18052 case OPC_REPL_OB:
18053 case OPC_REPL_PW:
18054 case OPC_REPL_QH:
18055 case OPC_REPLV_OB:
18056 case OPC_REPLV_PW:
18057 case OPC_REPLV_QH:
18058 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
18059 break;
18060 default: /* Invalid */
18061 MIPS_INVAL("MASK ABSQ_S.QH");
18062 generate_exception(ctx, EXCP_RI);
18063 break;
18065 break;
18066 case OPC_ADDU_OB_DSP:
18067 op2 = MASK_ADDU_OB(ctx->opcode);
18068 switch (op2) {
18069 case OPC_RADDU_L_OB:
18070 case OPC_SUBQ_PW:
18071 case OPC_SUBQ_S_PW:
18072 case OPC_SUBQ_QH:
18073 case OPC_SUBQ_S_QH:
18074 case OPC_SUBU_OB:
18075 case OPC_SUBU_S_OB:
18076 case OPC_SUBU_QH:
18077 case OPC_SUBU_S_QH:
18078 case OPC_SUBUH_OB:
18079 case OPC_SUBUH_R_OB:
18080 case OPC_ADDQ_PW:
18081 case OPC_ADDQ_S_PW:
18082 case OPC_ADDQ_QH:
18083 case OPC_ADDQ_S_QH:
18084 case OPC_ADDU_OB:
18085 case OPC_ADDU_S_OB:
18086 case OPC_ADDU_QH:
18087 case OPC_ADDU_S_QH:
18088 case OPC_ADDUH_OB:
18089 case OPC_ADDUH_R_OB:
18090 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18091 break;
18092 case OPC_MULEQ_S_PW_QHL:
18093 case OPC_MULEQ_S_PW_QHR:
18094 case OPC_MULEU_S_QH_OBL:
18095 case OPC_MULEU_S_QH_OBR:
18096 case OPC_MULQ_RS_QH:
18097 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
18098 break;
18099 default: /* Invalid */
18100 MIPS_INVAL("MASK ADDU.OB");
18101 generate_exception(ctx, EXCP_RI);
18102 break;
18104 break;
18105 case OPC_CMPU_EQ_OB_DSP:
18106 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
18107 switch (op2) {
18108 case OPC_PRECR_SRA_QH_PW:
18109 case OPC_PRECR_SRA_R_QH_PW:
18110 /* Return value is rt. */
18111 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
18112 break;
18113 case OPC_PRECR_OB_QH:
18114 case OPC_PRECRQ_OB_QH:
18115 case OPC_PRECRQ_PW_L:
18116 case OPC_PRECRQ_QH_PW:
18117 case OPC_PRECRQ_RS_QH_PW:
18118 case OPC_PRECRQU_S_OB_QH:
18119 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18120 break;
18121 case OPC_CMPU_EQ_OB:
18122 case OPC_CMPU_LT_OB:
18123 case OPC_CMPU_LE_OB:
18124 case OPC_CMP_EQ_QH:
18125 case OPC_CMP_LT_QH:
18126 case OPC_CMP_LE_QH:
18127 case OPC_CMP_EQ_PW:
18128 case OPC_CMP_LT_PW:
18129 case OPC_CMP_LE_PW:
18130 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
18131 break;
18132 case OPC_CMPGDU_EQ_OB:
18133 case OPC_CMPGDU_LT_OB:
18134 case OPC_CMPGDU_LE_OB:
18135 case OPC_CMPGU_EQ_OB:
18136 case OPC_CMPGU_LT_OB:
18137 case OPC_CMPGU_LE_OB:
18138 case OPC_PACKRL_PW:
18139 case OPC_PICK_OB:
18140 case OPC_PICK_PW:
18141 case OPC_PICK_QH:
18142 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
18143 break;
18144 default: /* Invalid */
18145 MIPS_INVAL("MASK CMPU_EQ.OB");
18146 generate_exception(ctx, EXCP_RI);
18147 break;
18149 break;
18150 case OPC_DAPPEND_DSP:
18151 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
18152 break;
18153 case OPC_DEXTR_W_DSP:
18154 op2 = MASK_DEXTR_W(ctx->opcode);
18155 switch (op2) {
18156 case OPC_DEXTP:
18157 case OPC_DEXTPDP:
18158 case OPC_DEXTPDPV:
18159 case OPC_DEXTPV:
18160 case OPC_DEXTR_L:
18161 case OPC_DEXTR_R_L:
18162 case OPC_DEXTR_RS_L:
18163 case OPC_DEXTR_W:
18164 case OPC_DEXTR_R_W:
18165 case OPC_DEXTR_RS_W:
18166 case OPC_DEXTR_S_H:
18167 case OPC_DEXTRV_L:
18168 case OPC_DEXTRV_R_L:
18169 case OPC_DEXTRV_RS_L:
18170 case OPC_DEXTRV_S_H:
18171 case OPC_DEXTRV_W:
18172 case OPC_DEXTRV_R_W:
18173 case OPC_DEXTRV_RS_W:
18174 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
18175 break;
18176 case OPC_DMTHLIP:
18177 case OPC_DSHILO:
18178 case OPC_DSHILOV:
18179 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
18180 break;
18181 default: /* Invalid */
18182 MIPS_INVAL("MASK EXTR.W");
18183 generate_exception(ctx, EXCP_RI);
18184 break;
18186 break;
18187 case OPC_DPAQ_W_QH_DSP:
18188 op2 = MASK_DPAQ_W_QH(ctx->opcode);
18189 switch (op2) {
18190 case OPC_DPAU_H_OBL:
18191 case OPC_DPAU_H_OBR:
18192 case OPC_DPSU_H_OBL:
18193 case OPC_DPSU_H_OBR:
18194 case OPC_DPA_W_QH:
18195 case OPC_DPAQ_S_W_QH:
18196 case OPC_DPS_W_QH:
18197 case OPC_DPSQ_S_W_QH:
18198 case OPC_MULSAQ_S_W_QH:
18199 case OPC_DPAQ_SA_L_PW:
18200 case OPC_DPSQ_SA_L_PW:
18201 case OPC_MULSAQ_S_L_PW:
18202 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
18203 break;
18204 case OPC_MAQ_S_W_QHLL:
18205 case OPC_MAQ_S_W_QHLR:
18206 case OPC_MAQ_S_W_QHRL:
18207 case OPC_MAQ_S_W_QHRR:
18208 case OPC_MAQ_SA_W_QHLL:
18209 case OPC_MAQ_SA_W_QHLR:
18210 case OPC_MAQ_SA_W_QHRL:
18211 case OPC_MAQ_SA_W_QHRR:
18212 case OPC_MAQ_S_L_PWL:
18213 case OPC_MAQ_S_L_PWR:
18214 case OPC_DMADD:
18215 case OPC_DMADDU:
18216 case OPC_DMSUB:
18217 case OPC_DMSUBU:
18218 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
18219 break;
18220 default: /* Invalid */
18221 MIPS_INVAL("MASK DPAQ.W.QH");
18222 generate_exception(ctx, EXCP_RI);
18223 break;
18225 break;
18226 case OPC_DINSV_DSP:
18227 op2 = MASK_INSV(ctx->opcode);
18228 switch (op2) {
18229 case OPC_DINSV:
18231 TCGv t0, t1;
18233 if (rt == 0) {
18234 MIPS_DEBUG("NOP");
18235 break;
18237 check_dsp(ctx);
18239 t0 = tcg_temp_new();
18240 t1 = tcg_temp_new();
18242 gen_load_gpr(t0, rt);
18243 gen_load_gpr(t1, rs);
18245 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
18247 tcg_temp_free(t0);
18248 tcg_temp_free(t1);
18249 break;
18251 default: /* Invalid */
18252 MIPS_INVAL("MASK DINSV");
18253 generate_exception(ctx, EXCP_RI);
18254 break;
18256 break;
18257 case OPC_SHLL_OB_DSP:
18258 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
18259 break;
18260 #endif
18261 default: /* Invalid */
18262 MIPS_INVAL("special3_legacy");
18263 generate_exception(ctx, EXCP_RI);
18264 break;
18268 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
18270 int rs, rt, rd, sa;
18271 uint32_t op1, op2;
18273 rs = (ctx->opcode >> 21) & 0x1f;
18274 rt = (ctx->opcode >> 16) & 0x1f;
18275 rd = (ctx->opcode >> 11) & 0x1f;
18276 sa = (ctx->opcode >> 6) & 0x1f;
18278 op1 = MASK_SPECIAL3(ctx->opcode);
18279 switch (op1) {
18280 case OPC_EXT:
18281 case OPC_INS:
18282 check_insn(ctx, ISA_MIPS32R2);
18283 gen_bitops(ctx, op1, rt, rs, sa, rd);
18284 break;
18285 case OPC_BSHFL:
18286 op2 = MASK_BSHFL(ctx->opcode);
18287 switch (op2) {
18288 case OPC_ALIGN ... OPC_ALIGN_END:
18289 case OPC_BITSWAP:
18290 check_insn(ctx, ISA_MIPS32R6);
18291 decode_opc_special3_r6(env, ctx);
18292 break;
18293 default:
18294 check_insn(ctx, ISA_MIPS32R2);
18295 gen_bshfl(ctx, op2, rt, rd);
18296 break;
18298 break;
18299 #if defined(TARGET_MIPS64)
18300 case OPC_DEXTM ... OPC_DEXT:
18301 case OPC_DINSM ... OPC_DINS:
18302 check_insn(ctx, ISA_MIPS64R2);
18303 check_mips_64(ctx);
18304 gen_bitops(ctx, op1, rt, rs, sa, rd);
18305 break;
18306 case OPC_DBSHFL:
18307 op2 = MASK_DBSHFL(ctx->opcode);
18308 switch (op2) {
18309 case OPC_DALIGN ... OPC_DALIGN_END:
18310 case OPC_DBITSWAP:
18311 check_insn(ctx, ISA_MIPS32R6);
18312 decode_opc_special3_r6(env, ctx);
18313 break;
18314 default:
18315 check_insn(ctx, ISA_MIPS64R2);
18316 check_mips_64(ctx);
18317 op2 = MASK_DBSHFL(ctx->opcode);
18318 gen_bshfl(ctx, op2, rt, rd);
18319 break;
18321 break;
18322 #endif
18323 case OPC_RDHWR:
18324 gen_rdhwr(ctx, rt, rd);
18325 break;
18326 case OPC_FORK:
18327 check_insn(ctx, ASE_MT);
18329 TCGv t0 = tcg_temp_new();
18330 TCGv t1 = tcg_temp_new();
18332 gen_load_gpr(t0, rt);
18333 gen_load_gpr(t1, rs);
18334 gen_helper_fork(t0, t1);
18335 tcg_temp_free(t0);
18336 tcg_temp_free(t1);
18338 break;
18339 case OPC_YIELD:
18340 check_insn(ctx, ASE_MT);
18342 TCGv t0 = tcg_temp_new();
18344 save_cpu_state(ctx, 1);
18345 gen_load_gpr(t0, rs);
18346 gen_helper_yield(t0, cpu_env, t0);
18347 gen_store_gpr(t0, rd);
18348 tcg_temp_free(t0);
18350 break;
18351 default:
18352 if (ctx->insn_flags & ISA_MIPS32R6) {
18353 decode_opc_special3_r6(env, ctx);
18354 } else {
18355 decode_opc_special3_legacy(env, ctx);
18360 /* MIPS SIMD Architecture (MSA) */
18361 static inline int check_msa_access(DisasContext *ctx)
18363 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
18364 !(ctx->hflags & MIPS_HFLAG_F64))) {
18365 generate_exception(ctx, EXCP_RI);
18366 return 0;
18369 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
18370 if (ctx->insn_flags & ASE_MSA) {
18371 generate_exception(ctx, EXCP_MSADIS);
18372 return 0;
18373 } else {
18374 generate_exception(ctx, EXCP_RI);
18375 return 0;
18378 return 1;
18381 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
18383 /* generates tcg ops to check if any element is 0 */
18384 /* Note this function only works with MSA_WRLEN = 128 */
18385 uint64_t eval_zero_or_big = 0;
18386 uint64_t eval_big = 0;
18387 TCGv_i64 t0 = tcg_temp_new_i64();
18388 TCGv_i64 t1 = tcg_temp_new_i64();
18389 switch (df) {
18390 case DF_BYTE:
18391 eval_zero_or_big = 0x0101010101010101ULL;
18392 eval_big = 0x8080808080808080ULL;
18393 break;
18394 case DF_HALF:
18395 eval_zero_or_big = 0x0001000100010001ULL;
18396 eval_big = 0x8000800080008000ULL;
18397 break;
18398 case DF_WORD:
18399 eval_zero_or_big = 0x0000000100000001ULL;
18400 eval_big = 0x8000000080000000ULL;
18401 break;
18402 case DF_DOUBLE:
18403 eval_zero_or_big = 0x0000000000000001ULL;
18404 eval_big = 0x8000000000000000ULL;
18405 break;
18407 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
18408 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
18409 tcg_gen_andi_i64(t0, t0, eval_big);
18410 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
18411 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
18412 tcg_gen_andi_i64(t1, t1, eval_big);
18413 tcg_gen_or_i64(t0, t0, t1);
18414 /* if all bits are zero then all elements are not zero */
18415 /* if some bit is non-zero then some element is zero */
18416 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
18417 tcg_gen_trunc_i64_tl(tresult, t0);
18418 tcg_temp_free_i64(t0);
18419 tcg_temp_free_i64(t1);
18422 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
18424 uint8_t df = (ctx->opcode >> 21) & 0x3;
18425 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18426 int64_t s16 = (int16_t)ctx->opcode;
18428 check_msa_access(ctx);
18430 if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
18431 MIPS_DEBUG("CTI in delay / forbidden slot");
18432 generate_exception(ctx, EXCP_RI);
18433 return;
18435 switch (op1) {
18436 case OPC_BZ_V:
18437 case OPC_BNZ_V:
18439 TCGv_i64 t0 = tcg_temp_new_i64();
18440 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
18441 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
18442 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
18443 tcg_gen_trunc_i64_tl(bcond, t0);
18444 tcg_temp_free_i64(t0);
18446 break;
18447 case OPC_BZ_B:
18448 case OPC_BZ_H:
18449 case OPC_BZ_W:
18450 case OPC_BZ_D:
18451 gen_check_zero_element(bcond, df, wt);
18452 break;
18453 case OPC_BNZ_B:
18454 case OPC_BNZ_H:
18455 case OPC_BNZ_W:
18456 case OPC_BNZ_D:
18457 gen_check_zero_element(bcond, df, wt);
18458 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
18459 break;
18462 ctx->btarget = ctx->pc + (s16 << 2) + 4;
18464 ctx->hflags |= MIPS_HFLAG_BC;
18465 ctx->hflags |= MIPS_HFLAG_BDS32;
18468 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
18470 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
18471 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
18472 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18473 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18475 TCGv_i32 twd = tcg_const_i32(wd);
18476 TCGv_i32 tws = tcg_const_i32(ws);
18477 TCGv_i32 ti8 = tcg_const_i32(i8);
18479 switch (MASK_MSA_I8(ctx->opcode)) {
18480 case OPC_ANDI_B:
18481 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
18482 break;
18483 case OPC_ORI_B:
18484 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
18485 break;
18486 case OPC_NORI_B:
18487 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
18488 break;
18489 case OPC_XORI_B:
18490 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
18491 break;
18492 case OPC_BMNZI_B:
18493 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
18494 break;
18495 case OPC_BMZI_B:
18496 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
18497 break;
18498 case OPC_BSELI_B:
18499 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
18500 break;
18501 case OPC_SHF_B:
18502 case OPC_SHF_H:
18503 case OPC_SHF_W:
18505 uint8_t df = (ctx->opcode >> 24) & 0x3;
18506 if (df == DF_DOUBLE) {
18507 generate_exception(ctx, EXCP_RI);
18508 } else {
18509 TCGv_i32 tdf = tcg_const_i32(df);
18510 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
18511 tcg_temp_free_i32(tdf);
18514 break;
18515 default:
18516 MIPS_INVAL("MSA instruction");
18517 generate_exception(ctx, EXCP_RI);
18518 break;
18521 tcg_temp_free_i32(twd);
18522 tcg_temp_free_i32(tws);
18523 tcg_temp_free_i32(ti8);
18526 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
18528 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18529 uint8_t df = (ctx->opcode >> 21) & 0x3;
18530 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
18531 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
18532 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18533 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18535 TCGv_i32 tdf = tcg_const_i32(df);
18536 TCGv_i32 twd = tcg_const_i32(wd);
18537 TCGv_i32 tws = tcg_const_i32(ws);
18538 TCGv_i32 timm = tcg_temp_new_i32();
18539 tcg_gen_movi_i32(timm, u5);
18541 switch (MASK_MSA_I5(ctx->opcode)) {
18542 case OPC_ADDVI_df:
18543 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
18544 break;
18545 case OPC_SUBVI_df:
18546 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
18547 break;
18548 case OPC_MAXI_S_df:
18549 tcg_gen_movi_i32(timm, s5);
18550 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
18551 break;
18552 case OPC_MAXI_U_df:
18553 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
18554 break;
18555 case OPC_MINI_S_df:
18556 tcg_gen_movi_i32(timm, s5);
18557 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
18558 break;
18559 case OPC_MINI_U_df:
18560 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
18561 break;
18562 case OPC_CEQI_df:
18563 tcg_gen_movi_i32(timm, s5);
18564 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
18565 break;
18566 case OPC_CLTI_S_df:
18567 tcg_gen_movi_i32(timm, s5);
18568 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
18569 break;
18570 case OPC_CLTI_U_df:
18571 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
18572 break;
18573 case OPC_CLEI_S_df:
18574 tcg_gen_movi_i32(timm, s5);
18575 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
18576 break;
18577 case OPC_CLEI_U_df:
18578 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
18579 break;
18580 case OPC_LDI_df:
18582 int32_t s10 = sextract32(ctx->opcode, 11, 10);
18583 tcg_gen_movi_i32(timm, s10);
18584 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
18586 break;
18587 default:
18588 MIPS_INVAL("MSA instruction");
18589 generate_exception(ctx, EXCP_RI);
18590 break;
18593 tcg_temp_free_i32(tdf);
18594 tcg_temp_free_i32(twd);
18595 tcg_temp_free_i32(tws);
18596 tcg_temp_free_i32(timm);
18599 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
18601 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18602 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
18603 uint32_t df = 0, m = 0;
18604 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18605 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18607 TCGv_i32 tdf;
18608 TCGv_i32 tm;
18609 TCGv_i32 twd;
18610 TCGv_i32 tws;
18612 if ((dfm & 0x40) == 0x00) {
18613 m = dfm & 0x3f;
18614 df = DF_DOUBLE;
18615 } else if ((dfm & 0x60) == 0x40) {
18616 m = dfm & 0x1f;
18617 df = DF_WORD;
18618 } else if ((dfm & 0x70) == 0x60) {
18619 m = dfm & 0x0f;
18620 df = DF_HALF;
18621 } else if ((dfm & 0x78) == 0x70) {
18622 m = dfm & 0x7;
18623 df = DF_BYTE;
18624 } else {
18625 generate_exception(ctx, EXCP_RI);
18626 return;
18629 tdf = tcg_const_i32(df);
18630 tm = tcg_const_i32(m);
18631 twd = tcg_const_i32(wd);
18632 tws = tcg_const_i32(ws);
18634 switch (MASK_MSA_BIT(ctx->opcode)) {
18635 case OPC_SLLI_df:
18636 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
18637 break;
18638 case OPC_SRAI_df:
18639 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
18640 break;
18641 case OPC_SRLI_df:
18642 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
18643 break;
18644 case OPC_BCLRI_df:
18645 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
18646 break;
18647 case OPC_BSETI_df:
18648 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
18649 break;
18650 case OPC_BNEGI_df:
18651 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
18652 break;
18653 case OPC_BINSLI_df:
18654 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
18655 break;
18656 case OPC_BINSRI_df:
18657 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
18658 break;
18659 case OPC_SAT_S_df:
18660 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
18661 break;
18662 case OPC_SAT_U_df:
18663 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
18664 break;
18665 case OPC_SRARI_df:
18666 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
18667 break;
18668 case OPC_SRLRI_df:
18669 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
18670 break;
18671 default:
18672 MIPS_INVAL("MSA instruction");
18673 generate_exception(ctx, EXCP_RI);
18674 break;
18677 tcg_temp_free_i32(tdf);
18678 tcg_temp_free_i32(tm);
18679 tcg_temp_free_i32(twd);
18680 tcg_temp_free_i32(tws);
18683 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
18685 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18686 uint8_t df = (ctx->opcode >> 21) & 0x3;
18687 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18688 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18689 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18691 TCGv_i32 tdf = tcg_const_i32(df);
18692 TCGv_i32 twd = tcg_const_i32(wd);
18693 TCGv_i32 tws = tcg_const_i32(ws);
18694 TCGv_i32 twt = tcg_const_i32(wt);
18696 switch (MASK_MSA_3R(ctx->opcode)) {
18697 case OPC_SLL_df:
18698 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
18699 break;
18700 case OPC_ADDV_df:
18701 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
18702 break;
18703 case OPC_CEQ_df:
18704 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
18705 break;
18706 case OPC_ADD_A_df:
18707 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
18708 break;
18709 case OPC_SUBS_S_df:
18710 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
18711 break;
18712 case OPC_MULV_df:
18713 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
18714 break;
18715 case OPC_SLD_df:
18716 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
18717 break;
18718 case OPC_VSHF_df:
18719 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
18720 break;
18721 case OPC_SRA_df:
18722 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
18723 break;
18724 case OPC_SUBV_df:
18725 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
18726 break;
18727 case OPC_ADDS_A_df:
18728 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
18729 break;
18730 case OPC_SUBS_U_df:
18731 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
18732 break;
18733 case OPC_MADDV_df:
18734 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
18735 break;
18736 case OPC_SPLAT_df:
18737 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
18738 break;
18739 case OPC_SRAR_df:
18740 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
18741 break;
18742 case OPC_SRL_df:
18743 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
18744 break;
18745 case OPC_MAX_S_df:
18746 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
18747 break;
18748 case OPC_CLT_S_df:
18749 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
18750 break;
18751 case OPC_ADDS_S_df:
18752 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
18753 break;
18754 case OPC_SUBSUS_U_df:
18755 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
18756 break;
18757 case OPC_MSUBV_df:
18758 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
18759 break;
18760 case OPC_PCKEV_df:
18761 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
18762 break;
18763 case OPC_SRLR_df:
18764 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
18765 break;
18766 case OPC_BCLR_df:
18767 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
18768 break;
18769 case OPC_MAX_U_df:
18770 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
18771 break;
18772 case OPC_CLT_U_df:
18773 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
18774 break;
18775 case OPC_ADDS_U_df:
18776 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
18777 break;
18778 case OPC_SUBSUU_S_df:
18779 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
18780 break;
18781 case OPC_PCKOD_df:
18782 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
18783 break;
18784 case OPC_BSET_df:
18785 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
18786 break;
18787 case OPC_MIN_S_df:
18788 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
18789 break;
18790 case OPC_CLE_S_df:
18791 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
18792 break;
18793 case OPC_AVE_S_df:
18794 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
18795 break;
18796 case OPC_ASUB_S_df:
18797 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
18798 break;
18799 case OPC_DIV_S_df:
18800 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
18801 break;
18802 case OPC_ILVL_df:
18803 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
18804 break;
18805 case OPC_BNEG_df:
18806 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
18807 break;
18808 case OPC_MIN_U_df:
18809 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
18810 break;
18811 case OPC_CLE_U_df:
18812 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
18813 break;
18814 case OPC_AVE_U_df:
18815 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
18816 break;
18817 case OPC_ASUB_U_df:
18818 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
18819 break;
18820 case OPC_DIV_U_df:
18821 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
18822 break;
18823 case OPC_ILVR_df:
18824 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
18825 break;
18826 case OPC_BINSL_df:
18827 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
18828 break;
18829 case OPC_MAX_A_df:
18830 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
18831 break;
18832 case OPC_AVER_S_df:
18833 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
18834 break;
18835 case OPC_MOD_S_df:
18836 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
18837 break;
18838 case OPC_ILVEV_df:
18839 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
18840 break;
18841 case OPC_BINSR_df:
18842 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
18843 break;
18844 case OPC_MIN_A_df:
18845 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
18846 break;
18847 case OPC_AVER_U_df:
18848 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
18849 break;
18850 case OPC_MOD_U_df:
18851 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
18852 break;
18853 case OPC_ILVOD_df:
18854 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
18855 break;
18857 case OPC_DOTP_S_df:
18858 case OPC_DOTP_U_df:
18859 case OPC_DPADD_S_df:
18860 case OPC_DPADD_U_df:
18861 case OPC_DPSUB_S_df:
18862 case OPC_HADD_S_df:
18863 case OPC_DPSUB_U_df:
18864 case OPC_HADD_U_df:
18865 case OPC_HSUB_S_df:
18866 case OPC_HSUB_U_df:
18867 if (df == DF_BYTE) {
18868 generate_exception(ctx, EXCP_RI);
18870 switch (MASK_MSA_3R(ctx->opcode)) {
18871 case OPC_DOTP_S_df:
18872 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
18873 break;
18874 case OPC_DOTP_U_df:
18875 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
18876 break;
18877 case OPC_DPADD_S_df:
18878 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
18879 break;
18880 case OPC_DPADD_U_df:
18881 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
18882 break;
18883 case OPC_DPSUB_S_df:
18884 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
18885 break;
18886 case OPC_HADD_S_df:
18887 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
18888 break;
18889 case OPC_DPSUB_U_df:
18890 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
18891 break;
18892 case OPC_HADD_U_df:
18893 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
18894 break;
18895 case OPC_HSUB_S_df:
18896 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
18897 break;
18898 case OPC_HSUB_U_df:
18899 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
18900 break;
18902 break;
18903 default:
18904 MIPS_INVAL("MSA instruction");
18905 generate_exception(ctx, EXCP_RI);
18906 break;
18908 tcg_temp_free_i32(twd);
18909 tcg_temp_free_i32(tws);
18910 tcg_temp_free_i32(twt);
18911 tcg_temp_free_i32(tdf);
18914 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
18916 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
18917 uint8_t source = (ctx->opcode >> 11) & 0x1f;
18918 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
18919 TCGv telm = tcg_temp_new();
18920 TCGv_i32 tsr = tcg_const_i32(source);
18921 TCGv_i32 tdt = tcg_const_i32(dest);
18923 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
18924 case OPC_CTCMSA:
18925 gen_load_gpr(telm, source);
18926 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
18927 break;
18928 case OPC_CFCMSA:
18929 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
18930 gen_store_gpr(telm, dest);
18931 break;
18932 case OPC_MOVE_V:
18933 gen_helper_msa_move_v(cpu_env, tdt, tsr);
18934 break;
18935 default:
18936 MIPS_INVAL("MSA instruction");
18937 generate_exception(ctx, EXCP_RI);
18938 break;
18941 tcg_temp_free(telm);
18942 tcg_temp_free_i32(tdt);
18943 tcg_temp_free_i32(tsr);
18946 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
18947 uint32_t n)
18949 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18950 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18951 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18953 TCGv_i32 tws = tcg_const_i32(ws);
18954 TCGv_i32 twd = tcg_const_i32(wd);
18955 TCGv_i32 tn = tcg_const_i32(n);
18956 TCGv_i32 tdf = tcg_const_i32(df);
18958 switch (MASK_MSA_ELM(ctx->opcode)) {
18959 case OPC_SLDI_df:
18960 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
18961 break;
18962 case OPC_SPLATI_df:
18963 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
18964 break;
18965 case OPC_INSVE_df:
18966 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
18967 break;
18968 case OPC_COPY_S_df:
18969 case OPC_COPY_U_df:
18970 case OPC_INSERT_df:
18971 #if !defined(TARGET_MIPS64)
18972 /* Double format valid only for MIPS64 */
18973 if (df == DF_DOUBLE) {
18974 generate_exception(ctx, EXCP_RI);
18975 break;
18977 #endif
18978 switch (MASK_MSA_ELM(ctx->opcode)) {
18979 case OPC_COPY_S_df:
18980 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
18981 break;
18982 case OPC_COPY_U_df:
18983 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
18984 break;
18985 case OPC_INSERT_df:
18986 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
18987 break;
18989 break;
18990 default:
18991 MIPS_INVAL("MSA instruction");
18992 generate_exception(ctx, EXCP_RI);
18994 tcg_temp_free_i32(twd);
18995 tcg_temp_free_i32(tws);
18996 tcg_temp_free_i32(tn);
18997 tcg_temp_free_i32(tdf);
19000 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
19002 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
19003 uint32_t df = 0, n = 0;
19005 if ((dfn & 0x30) == 0x00) {
19006 n = dfn & 0x0f;
19007 df = DF_BYTE;
19008 } else if ((dfn & 0x38) == 0x20) {
19009 n = dfn & 0x07;
19010 df = DF_HALF;
19011 } else if ((dfn & 0x3c) == 0x30) {
19012 n = dfn & 0x03;
19013 df = DF_WORD;
19014 } else if ((dfn & 0x3e) == 0x38) {
19015 n = dfn & 0x01;
19016 df = DF_DOUBLE;
19017 } else if (dfn == 0x3E) {
19018 /* CTCMSA, CFCMSA, MOVE.V */
19019 gen_msa_elm_3e(env, ctx);
19020 return;
19021 } else {
19022 generate_exception(ctx, EXCP_RI);
19023 return;
19026 gen_msa_elm_df(env, ctx, df, n);
19029 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
19031 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
19032 uint8_t df = (ctx->opcode >> 21) & 0x1;
19033 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19034 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19035 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19037 TCGv_i32 twd = tcg_const_i32(wd);
19038 TCGv_i32 tws = tcg_const_i32(ws);
19039 TCGv_i32 twt = tcg_const_i32(wt);
19040 TCGv_i32 tdf = tcg_temp_new_i32();
19042 /* adjust df value for floating-point instruction */
19043 tcg_gen_movi_i32(tdf, df + 2);
19045 switch (MASK_MSA_3RF(ctx->opcode)) {
19046 case OPC_FCAF_df:
19047 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
19048 break;
19049 case OPC_FADD_df:
19050 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
19051 break;
19052 case OPC_FCUN_df:
19053 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
19054 break;
19055 case OPC_FSUB_df:
19056 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
19057 break;
19058 case OPC_FCOR_df:
19059 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
19060 break;
19061 case OPC_FCEQ_df:
19062 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
19063 break;
19064 case OPC_FMUL_df:
19065 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
19066 break;
19067 case OPC_FCUNE_df:
19068 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
19069 break;
19070 case OPC_FCUEQ_df:
19071 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
19072 break;
19073 case OPC_FDIV_df:
19074 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
19075 break;
19076 case OPC_FCNE_df:
19077 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
19078 break;
19079 case OPC_FCLT_df:
19080 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
19081 break;
19082 case OPC_FMADD_df:
19083 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
19084 break;
19085 case OPC_MUL_Q_df:
19086 tcg_gen_movi_i32(tdf, df + 1);
19087 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
19088 break;
19089 case OPC_FCULT_df:
19090 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
19091 break;
19092 case OPC_FMSUB_df:
19093 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
19094 break;
19095 case OPC_MADD_Q_df:
19096 tcg_gen_movi_i32(tdf, df + 1);
19097 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
19098 break;
19099 case OPC_FCLE_df:
19100 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
19101 break;
19102 case OPC_MSUB_Q_df:
19103 tcg_gen_movi_i32(tdf, df + 1);
19104 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
19105 break;
19106 case OPC_FCULE_df:
19107 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
19108 break;
19109 case OPC_FEXP2_df:
19110 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
19111 break;
19112 case OPC_FSAF_df:
19113 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
19114 break;
19115 case OPC_FEXDO_df:
19116 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
19117 break;
19118 case OPC_FSUN_df:
19119 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
19120 break;
19121 case OPC_FSOR_df:
19122 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
19123 break;
19124 case OPC_FSEQ_df:
19125 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
19126 break;
19127 case OPC_FTQ_df:
19128 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
19129 break;
19130 case OPC_FSUNE_df:
19131 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
19132 break;
19133 case OPC_FSUEQ_df:
19134 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
19135 break;
19136 case OPC_FSNE_df:
19137 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
19138 break;
19139 case OPC_FSLT_df:
19140 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
19141 break;
19142 case OPC_FMIN_df:
19143 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
19144 break;
19145 case OPC_MULR_Q_df:
19146 tcg_gen_movi_i32(tdf, df + 1);
19147 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
19148 break;
19149 case OPC_FSULT_df:
19150 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
19151 break;
19152 case OPC_FMIN_A_df:
19153 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
19154 break;
19155 case OPC_MADDR_Q_df:
19156 tcg_gen_movi_i32(tdf, df + 1);
19157 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
19158 break;
19159 case OPC_FSLE_df:
19160 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
19161 break;
19162 case OPC_FMAX_df:
19163 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
19164 break;
19165 case OPC_MSUBR_Q_df:
19166 tcg_gen_movi_i32(tdf, df + 1);
19167 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
19168 break;
19169 case OPC_FSULE_df:
19170 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
19171 break;
19172 case OPC_FMAX_A_df:
19173 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
19174 break;
19175 default:
19176 MIPS_INVAL("MSA instruction");
19177 generate_exception(ctx, EXCP_RI);
19178 break;
19181 tcg_temp_free_i32(twd);
19182 tcg_temp_free_i32(tws);
19183 tcg_temp_free_i32(twt);
19184 tcg_temp_free_i32(tdf);
19187 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
19189 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
19190 (op & (0x7 << 18)))
19191 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19192 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19193 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19194 uint8_t df = (ctx->opcode >> 16) & 0x3;
19195 TCGv_i32 twd = tcg_const_i32(wd);
19196 TCGv_i32 tws = tcg_const_i32(ws);
19197 TCGv_i32 twt = tcg_const_i32(wt);
19198 TCGv_i32 tdf = tcg_const_i32(df);
19200 switch (MASK_MSA_2R(ctx->opcode)) {
19201 case OPC_FILL_df:
19202 #if !defined(TARGET_MIPS64)
19203 /* Double format valid only for MIPS64 */
19204 if (df == DF_DOUBLE) {
19205 generate_exception(ctx, EXCP_RI);
19206 break;
19208 #endif
19209 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
19210 break;
19211 case OPC_PCNT_df:
19212 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
19213 break;
19214 case OPC_NLOC_df:
19215 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
19216 break;
19217 case OPC_NLZC_df:
19218 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
19219 break;
19220 default:
19221 MIPS_INVAL("MSA instruction");
19222 generate_exception(ctx, EXCP_RI);
19223 break;
19226 tcg_temp_free_i32(twd);
19227 tcg_temp_free_i32(tws);
19228 tcg_temp_free_i32(twt);
19229 tcg_temp_free_i32(tdf);
19232 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
19234 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
19235 (op & (0xf << 17)))
19236 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19237 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19238 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19239 uint8_t df = (ctx->opcode >> 16) & 0x1;
19240 TCGv_i32 twd = tcg_const_i32(wd);
19241 TCGv_i32 tws = tcg_const_i32(ws);
19242 TCGv_i32 twt = tcg_const_i32(wt);
19243 /* adjust df value for floating-point instruction */
19244 TCGv_i32 tdf = tcg_const_i32(df + 2);
19246 switch (MASK_MSA_2RF(ctx->opcode)) {
19247 case OPC_FCLASS_df:
19248 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
19249 break;
19250 case OPC_FTRUNC_S_df:
19251 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
19252 break;
19253 case OPC_FTRUNC_U_df:
19254 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
19255 break;
19256 case OPC_FSQRT_df:
19257 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
19258 break;
19259 case OPC_FRSQRT_df:
19260 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
19261 break;
19262 case OPC_FRCP_df:
19263 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
19264 break;
19265 case OPC_FRINT_df:
19266 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
19267 break;
19268 case OPC_FLOG2_df:
19269 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
19270 break;
19271 case OPC_FEXUPL_df:
19272 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
19273 break;
19274 case OPC_FEXUPR_df:
19275 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
19276 break;
19277 case OPC_FFQL_df:
19278 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
19279 break;
19280 case OPC_FFQR_df:
19281 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
19282 break;
19283 case OPC_FTINT_S_df:
19284 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
19285 break;
19286 case OPC_FTINT_U_df:
19287 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
19288 break;
19289 case OPC_FFINT_S_df:
19290 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
19291 break;
19292 case OPC_FFINT_U_df:
19293 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
19294 break;
19297 tcg_temp_free_i32(twd);
19298 tcg_temp_free_i32(tws);
19299 tcg_temp_free_i32(twt);
19300 tcg_temp_free_i32(tdf);
19303 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
19305 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
19306 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19307 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19308 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19309 TCGv_i32 twd = tcg_const_i32(wd);
19310 TCGv_i32 tws = tcg_const_i32(ws);
19311 TCGv_i32 twt = tcg_const_i32(wt);
19313 switch (MASK_MSA_VEC(ctx->opcode)) {
19314 case OPC_AND_V:
19315 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
19316 break;
19317 case OPC_OR_V:
19318 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
19319 break;
19320 case OPC_NOR_V:
19321 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
19322 break;
19323 case OPC_XOR_V:
19324 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
19325 break;
19326 case OPC_BMNZ_V:
19327 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
19328 break;
19329 case OPC_BMZ_V:
19330 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
19331 break;
19332 case OPC_BSEL_V:
19333 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
19334 break;
19335 default:
19336 MIPS_INVAL("MSA instruction");
19337 generate_exception(ctx, EXCP_RI);
19338 break;
19341 tcg_temp_free_i32(twd);
19342 tcg_temp_free_i32(tws);
19343 tcg_temp_free_i32(twt);
19346 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
19348 switch (MASK_MSA_VEC(ctx->opcode)) {
19349 case OPC_AND_V:
19350 case OPC_OR_V:
19351 case OPC_NOR_V:
19352 case OPC_XOR_V:
19353 case OPC_BMNZ_V:
19354 case OPC_BMZ_V:
19355 case OPC_BSEL_V:
19356 gen_msa_vec_v(env, ctx);
19357 break;
19358 case OPC_MSA_2R:
19359 gen_msa_2r(env, ctx);
19360 break;
19361 case OPC_MSA_2RF:
19362 gen_msa_2rf(env, ctx);
19363 break;
19364 default:
19365 MIPS_INVAL("MSA instruction");
19366 generate_exception(ctx, EXCP_RI);
19367 break;
19371 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
19373 uint32_t opcode = ctx->opcode;
19374 check_insn(ctx, ASE_MSA);
19375 check_msa_access(ctx);
19377 switch (MASK_MSA_MINOR(opcode)) {
19378 case OPC_MSA_I8_00:
19379 case OPC_MSA_I8_01:
19380 case OPC_MSA_I8_02:
19381 gen_msa_i8(env, ctx);
19382 break;
19383 case OPC_MSA_I5_06:
19384 case OPC_MSA_I5_07:
19385 gen_msa_i5(env, ctx);
19386 break;
19387 case OPC_MSA_BIT_09:
19388 case OPC_MSA_BIT_0A:
19389 gen_msa_bit(env, ctx);
19390 break;
19391 case OPC_MSA_3R_0D:
19392 case OPC_MSA_3R_0E:
19393 case OPC_MSA_3R_0F:
19394 case OPC_MSA_3R_10:
19395 case OPC_MSA_3R_11:
19396 case OPC_MSA_3R_12:
19397 case OPC_MSA_3R_13:
19398 case OPC_MSA_3R_14:
19399 case OPC_MSA_3R_15:
19400 gen_msa_3r(env, ctx);
19401 break;
19402 case OPC_MSA_ELM:
19403 gen_msa_elm(env, ctx);
19404 break;
19405 case OPC_MSA_3RF_1A:
19406 case OPC_MSA_3RF_1B:
19407 case OPC_MSA_3RF_1C:
19408 gen_msa_3rf(env, ctx);
19409 break;
19410 case OPC_MSA_VEC:
19411 gen_msa_vec(env, ctx);
19412 break;
19413 case OPC_LD_B:
19414 case OPC_LD_H:
19415 case OPC_LD_W:
19416 case OPC_LD_D:
19417 case OPC_ST_B:
19418 case OPC_ST_H:
19419 case OPC_ST_W:
19420 case OPC_ST_D:
19422 int32_t s10 = sextract32(ctx->opcode, 16, 10);
19423 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
19424 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19425 uint8_t df = (ctx->opcode >> 0) & 0x3;
19427 TCGv_i32 twd = tcg_const_i32(wd);
19428 TCGv taddr = tcg_temp_new();
19429 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
19431 switch (MASK_MSA_MINOR(opcode)) {
19432 case OPC_LD_B:
19433 gen_helper_msa_ld_b(cpu_env, twd, taddr);
19434 break;
19435 case OPC_LD_H:
19436 gen_helper_msa_ld_h(cpu_env, twd, taddr);
19437 break;
19438 case OPC_LD_W:
19439 gen_helper_msa_ld_w(cpu_env, twd, taddr);
19440 break;
19441 case OPC_LD_D:
19442 gen_helper_msa_ld_d(cpu_env, twd, taddr);
19443 break;
19444 case OPC_ST_B:
19445 gen_helper_msa_st_b(cpu_env, twd, taddr);
19446 break;
19447 case OPC_ST_H:
19448 gen_helper_msa_st_h(cpu_env, twd, taddr);
19449 break;
19450 case OPC_ST_W:
19451 gen_helper_msa_st_w(cpu_env, twd, taddr);
19452 break;
19453 case OPC_ST_D:
19454 gen_helper_msa_st_d(cpu_env, twd, taddr);
19455 break;
19458 tcg_temp_free_i32(twd);
19459 tcg_temp_free(taddr);
19461 break;
19462 default:
19463 MIPS_INVAL("MSA instruction");
19464 generate_exception(ctx, EXCP_RI);
19465 break;
19470 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
19472 int32_t offset;
19473 int rs, rt, rd, sa;
19474 uint32_t op, op1;
19475 int16_t imm;
19477 /* make sure instructions are on a word boundary */
19478 if (ctx->pc & 0x3) {
19479 env->CP0_BadVAddr = ctx->pc;
19480 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
19481 ctx->bstate = BS_STOP;
19482 return;
19485 /* Handle blikely not taken case */
19486 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
19487 TCGLabel *l1 = gen_new_label();
19489 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
19490 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
19491 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
19492 gen_goto_tb(ctx, 1, ctx->pc + 4);
19493 gen_set_label(l1);
19496 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
19497 tcg_gen_debug_insn_start(ctx->pc);
19500 op = MASK_OP_MAJOR(ctx->opcode);
19501 rs = (ctx->opcode >> 21) & 0x1f;
19502 rt = (ctx->opcode >> 16) & 0x1f;
19503 rd = (ctx->opcode >> 11) & 0x1f;
19504 sa = (ctx->opcode >> 6) & 0x1f;
19505 imm = (int16_t)ctx->opcode;
19506 switch (op) {
19507 case OPC_SPECIAL:
19508 decode_opc_special(env, ctx);
19509 break;
19510 case OPC_SPECIAL2:
19511 decode_opc_special2_legacy(env, ctx);
19512 break;
19513 case OPC_SPECIAL3:
19514 decode_opc_special3(env, ctx);
19515 break;
19516 case OPC_REGIMM:
19517 op1 = MASK_REGIMM(ctx->opcode);
19518 switch (op1) {
19519 case OPC_BLTZL: /* REGIMM branches */
19520 case OPC_BGEZL:
19521 case OPC_BLTZALL:
19522 case OPC_BGEZALL:
19523 check_insn(ctx, ISA_MIPS2);
19524 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19525 /* Fallthrough */
19526 case OPC_BLTZ:
19527 case OPC_BGEZ:
19528 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19529 break;
19530 case OPC_BLTZAL:
19531 case OPC_BGEZAL:
19532 if (ctx->insn_flags & ISA_MIPS32R6) {
19533 if (rs == 0) {
19534 /* OPC_NAL, OPC_BAL */
19535 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
19536 } else {
19537 generate_exception(ctx, EXCP_RI);
19539 } else {
19540 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19542 break;
19543 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
19544 case OPC_TNEI:
19545 check_insn(ctx, ISA_MIPS2);
19546 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19547 gen_trap(ctx, op1, rs, -1, imm);
19548 break;
19549 case OPC_SYNCI:
19550 check_insn(ctx, ISA_MIPS32R2);
19551 /* Break the TB to be able to sync copied instructions
19552 immediately */
19553 ctx->bstate = BS_STOP;
19554 break;
19555 case OPC_BPOSGE32: /* MIPS DSP branch */
19556 #if defined(TARGET_MIPS64)
19557 case OPC_BPOSGE64:
19558 #endif
19559 check_dsp(ctx);
19560 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
19561 break;
19562 #if defined(TARGET_MIPS64)
19563 case OPC_DAHI:
19564 check_insn(ctx, ISA_MIPS32R6);
19565 check_mips_64(ctx);
19566 if (rs != 0) {
19567 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
19569 MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm);
19570 break;
19571 case OPC_DATI:
19572 check_insn(ctx, ISA_MIPS32R6);
19573 check_mips_64(ctx);
19574 if (rs != 0) {
19575 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
19577 MIPS_DEBUG("dati %s, %04x", regnames[rs], imm);
19578 break;
19579 #endif
19580 default: /* Invalid */
19581 MIPS_INVAL("regimm");
19582 generate_exception(ctx, EXCP_RI);
19583 break;
19585 break;
19586 case OPC_CP0:
19587 check_cp0_enabled(ctx);
19588 op1 = MASK_CP0(ctx->opcode);
19589 switch (op1) {
19590 case OPC_MFC0:
19591 case OPC_MTC0:
19592 case OPC_MFTR:
19593 case OPC_MTTR:
19594 case OPC_MFHC0:
19595 case OPC_MTHC0:
19596 #if defined(TARGET_MIPS64)
19597 case OPC_DMFC0:
19598 case OPC_DMTC0:
19599 #endif
19600 #ifndef CONFIG_USER_ONLY
19601 gen_cp0(env, ctx, op1, rt, rd);
19602 #endif /* !CONFIG_USER_ONLY */
19603 break;
19604 case OPC_C0_FIRST ... OPC_C0_LAST:
19605 #ifndef CONFIG_USER_ONLY
19606 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
19607 #endif /* !CONFIG_USER_ONLY */
19608 break;
19609 case OPC_MFMC0:
19610 #ifndef CONFIG_USER_ONLY
19612 uint32_t op2;
19613 TCGv t0 = tcg_temp_new();
19615 op2 = MASK_MFMC0(ctx->opcode);
19616 switch (op2) {
19617 case OPC_DMT:
19618 check_insn(ctx, ASE_MT);
19619 gen_helper_dmt(t0);
19620 gen_store_gpr(t0, rt);
19621 break;
19622 case OPC_EMT:
19623 check_insn(ctx, ASE_MT);
19624 gen_helper_emt(t0);
19625 gen_store_gpr(t0, rt);
19626 break;
19627 case OPC_DVPE:
19628 check_insn(ctx, ASE_MT);
19629 gen_helper_dvpe(t0, cpu_env);
19630 gen_store_gpr(t0, rt);
19631 break;
19632 case OPC_EVPE:
19633 check_insn(ctx, ASE_MT);
19634 gen_helper_evpe(t0, cpu_env);
19635 gen_store_gpr(t0, rt);
19636 break;
19637 case OPC_DI:
19638 check_insn(ctx, ISA_MIPS32R2);
19639 save_cpu_state(ctx, 1);
19640 gen_helper_di(t0, cpu_env);
19641 gen_store_gpr(t0, rt);
19642 /* Stop translation as we may have switched
19643 the execution mode. */
19644 ctx->bstate = BS_STOP;
19645 break;
19646 case OPC_EI:
19647 check_insn(ctx, ISA_MIPS32R2);
19648 save_cpu_state(ctx, 1);
19649 gen_helper_ei(t0, cpu_env);
19650 gen_store_gpr(t0, rt);
19651 /* Stop translation as we may have switched
19652 the execution mode. */
19653 ctx->bstate = BS_STOP;
19654 break;
19655 default: /* Invalid */
19656 MIPS_INVAL("mfmc0");
19657 generate_exception(ctx, EXCP_RI);
19658 break;
19660 tcg_temp_free(t0);
19662 #endif /* !CONFIG_USER_ONLY */
19663 break;
19664 case OPC_RDPGPR:
19665 check_insn(ctx, ISA_MIPS32R2);
19666 gen_load_srsgpr(rt, rd);
19667 break;
19668 case OPC_WRPGPR:
19669 check_insn(ctx, ISA_MIPS32R2);
19670 gen_store_srsgpr(rt, rd);
19671 break;
19672 default:
19673 MIPS_INVAL("cp0");
19674 generate_exception(ctx, EXCP_RI);
19675 break;
19677 break;
19678 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
19679 if (ctx->insn_flags & ISA_MIPS32R6) {
19680 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
19681 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19682 } else {
19683 /* OPC_ADDI */
19684 /* Arithmetic with immediate opcode */
19685 gen_arith_imm(ctx, op, rt, rs, imm);
19687 break;
19688 case OPC_ADDIU:
19689 gen_arith_imm(ctx, op, rt, rs, imm);
19690 break;
19691 case OPC_SLTI: /* Set on less than with immediate opcode */
19692 case OPC_SLTIU:
19693 gen_slt_imm(ctx, op, rt, rs, imm);
19694 break;
19695 case OPC_ANDI: /* Arithmetic with immediate opcode */
19696 case OPC_LUI: /* OPC_AUI */
19697 case OPC_ORI:
19698 case OPC_XORI:
19699 gen_logic_imm(ctx, op, rt, rs, imm);
19700 break;
19701 case OPC_J ... OPC_JAL: /* Jump */
19702 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19703 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19704 break;
19705 /* Branch */
19706 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
19707 if (ctx->insn_flags & ISA_MIPS32R6) {
19708 if (rt == 0) {
19709 generate_exception(ctx, EXCP_RI);
19710 break;
19712 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
19713 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19714 } else {
19715 /* OPC_BLEZL */
19716 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19718 break;
19719 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
19720 if (ctx->insn_flags & ISA_MIPS32R6) {
19721 if (rt == 0) {
19722 generate_exception(ctx, EXCP_RI);
19723 break;
19725 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
19726 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19727 } else {
19728 /* OPC_BGTZL */
19729 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19731 break;
19732 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
19733 if (rt == 0) {
19734 /* OPC_BLEZ */
19735 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19736 } else {
19737 check_insn(ctx, ISA_MIPS32R6);
19738 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
19739 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19741 break;
19742 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
19743 if (rt == 0) {
19744 /* OPC_BGTZ */
19745 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19746 } else {
19747 check_insn(ctx, ISA_MIPS32R6);
19748 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
19749 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19751 break;
19752 case OPC_BEQL:
19753 case OPC_BNEL:
19754 check_insn(ctx, ISA_MIPS2);
19755 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19756 /* Fallthrough */
19757 case OPC_BEQ:
19758 case OPC_BNE:
19759 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19760 break;
19761 case OPC_LL: /* Load and stores */
19762 check_insn(ctx, ISA_MIPS2);
19763 /* Fallthrough */
19764 case OPC_LWL:
19765 case OPC_LWR:
19766 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19767 /* Fallthrough */
19768 case OPC_LB ... OPC_LH:
19769 case OPC_LW ... OPC_LHU:
19770 gen_ld(ctx, op, rt, rs, imm);
19771 break;
19772 case OPC_SWL:
19773 case OPC_SWR:
19774 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19775 /* fall through */
19776 case OPC_SB ... OPC_SH:
19777 case OPC_SW:
19778 gen_st(ctx, op, rt, rs, imm);
19779 break;
19780 case OPC_SC:
19781 check_insn(ctx, ISA_MIPS2);
19782 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19783 gen_st_cond(ctx, op, rt, rs, imm);
19784 break;
19785 case OPC_CACHE:
19786 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19787 check_cp0_enabled(ctx);
19788 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
19789 /* Treat as NOP. */
19790 break;
19791 case OPC_PREF:
19792 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19793 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
19794 /* Treat as NOP. */
19795 break;
19797 /* Floating point (COP1). */
19798 case OPC_LWC1:
19799 case OPC_LDC1:
19800 case OPC_SWC1:
19801 case OPC_SDC1:
19802 gen_cop1_ldst(ctx, op, rt, rs, imm);
19803 break;
19805 case OPC_CP1:
19806 op1 = MASK_CP1(ctx->opcode);
19808 switch (op1) {
19809 case OPC_MFHC1:
19810 case OPC_MTHC1:
19811 check_cp1_enabled(ctx);
19812 check_insn(ctx, ISA_MIPS32R2);
19813 case OPC_MFC1:
19814 case OPC_CFC1:
19815 case OPC_MTC1:
19816 case OPC_CTC1:
19817 check_cp1_enabled(ctx);
19818 gen_cp1(ctx, op1, rt, rd);
19819 break;
19820 #if defined(TARGET_MIPS64)
19821 case OPC_DMFC1:
19822 case OPC_DMTC1:
19823 check_cp1_enabled(ctx);
19824 check_insn(ctx, ISA_MIPS3);
19825 check_mips_64(ctx);
19826 gen_cp1(ctx, op1, rt, rd);
19827 break;
19828 #endif
19829 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
19830 check_cp1_enabled(ctx);
19831 if (ctx->insn_flags & ISA_MIPS32R6) {
19832 /* OPC_BC1EQZ */
19833 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19834 rt, imm << 2, 4);
19835 } else {
19836 /* OPC_BC1ANY2 */
19837 check_cop1x(ctx);
19838 check_insn(ctx, ASE_MIPS3D);
19839 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19840 (rt >> 2) & 0x7, imm << 2);
19842 break;
19843 case OPC_BC1NEZ:
19844 check_cp1_enabled(ctx);
19845 check_insn(ctx, ISA_MIPS32R6);
19846 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19847 rt, imm << 2, 4);
19848 break;
19849 case OPC_BC1ANY4:
19850 check_cp1_enabled(ctx);
19851 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19852 check_cop1x(ctx);
19853 check_insn(ctx, ASE_MIPS3D);
19854 /* fall through */
19855 case OPC_BC1:
19856 check_cp1_enabled(ctx);
19857 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19858 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19859 (rt >> 2) & 0x7, imm << 2);
19860 break;
19861 case OPC_PS_FMT:
19862 check_ps(ctx);
19863 /* fall through */
19864 case OPC_S_FMT:
19865 case OPC_D_FMT:
19866 check_cp1_enabled(ctx);
19867 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19868 (imm >> 8) & 0x7);
19869 break;
19870 case OPC_W_FMT:
19871 case OPC_L_FMT:
19873 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
19874 check_cp1_enabled(ctx);
19875 if (ctx->insn_flags & ISA_MIPS32R6) {
19876 switch (r6_op) {
19877 case R6_OPC_CMP_AF_S:
19878 case R6_OPC_CMP_UN_S:
19879 case R6_OPC_CMP_EQ_S:
19880 case R6_OPC_CMP_UEQ_S:
19881 case R6_OPC_CMP_LT_S:
19882 case R6_OPC_CMP_ULT_S:
19883 case R6_OPC_CMP_LE_S:
19884 case R6_OPC_CMP_ULE_S:
19885 case R6_OPC_CMP_SAF_S:
19886 case R6_OPC_CMP_SUN_S:
19887 case R6_OPC_CMP_SEQ_S:
19888 case R6_OPC_CMP_SEUQ_S:
19889 case R6_OPC_CMP_SLT_S:
19890 case R6_OPC_CMP_SULT_S:
19891 case R6_OPC_CMP_SLE_S:
19892 case R6_OPC_CMP_SULE_S:
19893 case R6_OPC_CMP_OR_S:
19894 case R6_OPC_CMP_UNE_S:
19895 case R6_OPC_CMP_NE_S:
19896 case R6_OPC_CMP_SOR_S:
19897 case R6_OPC_CMP_SUNE_S:
19898 case R6_OPC_CMP_SNE_S:
19899 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19900 break;
19901 case R6_OPC_CMP_AF_D:
19902 case R6_OPC_CMP_UN_D:
19903 case R6_OPC_CMP_EQ_D:
19904 case R6_OPC_CMP_UEQ_D:
19905 case R6_OPC_CMP_LT_D:
19906 case R6_OPC_CMP_ULT_D:
19907 case R6_OPC_CMP_LE_D:
19908 case R6_OPC_CMP_ULE_D:
19909 case R6_OPC_CMP_SAF_D:
19910 case R6_OPC_CMP_SUN_D:
19911 case R6_OPC_CMP_SEQ_D:
19912 case R6_OPC_CMP_SEUQ_D:
19913 case R6_OPC_CMP_SLT_D:
19914 case R6_OPC_CMP_SULT_D:
19915 case R6_OPC_CMP_SLE_D:
19916 case R6_OPC_CMP_SULE_D:
19917 case R6_OPC_CMP_OR_D:
19918 case R6_OPC_CMP_UNE_D:
19919 case R6_OPC_CMP_NE_D:
19920 case R6_OPC_CMP_SOR_D:
19921 case R6_OPC_CMP_SUNE_D:
19922 case R6_OPC_CMP_SNE_D:
19923 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19924 break;
19925 default:
19926 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
19927 rt, rd, sa, (imm >> 8) & 0x7);
19929 break;
19931 } else {
19932 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19933 (imm >> 8) & 0x7);
19935 break;
19937 case OPC_BZ_V:
19938 case OPC_BNZ_V:
19939 case OPC_BZ_B:
19940 case OPC_BZ_H:
19941 case OPC_BZ_W:
19942 case OPC_BZ_D:
19943 case OPC_BNZ_B:
19944 case OPC_BNZ_H:
19945 case OPC_BNZ_W:
19946 case OPC_BNZ_D:
19947 check_insn(ctx, ASE_MSA);
19948 gen_msa_branch(env, ctx, op1);
19949 break;
19950 default:
19951 MIPS_INVAL("cp1");
19952 generate_exception(ctx, EXCP_RI);
19953 break;
19955 break;
19957 /* Compact branches [R6] and COP2 [non-R6] */
19958 case OPC_BC: /* OPC_LWC2 */
19959 case OPC_BALC: /* OPC_SWC2 */
19960 if (ctx->insn_flags & ISA_MIPS32R6) {
19961 /* OPC_BC, OPC_BALC */
19962 gen_compute_compact_branch(ctx, op, 0, 0,
19963 sextract32(ctx->opcode << 2, 0, 28));
19964 } else {
19965 /* OPC_LWC2, OPC_SWC2 */
19966 /* COP2: Not implemented. */
19967 generate_exception_err(ctx, EXCP_CpU, 2);
19969 break;
19970 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
19971 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
19972 if (ctx->insn_flags & ISA_MIPS32R6) {
19973 if (rs != 0) {
19974 /* OPC_BEQZC, OPC_BNEZC */
19975 gen_compute_compact_branch(ctx, op, rs, 0,
19976 sextract32(ctx->opcode << 2, 0, 23));
19977 } else {
19978 /* OPC_JIC, OPC_JIALC */
19979 gen_compute_compact_branch(ctx, op, 0, rt, imm);
19981 } else {
19982 /* OPC_LWC2, OPC_SWC2 */
19983 /* COP2: Not implemented. */
19984 generate_exception_err(ctx, EXCP_CpU, 2);
19986 break;
19987 case OPC_CP2:
19988 check_insn(ctx, INSN_LOONGSON2F);
19989 /* Note that these instructions use different fields. */
19990 gen_loongson_multimedia(ctx, sa, rd, rt);
19991 break;
19993 case OPC_CP3:
19994 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19995 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19996 check_cp1_enabled(ctx);
19997 op1 = MASK_CP3(ctx->opcode);
19998 switch (op1) {
19999 case OPC_LUXC1:
20000 case OPC_SUXC1:
20001 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
20002 /* Fallthrough */
20003 case OPC_LWXC1:
20004 case OPC_LDXC1:
20005 case OPC_SWXC1:
20006 case OPC_SDXC1:
20007 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20008 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
20009 break;
20010 case OPC_PREFX:
20011 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20012 /* Treat as NOP. */
20013 break;
20014 case OPC_ALNV_PS:
20015 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
20016 /* Fallthrough */
20017 case OPC_MADD_S:
20018 case OPC_MADD_D:
20019 case OPC_MADD_PS:
20020 case OPC_MSUB_S:
20021 case OPC_MSUB_D:
20022 case OPC_MSUB_PS:
20023 case OPC_NMADD_S:
20024 case OPC_NMADD_D:
20025 case OPC_NMADD_PS:
20026 case OPC_NMSUB_S:
20027 case OPC_NMSUB_D:
20028 case OPC_NMSUB_PS:
20029 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20030 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
20031 break;
20032 default:
20033 MIPS_INVAL("cp3");
20034 generate_exception (ctx, EXCP_RI);
20035 break;
20037 } else {
20038 generate_exception_err(ctx, EXCP_CpU, 1);
20040 break;
20042 #if defined(TARGET_MIPS64)
20043 /* MIPS64 opcodes */
20044 case OPC_LDL ... OPC_LDR:
20045 case OPC_LLD:
20046 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20047 /* fall through */
20048 case OPC_LWU:
20049 case OPC_LD:
20050 check_insn(ctx, ISA_MIPS3);
20051 check_mips_64(ctx);
20052 gen_ld(ctx, op, rt, rs, imm);
20053 break;
20054 case OPC_SDL ... OPC_SDR:
20055 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20056 /* fall through */
20057 case OPC_SD:
20058 check_insn(ctx, ISA_MIPS3);
20059 check_mips_64(ctx);
20060 gen_st(ctx, op, rt, rs, imm);
20061 break;
20062 case OPC_SCD:
20063 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20064 check_insn(ctx, ISA_MIPS3);
20065 check_mips_64(ctx);
20066 gen_st_cond(ctx, op, rt, rs, imm);
20067 break;
20068 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
20069 if (ctx->insn_flags & ISA_MIPS32R6) {
20070 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
20071 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
20072 } else {
20073 /* OPC_DADDI */
20074 check_insn(ctx, ISA_MIPS3);
20075 check_mips_64(ctx);
20076 gen_arith_imm(ctx, op, rt, rs, imm);
20078 break;
20079 case OPC_DADDIU:
20080 check_insn(ctx, ISA_MIPS3);
20081 check_mips_64(ctx);
20082 gen_arith_imm(ctx, op, rt, rs, imm);
20083 break;
20084 #else
20085 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
20086 if (ctx->insn_flags & ISA_MIPS32R6) {
20087 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
20088 } else {
20089 MIPS_INVAL("major opcode");
20090 generate_exception(ctx, EXCP_RI);
20092 break;
20093 #endif
20094 case OPC_DAUI: /* OPC_JALX */
20095 if (ctx->insn_flags & ISA_MIPS32R6) {
20096 #if defined(TARGET_MIPS64)
20097 /* OPC_DAUI */
20098 check_mips_64(ctx);
20099 if (rt != 0) {
20100 TCGv t0 = tcg_temp_new();
20101 gen_load_gpr(t0, rs);
20102 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
20103 tcg_temp_free(t0);
20105 MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm);
20106 #else
20107 generate_exception(ctx, EXCP_RI);
20108 MIPS_INVAL("major opcode");
20109 #endif
20110 } else {
20111 /* OPC_JALX */
20112 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
20113 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
20114 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
20116 break;
20117 case OPC_MSA: /* OPC_MDMX */
20118 /* MDMX: Not implemented. */
20119 gen_msa(env, ctx);
20120 break;
20121 case OPC_PCREL:
20122 check_insn(ctx, ISA_MIPS32R6);
20123 gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
20124 break;
20125 default: /* Invalid */
20126 MIPS_INVAL("major opcode");
20127 generate_exception(ctx, EXCP_RI);
20128 break;
20132 static inline void
20133 gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
20134 bool search_pc)
20136 CPUState *cs = CPU(cpu);
20137 CPUMIPSState *env = &cpu->env;
20138 DisasContext ctx;
20139 target_ulong pc_start;
20140 target_ulong next_page_start;
20141 CPUBreakpoint *bp;
20142 int j, lj = -1;
20143 int num_insns;
20144 int max_insns;
20145 int insn_bytes;
20146 int is_slot;
20148 if (search_pc)
20149 qemu_log("search pc %d\n", search_pc);
20151 pc_start = tb->pc;
20152 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
20153 ctx.pc = pc_start;
20154 ctx.saved_pc = -1;
20155 ctx.singlestep_enabled = cs->singlestep_enabled;
20156 ctx.insn_flags = env->insn_flags;
20157 ctx.CP0_Config1 = env->CP0_Config1;
20158 ctx.tb = tb;
20159 ctx.bstate = BS_NONE;
20160 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
20161 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
20162 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
20163 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
20164 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
20165 ctx.PAMask = env->PAMask;
20166 ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
20167 ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
20168 /* Restore delay slot state from the tb context. */
20169 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
20170 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
20171 ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
20172 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
20173 restore_cpu_state(env, &ctx);
20174 #ifdef CONFIG_USER_ONLY
20175 ctx.mem_idx = MIPS_HFLAG_UM;
20176 #else
20177 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
20178 #endif
20179 ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
20180 MO_UNALN : MO_ALIGN;
20181 num_insns = 0;
20182 max_insns = tb->cflags & CF_COUNT_MASK;
20183 if (max_insns == 0)
20184 max_insns = CF_COUNT_MASK;
20185 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
20186 gen_tb_start(tb);
20187 while (ctx.bstate == BS_NONE) {
20188 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
20189 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
20190 if (bp->pc == ctx.pc) {
20191 save_cpu_state(&ctx, 1);
20192 ctx.bstate = BS_BRANCH;
20193 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
20194 /* Include the breakpoint location or the tb won't
20195 * be flushed when it must be. */
20196 ctx.pc += 4;
20197 goto done_generating;
20202 if (search_pc) {
20203 j = tcg_op_buf_count();
20204 if (lj < j) {
20205 lj++;
20206 while (lj < j)
20207 tcg_ctx.gen_opc_instr_start[lj++] = 0;
20209 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
20210 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
20211 gen_opc_btarget[lj] = ctx.btarget;
20212 tcg_ctx.gen_opc_instr_start[lj] = 1;
20213 tcg_ctx.gen_opc_icount[lj] = num_insns;
20215 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
20216 gen_io_start();
20218 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
20219 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
20220 ctx.opcode = cpu_ldl_code(env, ctx.pc);
20221 insn_bytes = 4;
20222 decode_opc(env, &ctx);
20223 } else if (ctx.insn_flags & ASE_MICROMIPS) {
20224 ctx.opcode = cpu_lduw_code(env, ctx.pc);
20225 insn_bytes = decode_micromips_opc(env, &ctx);
20226 } else if (ctx.insn_flags & ASE_MIPS16) {
20227 ctx.opcode = cpu_lduw_code(env, ctx.pc);
20228 insn_bytes = decode_mips16_opc(env, &ctx);
20229 } else {
20230 generate_exception(&ctx, EXCP_RI);
20231 ctx.bstate = BS_STOP;
20232 break;
20235 if (ctx.hflags & MIPS_HFLAG_BMASK) {
20236 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
20237 MIPS_HFLAG_FBNSLOT))) {
20238 /* force to generate branch as there is neither delay nor
20239 forbidden slot */
20240 is_slot = 1;
20242 if ((ctx.hflags & MIPS_HFLAG_M16) &&
20243 (ctx.hflags & MIPS_HFLAG_FBNSLOT)) {
20244 /* Force to generate branch as microMIPS R6 doesn't restrict
20245 branches in the forbidden slot. */
20246 is_slot = 1;
20249 if (is_slot) {
20250 gen_branch(&ctx, insn_bytes);
20252 ctx.pc += insn_bytes;
20254 num_insns++;
20256 /* Execute a branch and its delay slot as a single instruction.
20257 This is what GDB expects and is consistent with what the
20258 hardware does (e.g. if a delay slot instruction faults, the
20259 reported PC is the PC of the branch). */
20260 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
20261 break;
20264 if (ctx.pc >= next_page_start) {
20265 break;
20268 if (tcg_op_buf_full()) {
20269 break;
20272 if (num_insns >= max_insns)
20273 break;
20275 if (singlestep)
20276 break;
20278 if (tb->cflags & CF_LAST_IO) {
20279 gen_io_end();
20281 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
20282 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
20283 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
20284 } else {
20285 switch (ctx.bstate) {
20286 case BS_STOP:
20287 gen_goto_tb(&ctx, 0, ctx.pc);
20288 break;
20289 case BS_NONE:
20290 save_cpu_state(&ctx, 0);
20291 gen_goto_tb(&ctx, 0, ctx.pc);
20292 break;
20293 case BS_EXCP:
20294 tcg_gen_exit_tb(0);
20295 break;
20296 case BS_BRANCH:
20297 default:
20298 break;
20301 done_generating:
20302 gen_tb_end(tb, num_insns);
20304 if (search_pc) {
20305 j = tcg_op_buf_count();
20306 lj++;
20307 while (lj <= j)
20308 tcg_ctx.gen_opc_instr_start[lj++] = 0;
20309 } else {
20310 tb->size = ctx.pc - pc_start;
20311 tb->icount = num_insns;
20313 #ifdef DEBUG_DISAS
20314 LOG_DISAS("\n");
20315 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
20316 qemu_log("IN: %s\n", lookup_symbol(pc_start));
20317 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
20318 qemu_log("\n");
20320 #endif
20323 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
20325 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
20328 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
20330 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
20333 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
20334 int flags)
20336 int i;
20337 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
20339 #define printfpr(fp) \
20340 do { \
20341 if (is_fpu64) \
20342 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20343 " fd:%13g fs:%13g psu: %13g\n", \
20344 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
20345 (double)(fp)->fd, \
20346 (double)(fp)->fs[FP_ENDIAN_IDX], \
20347 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
20348 else { \
20349 fpr_t tmp; \
20350 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
20351 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
20352 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20353 " fd:%13g fs:%13g psu:%13g\n", \
20354 tmp.w[FP_ENDIAN_IDX], tmp.d, \
20355 (double)tmp.fd, \
20356 (double)tmp.fs[FP_ENDIAN_IDX], \
20357 (double)tmp.fs[!FP_ENDIAN_IDX]); \
20359 } while(0)
20362 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
20363 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
20364 get_float_exception_flags(&env->active_fpu.fp_status));
20365 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
20366 fpu_fprintf(f, "%3s: ", fregnames[i]);
20367 printfpr(&env->active_fpu.fpr[i]);
20370 #undef printfpr
20373 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
20374 /* Debug help: The architecture requires 32bit code to maintain proper
20375 sign-extended values on 64bit machines. */
20377 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
20379 static void
20380 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
20381 fprintf_function cpu_fprintf,
20382 int flags)
20384 int i;
20386 if (!SIGN_EXT_P(env->active_tc.PC))
20387 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
20388 if (!SIGN_EXT_P(env->active_tc.HI[0]))
20389 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
20390 if (!SIGN_EXT_P(env->active_tc.LO[0]))
20391 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
20392 if (!SIGN_EXT_P(env->btarget))
20393 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
20395 for (i = 0; i < 32; i++) {
20396 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
20397 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
20400 if (!SIGN_EXT_P(env->CP0_EPC))
20401 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
20402 if (!SIGN_EXT_P(env->lladdr))
20403 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
20405 #endif
20407 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
20408 int flags)
20410 MIPSCPU *cpu = MIPS_CPU(cs);
20411 CPUMIPSState *env = &cpu->env;
20412 int i;
20414 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
20415 " LO=0x" TARGET_FMT_lx " ds %04x "
20416 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
20417 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
20418 env->hflags, env->btarget, env->bcond);
20419 for (i = 0; i < 32; i++) {
20420 if ((i & 3) == 0)
20421 cpu_fprintf(f, "GPR%02d:", i);
20422 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
20423 if ((i & 3) == 3)
20424 cpu_fprintf(f, "\n");
20427 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
20428 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
20429 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
20430 PRIx64 "\n",
20431 env->CP0_Config0, env->CP0_Config1, env->lladdr);
20432 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
20433 env->CP0_Config2, env->CP0_Config3);
20434 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
20435 env->CP0_Config4, env->CP0_Config5);
20436 if (env->hflags & MIPS_HFLAG_FPU)
20437 fpu_dump_state(env, f, cpu_fprintf, flags);
20438 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
20439 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
20440 #endif
20443 void mips_tcg_init(void)
20445 int i;
20446 static int inited;
20448 /* Initialize various static tables. */
20449 if (inited)
20450 return;
20452 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
20453 TCGV_UNUSED(cpu_gpr[0]);
20454 for (i = 1; i < 32; i++)
20455 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
20456 offsetof(CPUMIPSState, active_tc.gpr[i]),
20457 regnames[i]);
20459 for (i = 0; i < 32; i++) {
20460 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
20461 msa_wr_d[i * 2] =
20462 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]);
20463 /* The scalar floating-point unit (FPU) registers are mapped on
20464 * the MSA vector registers. */
20465 fpu_f64[i] = msa_wr_d[i * 2];
20466 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
20467 msa_wr_d[i * 2 + 1] =
20468 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + 1]);
20471 cpu_PC = tcg_global_mem_new(TCG_AREG0,
20472 offsetof(CPUMIPSState, active_tc.PC), "PC");
20473 for (i = 0; i < MIPS_DSP_ACC; i++) {
20474 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
20475 offsetof(CPUMIPSState, active_tc.HI[i]),
20476 regnames_HI[i]);
20477 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
20478 offsetof(CPUMIPSState, active_tc.LO[i]),
20479 regnames_LO[i]);
20481 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
20482 offsetof(CPUMIPSState, active_tc.DSPControl),
20483 "DSPControl");
20484 bcond = tcg_global_mem_new(TCG_AREG0,
20485 offsetof(CPUMIPSState, bcond), "bcond");
20486 btarget = tcg_global_mem_new(TCG_AREG0,
20487 offsetof(CPUMIPSState, btarget), "btarget");
20488 hflags = tcg_global_mem_new_i32(TCG_AREG0,
20489 offsetof(CPUMIPSState, hflags), "hflags");
20491 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
20492 offsetof(CPUMIPSState, active_fpu.fcr0),
20493 "fcr0");
20494 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
20495 offsetof(CPUMIPSState, active_fpu.fcr31),
20496 "fcr31");
20498 inited = 1;
20501 #include "translate_init.c"
20503 MIPSCPU *cpu_mips_init(const char *cpu_model)
20505 MIPSCPU *cpu;
20506 CPUMIPSState *env;
20507 const mips_def_t *def;
20509 def = cpu_mips_find_by_name(cpu_model);
20510 if (!def)
20511 return NULL;
20512 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
20513 env = &cpu->env;
20514 env->cpu_model = def;
20516 #ifndef CONFIG_USER_ONLY
20517 mmu_init(env, def);
20518 #endif
20519 fpu_init(env, def);
20520 mvp_init(env, def);
20522 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
20524 return cpu;
20527 void cpu_state_reset(CPUMIPSState *env)
20529 MIPSCPU *cpu = mips_env_get_cpu(env);
20530 CPUState *cs = CPU(cpu);
20532 /* Reset registers to their default values */
20533 env->CP0_PRid = env->cpu_model->CP0_PRid;
20534 env->CP0_Config0 = env->cpu_model->CP0_Config0;
20535 #ifdef TARGET_WORDS_BIGENDIAN
20536 env->CP0_Config0 |= (1 << CP0C0_BE);
20537 #endif
20538 env->CP0_Config1 = env->cpu_model->CP0_Config1;
20539 env->CP0_Config2 = env->cpu_model->CP0_Config2;
20540 env->CP0_Config3 = env->cpu_model->CP0_Config3;
20541 env->CP0_Config4 = env->cpu_model->CP0_Config4;
20542 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
20543 env->CP0_Config5 = env->cpu_model->CP0_Config5;
20544 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
20545 env->CP0_Config6 = env->cpu_model->CP0_Config6;
20546 env->CP0_Config7 = env->cpu_model->CP0_Config7;
20547 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
20548 << env->cpu_model->CP0_LLAddr_shift;
20549 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
20550 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
20551 env->CCRes = env->cpu_model->CCRes;
20552 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
20553 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
20554 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
20555 env->current_tc = 0;
20556 env->SEGBITS = env->cpu_model->SEGBITS;
20557 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
20558 #if defined(TARGET_MIPS64)
20559 if (env->cpu_model->insn_flags & ISA_MIPS3) {
20560 env->SEGMask |= 3ULL << 62;
20562 #endif
20563 env->PABITS = env->cpu_model->PABITS;
20564 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
20565 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
20566 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
20567 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
20568 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
20569 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
20570 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
20571 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
20572 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
20573 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
20574 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
20575 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
20576 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
20577 env->msair = env->cpu_model->MSAIR;
20578 env->insn_flags = env->cpu_model->insn_flags;
20580 #if defined(CONFIG_USER_ONLY)
20581 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
20582 # ifdef TARGET_MIPS64
20583 /* Enable 64-bit register mode. */
20584 env->CP0_Status |= (1 << CP0St_PX);
20585 # endif
20586 # ifdef TARGET_ABI_MIPSN64
20587 /* Enable 64-bit address mode. */
20588 env->CP0_Status |= (1 << CP0St_UX);
20589 # endif
20590 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
20591 hardware registers. */
20592 env->CP0_HWREna |= 0x0000000F;
20593 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
20594 env->CP0_Status |= (1 << CP0St_CU1);
20596 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
20597 env->CP0_Status |= (1 << CP0St_MX);
20599 # if defined(TARGET_MIPS64)
20600 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
20601 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
20602 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
20603 env->CP0_Status |= (1 << CP0St_FR);
20605 # endif
20606 #else
20607 if (env->hflags & MIPS_HFLAG_BMASK) {
20608 /* If the exception was raised from a delay slot,
20609 come back to the jump. */
20610 env->CP0_ErrorEPC = (env->active_tc.PC
20611 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
20612 } else {
20613 env->CP0_ErrorEPC = env->active_tc.PC;
20615 env->active_tc.PC = (int32_t)0xBFC00000;
20616 env->CP0_Random = env->tlb->nb_tlb - 1;
20617 env->tlb->tlb_in_use = env->tlb->nb_tlb;
20618 env->CP0_Wired = 0;
20619 env->CP0_EBase = (cs->cpu_index & 0x3FF);
20620 if (kvm_enabled()) {
20621 env->CP0_EBase |= 0x40000000;
20622 } else {
20623 env->CP0_EBase |= 0x80000000;
20625 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
20626 /* vectored interrupts not implemented, timer on int 7,
20627 no performance counters. */
20628 env->CP0_IntCtl = 0xe0000000;
20630 int i;
20632 for (i = 0; i < 7; i++) {
20633 env->CP0_WatchLo[i] = 0;
20634 env->CP0_WatchHi[i] = 0x80000000;
20636 env->CP0_WatchLo[7] = 0;
20637 env->CP0_WatchHi[7] = 0;
20639 /* Count register increments in debug mode, EJTAG version 1 */
20640 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
20642 cpu_mips_store_count(env, 1);
20644 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
20645 int i;
20647 /* Only TC0 on VPE 0 starts as active. */
20648 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
20649 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
20650 env->tcs[i].CP0_TCHalt = 1;
20652 env->active_tc.CP0_TCHalt = 1;
20653 cs->halted = 1;
20655 if (cs->cpu_index == 0) {
20656 /* VPE0 starts up enabled. */
20657 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
20658 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
20660 /* TC0 starts up unhalted. */
20661 cs->halted = 0;
20662 env->active_tc.CP0_TCHalt = 0;
20663 env->tcs[0].CP0_TCHalt = 0;
20664 /* With thread 0 active. */
20665 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
20666 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
20669 #endif
20670 if ((env->insn_flags & ISA_MIPS32R6) &&
20671 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
20672 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
20673 env->CP0_Status |= (1 << CP0St_FR);
20676 /* MSA */
20677 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
20678 msa_reset(env);
20681 compute_hflags(env);
20682 restore_rounding_mode(env);
20683 restore_flush_mode(env);
20684 restore_pamask(env);
20685 cs->exception_index = EXCP_NONE;
20687 if (semihosting_get_argc()) {
20688 /* UHI interface can be used to obtain argc and argv */
20689 env->active_tc.gpr[4] = -1;
20693 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
20695 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
20696 env->hflags &= ~MIPS_HFLAG_BMASK;
20697 env->hflags |= gen_opc_hflags[pc_pos];
20698 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
20699 case MIPS_HFLAG_BR:
20700 break;
20701 case MIPS_HFLAG_BC:
20702 case MIPS_HFLAG_BL:
20703 case MIPS_HFLAG_B:
20704 env->btarget = gen_opc_btarget[pc_pos];
20705 break;