ahci: remove cmd_fis argument from write_fis_d2h
[qemu/ar7.git] / target-mips / translate.c
blob93cb4f27315f00cad0df582e4915b646e5226a47
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_extrl_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_extrl_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 /* Do a byte access to possibly trigger a page
2146 fault with the unaligned address. */
2147 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2148 tcg_gen_andi_tl(t1, t0, 7);
2149 #ifndef TARGET_WORDS_BIGENDIAN
2150 tcg_gen_xori_tl(t1, t1, 7);
2151 #endif
2152 tcg_gen_shli_tl(t1, t1, 3);
2153 tcg_gen_andi_tl(t0, t0, ~7);
2154 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2155 tcg_gen_shl_tl(t0, t0, t1);
2156 t2 = tcg_const_tl(-1);
2157 tcg_gen_shl_tl(t2, t2, t1);
2158 gen_load_gpr(t1, rt);
2159 tcg_gen_andc_tl(t1, t1, t2);
2160 tcg_temp_free(t2);
2161 tcg_gen_or_tl(t0, t0, t1);
2162 tcg_temp_free(t1);
2163 gen_store_gpr(t0, rt);
2164 opn = "ldl";
2165 break;
2166 case OPC_LDR:
2167 t1 = tcg_temp_new();
2168 /* Do a byte access to possibly trigger a page
2169 fault with the unaligned address. */
2170 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2171 tcg_gen_andi_tl(t1, t0, 7);
2172 #ifdef TARGET_WORDS_BIGENDIAN
2173 tcg_gen_xori_tl(t1, t1, 7);
2174 #endif
2175 tcg_gen_shli_tl(t1, t1, 3);
2176 tcg_gen_andi_tl(t0, t0, ~7);
2177 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2178 tcg_gen_shr_tl(t0, t0, t1);
2179 tcg_gen_xori_tl(t1, t1, 63);
2180 t2 = tcg_const_tl(0xfffffffffffffffeull);
2181 tcg_gen_shl_tl(t2, t2, t1);
2182 gen_load_gpr(t1, rt);
2183 tcg_gen_and_tl(t1, t1, t2);
2184 tcg_temp_free(t2);
2185 tcg_gen_or_tl(t0, t0, t1);
2186 tcg_temp_free(t1);
2187 gen_store_gpr(t0, rt);
2188 opn = "ldr";
2189 break;
2190 case OPC_LDPC:
2191 t1 = tcg_const_tl(pc_relative_pc(ctx));
2192 gen_op_addr_add(ctx, t0, t0, t1);
2193 tcg_temp_free(t1);
2194 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2195 gen_store_gpr(t0, rt);
2196 opn = "ldpc";
2197 break;
2198 #endif
2199 case OPC_LWPC:
2200 t1 = tcg_const_tl(pc_relative_pc(ctx));
2201 gen_op_addr_add(ctx, t0, t0, t1);
2202 tcg_temp_free(t1);
2203 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2204 gen_store_gpr(t0, rt);
2205 opn = "lwpc";
2206 break;
2207 case OPC_LW:
2208 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
2209 ctx->default_tcg_memop_mask);
2210 gen_store_gpr(t0, rt);
2211 opn = "lw";
2212 break;
2213 case OPC_LH:
2214 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
2215 ctx->default_tcg_memop_mask);
2216 gen_store_gpr(t0, rt);
2217 opn = "lh";
2218 break;
2219 case OPC_LHU:
2220 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW |
2221 ctx->default_tcg_memop_mask);
2222 gen_store_gpr(t0, rt);
2223 opn = "lhu";
2224 break;
2225 case OPC_LB:
2226 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
2227 gen_store_gpr(t0, rt);
2228 opn = "lb";
2229 break;
2230 case OPC_LBU:
2231 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
2232 gen_store_gpr(t0, rt);
2233 opn = "lbu";
2234 break;
2235 case OPC_LWL:
2236 t1 = tcg_temp_new();
2237 /* Do a byte access to possibly trigger a page
2238 fault with the unaligned address. */
2239 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2240 tcg_gen_andi_tl(t1, t0, 3);
2241 #ifndef TARGET_WORDS_BIGENDIAN
2242 tcg_gen_xori_tl(t1, t1, 3);
2243 #endif
2244 tcg_gen_shli_tl(t1, t1, 3);
2245 tcg_gen_andi_tl(t0, t0, ~3);
2246 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2247 tcg_gen_shl_tl(t0, t0, t1);
2248 t2 = tcg_const_tl(-1);
2249 tcg_gen_shl_tl(t2, t2, t1);
2250 gen_load_gpr(t1, rt);
2251 tcg_gen_andc_tl(t1, t1, t2);
2252 tcg_temp_free(t2);
2253 tcg_gen_or_tl(t0, t0, t1);
2254 tcg_temp_free(t1);
2255 tcg_gen_ext32s_tl(t0, t0);
2256 gen_store_gpr(t0, rt);
2257 opn = "lwl";
2258 break;
2259 case OPC_LWR:
2260 t1 = tcg_temp_new();
2261 /* Do a byte access to possibly trigger a page
2262 fault with the unaligned address. */
2263 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2264 tcg_gen_andi_tl(t1, t0, 3);
2265 #ifdef TARGET_WORDS_BIGENDIAN
2266 tcg_gen_xori_tl(t1, t1, 3);
2267 #endif
2268 tcg_gen_shli_tl(t1, t1, 3);
2269 tcg_gen_andi_tl(t0, t0, ~3);
2270 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2271 tcg_gen_shr_tl(t0, t0, t1);
2272 tcg_gen_xori_tl(t1, t1, 31);
2273 t2 = tcg_const_tl(0xfffffffeull);
2274 tcg_gen_shl_tl(t2, t2, t1);
2275 gen_load_gpr(t1, rt);
2276 tcg_gen_and_tl(t1, t1, t2);
2277 tcg_temp_free(t2);
2278 tcg_gen_or_tl(t0, t0, t1);
2279 tcg_temp_free(t1);
2280 tcg_gen_ext32s_tl(t0, t0);
2281 gen_store_gpr(t0, rt);
2282 opn = "lwr";
2283 break;
2284 case OPC_LL:
2285 case R6_OPC_LL:
2286 save_cpu_state(ctx, 1);
2287 op_ld_ll(t0, t0, ctx);
2288 gen_store_gpr(t0, rt);
2289 opn = "ll";
2290 break;
2292 (void)opn; /* avoid a compiler warning */
2293 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2294 tcg_temp_free(t0);
2297 /* Store */
2298 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2299 int base, int16_t offset)
2301 const char *opn = "st";
2302 TCGv t0 = tcg_temp_new();
2303 TCGv t1 = tcg_temp_new();
2305 gen_base_offset_addr(ctx, t0, base, offset);
2306 gen_load_gpr(t1, rt);
2307 switch (opc) {
2308 #if defined(TARGET_MIPS64)
2309 case OPC_SD:
2310 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
2311 ctx->default_tcg_memop_mask);
2312 opn = "sd";
2313 break;
2314 case OPC_SDL:
2315 save_cpu_state(ctx, 1);
2316 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
2317 opn = "sdl";
2318 break;
2319 case OPC_SDR:
2320 save_cpu_state(ctx, 1);
2321 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2322 opn = "sdr";
2323 break;
2324 #endif
2325 case OPC_SW:
2326 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
2327 ctx->default_tcg_memop_mask);
2328 opn = "sw";
2329 break;
2330 case OPC_SH:
2331 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
2332 ctx->default_tcg_memop_mask);
2333 opn = "sh";
2334 break;
2335 case OPC_SB:
2336 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2337 opn = "sb";
2338 break;
2339 case OPC_SWL:
2340 save_cpu_state(ctx, 1);
2341 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2342 opn = "swl";
2343 break;
2344 case OPC_SWR:
2345 save_cpu_state(ctx, 1);
2346 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2347 opn = "swr";
2348 break;
2350 (void)opn; /* avoid a compiler warning */
2351 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2352 tcg_temp_free(t0);
2353 tcg_temp_free(t1);
2357 /* Store conditional */
2358 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2359 int base, int16_t offset)
2361 const char *opn = "st_cond";
2362 TCGv t0, t1;
2364 #ifdef CONFIG_USER_ONLY
2365 t0 = tcg_temp_local_new();
2366 t1 = tcg_temp_local_new();
2367 #else
2368 t0 = tcg_temp_new();
2369 t1 = tcg_temp_new();
2370 #endif
2371 gen_base_offset_addr(ctx, t0, base, offset);
2372 gen_load_gpr(t1, rt);
2373 switch (opc) {
2374 #if defined(TARGET_MIPS64)
2375 case OPC_SCD:
2376 case R6_OPC_SCD:
2377 save_cpu_state(ctx, 1);
2378 op_st_scd(t1, t0, rt, ctx);
2379 opn = "scd";
2380 break;
2381 #endif
2382 case OPC_SC:
2383 case R6_OPC_SC:
2384 save_cpu_state(ctx, 1);
2385 op_st_sc(t1, t0, rt, ctx);
2386 opn = "sc";
2387 break;
2389 (void)opn; /* avoid a compiler warning */
2390 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2391 tcg_temp_free(t1);
2392 tcg_temp_free(t0);
2395 /* Load and store */
2396 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2397 int base, int16_t offset)
2399 const char *opn = "flt_ldst";
2400 TCGv t0 = tcg_temp_new();
2402 gen_base_offset_addr(ctx, t0, base, offset);
2403 /* Don't do NOP if destination is zero: we must perform the actual
2404 memory access. */
2405 switch (opc) {
2406 case OPC_LWC1:
2408 TCGv_i32 fp0 = tcg_temp_new_i32();
2409 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2410 ctx->default_tcg_memop_mask);
2411 gen_store_fpr32(ctx, fp0, ft);
2412 tcg_temp_free_i32(fp0);
2414 opn = "lwc1";
2415 break;
2416 case OPC_SWC1:
2418 TCGv_i32 fp0 = tcg_temp_new_i32();
2419 gen_load_fpr32(ctx, fp0, ft);
2420 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2421 ctx->default_tcg_memop_mask);
2422 tcg_temp_free_i32(fp0);
2424 opn = "swc1";
2425 break;
2426 case OPC_LDC1:
2428 TCGv_i64 fp0 = tcg_temp_new_i64();
2429 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2430 ctx->default_tcg_memop_mask);
2431 gen_store_fpr64(ctx, fp0, ft);
2432 tcg_temp_free_i64(fp0);
2434 opn = "ldc1";
2435 break;
2436 case OPC_SDC1:
2438 TCGv_i64 fp0 = tcg_temp_new_i64();
2439 gen_load_fpr64(ctx, fp0, ft);
2440 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2441 ctx->default_tcg_memop_mask);
2442 tcg_temp_free_i64(fp0);
2444 opn = "sdc1";
2445 break;
2446 default:
2447 MIPS_INVAL(opn);
2448 generate_exception(ctx, EXCP_RI);
2449 goto out;
2451 (void)opn; /* avoid a compiler warning */
2452 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
2453 out:
2454 tcg_temp_free(t0);
2457 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2458 int rs, int16_t imm)
2460 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2461 check_cp1_enabled(ctx);
2462 switch (op) {
2463 case OPC_LDC1:
2464 case OPC_SDC1:
2465 check_insn(ctx, ISA_MIPS2);
2466 /* Fallthrough */
2467 default:
2468 gen_flt_ldst(ctx, op, rt, rs, imm);
2470 } else {
2471 generate_exception_err(ctx, EXCP_CpU, 1);
2475 /* Arithmetic with immediate operand */
2476 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2477 int rt, int rs, int16_t imm)
2479 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2480 const char *opn = "imm arith";
2482 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2483 /* If no destination, treat it as a NOP.
2484 For addi, we must generate the overflow exception when needed. */
2485 MIPS_DEBUG("NOP");
2486 return;
2488 switch (opc) {
2489 case OPC_ADDI:
2491 TCGv t0 = tcg_temp_local_new();
2492 TCGv t1 = tcg_temp_new();
2493 TCGv t2 = tcg_temp_new();
2494 TCGLabel *l1 = gen_new_label();
2496 gen_load_gpr(t1, rs);
2497 tcg_gen_addi_tl(t0, t1, uimm);
2498 tcg_gen_ext32s_tl(t0, t0);
2500 tcg_gen_xori_tl(t1, t1, ~uimm);
2501 tcg_gen_xori_tl(t2, t0, uimm);
2502 tcg_gen_and_tl(t1, t1, t2);
2503 tcg_temp_free(t2);
2504 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2505 tcg_temp_free(t1);
2506 /* operands of same sign, result different sign */
2507 generate_exception(ctx, EXCP_OVERFLOW);
2508 gen_set_label(l1);
2509 tcg_gen_ext32s_tl(t0, t0);
2510 gen_store_gpr(t0, rt);
2511 tcg_temp_free(t0);
2513 opn = "addi";
2514 break;
2515 case OPC_ADDIU:
2516 if (rs != 0) {
2517 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2518 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2519 } else {
2520 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2522 opn = "addiu";
2523 break;
2524 #if defined(TARGET_MIPS64)
2525 case OPC_DADDI:
2527 TCGv t0 = tcg_temp_local_new();
2528 TCGv t1 = tcg_temp_new();
2529 TCGv t2 = tcg_temp_new();
2530 TCGLabel *l1 = gen_new_label();
2532 gen_load_gpr(t1, rs);
2533 tcg_gen_addi_tl(t0, t1, uimm);
2535 tcg_gen_xori_tl(t1, t1, ~uimm);
2536 tcg_gen_xori_tl(t2, t0, uimm);
2537 tcg_gen_and_tl(t1, t1, t2);
2538 tcg_temp_free(t2);
2539 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2540 tcg_temp_free(t1);
2541 /* operands of same sign, result different sign */
2542 generate_exception(ctx, EXCP_OVERFLOW);
2543 gen_set_label(l1);
2544 gen_store_gpr(t0, rt);
2545 tcg_temp_free(t0);
2547 opn = "daddi";
2548 break;
2549 case OPC_DADDIU:
2550 if (rs != 0) {
2551 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2552 } else {
2553 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2555 opn = "daddiu";
2556 break;
2557 #endif
2559 (void)opn; /* avoid a compiler warning */
2560 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2563 /* Logic with immediate operand */
2564 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2565 int rt, int rs, int16_t imm)
2567 target_ulong uimm;
2569 if (rt == 0) {
2570 /* If no destination, treat it as a NOP. */
2571 MIPS_DEBUG("NOP");
2572 return;
2574 uimm = (uint16_t)imm;
2575 switch (opc) {
2576 case OPC_ANDI:
2577 if (likely(rs != 0))
2578 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2579 else
2580 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2581 MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
2582 regnames[rs], uimm);
2583 break;
2584 case OPC_ORI:
2585 if (rs != 0)
2586 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2587 else
2588 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2589 MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
2590 regnames[rs], uimm);
2591 break;
2592 case OPC_XORI:
2593 if (likely(rs != 0))
2594 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2595 else
2596 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2597 MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
2598 regnames[rs], uimm);
2599 break;
2600 case OPC_LUI:
2601 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2602 /* OPC_AUI */
2603 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2604 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2605 MIPS_DEBUG("aui %s, %s, %04x", regnames[rt], regnames[rs], imm);
2606 } else {
2607 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2608 MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
2610 break;
2612 default:
2613 MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
2614 break;
2618 /* Set on less than with immediate operand */
2619 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2620 int rt, int rs, int16_t imm)
2622 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2623 const char *opn = "imm arith";
2624 TCGv t0;
2626 if (rt == 0) {
2627 /* If no destination, treat it as a NOP. */
2628 MIPS_DEBUG("NOP");
2629 return;
2631 t0 = tcg_temp_new();
2632 gen_load_gpr(t0, rs);
2633 switch (opc) {
2634 case OPC_SLTI:
2635 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2636 opn = "slti";
2637 break;
2638 case OPC_SLTIU:
2639 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2640 opn = "sltiu";
2641 break;
2643 (void)opn; /* avoid a compiler warning */
2644 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2645 tcg_temp_free(t0);
2648 /* Shifts with immediate operand */
2649 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2650 int rt, int rs, int16_t imm)
2652 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2653 const char *opn = "imm shift";
2654 TCGv t0;
2656 if (rt == 0) {
2657 /* If no destination, treat it as a NOP. */
2658 MIPS_DEBUG("NOP");
2659 return;
2662 t0 = tcg_temp_new();
2663 gen_load_gpr(t0, rs);
2664 switch (opc) {
2665 case OPC_SLL:
2666 tcg_gen_shli_tl(t0, t0, uimm);
2667 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2668 opn = "sll";
2669 break;
2670 case OPC_SRA:
2671 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2672 opn = "sra";
2673 break;
2674 case OPC_SRL:
2675 if (uimm != 0) {
2676 tcg_gen_ext32u_tl(t0, t0);
2677 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2678 } else {
2679 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2681 opn = "srl";
2682 break;
2683 case OPC_ROTR:
2684 if (uimm != 0) {
2685 TCGv_i32 t1 = tcg_temp_new_i32();
2687 tcg_gen_trunc_tl_i32(t1, t0);
2688 tcg_gen_rotri_i32(t1, t1, uimm);
2689 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2690 tcg_temp_free_i32(t1);
2691 } else {
2692 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2694 opn = "rotr";
2695 break;
2696 #if defined(TARGET_MIPS64)
2697 case OPC_DSLL:
2698 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2699 opn = "dsll";
2700 break;
2701 case OPC_DSRA:
2702 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2703 opn = "dsra";
2704 break;
2705 case OPC_DSRL:
2706 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2707 opn = "dsrl";
2708 break;
2709 case OPC_DROTR:
2710 if (uimm != 0) {
2711 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2712 } else {
2713 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2715 opn = "drotr";
2716 break;
2717 case OPC_DSLL32:
2718 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2719 opn = "dsll32";
2720 break;
2721 case OPC_DSRA32:
2722 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2723 opn = "dsra32";
2724 break;
2725 case OPC_DSRL32:
2726 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2727 opn = "dsrl32";
2728 break;
2729 case OPC_DROTR32:
2730 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2731 opn = "drotr32";
2732 break;
2733 #endif
2735 (void)opn; /* avoid a compiler warning */
2736 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2737 tcg_temp_free(t0);
2740 /* Arithmetic */
2741 static void gen_arith(DisasContext *ctx, uint32_t opc,
2742 int rd, int rs, int rt)
2744 const char *opn = "arith";
2746 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2747 && opc != OPC_DADD && opc != OPC_DSUB) {
2748 /* If no destination, treat it as a NOP.
2749 For add & sub, we must generate the overflow exception when needed. */
2750 MIPS_DEBUG("NOP");
2751 return;
2754 switch (opc) {
2755 case OPC_ADD:
2757 TCGv t0 = tcg_temp_local_new();
2758 TCGv t1 = tcg_temp_new();
2759 TCGv t2 = tcg_temp_new();
2760 TCGLabel *l1 = gen_new_label();
2762 gen_load_gpr(t1, rs);
2763 gen_load_gpr(t2, rt);
2764 tcg_gen_add_tl(t0, t1, t2);
2765 tcg_gen_ext32s_tl(t0, t0);
2766 tcg_gen_xor_tl(t1, t1, t2);
2767 tcg_gen_xor_tl(t2, t0, t2);
2768 tcg_gen_andc_tl(t1, t2, t1);
2769 tcg_temp_free(t2);
2770 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2771 tcg_temp_free(t1);
2772 /* operands of same sign, result different sign */
2773 generate_exception(ctx, EXCP_OVERFLOW);
2774 gen_set_label(l1);
2775 gen_store_gpr(t0, rd);
2776 tcg_temp_free(t0);
2778 opn = "add";
2779 break;
2780 case OPC_ADDU:
2781 if (rs != 0 && rt != 0) {
2782 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2783 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2784 } else if (rs == 0 && rt != 0) {
2785 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2786 } else if (rs != 0 && rt == 0) {
2787 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2788 } else {
2789 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2791 opn = "addu";
2792 break;
2793 case OPC_SUB:
2795 TCGv t0 = tcg_temp_local_new();
2796 TCGv t1 = tcg_temp_new();
2797 TCGv t2 = tcg_temp_new();
2798 TCGLabel *l1 = gen_new_label();
2800 gen_load_gpr(t1, rs);
2801 gen_load_gpr(t2, rt);
2802 tcg_gen_sub_tl(t0, t1, t2);
2803 tcg_gen_ext32s_tl(t0, t0);
2804 tcg_gen_xor_tl(t2, t1, t2);
2805 tcg_gen_xor_tl(t1, t0, t1);
2806 tcg_gen_and_tl(t1, t1, t2);
2807 tcg_temp_free(t2);
2808 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2809 tcg_temp_free(t1);
2810 /* operands of different sign, first operand and result different sign */
2811 generate_exception(ctx, EXCP_OVERFLOW);
2812 gen_set_label(l1);
2813 gen_store_gpr(t0, rd);
2814 tcg_temp_free(t0);
2816 opn = "sub";
2817 break;
2818 case OPC_SUBU:
2819 if (rs != 0 && rt != 0) {
2820 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2821 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2822 } else if (rs == 0 && rt != 0) {
2823 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2824 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2825 } else if (rs != 0 && rt == 0) {
2826 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2827 } else {
2828 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2830 opn = "subu";
2831 break;
2832 #if defined(TARGET_MIPS64)
2833 case OPC_DADD:
2835 TCGv t0 = tcg_temp_local_new();
2836 TCGv t1 = tcg_temp_new();
2837 TCGv t2 = tcg_temp_new();
2838 TCGLabel *l1 = gen_new_label();
2840 gen_load_gpr(t1, rs);
2841 gen_load_gpr(t2, rt);
2842 tcg_gen_add_tl(t0, t1, t2);
2843 tcg_gen_xor_tl(t1, t1, t2);
2844 tcg_gen_xor_tl(t2, t0, t2);
2845 tcg_gen_andc_tl(t1, t2, t1);
2846 tcg_temp_free(t2);
2847 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2848 tcg_temp_free(t1);
2849 /* operands of same sign, result different sign */
2850 generate_exception(ctx, EXCP_OVERFLOW);
2851 gen_set_label(l1);
2852 gen_store_gpr(t0, rd);
2853 tcg_temp_free(t0);
2855 opn = "dadd";
2856 break;
2857 case OPC_DADDU:
2858 if (rs != 0 && rt != 0) {
2859 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2860 } else if (rs == 0 && rt != 0) {
2861 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2862 } else if (rs != 0 && rt == 0) {
2863 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2864 } else {
2865 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2867 opn = "daddu";
2868 break;
2869 case OPC_DSUB:
2871 TCGv t0 = tcg_temp_local_new();
2872 TCGv t1 = tcg_temp_new();
2873 TCGv t2 = tcg_temp_new();
2874 TCGLabel *l1 = gen_new_label();
2876 gen_load_gpr(t1, rs);
2877 gen_load_gpr(t2, rt);
2878 tcg_gen_sub_tl(t0, t1, t2);
2879 tcg_gen_xor_tl(t2, t1, t2);
2880 tcg_gen_xor_tl(t1, t0, t1);
2881 tcg_gen_and_tl(t1, t1, t2);
2882 tcg_temp_free(t2);
2883 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2884 tcg_temp_free(t1);
2885 /* operands of different sign, first operand and result different sign */
2886 generate_exception(ctx, EXCP_OVERFLOW);
2887 gen_set_label(l1);
2888 gen_store_gpr(t0, rd);
2889 tcg_temp_free(t0);
2891 opn = "dsub";
2892 break;
2893 case OPC_DSUBU:
2894 if (rs != 0 && rt != 0) {
2895 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2896 } else if (rs == 0 && rt != 0) {
2897 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2898 } else if (rs != 0 && rt == 0) {
2899 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2900 } else {
2901 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2903 opn = "dsubu";
2904 break;
2905 #endif
2906 case OPC_MUL:
2907 if (likely(rs != 0 && rt != 0)) {
2908 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2909 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2910 } else {
2911 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2913 opn = "mul";
2914 break;
2916 (void)opn; /* avoid a compiler warning */
2917 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2920 /* Conditional move */
2921 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2922 int rd, int rs, int rt)
2924 const char *opn = "cond move";
2925 TCGv t0, t1, t2;
2927 if (rd == 0) {
2928 /* If no destination, treat it as a NOP. */
2929 MIPS_DEBUG("NOP");
2930 return;
2933 t0 = tcg_temp_new();
2934 gen_load_gpr(t0, rt);
2935 t1 = tcg_const_tl(0);
2936 t2 = tcg_temp_new();
2937 gen_load_gpr(t2, rs);
2938 switch (opc) {
2939 case OPC_MOVN:
2940 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2941 opn = "movn";
2942 break;
2943 case OPC_MOVZ:
2944 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2945 opn = "movz";
2946 break;
2947 case OPC_SELNEZ:
2948 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2949 opn = "selnez";
2950 break;
2951 case OPC_SELEQZ:
2952 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2953 opn = "seleqz";
2954 break;
2956 tcg_temp_free(t2);
2957 tcg_temp_free(t1);
2958 tcg_temp_free(t0);
2960 (void)opn; /* avoid a compiler warning */
2961 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2964 /* Logic */
2965 static void gen_logic(DisasContext *ctx, uint32_t opc,
2966 int rd, int rs, int rt)
2968 const char *opn = "logic";
2970 if (rd == 0) {
2971 /* If no destination, treat it as a NOP. */
2972 MIPS_DEBUG("NOP");
2973 return;
2976 switch (opc) {
2977 case OPC_AND:
2978 if (likely(rs != 0 && rt != 0)) {
2979 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2980 } else {
2981 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2983 opn = "and";
2984 break;
2985 case OPC_NOR:
2986 if (rs != 0 && rt != 0) {
2987 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2988 } else if (rs == 0 && rt != 0) {
2989 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2990 } else if (rs != 0 && rt == 0) {
2991 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2992 } else {
2993 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2995 opn = "nor";
2996 break;
2997 case OPC_OR:
2998 if (likely(rs != 0 && rt != 0)) {
2999 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3000 } else if (rs == 0 && rt != 0) {
3001 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3002 } else if (rs != 0 && rt == 0) {
3003 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3004 } else {
3005 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3007 opn = "or";
3008 break;
3009 case OPC_XOR:
3010 if (likely(rs != 0 && rt != 0)) {
3011 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3012 } else if (rs == 0 && rt != 0) {
3013 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3014 } else if (rs != 0 && rt == 0) {
3015 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3016 } else {
3017 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3019 opn = "xor";
3020 break;
3022 (void)opn; /* avoid a compiler warning */
3023 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3026 /* Set on lower than */
3027 static void gen_slt(DisasContext *ctx, uint32_t opc,
3028 int rd, int rs, int rt)
3030 const char *opn = "slt";
3031 TCGv t0, t1;
3033 if (rd == 0) {
3034 /* If no destination, treat it as a NOP. */
3035 MIPS_DEBUG("NOP");
3036 return;
3039 t0 = tcg_temp_new();
3040 t1 = tcg_temp_new();
3041 gen_load_gpr(t0, rs);
3042 gen_load_gpr(t1, rt);
3043 switch (opc) {
3044 case OPC_SLT:
3045 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3046 opn = "slt";
3047 break;
3048 case OPC_SLTU:
3049 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3050 opn = "sltu";
3051 break;
3053 (void)opn; /* avoid a compiler warning */
3054 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3055 tcg_temp_free(t0);
3056 tcg_temp_free(t1);
3059 /* Shifts */
3060 static void gen_shift(DisasContext *ctx, uint32_t opc,
3061 int rd, int rs, int rt)
3063 const char *opn = "shifts";
3064 TCGv t0, t1;
3066 if (rd == 0) {
3067 /* If no destination, treat it as a NOP.
3068 For add & sub, we must generate the overflow exception when needed. */
3069 MIPS_DEBUG("NOP");
3070 return;
3073 t0 = tcg_temp_new();
3074 t1 = tcg_temp_new();
3075 gen_load_gpr(t0, rs);
3076 gen_load_gpr(t1, rt);
3077 switch (opc) {
3078 case OPC_SLLV:
3079 tcg_gen_andi_tl(t0, t0, 0x1f);
3080 tcg_gen_shl_tl(t0, t1, t0);
3081 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3082 opn = "sllv";
3083 break;
3084 case OPC_SRAV:
3085 tcg_gen_andi_tl(t0, t0, 0x1f);
3086 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3087 opn = "srav";
3088 break;
3089 case OPC_SRLV:
3090 tcg_gen_ext32u_tl(t1, t1);
3091 tcg_gen_andi_tl(t0, t0, 0x1f);
3092 tcg_gen_shr_tl(t0, t1, t0);
3093 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3094 opn = "srlv";
3095 break;
3096 case OPC_ROTRV:
3098 TCGv_i32 t2 = tcg_temp_new_i32();
3099 TCGv_i32 t3 = tcg_temp_new_i32();
3101 tcg_gen_trunc_tl_i32(t2, t0);
3102 tcg_gen_trunc_tl_i32(t3, t1);
3103 tcg_gen_andi_i32(t2, t2, 0x1f);
3104 tcg_gen_rotr_i32(t2, t3, t2);
3105 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3106 tcg_temp_free_i32(t2);
3107 tcg_temp_free_i32(t3);
3108 opn = "rotrv";
3110 break;
3111 #if defined(TARGET_MIPS64)
3112 case OPC_DSLLV:
3113 tcg_gen_andi_tl(t0, t0, 0x3f);
3114 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3115 opn = "dsllv";
3116 break;
3117 case OPC_DSRAV:
3118 tcg_gen_andi_tl(t0, t0, 0x3f);
3119 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3120 opn = "dsrav";
3121 break;
3122 case OPC_DSRLV:
3123 tcg_gen_andi_tl(t0, t0, 0x3f);
3124 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3125 opn = "dsrlv";
3126 break;
3127 case OPC_DROTRV:
3128 tcg_gen_andi_tl(t0, t0, 0x3f);
3129 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3130 opn = "drotrv";
3131 break;
3132 #endif
3134 (void)opn; /* avoid a compiler warning */
3135 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3136 tcg_temp_free(t0);
3137 tcg_temp_free(t1);
3140 /* Arithmetic on HI/LO registers */
3141 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3143 const char *opn = "hilo";
3145 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3146 /* Treat as NOP. */
3147 MIPS_DEBUG("NOP");
3148 return;
3151 if (acc != 0) {
3152 check_dsp(ctx);
3155 switch (opc) {
3156 case OPC_MFHI:
3157 #if defined(TARGET_MIPS64)
3158 if (acc != 0) {
3159 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3160 } else
3161 #endif
3163 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3165 opn = "mfhi";
3166 break;
3167 case OPC_MFLO:
3168 #if defined(TARGET_MIPS64)
3169 if (acc != 0) {
3170 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3171 } else
3172 #endif
3174 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3176 opn = "mflo";
3177 break;
3178 case OPC_MTHI:
3179 if (reg != 0) {
3180 #if defined(TARGET_MIPS64)
3181 if (acc != 0) {
3182 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3183 } else
3184 #endif
3186 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3188 } else {
3189 tcg_gen_movi_tl(cpu_HI[acc], 0);
3191 opn = "mthi";
3192 break;
3193 case OPC_MTLO:
3194 if (reg != 0) {
3195 #if defined(TARGET_MIPS64)
3196 if (acc != 0) {
3197 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3198 } else
3199 #endif
3201 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3203 } else {
3204 tcg_gen_movi_tl(cpu_LO[acc], 0);
3206 opn = "mtlo";
3207 break;
3209 (void)opn; /* avoid a compiler warning */
3210 MIPS_DEBUG("%s %s", opn, regnames[reg]);
3213 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3214 TCGMemOp memop)
3216 TCGv t0 = tcg_const_tl(addr);
3217 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3218 gen_store_gpr(t0, reg);
3219 tcg_temp_free(t0);
3222 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3223 int rs)
3225 target_long offset;
3226 target_long addr;
3228 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3229 case OPC_ADDIUPC:
3230 if (rs != 0) {
3231 offset = sextract32(ctx->opcode << 2, 0, 21);
3232 addr = addr_add(ctx, pc, offset);
3233 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3235 break;
3236 case R6_OPC_LWPC:
3237 offset = sextract32(ctx->opcode << 2, 0, 21);
3238 addr = addr_add(ctx, pc, offset);
3239 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3240 break;
3241 #if defined(TARGET_MIPS64)
3242 case OPC_LWUPC:
3243 check_mips_64(ctx);
3244 offset = sextract32(ctx->opcode << 2, 0, 21);
3245 addr = addr_add(ctx, pc, offset);
3246 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3247 break;
3248 #endif
3249 default:
3250 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3251 case OPC_AUIPC:
3252 if (rs != 0) {
3253 offset = sextract32(ctx->opcode, 0, 16) << 16;
3254 addr = addr_add(ctx, pc, offset);
3255 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3257 break;
3258 case OPC_ALUIPC:
3259 if (rs != 0) {
3260 offset = sextract32(ctx->opcode, 0, 16) << 16;
3261 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3262 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3264 break;
3265 #if defined(TARGET_MIPS64)
3266 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3267 case R6_OPC_LDPC + (1 << 16):
3268 case R6_OPC_LDPC + (2 << 16):
3269 case R6_OPC_LDPC + (3 << 16):
3270 check_mips_64(ctx);
3271 offset = sextract32(ctx->opcode << 3, 0, 21);
3272 addr = addr_add(ctx, (pc & ~0x7), offset);
3273 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3274 break;
3275 #endif
3276 default:
3277 MIPS_INVAL("OPC_PCREL");
3278 generate_exception(ctx, EXCP_RI);
3279 break;
3281 break;
3285 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3287 const char *opn = "r6 mul/div";
3288 TCGv t0, t1;
3290 if (rd == 0) {
3291 /* Treat as NOP. */
3292 MIPS_DEBUG("NOP");
3293 return;
3296 t0 = tcg_temp_new();
3297 t1 = tcg_temp_new();
3299 gen_load_gpr(t0, rs);
3300 gen_load_gpr(t1, rt);
3302 switch (opc) {
3303 case R6_OPC_DIV:
3305 TCGv t2 = tcg_temp_new();
3306 TCGv t3 = tcg_temp_new();
3307 tcg_gen_ext32s_tl(t0, t0);
3308 tcg_gen_ext32s_tl(t1, t1);
3309 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3310 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3311 tcg_gen_and_tl(t2, t2, t3);
3312 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3313 tcg_gen_or_tl(t2, t2, t3);
3314 tcg_gen_movi_tl(t3, 0);
3315 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3316 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3317 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3318 tcg_temp_free(t3);
3319 tcg_temp_free(t2);
3321 opn = "div";
3322 break;
3323 case R6_OPC_MOD:
3325 TCGv t2 = tcg_temp_new();
3326 TCGv t3 = tcg_temp_new();
3327 tcg_gen_ext32s_tl(t0, t0);
3328 tcg_gen_ext32s_tl(t1, t1);
3329 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3330 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3331 tcg_gen_and_tl(t2, t2, t3);
3332 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3333 tcg_gen_or_tl(t2, t2, t3);
3334 tcg_gen_movi_tl(t3, 0);
3335 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3336 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3337 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3338 tcg_temp_free(t3);
3339 tcg_temp_free(t2);
3341 opn = "mod";
3342 break;
3343 case R6_OPC_DIVU:
3345 TCGv t2 = tcg_const_tl(0);
3346 TCGv t3 = tcg_const_tl(1);
3347 tcg_gen_ext32u_tl(t0, t0);
3348 tcg_gen_ext32u_tl(t1, t1);
3349 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3350 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3351 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3352 tcg_temp_free(t3);
3353 tcg_temp_free(t2);
3355 opn = "divu";
3356 break;
3357 case R6_OPC_MODU:
3359 TCGv t2 = tcg_const_tl(0);
3360 TCGv t3 = tcg_const_tl(1);
3361 tcg_gen_ext32u_tl(t0, t0);
3362 tcg_gen_ext32u_tl(t1, t1);
3363 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3364 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3365 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3366 tcg_temp_free(t3);
3367 tcg_temp_free(t2);
3369 opn = "modu";
3370 break;
3371 case R6_OPC_MUL:
3373 TCGv_i32 t2 = tcg_temp_new_i32();
3374 TCGv_i32 t3 = tcg_temp_new_i32();
3375 tcg_gen_trunc_tl_i32(t2, t0);
3376 tcg_gen_trunc_tl_i32(t3, t1);
3377 tcg_gen_mul_i32(t2, t2, t3);
3378 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3379 tcg_temp_free_i32(t2);
3380 tcg_temp_free_i32(t3);
3382 opn = "mul";
3383 break;
3384 case R6_OPC_MUH:
3386 TCGv_i32 t2 = tcg_temp_new_i32();
3387 TCGv_i32 t3 = tcg_temp_new_i32();
3388 tcg_gen_trunc_tl_i32(t2, t0);
3389 tcg_gen_trunc_tl_i32(t3, t1);
3390 tcg_gen_muls2_i32(t2, t3, t2, t3);
3391 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3392 tcg_temp_free_i32(t2);
3393 tcg_temp_free_i32(t3);
3395 opn = "muh";
3396 break;
3397 case R6_OPC_MULU:
3399 TCGv_i32 t2 = tcg_temp_new_i32();
3400 TCGv_i32 t3 = tcg_temp_new_i32();
3401 tcg_gen_trunc_tl_i32(t2, t0);
3402 tcg_gen_trunc_tl_i32(t3, t1);
3403 tcg_gen_mul_i32(t2, t2, t3);
3404 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3405 tcg_temp_free_i32(t2);
3406 tcg_temp_free_i32(t3);
3408 opn = "mulu";
3409 break;
3410 case R6_OPC_MUHU:
3412 TCGv_i32 t2 = tcg_temp_new_i32();
3413 TCGv_i32 t3 = tcg_temp_new_i32();
3414 tcg_gen_trunc_tl_i32(t2, t0);
3415 tcg_gen_trunc_tl_i32(t3, t1);
3416 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3417 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3418 tcg_temp_free_i32(t2);
3419 tcg_temp_free_i32(t3);
3421 opn = "muhu";
3422 break;
3423 #if defined(TARGET_MIPS64)
3424 case R6_OPC_DDIV:
3426 TCGv t2 = tcg_temp_new();
3427 TCGv t3 = tcg_temp_new();
3428 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3429 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3430 tcg_gen_and_tl(t2, t2, t3);
3431 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3432 tcg_gen_or_tl(t2, t2, t3);
3433 tcg_gen_movi_tl(t3, 0);
3434 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3435 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3436 tcg_temp_free(t3);
3437 tcg_temp_free(t2);
3439 opn = "ddiv";
3440 break;
3441 case R6_OPC_DMOD:
3443 TCGv t2 = tcg_temp_new();
3444 TCGv t3 = tcg_temp_new();
3445 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3446 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3447 tcg_gen_and_tl(t2, t2, t3);
3448 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3449 tcg_gen_or_tl(t2, t2, t3);
3450 tcg_gen_movi_tl(t3, 0);
3451 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3452 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3453 tcg_temp_free(t3);
3454 tcg_temp_free(t2);
3456 opn = "dmod";
3457 break;
3458 case R6_OPC_DDIVU:
3460 TCGv t2 = tcg_const_tl(0);
3461 TCGv t3 = tcg_const_tl(1);
3462 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3463 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3464 tcg_temp_free(t3);
3465 tcg_temp_free(t2);
3467 opn = "ddivu";
3468 break;
3469 case R6_OPC_DMODU:
3471 TCGv t2 = tcg_const_tl(0);
3472 TCGv t3 = tcg_const_tl(1);
3473 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3474 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3475 tcg_temp_free(t3);
3476 tcg_temp_free(t2);
3478 opn = "dmodu";
3479 break;
3480 case R6_OPC_DMUL:
3481 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3482 opn = "dmul";
3483 break;
3484 case R6_OPC_DMUH:
3486 TCGv t2 = tcg_temp_new();
3487 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3488 tcg_temp_free(t2);
3490 opn = "dmuh";
3491 break;
3492 case R6_OPC_DMULU:
3493 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3494 opn = "dmulu";
3495 break;
3496 case R6_OPC_DMUHU:
3498 TCGv t2 = tcg_temp_new();
3499 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3500 tcg_temp_free(t2);
3502 opn = "dmuhu";
3503 break;
3504 #endif
3505 default:
3506 MIPS_INVAL(opn);
3507 generate_exception(ctx, EXCP_RI);
3508 goto out;
3510 (void)opn; /* avoid a compiler warning */
3511 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3512 out:
3513 tcg_temp_free(t0);
3514 tcg_temp_free(t1);
3517 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3518 int acc, int rs, int rt)
3520 const char *opn = "mul/div";
3521 TCGv t0, t1;
3523 t0 = tcg_temp_new();
3524 t1 = tcg_temp_new();
3526 gen_load_gpr(t0, rs);
3527 gen_load_gpr(t1, rt);
3529 if (acc != 0) {
3530 check_dsp(ctx);
3533 switch (opc) {
3534 case OPC_DIV:
3536 TCGv t2 = tcg_temp_new();
3537 TCGv t3 = tcg_temp_new();
3538 tcg_gen_ext32s_tl(t0, t0);
3539 tcg_gen_ext32s_tl(t1, t1);
3540 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3541 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3542 tcg_gen_and_tl(t2, t2, t3);
3543 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3544 tcg_gen_or_tl(t2, t2, t3);
3545 tcg_gen_movi_tl(t3, 0);
3546 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3547 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3548 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3549 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3550 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3551 tcg_temp_free(t3);
3552 tcg_temp_free(t2);
3554 opn = "div";
3555 break;
3556 case OPC_DIVU:
3558 TCGv t2 = tcg_const_tl(0);
3559 TCGv t3 = tcg_const_tl(1);
3560 tcg_gen_ext32u_tl(t0, t0);
3561 tcg_gen_ext32u_tl(t1, t1);
3562 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3563 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3564 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3565 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3566 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3567 tcg_temp_free(t3);
3568 tcg_temp_free(t2);
3570 opn = "divu";
3571 break;
3572 case OPC_MULT:
3574 TCGv_i32 t2 = tcg_temp_new_i32();
3575 TCGv_i32 t3 = tcg_temp_new_i32();
3576 tcg_gen_trunc_tl_i32(t2, t0);
3577 tcg_gen_trunc_tl_i32(t3, t1);
3578 tcg_gen_muls2_i32(t2, t3, t2, t3);
3579 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3580 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3581 tcg_temp_free_i32(t2);
3582 tcg_temp_free_i32(t3);
3584 opn = "mult";
3585 break;
3586 case OPC_MULTU:
3588 TCGv_i32 t2 = tcg_temp_new_i32();
3589 TCGv_i32 t3 = tcg_temp_new_i32();
3590 tcg_gen_trunc_tl_i32(t2, t0);
3591 tcg_gen_trunc_tl_i32(t3, t1);
3592 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3593 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3594 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3595 tcg_temp_free_i32(t2);
3596 tcg_temp_free_i32(t3);
3598 opn = "multu";
3599 break;
3600 #if defined(TARGET_MIPS64)
3601 case OPC_DDIV:
3603 TCGv t2 = tcg_temp_new();
3604 TCGv t3 = tcg_temp_new();
3605 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3606 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3607 tcg_gen_and_tl(t2, t2, t3);
3608 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3609 tcg_gen_or_tl(t2, t2, t3);
3610 tcg_gen_movi_tl(t3, 0);
3611 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3612 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3613 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3614 tcg_temp_free(t3);
3615 tcg_temp_free(t2);
3617 opn = "ddiv";
3618 break;
3619 case OPC_DDIVU:
3621 TCGv t2 = tcg_const_tl(0);
3622 TCGv t3 = tcg_const_tl(1);
3623 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3624 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3625 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3626 tcg_temp_free(t3);
3627 tcg_temp_free(t2);
3629 opn = "ddivu";
3630 break;
3631 case OPC_DMULT:
3632 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3633 opn = "dmult";
3634 break;
3635 case OPC_DMULTU:
3636 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3637 opn = "dmultu";
3638 break;
3639 #endif
3640 case OPC_MADD:
3642 TCGv_i64 t2 = tcg_temp_new_i64();
3643 TCGv_i64 t3 = tcg_temp_new_i64();
3645 tcg_gen_ext_tl_i64(t2, t0);
3646 tcg_gen_ext_tl_i64(t3, t1);
3647 tcg_gen_mul_i64(t2, t2, t3);
3648 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3649 tcg_gen_add_i64(t2, t2, t3);
3650 tcg_temp_free_i64(t3);
3651 tcg_gen_trunc_i64_tl(t0, t2);
3652 tcg_gen_shri_i64(t2, t2, 32);
3653 tcg_gen_trunc_i64_tl(t1, t2);
3654 tcg_temp_free_i64(t2);
3655 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3656 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3658 opn = "madd";
3659 break;
3660 case OPC_MADDU:
3662 TCGv_i64 t2 = tcg_temp_new_i64();
3663 TCGv_i64 t3 = tcg_temp_new_i64();
3665 tcg_gen_ext32u_tl(t0, t0);
3666 tcg_gen_ext32u_tl(t1, t1);
3667 tcg_gen_extu_tl_i64(t2, t0);
3668 tcg_gen_extu_tl_i64(t3, t1);
3669 tcg_gen_mul_i64(t2, t2, t3);
3670 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3671 tcg_gen_add_i64(t2, t2, t3);
3672 tcg_temp_free_i64(t3);
3673 tcg_gen_trunc_i64_tl(t0, t2);
3674 tcg_gen_shri_i64(t2, t2, 32);
3675 tcg_gen_trunc_i64_tl(t1, t2);
3676 tcg_temp_free_i64(t2);
3677 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3678 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3680 opn = "maddu";
3681 break;
3682 case OPC_MSUB:
3684 TCGv_i64 t2 = tcg_temp_new_i64();
3685 TCGv_i64 t3 = tcg_temp_new_i64();
3687 tcg_gen_ext_tl_i64(t2, t0);
3688 tcg_gen_ext_tl_i64(t3, t1);
3689 tcg_gen_mul_i64(t2, t2, t3);
3690 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3691 tcg_gen_sub_i64(t2, t3, t2);
3692 tcg_temp_free_i64(t3);
3693 tcg_gen_trunc_i64_tl(t0, t2);
3694 tcg_gen_shri_i64(t2, t2, 32);
3695 tcg_gen_trunc_i64_tl(t1, t2);
3696 tcg_temp_free_i64(t2);
3697 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3698 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3700 opn = "msub";
3701 break;
3702 case OPC_MSUBU:
3704 TCGv_i64 t2 = tcg_temp_new_i64();
3705 TCGv_i64 t3 = tcg_temp_new_i64();
3707 tcg_gen_ext32u_tl(t0, t0);
3708 tcg_gen_ext32u_tl(t1, t1);
3709 tcg_gen_extu_tl_i64(t2, t0);
3710 tcg_gen_extu_tl_i64(t3, t1);
3711 tcg_gen_mul_i64(t2, t2, t3);
3712 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3713 tcg_gen_sub_i64(t2, t3, t2);
3714 tcg_temp_free_i64(t3);
3715 tcg_gen_trunc_i64_tl(t0, t2);
3716 tcg_gen_shri_i64(t2, t2, 32);
3717 tcg_gen_trunc_i64_tl(t1, t2);
3718 tcg_temp_free_i64(t2);
3719 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3720 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3722 opn = "msubu";
3723 break;
3724 default:
3725 MIPS_INVAL(opn);
3726 generate_exception(ctx, EXCP_RI);
3727 goto out;
3729 (void)opn; /* avoid a compiler warning */
3730 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3731 out:
3732 tcg_temp_free(t0);
3733 tcg_temp_free(t1);
3736 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3737 int rd, int rs, int rt)
3739 const char *opn = "mul vr54xx";
3740 TCGv t0 = tcg_temp_new();
3741 TCGv t1 = tcg_temp_new();
3743 gen_load_gpr(t0, rs);
3744 gen_load_gpr(t1, rt);
3746 switch (opc) {
3747 case OPC_VR54XX_MULS:
3748 gen_helper_muls(t0, cpu_env, t0, t1);
3749 opn = "muls";
3750 break;
3751 case OPC_VR54XX_MULSU:
3752 gen_helper_mulsu(t0, cpu_env, t0, t1);
3753 opn = "mulsu";
3754 break;
3755 case OPC_VR54XX_MACC:
3756 gen_helper_macc(t0, cpu_env, t0, t1);
3757 opn = "macc";
3758 break;
3759 case OPC_VR54XX_MACCU:
3760 gen_helper_maccu(t0, cpu_env, t0, t1);
3761 opn = "maccu";
3762 break;
3763 case OPC_VR54XX_MSAC:
3764 gen_helper_msac(t0, cpu_env, t0, t1);
3765 opn = "msac";
3766 break;
3767 case OPC_VR54XX_MSACU:
3768 gen_helper_msacu(t0, cpu_env, t0, t1);
3769 opn = "msacu";
3770 break;
3771 case OPC_VR54XX_MULHI:
3772 gen_helper_mulhi(t0, cpu_env, t0, t1);
3773 opn = "mulhi";
3774 break;
3775 case OPC_VR54XX_MULHIU:
3776 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3777 opn = "mulhiu";
3778 break;
3779 case OPC_VR54XX_MULSHI:
3780 gen_helper_mulshi(t0, cpu_env, t0, t1);
3781 opn = "mulshi";
3782 break;
3783 case OPC_VR54XX_MULSHIU:
3784 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3785 opn = "mulshiu";
3786 break;
3787 case OPC_VR54XX_MACCHI:
3788 gen_helper_macchi(t0, cpu_env, t0, t1);
3789 opn = "macchi";
3790 break;
3791 case OPC_VR54XX_MACCHIU:
3792 gen_helper_macchiu(t0, cpu_env, t0, t1);
3793 opn = "macchiu";
3794 break;
3795 case OPC_VR54XX_MSACHI:
3796 gen_helper_msachi(t0, cpu_env, t0, t1);
3797 opn = "msachi";
3798 break;
3799 case OPC_VR54XX_MSACHIU:
3800 gen_helper_msachiu(t0, cpu_env, t0, t1);
3801 opn = "msachiu";
3802 break;
3803 default:
3804 MIPS_INVAL("mul vr54xx");
3805 generate_exception(ctx, EXCP_RI);
3806 goto out;
3808 gen_store_gpr(t0, rd);
3809 (void)opn; /* avoid a compiler warning */
3810 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3812 out:
3813 tcg_temp_free(t0);
3814 tcg_temp_free(t1);
3817 static void gen_cl (DisasContext *ctx, uint32_t opc,
3818 int rd, int rs)
3820 const char *opn = "CLx";
3821 TCGv t0;
3823 if (rd == 0) {
3824 /* Treat as NOP. */
3825 MIPS_DEBUG("NOP");
3826 return;
3828 t0 = tcg_temp_new();
3829 gen_load_gpr(t0, rs);
3830 switch (opc) {
3831 case OPC_CLO:
3832 case R6_OPC_CLO:
3833 gen_helper_clo(cpu_gpr[rd], t0);
3834 opn = "clo";
3835 break;
3836 case OPC_CLZ:
3837 case R6_OPC_CLZ:
3838 gen_helper_clz(cpu_gpr[rd], t0);
3839 opn = "clz";
3840 break;
3841 #if defined(TARGET_MIPS64)
3842 case OPC_DCLO:
3843 case R6_OPC_DCLO:
3844 gen_helper_dclo(cpu_gpr[rd], t0);
3845 opn = "dclo";
3846 break;
3847 case OPC_DCLZ:
3848 case R6_OPC_DCLZ:
3849 gen_helper_dclz(cpu_gpr[rd], t0);
3850 opn = "dclz";
3851 break;
3852 #endif
3854 (void)opn; /* avoid a compiler warning */
3855 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3856 tcg_temp_free(t0);
3859 /* Godson integer instructions */
3860 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3861 int rd, int rs, int rt)
3863 const char *opn = "loongson";
3864 TCGv t0, t1;
3866 if (rd == 0) {
3867 /* Treat as NOP. */
3868 MIPS_DEBUG("NOP");
3869 return;
3872 switch (opc) {
3873 case OPC_MULT_G_2E:
3874 case OPC_MULT_G_2F:
3875 case OPC_MULTU_G_2E:
3876 case OPC_MULTU_G_2F:
3877 #if defined(TARGET_MIPS64)
3878 case OPC_DMULT_G_2E:
3879 case OPC_DMULT_G_2F:
3880 case OPC_DMULTU_G_2E:
3881 case OPC_DMULTU_G_2F:
3882 #endif
3883 t0 = tcg_temp_new();
3884 t1 = tcg_temp_new();
3885 break;
3886 default:
3887 t0 = tcg_temp_local_new();
3888 t1 = tcg_temp_local_new();
3889 break;
3892 gen_load_gpr(t0, rs);
3893 gen_load_gpr(t1, rt);
3895 switch (opc) {
3896 case OPC_MULT_G_2E:
3897 case OPC_MULT_G_2F:
3898 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3899 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3900 opn = "mult.g";
3901 break;
3902 case OPC_MULTU_G_2E:
3903 case OPC_MULTU_G_2F:
3904 tcg_gen_ext32u_tl(t0, t0);
3905 tcg_gen_ext32u_tl(t1, t1);
3906 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3907 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3908 opn = "multu.g";
3909 break;
3910 case OPC_DIV_G_2E:
3911 case OPC_DIV_G_2F:
3913 TCGLabel *l1 = gen_new_label();
3914 TCGLabel *l2 = gen_new_label();
3915 TCGLabel *l3 = gen_new_label();
3916 tcg_gen_ext32s_tl(t0, t0);
3917 tcg_gen_ext32s_tl(t1, t1);
3918 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3919 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3920 tcg_gen_br(l3);
3921 gen_set_label(l1);
3922 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3923 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3924 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3925 tcg_gen_br(l3);
3926 gen_set_label(l2);
3927 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3928 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3929 gen_set_label(l3);
3931 opn = "div.g";
3932 break;
3933 case OPC_DIVU_G_2E:
3934 case OPC_DIVU_G_2F:
3936 TCGLabel *l1 = gen_new_label();
3937 TCGLabel *l2 = gen_new_label();
3938 tcg_gen_ext32u_tl(t0, t0);
3939 tcg_gen_ext32u_tl(t1, t1);
3940 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3941 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3942 tcg_gen_br(l2);
3943 gen_set_label(l1);
3944 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3945 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3946 gen_set_label(l2);
3948 opn = "divu.g";
3949 break;
3950 case OPC_MOD_G_2E:
3951 case OPC_MOD_G_2F:
3953 TCGLabel *l1 = gen_new_label();
3954 TCGLabel *l2 = gen_new_label();
3955 TCGLabel *l3 = gen_new_label();
3956 tcg_gen_ext32u_tl(t0, t0);
3957 tcg_gen_ext32u_tl(t1, t1);
3958 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3959 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3960 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3961 gen_set_label(l1);
3962 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3963 tcg_gen_br(l3);
3964 gen_set_label(l2);
3965 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3966 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3967 gen_set_label(l3);
3969 opn = "mod.g";
3970 break;
3971 case OPC_MODU_G_2E:
3972 case OPC_MODU_G_2F:
3974 TCGLabel *l1 = gen_new_label();
3975 TCGLabel *l2 = gen_new_label();
3976 tcg_gen_ext32u_tl(t0, t0);
3977 tcg_gen_ext32u_tl(t1, t1);
3978 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3979 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3980 tcg_gen_br(l2);
3981 gen_set_label(l1);
3982 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3983 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3984 gen_set_label(l2);
3986 opn = "modu.g";
3987 break;
3988 #if defined(TARGET_MIPS64)
3989 case OPC_DMULT_G_2E:
3990 case OPC_DMULT_G_2F:
3991 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3992 opn = "dmult.g";
3993 break;
3994 case OPC_DMULTU_G_2E:
3995 case OPC_DMULTU_G_2F:
3996 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3997 opn = "dmultu.g";
3998 break;
3999 case OPC_DDIV_G_2E:
4000 case OPC_DDIV_G_2F:
4002 TCGLabel *l1 = gen_new_label();
4003 TCGLabel *l2 = gen_new_label();
4004 TCGLabel *l3 = gen_new_label();
4005 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4006 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4007 tcg_gen_br(l3);
4008 gen_set_label(l1);
4009 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4010 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4011 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4012 tcg_gen_br(l3);
4013 gen_set_label(l2);
4014 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4015 gen_set_label(l3);
4017 opn = "ddiv.g";
4018 break;
4019 case OPC_DDIVU_G_2E:
4020 case OPC_DDIVU_G_2F:
4022 TCGLabel *l1 = gen_new_label();
4023 TCGLabel *l2 = gen_new_label();
4024 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4025 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4026 tcg_gen_br(l2);
4027 gen_set_label(l1);
4028 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4029 gen_set_label(l2);
4031 opn = "ddivu.g";
4032 break;
4033 case OPC_DMOD_G_2E:
4034 case OPC_DMOD_G_2F:
4036 TCGLabel *l1 = gen_new_label();
4037 TCGLabel *l2 = gen_new_label();
4038 TCGLabel *l3 = gen_new_label();
4039 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4040 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4041 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4042 gen_set_label(l1);
4043 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4044 tcg_gen_br(l3);
4045 gen_set_label(l2);
4046 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4047 gen_set_label(l3);
4049 opn = "dmod.g";
4050 break;
4051 case OPC_DMODU_G_2E:
4052 case OPC_DMODU_G_2F:
4054 TCGLabel *l1 = gen_new_label();
4055 TCGLabel *l2 = gen_new_label();
4056 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4057 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4058 tcg_gen_br(l2);
4059 gen_set_label(l1);
4060 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4061 gen_set_label(l2);
4063 opn = "dmodu.g";
4064 break;
4065 #endif
4068 (void)opn; /* avoid a compiler warning */
4069 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
4070 tcg_temp_free(t0);
4071 tcg_temp_free(t1);
4074 /* Loongson multimedia instructions */
4075 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4077 const char *opn = "loongson_cp2";
4078 uint32_t opc, shift_max;
4079 TCGv_i64 t0, t1;
4081 opc = MASK_LMI(ctx->opcode);
4082 switch (opc) {
4083 case OPC_ADD_CP2:
4084 case OPC_SUB_CP2:
4085 case OPC_DADD_CP2:
4086 case OPC_DSUB_CP2:
4087 t0 = tcg_temp_local_new_i64();
4088 t1 = tcg_temp_local_new_i64();
4089 break;
4090 default:
4091 t0 = tcg_temp_new_i64();
4092 t1 = tcg_temp_new_i64();
4093 break;
4096 gen_load_fpr64(ctx, t0, rs);
4097 gen_load_fpr64(ctx, t1, rt);
4099 #define LMI_HELPER(UP, LO) \
4100 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
4101 #define LMI_HELPER_1(UP, LO) \
4102 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
4103 #define LMI_DIRECT(UP, LO, OP) \
4104 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
4106 switch (opc) {
4107 LMI_HELPER(PADDSH, paddsh);
4108 LMI_HELPER(PADDUSH, paddush);
4109 LMI_HELPER(PADDH, paddh);
4110 LMI_HELPER(PADDW, paddw);
4111 LMI_HELPER(PADDSB, paddsb);
4112 LMI_HELPER(PADDUSB, paddusb);
4113 LMI_HELPER(PADDB, paddb);
4115 LMI_HELPER(PSUBSH, psubsh);
4116 LMI_HELPER(PSUBUSH, psubush);
4117 LMI_HELPER(PSUBH, psubh);
4118 LMI_HELPER(PSUBW, psubw);
4119 LMI_HELPER(PSUBSB, psubsb);
4120 LMI_HELPER(PSUBUSB, psubusb);
4121 LMI_HELPER(PSUBB, psubb);
4123 LMI_HELPER(PSHUFH, pshufh);
4124 LMI_HELPER(PACKSSWH, packsswh);
4125 LMI_HELPER(PACKSSHB, packsshb);
4126 LMI_HELPER(PACKUSHB, packushb);
4128 LMI_HELPER(PUNPCKLHW, punpcklhw);
4129 LMI_HELPER(PUNPCKHHW, punpckhhw);
4130 LMI_HELPER(PUNPCKLBH, punpcklbh);
4131 LMI_HELPER(PUNPCKHBH, punpckhbh);
4132 LMI_HELPER(PUNPCKLWD, punpcklwd);
4133 LMI_HELPER(PUNPCKHWD, punpckhwd);
4135 LMI_HELPER(PAVGH, pavgh);
4136 LMI_HELPER(PAVGB, pavgb);
4137 LMI_HELPER(PMAXSH, pmaxsh);
4138 LMI_HELPER(PMINSH, pminsh);
4139 LMI_HELPER(PMAXUB, pmaxub);
4140 LMI_HELPER(PMINUB, pminub);
4142 LMI_HELPER(PCMPEQW, pcmpeqw);
4143 LMI_HELPER(PCMPGTW, pcmpgtw);
4144 LMI_HELPER(PCMPEQH, pcmpeqh);
4145 LMI_HELPER(PCMPGTH, pcmpgth);
4146 LMI_HELPER(PCMPEQB, pcmpeqb);
4147 LMI_HELPER(PCMPGTB, pcmpgtb);
4149 LMI_HELPER(PSLLW, psllw);
4150 LMI_HELPER(PSLLH, psllh);
4151 LMI_HELPER(PSRLW, psrlw);
4152 LMI_HELPER(PSRLH, psrlh);
4153 LMI_HELPER(PSRAW, psraw);
4154 LMI_HELPER(PSRAH, psrah);
4156 LMI_HELPER(PMULLH, pmullh);
4157 LMI_HELPER(PMULHH, pmulhh);
4158 LMI_HELPER(PMULHUH, pmulhuh);
4159 LMI_HELPER(PMADDHW, pmaddhw);
4161 LMI_HELPER(PASUBUB, pasubub);
4162 LMI_HELPER_1(BIADD, biadd);
4163 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4165 LMI_DIRECT(PADDD, paddd, add);
4166 LMI_DIRECT(PSUBD, psubd, sub);
4167 LMI_DIRECT(XOR_CP2, xor, xor);
4168 LMI_DIRECT(NOR_CP2, nor, nor);
4169 LMI_DIRECT(AND_CP2, and, and);
4170 LMI_DIRECT(PANDN, pandn, andc);
4171 LMI_DIRECT(OR, or, or);
4173 case OPC_PINSRH_0:
4174 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4175 opn = "pinsrh_0";
4176 break;
4177 case OPC_PINSRH_1:
4178 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4179 opn = "pinsrh_1";
4180 break;
4181 case OPC_PINSRH_2:
4182 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4183 opn = "pinsrh_2";
4184 break;
4185 case OPC_PINSRH_3:
4186 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4187 opn = "pinsrh_3";
4188 break;
4190 case OPC_PEXTRH:
4191 tcg_gen_andi_i64(t1, t1, 3);
4192 tcg_gen_shli_i64(t1, t1, 4);
4193 tcg_gen_shr_i64(t0, t0, t1);
4194 tcg_gen_ext16u_i64(t0, t0);
4195 opn = "pextrh";
4196 break;
4198 case OPC_ADDU_CP2:
4199 tcg_gen_add_i64(t0, t0, t1);
4200 tcg_gen_ext32s_i64(t0, t0);
4201 opn = "addu";
4202 break;
4203 case OPC_SUBU_CP2:
4204 tcg_gen_sub_i64(t0, t0, t1);
4205 tcg_gen_ext32s_i64(t0, t0);
4206 opn = "addu";
4207 break;
4209 case OPC_SLL_CP2:
4210 opn = "sll";
4211 shift_max = 32;
4212 goto do_shift;
4213 case OPC_SRL_CP2:
4214 opn = "srl";
4215 shift_max = 32;
4216 goto do_shift;
4217 case OPC_SRA_CP2:
4218 opn = "sra";
4219 shift_max = 32;
4220 goto do_shift;
4221 case OPC_DSLL_CP2:
4222 opn = "dsll";
4223 shift_max = 64;
4224 goto do_shift;
4225 case OPC_DSRL_CP2:
4226 opn = "dsrl";
4227 shift_max = 64;
4228 goto do_shift;
4229 case OPC_DSRA_CP2:
4230 opn = "dsra";
4231 shift_max = 64;
4232 goto do_shift;
4233 do_shift:
4234 /* Make sure shift count isn't TCG undefined behaviour. */
4235 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4237 switch (opc) {
4238 case OPC_SLL_CP2:
4239 case OPC_DSLL_CP2:
4240 tcg_gen_shl_i64(t0, t0, t1);
4241 break;
4242 case OPC_SRA_CP2:
4243 case OPC_DSRA_CP2:
4244 /* Since SRA is UndefinedResult without sign-extended inputs,
4245 we can treat SRA and DSRA the same. */
4246 tcg_gen_sar_i64(t0, t0, t1);
4247 break;
4248 case OPC_SRL_CP2:
4249 /* We want to shift in zeros for SRL; zero-extend first. */
4250 tcg_gen_ext32u_i64(t0, t0);
4251 /* FALLTHRU */
4252 case OPC_DSRL_CP2:
4253 tcg_gen_shr_i64(t0, t0, t1);
4254 break;
4257 if (shift_max == 32) {
4258 tcg_gen_ext32s_i64(t0, t0);
4261 /* Shifts larger than MAX produce zero. */
4262 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4263 tcg_gen_neg_i64(t1, t1);
4264 tcg_gen_and_i64(t0, t0, t1);
4265 break;
4267 case OPC_ADD_CP2:
4268 case OPC_DADD_CP2:
4270 TCGv_i64 t2 = tcg_temp_new_i64();
4271 TCGLabel *lab = gen_new_label();
4273 tcg_gen_mov_i64(t2, t0);
4274 tcg_gen_add_i64(t0, t1, t2);
4275 if (opc == OPC_ADD_CP2) {
4276 tcg_gen_ext32s_i64(t0, t0);
4278 tcg_gen_xor_i64(t1, t1, t2);
4279 tcg_gen_xor_i64(t2, t2, t0);
4280 tcg_gen_andc_i64(t1, t2, t1);
4281 tcg_temp_free_i64(t2);
4282 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4283 generate_exception(ctx, EXCP_OVERFLOW);
4284 gen_set_label(lab);
4286 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
4287 break;
4290 case OPC_SUB_CP2:
4291 case OPC_DSUB_CP2:
4293 TCGv_i64 t2 = tcg_temp_new_i64();
4294 TCGLabel *lab = gen_new_label();
4296 tcg_gen_mov_i64(t2, t0);
4297 tcg_gen_sub_i64(t0, t1, t2);
4298 if (opc == OPC_SUB_CP2) {
4299 tcg_gen_ext32s_i64(t0, t0);
4301 tcg_gen_xor_i64(t1, t1, t2);
4302 tcg_gen_xor_i64(t2, t2, t0);
4303 tcg_gen_and_i64(t1, t1, t2);
4304 tcg_temp_free_i64(t2);
4305 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4306 generate_exception(ctx, EXCP_OVERFLOW);
4307 gen_set_label(lab);
4309 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
4310 break;
4313 case OPC_PMULUW:
4314 tcg_gen_ext32u_i64(t0, t0);
4315 tcg_gen_ext32u_i64(t1, t1);
4316 tcg_gen_mul_i64(t0, t0, t1);
4317 opn = "pmuluw";
4318 break;
4320 case OPC_SEQU_CP2:
4321 case OPC_SEQ_CP2:
4322 case OPC_SLTU_CP2:
4323 case OPC_SLT_CP2:
4324 case OPC_SLEU_CP2:
4325 case OPC_SLE_CP2:
4326 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4327 FD field is the CC field? */
4328 default:
4329 MIPS_INVAL(opn);
4330 generate_exception(ctx, EXCP_RI);
4331 return;
4334 #undef LMI_HELPER
4335 #undef LMI_DIRECT
4337 gen_store_fpr64(ctx, t0, rd);
4339 (void)opn; /* avoid a compiler warning */
4340 MIPS_DEBUG("%s %s, %s, %s", opn,
4341 fregnames[rd], fregnames[rs], fregnames[rt]);
4342 tcg_temp_free_i64(t0);
4343 tcg_temp_free_i64(t1);
4346 /* Traps */
4347 static void gen_trap (DisasContext *ctx, uint32_t opc,
4348 int rs, int rt, int16_t imm)
4350 int cond;
4351 TCGv t0 = tcg_temp_new();
4352 TCGv t1 = tcg_temp_new();
4354 cond = 0;
4355 /* Load needed operands */
4356 switch (opc) {
4357 case OPC_TEQ:
4358 case OPC_TGE:
4359 case OPC_TGEU:
4360 case OPC_TLT:
4361 case OPC_TLTU:
4362 case OPC_TNE:
4363 /* Compare two registers */
4364 if (rs != rt) {
4365 gen_load_gpr(t0, rs);
4366 gen_load_gpr(t1, rt);
4367 cond = 1;
4369 break;
4370 case OPC_TEQI:
4371 case OPC_TGEI:
4372 case OPC_TGEIU:
4373 case OPC_TLTI:
4374 case OPC_TLTIU:
4375 case OPC_TNEI:
4376 /* Compare register to immediate */
4377 if (rs != 0 || imm != 0) {
4378 gen_load_gpr(t0, rs);
4379 tcg_gen_movi_tl(t1, (int32_t)imm);
4380 cond = 1;
4382 break;
4384 if (cond == 0) {
4385 switch (opc) {
4386 case OPC_TEQ: /* rs == rs */
4387 case OPC_TEQI: /* r0 == 0 */
4388 case OPC_TGE: /* rs >= rs */
4389 case OPC_TGEI: /* r0 >= 0 */
4390 case OPC_TGEU: /* rs >= rs unsigned */
4391 case OPC_TGEIU: /* r0 >= 0 unsigned */
4392 /* Always trap */
4393 generate_exception(ctx, EXCP_TRAP);
4394 break;
4395 case OPC_TLT: /* rs < rs */
4396 case OPC_TLTI: /* r0 < 0 */
4397 case OPC_TLTU: /* rs < rs unsigned */
4398 case OPC_TLTIU: /* r0 < 0 unsigned */
4399 case OPC_TNE: /* rs != rs */
4400 case OPC_TNEI: /* r0 != 0 */
4401 /* Never trap: treat as NOP. */
4402 break;
4404 } else {
4405 TCGLabel *l1 = gen_new_label();
4407 switch (opc) {
4408 case OPC_TEQ:
4409 case OPC_TEQI:
4410 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4411 break;
4412 case OPC_TGE:
4413 case OPC_TGEI:
4414 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4415 break;
4416 case OPC_TGEU:
4417 case OPC_TGEIU:
4418 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4419 break;
4420 case OPC_TLT:
4421 case OPC_TLTI:
4422 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4423 break;
4424 case OPC_TLTU:
4425 case OPC_TLTIU:
4426 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4427 break;
4428 case OPC_TNE:
4429 case OPC_TNEI:
4430 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4431 break;
4433 generate_exception(ctx, EXCP_TRAP);
4434 gen_set_label(l1);
4436 tcg_temp_free(t0);
4437 tcg_temp_free(t1);
4440 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4442 TranslationBlock *tb;
4443 tb = ctx->tb;
4444 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
4445 likely(!ctx->singlestep_enabled)) {
4446 tcg_gen_goto_tb(n);
4447 gen_save_pc(dest);
4448 tcg_gen_exit_tb((uintptr_t)tb + n);
4449 } else {
4450 gen_save_pc(dest);
4451 if (ctx->singlestep_enabled) {
4452 save_cpu_state(ctx, 0);
4453 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
4455 tcg_gen_exit_tb(0);
4459 /* Branches (before delay slot) */
4460 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4461 int insn_bytes,
4462 int rs, int rt, int32_t offset,
4463 int delayslot_size)
4465 target_ulong btgt = -1;
4466 int blink = 0;
4467 int bcond_compute = 0;
4468 TCGv t0 = tcg_temp_new();
4469 TCGv t1 = tcg_temp_new();
4471 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4472 #ifdef MIPS_DEBUG_DISAS
4473 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4474 TARGET_FMT_lx "\n", ctx->pc);
4475 #endif
4476 generate_exception(ctx, EXCP_RI);
4477 goto out;
4480 /* Load needed operands */
4481 switch (opc) {
4482 case OPC_BEQ:
4483 case OPC_BEQL:
4484 case OPC_BNE:
4485 case OPC_BNEL:
4486 /* Compare two registers */
4487 if (rs != rt) {
4488 gen_load_gpr(t0, rs);
4489 gen_load_gpr(t1, rt);
4490 bcond_compute = 1;
4492 btgt = ctx->pc + insn_bytes + offset;
4493 break;
4494 case OPC_BGEZ:
4495 case OPC_BGEZAL:
4496 case OPC_BGEZALL:
4497 case OPC_BGEZL:
4498 case OPC_BGTZ:
4499 case OPC_BGTZL:
4500 case OPC_BLEZ:
4501 case OPC_BLEZL:
4502 case OPC_BLTZ:
4503 case OPC_BLTZAL:
4504 case OPC_BLTZALL:
4505 case OPC_BLTZL:
4506 /* Compare to zero */
4507 if (rs != 0) {
4508 gen_load_gpr(t0, rs);
4509 bcond_compute = 1;
4511 btgt = ctx->pc + insn_bytes + offset;
4512 break;
4513 case OPC_BPOSGE32:
4514 #if defined(TARGET_MIPS64)
4515 case OPC_BPOSGE64:
4516 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4517 #else
4518 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4519 #endif
4520 bcond_compute = 1;
4521 btgt = ctx->pc + insn_bytes + offset;
4522 break;
4523 case OPC_J:
4524 case OPC_JAL:
4525 case OPC_JALX:
4526 /* Jump to immediate */
4527 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4528 break;
4529 case OPC_JR:
4530 case OPC_JALR:
4531 /* Jump to register */
4532 if (offset != 0 && offset != 16) {
4533 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4534 others are reserved. */
4535 MIPS_INVAL("jump hint");
4536 generate_exception(ctx, EXCP_RI);
4537 goto out;
4539 gen_load_gpr(btarget, rs);
4540 break;
4541 default:
4542 MIPS_INVAL("branch/jump");
4543 generate_exception(ctx, EXCP_RI);
4544 goto out;
4546 if (bcond_compute == 0) {
4547 /* No condition to be computed */
4548 switch (opc) {
4549 case OPC_BEQ: /* rx == rx */
4550 case OPC_BEQL: /* rx == rx likely */
4551 case OPC_BGEZ: /* 0 >= 0 */
4552 case OPC_BGEZL: /* 0 >= 0 likely */
4553 case OPC_BLEZ: /* 0 <= 0 */
4554 case OPC_BLEZL: /* 0 <= 0 likely */
4555 /* Always take */
4556 ctx->hflags |= MIPS_HFLAG_B;
4557 MIPS_DEBUG("balways");
4558 break;
4559 case OPC_BGEZAL: /* 0 >= 0 */
4560 case OPC_BGEZALL: /* 0 >= 0 likely */
4561 /* Always take and link */
4562 blink = 31;
4563 ctx->hflags |= MIPS_HFLAG_B;
4564 MIPS_DEBUG("balways and link");
4565 break;
4566 case OPC_BNE: /* rx != rx */
4567 case OPC_BGTZ: /* 0 > 0 */
4568 case OPC_BLTZ: /* 0 < 0 */
4569 /* Treat as NOP. */
4570 MIPS_DEBUG("bnever (NOP)");
4571 goto out;
4572 case OPC_BLTZAL: /* 0 < 0 */
4573 /* Handle as an unconditional branch to get correct delay
4574 slot checking. */
4575 blink = 31;
4576 btgt = ctx->pc + insn_bytes + delayslot_size;
4577 ctx->hflags |= MIPS_HFLAG_B;
4578 MIPS_DEBUG("bnever and link");
4579 break;
4580 case OPC_BLTZALL: /* 0 < 0 likely */
4581 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4582 /* Skip the instruction in the delay slot */
4583 MIPS_DEBUG("bnever, link and skip");
4584 ctx->pc += 4;
4585 goto out;
4586 case OPC_BNEL: /* rx != rx likely */
4587 case OPC_BGTZL: /* 0 > 0 likely */
4588 case OPC_BLTZL: /* 0 < 0 likely */
4589 /* Skip the instruction in the delay slot */
4590 MIPS_DEBUG("bnever and skip");
4591 ctx->pc += 4;
4592 goto out;
4593 case OPC_J:
4594 ctx->hflags |= MIPS_HFLAG_B;
4595 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
4596 break;
4597 case OPC_JALX:
4598 ctx->hflags |= MIPS_HFLAG_BX;
4599 /* Fallthrough */
4600 case OPC_JAL:
4601 blink = 31;
4602 ctx->hflags |= MIPS_HFLAG_B;
4603 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
4604 break;
4605 case OPC_JR:
4606 ctx->hflags |= MIPS_HFLAG_BR;
4607 MIPS_DEBUG("jr %s", regnames[rs]);
4608 break;
4609 case OPC_JALR:
4610 blink = rt;
4611 ctx->hflags |= MIPS_HFLAG_BR;
4612 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
4613 break;
4614 default:
4615 MIPS_INVAL("branch/jump");
4616 generate_exception(ctx, EXCP_RI);
4617 goto out;
4619 } else {
4620 switch (opc) {
4621 case OPC_BEQ:
4622 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4623 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
4624 regnames[rs], regnames[rt], btgt);
4625 goto not_likely;
4626 case OPC_BEQL:
4627 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4628 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
4629 regnames[rs], regnames[rt], btgt);
4630 goto likely;
4631 case OPC_BNE:
4632 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4633 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
4634 regnames[rs], regnames[rt], btgt);
4635 goto not_likely;
4636 case OPC_BNEL:
4637 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4638 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
4639 regnames[rs], regnames[rt], btgt);
4640 goto likely;
4641 case OPC_BGEZ:
4642 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4643 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4644 goto not_likely;
4645 case OPC_BGEZL:
4646 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4647 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4648 goto likely;
4649 case OPC_BGEZAL:
4650 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4651 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4652 blink = 31;
4653 goto not_likely;
4654 case OPC_BGEZALL:
4655 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4656 blink = 31;
4657 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4658 goto likely;
4659 case OPC_BGTZ:
4660 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4661 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4662 goto not_likely;
4663 case OPC_BGTZL:
4664 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4665 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4666 goto likely;
4667 case OPC_BLEZ:
4668 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4669 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4670 goto not_likely;
4671 case OPC_BLEZL:
4672 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4673 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4674 goto likely;
4675 case OPC_BLTZ:
4676 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4677 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4678 goto not_likely;
4679 case OPC_BLTZL:
4680 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4681 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4682 goto likely;
4683 case OPC_BPOSGE32:
4684 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4685 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
4686 goto not_likely;
4687 #if defined(TARGET_MIPS64)
4688 case OPC_BPOSGE64:
4689 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4690 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
4691 goto not_likely;
4692 #endif
4693 case OPC_BLTZAL:
4694 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4695 blink = 31;
4696 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4697 not_likely:
4698 ctx->hflags |= MIPS_HFLAG_BC;
4699 break;
4700 case OPC_BLTZALL:
4701 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4702 blink = 31;
4703 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4704 likely:
4705 ctx->hflags |= MIPS_HFLAG_BL;
4706 break;
4707 default:
4708 MIPS_INVAL("conditional branch/jump");
4709 generate_exception(ctx, EXCP_RI);
4710 goto out;
4713 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
4714 blink, ctx->hflags, btgt);
4716 ctx->btarget = btgt;
4718 switch (delayslot_size) {
4719 case 2:
4720 ctx->hflags |= MIPS_HFLAG_BDS16;
4721 break;
4722 case 4:
4723 ctx->hflags |= MIPS_HFLAG_BDS32;
4724 break;
4727 if (blink > 0) {
4728 int post_delay = insn_bytes + delayslot_size;
4729 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4731 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4734 out:
4735 if (insn_bytes == 2)
4736 ctx->hflags |= MIPS_HFLAG_B16;
4737 tcg_temp_free(t0);
4738 tcg_temp_free(t1);
4741 /* special3 bitfield operations */
4742 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4743 int rs, int lsb, int msb)
4745 TCGv t0 = tcg_temp_new();
4746 TCGv t1 = tcg_temp_new();
4748 gen_load_gpr(t1, rs);
4749 switch (opc) {
4750 case OPC_EXT:
4751 if (lsb + msb > 31) {
4752 goto fail;
4754 tcg_gen_shri_tl(t0, t1, lsb);
4755 if (msb != 31) {
4756 tcg_gen_andi_tl(t0, t0, (1U << (msb + 1)) - 1);
4757 } else {
4758 tcg_gen_ext32s_tl(t0, t0);
4760 break;
4761 #if defined(TARGET_MIPS64)
4762 case OPC_DEXTU:
4763 lsb += 32;
4764 goto do_dext;
4765 case OPC_DEXTM:
4766 msb += 32;
4767 goto do_dext;
4768 case OPC_DEXT:
4769 do_dext:
4770 if (lsb + msb > 63) {
4771 goto fail;
4773 tcg_gen_shri_tl(t0, t1, lsb);
4774 if (msb != 63) {
4775 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4777 break;
4778 #endif
4779 case OPC_INS:
4780 if (lsb > msb) {
4781 goto fail;
4783 gen_load_gpr(t0, rt);
4784 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4785 tcg_gen_ext32s_tl(t0, t0);
4786 break;
4787 #if defined(TARGET_MIPS64)
4788 case OPC_DINSU:
4789 lsb += 32;
4790 /* FALLTHRU */
4791 case OPC_DINSM:
4792 msb += 32;
4793 /* FALLTHRU */
4794 case OPC_DINS:
4795 if (lsb > msb) {
4796 goto fail;
4798 gen_load_gpr(t0, rt);
4799 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4800 break;
4801 #endif
4802 default:
4803 fail:
4804 MIPS_INVAL("bitops");
4805 generate_exception(ctx, EXCP_RI);
4806 tcg_temp_free(t0);
4807 tcg_temp_free(t1);
4808 return;
4810 gen_store_gpr(t0, rt);
4811 tcg_temp_free(t0);
4812 tcg_temp_free(t1);
4815 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4817 TCGv t0;
4819 if (rd == 0) {
4820 /* If no destination, treat it as a NOP. */
4821 MIPS_DEBUG("NOP");
4822 return;
4825 t0 = tcg_temp_new();
4826 gen_load_gpr(t0, rt);
4827 switch (op2) {
4828 case OPC_WSBH:
4830 TCGv t1 = tcg_temp_new();
4832 tcg_gen_shri_tl(t1, t0, 8);
4833 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4834 tcg_gen_shli_tl(t0, t0, 8);
4835 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4836 tcg_gen_or_tl(t0, t0, t1);
4837 tcg_temp_free(t1);
4838 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4840 break;
4841 case OPC_SEB:
4842 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4843 break;
4844 case OPC_SEH:
4845 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4846 break;
4847 #if defined(TARGET_MIPS64)
4848 case OPC_DSBH:
4850 TCGv t1 = tcg_temp_new();
4852 tcg_gen_shri_tl(t1, t0, 8);
4853 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4854 tcg_gen_shli_tl(t0, t0, 8);
4855 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4856 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4857 tcg_temp_free(t1);
4859 break;
4860 case OPC_DSHD:
4862 TCGv t1 = tcg_temp_new();
4864 tcg_gen_shri_tl(t1, t0, 16);
4865 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4866 tcg_gen_shli_tl(t0, t0, 16);
4867 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4868 tcg_gen_or_tl(t0, t0, t1);
4869 tcg_gen_shri_tl(t1, t0, 32);
4870 tcg_gen_shli_tl(t0, t0, 32);
4871 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4872 tcg_temp_free(t1);
4874 break;
4875 #endif
4876 default:
4877 MIPS_INVAL("bsfhl");
4878 generate_exception(ctx, EXCP_RI);
4879 tcg_temp_free(t0);
4880 return;
4882 tcg_temp_free(t0);
4885 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4886 int imm2)
4888 TCGv t0;
4889 TCGv t1;
4890 if (rd == 0) {
4891 /* Treat as NOP. */
4892 return;
4894 t0 = tcg_temp_new();
4895 t1 = tcg_temp_new();
4896 gen_load_gpr(t0, rs);
4897 gen_load_gpr(t1, rt);
4898 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4899 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4900 if (opc == OPC_LSA) {
4901 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4904 tcg_temp_free(t1);
4905 tcg_temp_free(t0);
4907 return;
4910 static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
4911 int bp)
4913 TCGv t0;
4914 if (rd == 0) {
4915 /* Treat as NOP. */
4916 return;
4918 t0 = tcg_temp_new();
4919 gen_load_gpr(t0, rt);
4920 if (bp == 0) {
4921 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4922 } else {
4923 TCGv t1 = tcg_temp_new();
4924 gen_load_gpr(t1, rs);
4925 switch (opc) {
4926 case OPC_ALIGN:
4928 TCGv_i64 t2 = tcg_temp_new_i64();
4929 tcg_gen_concat_tl_i64(t2, t1, t0);
4930 tcg_gen_shri_i64(t2, t2, 8 * (4 - bp));
4931 gen_move_low32(cpu_gpr[rd], t2);
4932 tcg_temp_free_i64(t2);
4934 break;
4935 #if defined(TARGET_MIPS64)
4936 case OPC_DALIGN:
4937 tcg_gen_shli_tl(t0, t0, 8 * bp);
4938 tcg_gen_shri_tl(t1, t1, 8 * (8 - bp));
4939 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4940 break;
4941 #endif
4943 tcg_temp_free(t1);
4946 tcg_temp_free(t0);
4949 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4951 TCGv t0;
4952 if (rd == 0) {
4953 /* Treat as NOP. */
4954 return;
4956 t0 = tcg_temp_new();
4957 gen_load_gpr(t0, rt);
4958 switch (opc) {
4959 case OPC_BITSWAP:
4960 gen_helper_bitswap(cpu_gpr[rd], t0);
4961 break;
4962 #if defined(TARGET_MIPS64)
4963 case OPC_DBITSWAP:
4964 gen_helper_dbitswap(cpu_gpr[rd], t0);
4965 break;
4966 #endif
4968 tcg_temp_free(t0);
4971 #ifndef CONFIG_USER_ONLY
4972 /* CP0 (MMU and control) */
4973 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4975 TCGv_i64 t0 = tcg_temp_new_i64();
4976 TCGv_i64 t1 = tcg_temp_new_i64();
4978 tcg_gen_ext_tl_i64(t0, arg);
4979 tcg_gen_ld_i64(t1, cpu_env, off);
4980 #if defined(TARGET_MIPS64)
4981 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4982 #else
4983 tcg_gen_concat32_i64(t1, t1, t0);
4984 #endif
4985 tcg_gen_st_i64(t1, cpu_env, off);
4986 tcg_temp_free_i64(t1);
4987 tcg_temp_free_i64(t0);
4990 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4992 TCGv_i64 t0 = tcg_temp_new_i64();
4993 TCGv_i64 t1 = tcg_temp_new_i64();
4995 tcg_gen_ext_tl_i64(t0, arg);
4996 tcg_gen_ld_i64(t1, cpu_env, off);
4997 tcg_gen_concat32_i64(t1, t1, t0);
4998 tcg_gen_st_i64(t1, cpu_env, off);
4999 tcg_temp_free_i64(t1);
5000 tcg_temp_free_i64(t0);
5003 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5005 TCGv_i64 t0 = tcg_temp_new_i64();
5007 tcg_gen_ld_i64(t0, cpu_env, off);
5008 #if defined(TARGET_MIPS64)
5009 tcg_gen_shri_i64(t0, t0, 30);
5010 #else
5011 tcg_gen_shri_i64(t0, t0, 32);
5012 #endif
5013 gen_move_low32(arg, t0);
5014 tcg_temp_free_i64(t0);
5017 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5019 TCGv_i64 t0 = tcg_temp_new_i64();
5021 tcg_gen_ld_i64(t0, cpu_env, off);
5022 tcg_gen_shri_i64(t0, t0, 32 + shift);
5023 gen_move_low32(arg, t0);
5024 tcg_temp_free_i64(t0);
5027 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
5029 TCGv_i32 t0 = tcg_temp_new_i32();
5031 tcg_gen_ld_i32(t0, cpu_env, off);
5032 tcg_gen_ext_i32_tl(arg, t0);
5033 tcg_temp_free_i32(t0);
5036 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
5038 tcg_gen_ld_tl(arg, cpu_env, off);
5039 tcg_gen_ext32s_tl(arg, arg);
5042 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
5044 TCGv_i32 t0 = tcg_temp_new_i32();
5046 tcg_gen_trunc_tl_i32(t0, arg);
5047 tcg_gen_st_i32(t0, cpu_env, off);
5048 tcg_temp_free_i32(t0);
5051 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
5053 tcg_gen_ext32s_tl(arg, arg);
5054 tcg_gen_st_tl(arg, cpu_env, off);
5057 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5059 const char *rn = "invalid";
5061 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
5062 goto mfhc0_read_zero;
5065 switch (reg) {
5066 case 2:
5067 switch (sel) {
5068 case 0:
5069 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5070 rn = "EntryLo0";
5071 break;
5072 default:
5073 goto mfhc0_read_zero;
5075 break;
5076 case 3:
5077 switch (sel) {
5078 case 0:
5079 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5080 rn = "EntryLo1";
5081 break;
5082 default:
5083 goto mfhc0_read_zero;
5085 break;
5086 case 17:
5087 switch (sel) {
5088 case 0:
5089 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
5090 ctx->CP0_LLAddr_shift);
5091 rn = "LLAddr";
5092 break;
5093 default:
5094 goto mfhc0_read_zero;
5096 break;
5097 case 28:
5098 switch (sel) {
5099 case 0:
5100 case 2:
5101 case 4:
5102 case 6:
5103 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5104 rn = "TagLo";
5105 break;
5106 default:
5107 goto mfhc0_read_zero;
5109 break;
5110 default:
5111 goto mfhc0_read_zero;
5114 (void)rn; /* avoid a compiler warning */
5115 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5116 return;
5118 mfhc0_read_zero:
5119 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5120 tcg_gen_movi_tl(arg, 0);
5123 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5125 const char *rn = "invalid";
5126 uint64_t mask = ctx->PAMask >> 36;
5128 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
5129 goto mthc0_nop;
5132 switch (reg) {
5133 case 2:
5134 switch (sel) {
5135 case 0:
5136 tcg_gen_andi_tl(arg, arg, mask);
5137 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5138 rn = "EntryLo0";
5139 break;
5140 default:
5141 goto mthc0_nop;
5143 break;
5144 case 3:
5145 switch (sel) {
5146 case 0:
5147 tcg_gen_andi_tl(arg, arg, mask);
5148 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5149 rn = "EntryLo1";
5150 break;
5151 default:
5152 goto mthc0_nop;
5154 break;
5155 case 17:
5156 switch (sel) {
5157 case 0:
5158 /* LLAddr is read-only (the only exception is bit 0 if LLB is
5159 supported); the CP0_LLAddr_rw_bitmask does not seem to be
5160 relevant for modern MIPS cores supporting MTHC0, therefore
5161 treating MTHC0 to LLAddr as NOP. */
5162 rn = "LLAddr";
5163 break;
5164 default:
5165 goto mthc0_nop;
5167 break;
5168 case 28:
5169 switch (sel) {
5170 case 0:
5171 case 2:
5172 case 4:
5173 case 6:
5174 tcg_gen_andi_tl(arg, arg, mask);
5175 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5176 rn = "TagLo";
5177 break;
5178 default:
5179 goto mthc0_nop;
5181 break;
5182 default:
5183 goto mthc0_nop;
5186 (void)rn; /* avoid a compiler warning */
5187 mthc0_nop:
5188 LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
5191 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5193 if (ctx->insn_flags & ISA_MIPS32R6) {
5194 tcg_gen_movi_tl(arg, 0);
5195 } else {
5196 tcg_gen_movi_tl(arg, ~0);
5200 #define CP0_CHECK(c) \
5201 do { \
5202 if (!(c)) { \
5203 goto cp0_unimplemented; \
5205 } while (0)
5207 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5209 const char *rn = "invalid";
5211 if (sel != 0)
5212 check_insn(ctx, ISA_MIPS32);
5214 switch (reg) {
5215 case 0:
5216 switch (sel) {
5217 case 0:
5218 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5219 rn = "Index";
5220 break;
5221 case 1:
5222 CP0_CHECK(ctx->insn_flags & ASE_MT);
5223 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5224 rn = "MVPControl";
5225 break;
5226 case 2:
5227 CP0_CHECK(ctx->insn_flags & ASE_MT);
5228 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5229 rn = "MVPConf0";
5230 break;
5231 case 3:
5232 CP0_CHECK(ctx->insn_flags & ASE_MT);
5233 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5234 rn = "MVPConf1";
5235 break;
5236 default:
5237 goto cp0_unimplemented;
5239 break;
5240 case 1:
5241 switch (sel) {
5242 case 0:
5243 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5244 gen_helper_mfc0_random(arg, cpu_env);
5245 rn = "Random";
5246 break;
5247 case 1:
5248 CP0_CHECK(ctx->insn_flags & ASE_MT);
5249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5250 rn = "VPEControl";
5251 break;
5252 case 2:
5253 CP0_CHECK(ctx->insn_flags & ASE_MT);
5254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5255 rn = "VPEConf0";
5256 break;
5257 case 3:
5258 CP0_CHECK(ctx->insn_flags & ASE_MT);
5259 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5260 rn = "VPEConf1";
5261 break;
5262 case 4:
5263 CP0_CHECK(ctx->insn_flags & ASE_MT);
5264 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5265 rn = "YQMask";
5266 break;
5267 case 5:
5268 CP0_CHECK(ctx->insn_flags & ASE_MT);
5269 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5270 rn = "VPESchedule";
5271 break;
5272 case 6:
5273 CP0_CHECK(ctx->insn_flags & ASE_MT);
5274 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5275 rn = "VPEScheFBack";
5276 break;
5277 case 7:
5278 CP0_CHECK(ctx->insn_flags & ASE_MT);
5279 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5280 rn = "VPEOpt";
5281 break;
5282 default:
5283 goto cp0_unimplemented;
5285 break;
5286 case 2:
5287 switch (sel) {
5288 case 0:
5290 TCGv_i64 tmp = tcg_temp_new_i64();
5291 tcg_gen_ld_i64(tmp, cpu_env,
5292 offsetof(CPUMIPSState, CP0_EntryLo0));
5293 #if defined(TARGET_MIPS64)
5294 if (ctx->rxi) {
5295 /* Move RI/XI fields to bits 31:30 */
5296 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5297 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5299 #endif
5300 gen_move_low32(arg, tmp);
5301 tcg_temp_free_i64(tmp);
5303 rn = "EntryLo0";
5304 break;
5305 case 1:
5306 CP0_CHECK(ctx->insn_flags & ASE_MT);
5307 gen_helper_mfc0_tcstatus(arg, cpu_env);
5308 rn = "TCStatus";
5309 break;
5310 case 2:
5311 CP0_CHECK(ctx->insn_flags & ASE_MT);
5312 gen_helper_mfc0_tcbind(arg, cpu_env);
5313 rn = "TCBind";
5314 break;
5315 case 3:
5316 CP0_CHECK(ctx->insn_flags & ASE_MT);
5317 gen_helper_mfc0_tcrestart(arg, cpu_env);
5318 rn = "TCRestart";
5319 break;
5320 case 4:
5321 CP0_CHECK(ctx->insn_flags & ASE_MT);
5322 gen_helper_mfc0_tchalt(arg, cpu_env);
5323 rn = "TCHalt";
5324 break;
5325 case 5:
5326 CP0_CHECK(ctx->insn_flags & ASE_MT);
5327 gen_helper_mfc0_tccontext(arg, cpu_env);
5328 rn = "TCContext";
5329 break;
5330 case 6:
5331 CP0_CHECK(ctx->insn_flags & ASE_MT);
5332 gen_helper_mfc0_tcschedule(arg, cpu_env);
5333 rn = "TCSchedule";
5334 break;
5335 case 7:
5336 CP0_CHECK(ctx->insn_flags & ASE_MT);
5337 gen_helper_mfc0_tcschefback(arg, cpu_env);
5338 rn = "TCScheFBack";
5339 break;
5340 default:
5341 goto cp0_unimplemented;
5343 break;
5344 case 3:
5345 switch (sel) {
5346 case 0:
5348 TCGv_i64 tmp = tcg_temp_new_i64();
5349 tcg_gen_ld_i64(tmp, cpu_env,
5350 offsetof(CPUMIPSState, CP0_EntryLo1));
5351 #if defined(TARGET_MIPS64)
5352 if (ctx->rxi) {
5353 /* Move RI/XI fields to bits 31:30 */
5354 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5355 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5357 #endif
5358 gen_move_low32(arg, tmp);
5359 tcg_temp_free_i64(tmp);
5361 rn = "EntryLo1";
5362 break;
5363 default:
5364 goto cp0_unimplemented;
5366 break;
5367 case 4:
5368 switch (sel) {
5369 case 0:
5370 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5371 tcg_gen_ext32s_tl(arg, arg);
5372 rn = "Context";
5373 break;
5374 case 1:
5375 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5376 rn = "ContextConfig";
5377 goto cp0_unimplemented;
5378 // break;
5379 case 2:
5380 CP0_CHECK(ctx->ulri);
5381 tcg_gen_ld32s_tl(arg, cpu_env,
5382 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5383 rn = "UserLocal";
5384 break;
5385 default:
5386 goto cp0_unimplemented;
5388 break;
5389 case 5:
5390 switch (sel) {
5391 case 0:
5392 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5393 rn = "PageMask";
5394 break;
5395 case 1:
5396 check_insn(ctx, ISA_MIPS32R2);
5397 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5398 rn = "PageGrain";
5399 break;
5400 default:
5401 goto cp0_unimplemented;
5403 break;
5404 case 6:
5405 switch (sel) {
5406 case 0:
5407 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5408 rn = "Wired";
5409 break;
5410 case 1:
5411 check_insn(ctx, ISA_MIPS32R2);
5412 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5413 rn = "SRSConf0";
5414 break;
5415 case 2:
5416 check_insn(ctx, ISA_MIPS32R2);
5417 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5418 rn = "SRSConf1";
5419 break;
5420 case 3:
5421 check_insn(ctx, ISA_MIPS32R2);
5422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5423 rn = "SRSConf2";
5424 break;
5425 case 4:
5426 check_insn(ctx, ISA_MIPS32R2);
5427 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5428 rn = "SRSConf3";
5429 break;
5430 case 5:
5431 check_insn(ctx, ISA_MIPS32R2);
5432 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5433 rn = "SRSConf4";
5434 break;
5435 default:
5436 goto cp0_unimplemented;
5438 break;
5439 case 7:
5440 switch (sel) {
5441 case 0:
5442 check_insn(ctx, ISA_MIPS32R2);
5443 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5444 rn = "HWREna";
5445 break;
5446 default:
5447 goto cp0_unimplemented;
5449 break;
5450 case 8:
5451 switch (sel) {
5452 case 0:
5453 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5454 tcg_gen_ext32s_tl(arg, arg);
5455 rn = "BadVAddr";
5456 break;
5457 case 1:
5458 CP0_CHECK(ctx->bi);
5459 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5460 rn = "BadInstr";
5461 break;
5462 case 2:
5463 CP0_CHECK(ctx->bp);
5464 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5465 rn = "BadInstrP";
5466 break;
5467 default:
5468 goto cp0_unimplemented;
5470 break;
5471 case 9:
5472 switch (sel) {
5473 case 0:
5474 /* Mark as an IO operation because we read the time. */
5475 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5476 gen_io_start();
5478 gen_helper_mfc0_count(arg, cpu_env);
5479 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5480 gen_io_end();
5482 /* Break the TB to be able to take timer interrupts immediately
5483 after reading count. */
5484 ctx->bstate = BS_STOP;
5485 rn = "Count";
5486 break;
5487 /* 6,7 are implementation dependent */
5488 default:
5489 goto cp0_unimplemented;
5491 break;
5492 case 10:
5493 switch (sel) {
5494 case 0:
5495 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5496 tcg_gen_ext32s_tl(arg, arg);
5497 rn = "EntryHi";
5498 break;
5499 default:
5500 goto cp0_unimplemented;
5502 break;
5503 case 11:
5504 switch (sel) {
5505 case 0:
5506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5507 rn = "Compare";
5508 break;
5509 /* 6,7 are implementation dependent */
5510 default:
5511 goto cp0_unimplemented;
5513 break;
5514 case 12:
5515 switch (sel) {
5516 case 0:
5517 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5518 rn = "Status";
5519 break;
5520 case 1:
5521 check_insn(ctx, ISA_MIPS32R2);
5522 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5523 rn = "IntCtl";
5524 break;
5525 case 2:
5526 check_insn(ctx, ISA_MIPS32R2);
5527 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5528 rn = "SRSCtl";
5529 break;
5530 case 3:
5531 check_insn(ctx, ISA_MIPS32R2);
5532 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5533 rn = "SRSMap";
5534 break;
5535 default:
5536 goto cp0_unimplemented;
5538 break;
5539 case 13:
5540 switch (sel) {
5541 case 0:
5542 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5543 rn = "Cause";
5544 break;
5545 default:
5546 goto cp0_unimplemented;
5548 break;
5549 case 14:
5550 switch (sel) {
5551 case 0:
5552 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5553 tcg_gen_ext32s_tl(arg, arg);
5554 rn = "EPC";
5555 break;
5556 default:
5557 goto cp0_unimplemented;
5559 break;
5560 case 15:
5561 switch (sel) {
5562 case 0:
5563 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5564 rn = "PRid";
5565 break;
5566 case 1:
5567 check_insn(ctx, ISA_MIPS32R2);
5568 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5569 rn = "EBase";
5570 break;
5571 default:
5572 goto cp0_unimplemented;
5574 break;
5575 case 16:
5576 switch (sel) {
5577 case 0:
5578 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5579 rn = "Config";
5580 break;
5581 case 1:
5582 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5583 rn = "Config1";
5584 break;
5585 case 2:
5586 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5587 rn = "Config2";
5588 break;
5589 case 3:
5590 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5591 rn = "Config3";
5592 break;
5593 case 4:
5594 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5595 rn = "Config4";
5596 break;
5597 case 5:
5598 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5599 rn = "Config5";
5600 break;
5601 /* 6,7 are implementation dependent */
5602 case 6:
5603 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5604 rn = "Config6";
5605 break;
5606 case 7:
5607 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5608 rn = "Config7";
5609 break;
5610 default:
5611 goto cp0_unimplemented;
5613 break;
5614 case 17:
5615 switch (sel) {
5616 case 0:
5617 gen_helper_mfc0_lladdr(arg, cpu_env);
5618 rn = "LLAddr";
5619 break;
5620 default:
5621 goto cp0_unimplemented;
5623 break;
5624 case 18:
5625 switch (sel) {
5626 case 0 ... 7:
5627 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5628 rn = "WatchLo";
5629 break;
5630 default:
5631 goto cp0_unimplemented;
5633 break;
5634 case 19:
5635 switch (sel) {
5636 case 0 ...7:
5637 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5638 rn = "WatchHi";
5639 break;
5640 default:
5641 goto cp0_unimplemented;
5643 break;
5644 case 20:
5645 switch (sel) {
5646 case 0:
5647 #if defined(TARGET_MIPS64)
5648 check_insn(ctx, ISA_MIPS3);
5649 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5650 tcg_gen_ext32s_tl(arg, arg);
5651 rn = "XContext";
5652 break;
5653 #endif
5654 default:
5655 goto cp0_unimplemented;
5657 break;
5658 case 21:
5659 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5660 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5661 switch (sel) {
5662 case 0:
5663 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5664 rn = "Framemask";
5665 break;
5666 default:
5667 goto cp0_unimplemented;
5669 break;
5670 case 22:
5671 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5672 rn = "'Diagnostic"; /* implementation dependent */
5673 break;
5674 case 23:
5675 switch (sel) {
5676 case 0:
5677 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5678 rn = "Debug";
5679 break;
5680 case 1:
5681 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5682 rn = "TraceControl";
5683 // break;
5684 case 2:
5685 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5686 rn = "TraceControl2";
5687 // break;
5688 case 3:
5689 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5690 rn = "UserTraceData";
5691 // break;
5692 case 4:
5693 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5694 rn = "TraceBPC";
5695 // break;
5696 default:
5697 goto cp0_unimplemented;
5699 break;
5700 case 24:
5701 switch (sel) {
5702 case 0:
5703 /* EJTAG support */
5704 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5705 tcg_gen_ext32s_tl(arg, arg);
5706 rn = "DEPC";
5707 break;
5708 default:
5709 goto cp0_unimplemented;
5711 break;
5712 case 25:
5713 switch (sel) {
5714 case 0:
5715 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5716 rn = "Performance0";
5717 break;
5718 case 1:
5719 // gen_helper_mfc0_performance1(arg);
5720 rn = "Performance1";
5721 // break;
5722 case 2:
5723 // gen_helper_mfc0_performance2(arg);
5724 rn = "Performance2";
5725 // break;
5726 case 3:
5727 // gen_helper_mfc0_performance3(arg);
5728 rn = "Performance3";
5729 // break;
5730 case 4:
5731 // gen_helper_mfc0_performance4(arg);
5732 rn = "Performance4";
5733 // break;
5734 case 5:
5735 // gen_helper_mfc0_performance5(arg);
5736 rn = "Performance5";
5737 // break;
5738 case 6:
5739 // gen_helper_mfc0_performance6(arg);
5740 rn = "Performance6";
5741 // break;
5742 case 7:
5743 // gen_helper_mfc0_performance7(arg);
5744 rn = "Performance7";
5745 // break;
5746 default:
5747 goto cp0_unimplemented;
5749 break;
5750 case 26:
5751 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5752 rn = "ECC";
5753 break;
5754 case 27:
5755 switch (sel) {
5756 case 0 ... 3:
5757 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5758 rn = "CacheErr";
5759 break;
5760 default:
5761 goto cp0_unimplemented;
5763 break;
5764 case 28:
5765 switch (sel) {
5766 case 0:
5767 case 2:
5768 case 4:
5769 case 6:
5771 TCGv_i64 tmp = tcg_temp_new_i64();
5772 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5773 gen_move_low32(arg, tmp);
5774 tcg_temp_free_i64(tmp);
5776 rn = "TagLo";
5777 break;
5778 case 1:
5779 case 3:
5780 case 5:
5781 case 7:
5782 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5783 rn = "DataLo";
5784 break;
5785 default:
5786 goto cp0_unimplemented;
5788 break;
5789 case 29:
5790 switch (sel) {
5791 case 0:
5792 case 2:
5793 case 4:
5794 case 6:
5795 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5796 rn = "TagHi";
5797 break;
5798 case 1:
5799 case 3:
5800 case 5:
5801 case 7:
5802 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5803 rn = "DataHi";
5804 break;
5805 default:
5806 goto cp0_unimplemented;
5808 break;
5809 case 30:
5810 switch (sel) {
5811 case 0:
5812 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5813 tcg_gen_ext32s_tl(arg, arg);
5814 rn = "ErrorEPC";
5815 break;
5816 default:
5817 goto cp0_unimplemented;
5819 break;
5820 case 31:
5821 switch (sel) {
5822 case 0:
5823 /* EJTAG support */
5824 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5825 rn = "DESAVE";
5826 break;
5827 case 2 ... 7:
5828 CP0_CHECK(ctx->kscrexist & (1 << sel));
5829 tcg_gen_ld_tl(arg, cpu_env,
5830 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5831 tcg_gen_ext32s_tl(arg, arg);
5832 rn = "KScratch";
5833 break;
5834 default:
5835 goto cp0_unimplemented;
5837 break;
5838 default:
5839 goto cp0_unimplemented;
5841 (void)rn; /* avoid a compiler warning */
5842 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5843 return;
5845 cp0_unimplemented:
5846 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5847 gen_mfc0_unimplemented(ctx, arg);
5850 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5852 const char *rn = "invalid";
5854 if (sel != 0)
5855 check_insn(ctx, ISA_MIPS32);
5857 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5858 gen_io_start();
5861 switch (reg) {
5862 case 0:
5863 switch (sel) {
5864 case 0:
5865 gen_helper_mtc0_index(cpu_env, arg);
5866 rn = "Index";
5867 break;
5868 case 1:
5869 CP0_CHECK(ctx->insn_flags & ASE_MT);
5870 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5871 rn = "MVPControl";
5872 break;
5873 case 2:
5874 CP0_CHECK(ctx->insn_flags & ASE_MT);
5875 /* ignored */
5876 rn = "MVPConf0";
5877 break;
5878 case 3:
5879 CP0_CHECK(ctx->insn_flags & ASE_MT);
5880 /* ignored */
5881 rn = "MVPConf1";
5882 break;
5883 default:
5884 goto cp0_unimplemented;
5886 break;
5887 case 1:
5888 switch (sel) {
5889 case 0:
5890 /* ignored */
5891 rn = "Random";
5892 break;
5893 case 1:
5894 CP0_CHECK(ctx->insn_flags & ASE_MT);
5895 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5896 rn = "VPEControl";
5897 break;
5898 case 2:
5899 CP0_CHECK(ctx->insn_flags & ASE_MT);
5900 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5901 rn = "VPEConf0";
5902 break;
5903 case 3:
5904 CP0_CHECK(ctx->insn_flags & ASE_MT);
5905 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5906 rn = "VPEConf1";
5907 break;
5908 case 4:
5909 CP0_CHECK(ctx->insn_flags & ASE_MT);
5910 gen_helper_mtc0_yqmask(cpu_env, arg);
5911 rn = "YQMask";
5912 break;
5913 case 5:
5914 CP0_CHECK(ctx->insn_flags & ASE_MT);
5915 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5916 rn = "VPESchedule";
5917 break;
5918 case 6:
5919 CP0_CHECK(ctx->insn_flags & ASE_MT);
5920 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5921 rn = "VPEScheFBack";
5922 break;
5923 case 7:
5924 CP0_CHECK(ctx->insn_flags & ASE_MT);
5925 gen_helper_mtc0_vpeopt(cpu_env, arg);
5926 rn = "VPEOpt";
5927 break;
5928 default:
5929 goto cp0_unimplemented;
5931 break;
5932 case 2:
5933 switch (sel) {
5934 case 0:
5935 gen_helper_mtc0_entrylo0(cpu_env, arg);
5936 rn = "EntryLo0";
5937 break;
5938 case 1:
5939 CP0_CHECK(ctx->insn_flags & ASE_MT);
5940 gen_helper_mtc0_tcstatus(cpu_env, arg);
5941 rn = "TCStatus";
5942 break;
5943 case 2:
5944 CP0_CHECK(ctx->insn_flags & ASE_MT);
5945 gen_helper_mtc0_tcbind(cpu_env, arg);
5946 rn = "TCBind";
5947 break;
5948 case 3:
5949 CP0_CHECK(ctx->insn_flags & ASE_MT);
5950 gen_helper_mtc0_tcrestart(cpu_env, arg);
5951 rn = "TCRestart";
5952 break;
5953 case 4:
5954 CP0_CHECK(ctx->insn_flags & ASE_MT);
5955 gen_helper_mtc0_tchalt(cpu_env, arg);
5956 rn = "TCHalt";
5957 break;
5958 case 5:
5959 CP0_CHECK(ctx->insn_flags & ASE_MT);
5960 gen_helper_mtc0_tccontext(cpu_env, arg);
5961 rn = "TCContext";
5962 break;
5963 case 6:
5964 CP0_CHECK(ctx->insn_flags & ASE_MT);
5965 gen_helper_mtc0_tcschedule(cpu_env, arg);
5966 rn = "TCSchedule";
5967 break;
5968 case 7:
5969 CP0_CHECK(ctx->insn_flags & ASE_MT);
5970 gen_helper_mtc0_tcschefback(cpu_env, arg);
5971 rn = "TCScheFBack";
5972 break;
5973 default:
5974 goto cp0_unimplemented;
5976 break;
5977 case 3:
5978 switch (sel) {
5979 case 0:
5980 gen_helper_mtc0_entrylo1(cpu_env, arg);
5981 rn = "EntryLo1";
5982 break;
5983 default:
5984 goto cp0_unimplemented;
5986 break;
5987 case 4:
5988 switch (sel) {
5989 case 0:
5990 gen_helper_mtc0_context(cpu_env, arg);
5991 rn = "Context";
5992 break;
5993 case 1:
5994 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5995 rn = "ContextConfig";
5996 goto cp0_unimplemented;
5997 // break;
5998 case 2:
5999 CP0_CHECK(ctx->ulri);
6000 tcg_gen_st_tl(arg, cpu_env,
6001 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6002 rn = "UserLocal";
6003 break;
6004 default:
6005 goto cp0_unimplemented;
6007 break;
6008 case 5:
6009 switch (sel) {
6010 case 0:
6011 gen_helper_mtc0_pagemask(cpu_env, arg);
6012 rn = "PageMask";
6013 break;
6014 case 1:
6015 check_insn(ctx, ISA_MIPS32R2);
6016 gen_helper_mtc0_pagegrain(cpu_env, arg);
6017 rn = "PageGrain";
6018 ctx->bstate = BS_STOP;
6019 break;
6020 default:
6021 goto cp0_unimplemented;
6023 break;
6024 case 6:
6025 switch (sel) {
6026 case 0:
6027 gen_helper_mtc0_wired(cpu_env, arg);
6028 rn = "Wired";
6029 break;
6030 case 1:
6031 check_insn(ctx, ISA_MIPS32R2);
6032 gen_helper_mtc0_srsconf0(cpu_env, arg);
6033 rn = "SRSConf0";
6034 break;
6035 case 2:
6036 check_insn(ctx, ISA_MIPS32R2);
6037 gen_helper_mtc0_srsconf1(cpu_env, arg);
6038 rn = "SRSConf1";
6039 break;
6040 case 3:
6041 check_insn(ctx, ISA_MIPS32R2);
6042 gen_helper_mtc0_srsconf2(cpu_env, arg);
6043 rn = "SRSConf2";
6044 break;
6045 case 4:
6046 check_insn(ctx, ISA_MIPS32R2);
6047 gen_helper_mtc0_srsconf3(cpu_env, arg);
6048 rn = "SRSConf3";
6049 break;
6050 case 5:
6051 check_insn(ctx, ISA_MIPS32R2);
6052 gen_helper_mtc0_srsconf4(cpu_env, arg);
6053 rn = "SRSConf4";
6054 break;
6055 default:
6056 goto cp0_unimplemented;
6058 break;
6059 case 7:
6060 switch (sel) {
6061 case 0:
6062 check_insn(ctx, ISA_MIPS32R2);
6063 gen_helper_mtc0_hwrena(cpu_env, arg);
6064 ctx->bstate = BS_STOP;
6065 rn = "HWREna";
6066 break;
6067 default:
6068 goto cp0_unimplemented;
6070 break;
6071 case 8:
6072 switch (sel) {
6073 case 0:
6074 /* ignored */
6075 rn = "BadVAddr";
6076 break;
6077 case 1:
6078 /* ignored */
6079 rn = "BadInstr";
6080 break;
6081 case 2:
6082 /* ignored */
6083 rn = "BadInstrP";
6084 break;
6085 default:
6086 goto cp0_unimplemented;
6088 break;
6089 case 9:
6090 switch (sel) {
6091 case 0:
6092 gen_helper_mtc0_count(cpu_env, arg);
6093 rn = "Count";
6094 break;
6095 /* 6,7 are implementation dependent */
6096 default:
6097 goto cp0_unimplemented;
6099 break;
6100 case 10:
6101 switch (sel) {
6102 case 0:
6103 gen_helper_mtc0_entryhi(cpu_env, arg);
6104 rn = "EntryHi";
6105 break;
6106 default:
6107 goto cp0_unimplemented;
6109 break;
6110 case 11:
6111 switch (sel) {
6112 case 0:
6113 gen_helper_mtc0_compare(cpu_env, arg);
6114 rn = "Compare";
6115 break;
6116 /* 6,7 are implementation dependent */
6117 default:
6118 goto cp0_unimplemented;
6120 break;
6121 case 12:
6122 switch (sel) {
6123 case 0:
6124 save_cpu_state(ctx, 1);
6125 gen_helper_mtc0_status(cpu_env, arg);
6126 /* BS_STOP isn't good enough here, hflags may have changed. */
6127 gen_save_pc(ctx->pc + 4);
6128 ctx->bstate = BS_EXCP;
6129 rn = "Status";
6130 break;
6131 case 1:
6132 check_insn(ctx, ISA_MIPS32R2);
6133 gen_helper_mtc0_intctl(cpu_env, arg);
6134 /* Stop translation as we may have switched the execution mode */
6135 ctx->bstate = BS_STOP;
6136 rn = "IntCtl";
6137 break;
6138 case 2:
6139 check_insn(ctx, ISA_MIPS32R2);
6140 gen_helper_mtc0_srsctl(cpu_env, arg);
6141 /* Stop translation as we may have switched the execution mode */
6142 ctx->bstate = BS_STOP;
6143 rn = "SRSCtl";
6144 break;
6145 case 3:
6146 check_insn(ctx, ISA_MIPS32R2);
6147 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6148 /* Stop translation as we may have switched the execution mode */
6149 ctx->bstate = BS_STOP;
6150 rn = "SRSMap";
6151 break;
6152 default:
6153 goto cp0_unimplemented;
6155 break;
6156 case 13:
6157 switch (sel) {
6158 case 0:
6159 save_cpu_state(ctx, 1);
6160 gen_helper_mtc0_cause(cpu_env, arg);
6161 rn = "Cause";
6162 break;
6163 default:
6164 goto cp0_unimplemented;
6166 break;
6167 case 14:
6168 switch (sel) {
6169 case 0:
6170 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
6171 rn = "EPC";
6172 break;
6173 default:
6174 goto cp0_unimplemented;
6176 break;
6177 case 15:
6178 switch (sel) {
6179 case 0:
6180 /* ignored */
6181 rn = "PRid";
6182 break;
6183 case 1:
6184 check_insn(ctx, ISA_MIPS32R2);
6185 gen_helper_mtc0_ebase(cpu_env, arg);
6186 rn = "EBase";
6187 break;
6188 default:
6189 goto cp0_unimplemented;
6191 break;
6192 case 16:
6193 switch (sel) {
6194 case 0:
6195 gen_helper_mtc0_config0(cpu_env, arg);
6196 rn = "Config";
6197 /* Stop translation as we may have switched the execution mode */
6198 ctx->bstate = BS_STOP;
6199 break;
6200 case 1:
6201 /* ignored, read only */
6202 rn = "Config1";
6203 break;
6204 case 2:
6205 gen_helper_mtc0_config2(cpu_env, arg);
6206 rn = "Config2";
6207 /* Stop translation as we may have switched the execution mode */
6208 ctx->bstate = BS_STOP;
6209 break;
6210 case 3:
6211 gen_helper_mtc0_config3(cpu_env, arg);
6212 rn = "Config3";
6213 /* Stop translation as we may have switched the execution mode */
6214 ctx->bstate = BS_STOP;
6215 break;
6216 case 4:
6217 gen_helper_mtc0_config4(cpu_env, arg);
6218 rn = "Config4";
6219 ctx->bstate = BS_STOP;
6220 break;
6221 case 5:
6222 gen_helper_mtc0_config5(cpu_env, arg);
6223 rn = "Config5";
6224 /* Stop translation as we may have switched the execution mode */
6225 ctx->bstate = BS_STOP;
6226 break;
6227 /* 6,7 are implementation dependent */
6228 case 6:
6229 /* ignored */
6230 rn = "Config6";
6231 break;
6232 case 7:
6233 /* ignored */
6234 rn = "Config7";
6235 break;
6236 default:
6237 rn = "Invalid config selector";
6238 goto cp0_unimplemented;
6240 break;
6241 case 17:
6242 switch (sel) {
6243 case 0:
6244 gen_helper_mtc0_lladdr(cpu_env, arg);
6245 rn = "LLAddr";
6246 break;
6247 default:
6248 goto cp0_unimplemented;
6250 break;
6251 case 18:
6252 switch (sel) {
6253 case 0 ... 7:
6254 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6255 rn = "WatchLo";
6256 break;
6257 default:
6258 goto cp0_unimplemented;
6260 break;
6261 case 19:
6262 switch (sel) {
6263 case 0 ... 7:
6264 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6265 rn = "WatchHi";
6266 break;
6267 default:
6268 goto cp0_unimplemented;
6270 break;
6271 case 20:
6272 switch (sel) {
6273 case 0:
6274 #if defined(TARGET_MIPS64)
6275 check_insn(ctx, ISA_MIPS3);
6276 gen_helper_mtc0_xcontext(cpu_env, arg);
6277 rn = "XContext";
6278 break;
6279 #endif
6280 default:
6281 goto cp0_unimplemented;
6283 break;
6284 case 21:
6285 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6286 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6287 switch (sel) {
6288 case 0:
6289 gen_helper_mtc0_framemask(cpu_env, arg);
6290 rn = "Framemask";
6291 break;
6292 default:
6293 goto cp0_unimplemented;
6295 break;
6296 case 22:
6297 /* ignored */
6298 rn = "Diagnostic"; /* implementation dependent */
6299 break;
6300 case 23:
6301 switch (sel) {
6302 case 0:
6303 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6304 /* BS_STOP isn't good enough here, hflags may have changed. */
6305 gen_save_pc(ctx->pc + 4);
6306 ctx->bstate = BS_EXCP;
6307 rn = "Debug";
6308 break;
6309 case 1:
6310 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6311 rn = "TraceControl";
6312 /* Stop translation as we may have switched the execution mode */
6313 ctx->bstate = BS_STOP;
6314 // break;
6315 case 2:
6316 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6317 rn = "TraceControl2";
6318 /* Stop translation as we may have switched the execution mode */
6319 ctx->bstate = BS_STOP;
6320 // break;
6321 case 3:
6322 /* Stop translation as we may have switched the execution mode */
6323 ctx->bstate = BS_STOP;
6324 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6325 rn = "UserTraceData";
6326 /* Stop translation as we may have switched the execution mode */
6327 ctx->bstate = BS_STOP;
6328 // break;
6329 case 4:
6330 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6331 /* Stop translation as we may have switched the execution mode */
6332 ctx->bstate = BS_STOP;
6333 rn = "TraceBPC";
6334 // break;
6335 default:
6336 goto cp0_unimplemented;
6338 break;
6339 case 24:
6340 switch (sel) {
6341 case 0:
6342 /* EJTAG support */
6343 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
6344 rn = "DEPC";
6345 break;
6346 default:
6347 goto cp0_unimplemented;
6349 break;
6350 case 25:
6351 switch (sel) {
6352 case 0:
6353 gen_helper_mtc0_performance0(cpu_env, arg);
6354 rn = "Performance0";
6355 break;
6356 case 1:
6357 // gen_helper_mtc0_performance1(arg);
6358 rn = "Performance1";
6359 // break;
6360 case 2:
6361 // gen_helper_mtc0_performance2(arg);
6362 rn = "Performance2";
6363 // break;
6364 case 3:
6365 // gen_helper_mtc0_performance3(arg);
6366 rn = "Performance3";
6367 // break;
6368 case 4:
6369 // gen_helper_mtc0_performance4(arg);
6370 rn = "Performance4";
6371 // break;
6372 case 5:
6373 // gen_helper_mtc0_performance5(arg);
6374 rn = "Performance5";
6375 // break;
6376 case 6:
6377 // gen_helper_mtc0_performance6(arg);
6378 rn = "Performance6";
6379 // break;
6380 case 7:
6381 // gen_helper_mtc0_performance7(arg);
6382 rn = "Performance7";
6383 // break;
6384 default:
6385 goto cp0_unimplemented;
6387 break;
6388 case 26:
6389 /* ignored */
6390 rn = "ECC";
6391 break;
6392 case 27:
6393 switch (sel) {
6394 case 0 ... 3:
6395 /* ignored */
6396 rn = "CacheErr";
6397 break;
6398 default:
6399 goto cp0_unimplemented;
6401 break;
6402 case 28:
6403 switch (sel) {
6404 case 0:
6405 case 2:
6406 case 4:
6407 case 6:
6408 gen_helper_mtc0_taglo(cpu_env, arg);
6409 rn = "TagLo";
6410 break;
6411 case 1:
6412 case 3:
6413 case 5:
6414 case 7:
6415 gen_helper_mtc0_datalo(cpu_env, arg);
6416 rn = "DataLo";
6417 break;
6418 default:
6419 goto cp0_unimplemented;
6421 break;
6422 case 29:
6423 switch (sel) {
6424 case 0:
6425 case 2:
6426 case 4:
6427 case 6:
6428 gen_helper_mtc0_taghi(cpu_env, arg);
6429 rn = "TagHi";
6430 break;
6431 case 1:
6432 case 3:
6433 case 5:
6434 case 7:
6435 gen_helper_mtc0_datahi(cpu_env, arg);
6436 rn = "DataHi";
6437 break;
6438 default:
6439 rn = "invalid sel";
6440 goto cp0_unimplemented;
6442 break;
6443 case 30:
6444 switch (sel) {
6445 case 0:
6446 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
6447 rn = "ErrorEPC";
6448 break;
6449 default:
6450 goto cp0_unimplemented;
6452 break;
6453 case 31:
6454 switch (sel) {
6455 case 0:
6456 /* EJTAG support */
6457 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6458 rn = "DESAVE";
6459 break;
6460 case 2 ... 7:
6461 CP0_CHECK(ctx->kscrexist & (1 << sel));
6462 tcg_gen_st_tl(arg, cpu_env,
6463 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6464 rn = "KScratch";
6465 break;
6466 default:
6467 goto cp0_unimplemented;
6469 /* Stop translation as we may have switched the execution mode */
6470 ctx->bstate = BS_STOP;
6471 break;
6472 default:
6473 goto cp0_unimplemented;
6475 (void)rn; /* avoid a compiler warning */
6476 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6477 /* For simplicity assume that all writes can cause interrupts. */
6478 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6479 gen_io_end();
6480 ctx->bstate = BS_STOP;
6482 return;
6484 cp0_unimplemented:
6485 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6488 #if defined(TARGET_MIPS64)
6489 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6491 const char *rn = "invalid";
6493 if (sel != 0)
6494 check_insn(ctx, ISA_MIPS64);
6496 switch (reg) {
6497 case 0:
6498 switch (sel) {
6499 case 0:
6500 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6501 rn = "Index";
6502 break;
6503 case 1:
6504 CP0_CHECK(ctx->insn_flags & ASE_MT);
6505 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6506 rn = "MVPControl";
6507 break;
6508 case 2:
6509 CP0_CHECK(ctx->insn_flags & ASE_MT);
6510 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6511 rn = "MVPConf0";
6512 break;
6513 case 3:
6514 CP0_CHECK(ctx->insn_flags & ASE_MT);
6515 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6516 rn = "MVPConf1";
6517 break;
6518 default:
6519 goto cp0_unimplemented;
6521 break;
6522 case 1:
6523 switch (sel) {
6524 case 0:
6525 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6526 gen_helper_mfc0_random(arg, cpu_env);
6527 rn = "Random";
6528 break;
6529 case 1:
6530 CP0_CHECK(ctx->insn_flags & ASE_MT);
6531 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6532 rn = "VPEControl";
6533 break;
6534 case 2:
6535 CP0_CHECK(ctx->insn_flags & ASE_MT);
6536 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6537 rn = "VPEConf0";
6538 break;
6539 case 3:
6540 CP0_CHECK(ctx->insn_flags & ASE_MT);
6541 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6542 rn = "VPEConf1";
6543 break;
6544 case 4:
6545 CP0_CHECK(ctx->insn_flags & ASE_MT);
6546 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6547 rn = "YQMask";
6548 break;
6549 case 5:
6550 CP0_CHECK(ctx->insn_flags & ASE_MT);
6551 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6552 rn = "VPESchedule";
6553 break;
6554 case 6:
6555 CP0_CHECK(ctx->insn_flags & ASE_MT);
6556 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6557 rn = "VPEScheFBack";
6558 break;
6559 case 7:
6560 CP0_CHECK(ctx->insn_flags & ASE_MT);
6561 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6562 rn = "VPEOpt";
6563 break;
6564 default:
6565 goto cp0_unimplemented;
6567 break;
6568 case 2:
6569 switch (sel) {
6570 case 0:
6571 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6572 rn = "EntryLo0";
6573 break;
6574 case 1:
6575 CP0_CHECK(ctx->insn_flags & ASE_MT);
6576 gen_helper_mfc0_tcstatus(arg, cpu_env);
6577 rn = "TCStatus";
6578 break;
6579 case 2:
6580 CP0_CHECK(ctx->insn_flags & ASE_MT);
6581 gen_helper_mfc0_tcbind(arg, cpu_env);
6582 rn = "TCBind";
6583 break;
6584 case 3:
6585 CP0_CHECK(ctx->insn_flags & ASE_MT);
6586 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6587 rn = "TCRestart";
6588 break;
6589 case 4:
6590 CP0_CHECK(ctx->insn_flags & ASE_MT);
6591 gen_helper_dmfc0_tchalt(arg, cpu_env);
6592 rn = "TCHalt";
6593 break;
6594 case 5:
6595 CP0_CHECK(ctx->insn_flags & ASE_MT);
6596 gen_helper_dmfc0_tccontext(arg, cpu_env);
6597 rn = "TCContext";
6598 break;
6599 case 6:
6600 CP0_CHECK(ctx->insn_flags & ASE_MT);
6601 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6602 rn = "TCSchedule";
6603 break;
6604 case 7:
6605 CP0_CHECK(ctx->insn_flags & ASE_MT);
6606 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6607 rn = "TCScheFBack";
6608 break;
6609 default:
6610 goto cp0_unimplemented;
6612 break;
6613 case 3:
6614 switch (sel) {
6615 case 0:
6616 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6617 rn = "EntryLo1";
6618 break;
6619 default:
6620 goto cp0_unimplemented;
6622 break;
6623 case 4:
6624 switch (sel) {
6625 case 0:
6626 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6627 rn = "Context";
6628 break;
6629 case 1:
6630 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6631 rn = "ContextConfig";
6632 goto cp0_unimplemented;
6633 // break;
6634 case 2:
6635 CP0_CHECK(ctx->ulri);
6636 tcg_gen_ld_tl(arg, cpu_env,
6637 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6638 rn = "UserLocal";
6639 break;
6640 default:
6641 goto cp0_unimplemented;
6643 break;
6644 case 5:
6645 switch (sel) {
6646 case 0:
6647 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6648 rn = "PageMask";
6649 break;
6650 case 1:
6651 check_insn(ctx, ISA_MIPS32R2);
6652 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6653 rn = "PageGrain";
6654 break;
6655 default:
6656 goto cp0_unimplemented;
6658 break;
6659 case 6:
6660 switch (sel) {
6661 case 0:
6662 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6663 rn = "Wired";
6664 break;
6665 case 1:
6666 check_insn(ctx, ISA_MIPS32R2);
6667 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6668 rn = "SRSConf0";
6669 break;
6670 case 2:
6671 check_insn(ctx, ISA_MIPS32R2);
6672 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6673 rn = "SRSConf1";
6674 break;
6675 case 3:
6676 check_insn(ctx, ISA_MIPS32R2);
6677 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6678 rn = "SRSConf2";
6679 break;
6680 case 4:
6681 check_insn(ctx, ISA_MIPS32R2);
6682 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6683 rn = "SRSConf3";
6684 break;
6685 case 5:
6686 check_insn(ctx, ISA_MIPS32R2);
6687 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6688 rn = "SRSConf4";
6689 break;
6690 default:
6691 goto cp0_unimplemented;
6693 break;
6694 case 7:
6695 switch (sel) {
6696 case 0:
6697 check_insn(ctx, ISA_MIPS32R2);
6698 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6699 rn = "HWREna";
6700 break;
6701 default:
6702 goto cp0_unimplemented;
6704 break;
6705 case 8:
6706 switch (sel) {
6707 case 0:
6708 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6709 rn = "BadVAddr";
6710 break;
6711 case 1:
6712 CP0_CHECK(ctx->bi);
6713 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6714 rn = "BadInstr";
6715 break;
6716 case 2:
6717 CP0_CHECK(ctx->bp);
6718 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6719 rn = "BadInstrP";
6720 break;
6721 default:
6722 goto cp0_unimplemented;
6724 break;
6725 case 9:
6726 switch (sel) {
6727 case 0:
6728 /* Mark as an IO operation because we read the time. */
6729 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6730 gen_io_start();
6732 gen_helper_mfc0_count(arg, cpu_env);
6733 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6734 gen_io_end();
6736 /* Break the TB to be able to take timer interrupts immediately
6737 after reading count. */
6738 ctx->bstate = BS_STOP;
6739 rn = "Count";
6740 break;
6741 /* 6,7 are implementation dependent */
6742 default:
6743 goto cp0_unimplemented;
6745 break;
6746 case 10:
6747 switch (sel) {
6748 case 0:
6749 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6750 rn = "EntryHi";
6751 break;
6752 default:
6753 goto cp0_unimplemented;
6755 break;
6756 case 11:
6757 switch (sel) {
6758 case 0:
6759 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6760 rn = "Compare";
6761 break;
6762 /* 6,7 are implementation dependent */
6763 default:
6764 goto cp0_unimplemented;
6766 break;
6767 case 12:
6768 switch (sel) {
6769 case 0:
6770 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6771 rn = "Status";
6772 break;
6773 case 1:
6774 check_insn(ctx, ISA_MIPS32R2);
6775 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6776 rn = "IntCtl";
6777 break;
6778 case 2:
6779 check_insn(ctx, ISA_MIPS32R2);
6780 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6781 rn = "SRSCtl";
6782 break;
6783 case 3:
6784 check_insn(ctx, ISA_MIPS32R2);
6785 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6786 rn = "SRSMap";
6787 break;
6788 default:
6789 goto cp0_unimplemented;
6791 break;
6792 case 13:
6793 switch (sel) {
6794 case 0:
6795 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6796 rn = "Cause";
6797 break;
6798 default:
6799 goto cp0_unimplemented;
6801 break;
6802 case 14:
6803 switch (sel) {
6804 case 0:
6805 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6806 rn = "EPC";
6807 break;
6808 default:
6809 goto cp0_unimplemented;
6811 break;
6812 case 15:
6813 switch (sel) {
6814 case 0:
6815 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6816 rn = "PRid";
6817 break;
6818 case 1:
6819 check_insn(ctx, ISA_MIPS32R2);
6820 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6821 rn = "EBase";
6822 break;
6823 default:
6824 goto cp0_unimplemented;
6826 break;
6827 case 16:
6828 switch (sel) {
6829 case 0:
6830 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6831 rn = "Config";
6832 break;
6833 case 1:
6834 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6835 rn = "Config1";
6836 break;
6837 case 2:
6838 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6839 rn = "Config2";
6840 break;
6841 case 3:
6842 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6843 rn = "Config3";
6844 break;
6845 case 4:
6846 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6847 rn = "Config4";
6848 break;
6849 case 5:
6850 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6851 rn = "Config5";
6852 break;
6853 /* 6,7 are implementation dependent */
6854 case 6:
6855 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6856 rn = "Config6";
6857 break;
6858 case 7:
6859 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6860 rn = "Config7";
6861 break;
6862 default:
6863 goto cp0_unimplemented;
6865 break;
6866 case 17:
6867 switch (sel) {
6868 case 0:
6869 gen_helper_dmfc0_lladdr(arg, cpu_env);
6870 rn = "LLAddr";
6871 break;
6872 default:
6873 goto cp0_unimplemented;
6875 break;
6876 case 18:
6877 switch (sel) {
6878 case 0 ... 7:
6879 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6880 rn = "WatchLo";
6881 break;
6882 default:
6883 goto cp0_unimplemented;
6885 break;
6886 case 19:
6887 switch (sel) {
6888 case 0 ... 7:
6889 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6890 rn = "WatchHi";
6891 break;
6892 default:
6893 goto cp0_unimplemented;
6895 break;
6896 case 20:
6897 switch (sel) {
6898 case 0:
6899 check_insn(ctx, ISA_MIPS3);
6900 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6901 rn = "XContext";
6902 break;
6903 default:
6904 goto cp0_unimplemented;
6906 break;
6907 case 21:
6908 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6909 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6910 switch (sel) {
6911 case 0:
6912 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6913 rn = "Framemask";
6914 break;
6915 default:
6916 goto cp0_unimplemented;
6918 break;
6919 case 22:
6920 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6921 rn = "'Diagnostic"; /* implementation dependent */
6922 break;
6923 case 23:
6924 switch (sel) {
6925 case 0:
6926 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6927 rn = "Debug";
6928 break;
6929 case 1:
6930 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6931 rn = "TraceControl";
6932 // break;
6933 case 2:
6934 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6935 rn = "TraceControl2";
6936 // break;
6937 case 3:
6938 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6939 rn = "UserTraceData";
6940 // break;
6941 case 4:
6942 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6943 rn = "TraceBPC";
6944 // break;
6945 default:
6946 goto cp0_unimplemented;
6948 break;
6949 case 24:
6950 switch (sel) {
6951 case 0:
6952 /* EJTAG support */
6953 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6954 rn = "DEPC";
6955 break;
6956 default:
6957 goto cp0_unimplemented;
6959 break;
6960 case 25:
6961 switch (sel) {
6962 case 0:
6963 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6964 rn = "Performance0";
6965 break;
6966 case 1:
6967 // gen_helper_dmfc0_performance1(arg);
6968 rn = "Performance1";
6969 // break;
6970 case 2:
6971 // gen_helper_dmfc0_performance2(arg);
6972 rn = "Performance2";
6973 // break;
6974 case 3:
6975 // gen_helper_dmfc0_performance3(arg);
6976 rn = "Performance3";
6977 // break;
6978 case 4:
6979 // gen_helper_dmfc0_performance4(arg);
6980 rn = "Performance4";
6981 // break;
6982 case 5:
6983 // gen_helper_dmfc0_performance5(arg);
6984 rn = "Performance5";
6985 // break;
6986 case 6:
6987 // gen_helper_dmfc0_performance6(arg);
6988 rn = "Performance6";
6989 // break;
6990 case 7:
6991 // gen_helper_dmfc0_performance7(arg);
6992 rn = "Performance7";
6993 // break;
6994 default:
6995 goto cp0_unimplemented;
6997 break;
6998 case 26:
6999 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7000 rn = "ECC";
7001 break;
7002 case 27:
7003 switch (sel) {
7004 /* ignored */
7005 case 0 ... 3:
7006 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7007 rn = "CacheErr";
7008 break;
7009 default:
7010 goto cp0_unimplemented;
7012 break;
7013 case 28:
7014 switch (sel) {
7015 case 0:
7016 case 2:
7017 case 4:
7018 case 6:
7019 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
7020 rn = "TagLo";
7021 break;
7022 case 1:
7023 case 3:
7024 case 5:
7025 case 7:
7026 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7027 rn = "DataLo";
7028 break;
7029 default:
7030 goto cp0_unimplemented;
7032 break;
7033 case 29:
7034 switch (sel) {
7035 case 0:
7036 case 2:
7037 case 4:
7038 case 6:
7039 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7040 rn = "TagHi";
7041 break;
7042 case 1:
7043 case 3:
7044 case 5:
7045 case 7:
7046 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7047 rn = "DataHi";
7048 break;
7049 default:
7050 goto cp0_unimplemented;
7052 break;
7053 case 30:
7054 switch (sel) {
7055 case 0:
7056 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7057 rn = "ErrorEPC";
7058 break;
7059 default:
7060 goto cp0_unimplemented;
7062 break;
7063 case 31:
7064 switch (sel) {
7065 case 0:
7066 /* EJTAG support */
7067 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7068 rn = "DESAVE";
7069 break;
7070 case 2 ... 7:
7071 CP0_CHECK(ctx->kscrexist & (1 << sel));
7072 tcg_gen_ld_tl(arg, cpu_env,
7073 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7074 rn = "KScratch";
7075 break;
7076 default:
7077 goto cp0_unimplemented;
7079 break;
7080 default:
7081 goto cp0_unimplemented;
7083 (void)rn; /* avoid a compiler warning */
7084 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7085 return;
7087 cp0_unimplemented:
7088 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7089 gen_mfc0_unimplemented(ctx, arg);
7092 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7094 const char *rn = "invalid";
7096 if (sel != 0)
7097 check_insn(ctx, ISA_MIPS64);
7099 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7100 gen_io_start();
7103 switch (reg) {
7104 case 0:
7105 switch (sel) {
7106 case 0:
7107 gen_helper_mtc0_index(cpu_env, arg);
7108 rn = "Index";
7109 break;
7110 case 1:
7111 CP0_CHECK(ctx->insn_flags & ASE_MT);
7112 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7113 rn = "MVPControl";
7114 break;
7115 case 2:
7116 CP0_CHECK(ctx->insn_flags & ASE_MT);
7117 /* ignored */
7118 rn = "MVPConf0";
7119 break;
7120 case 3:
7121 CP0_CHECK(ctx->insn_flags & ASE_MT);
7122 /* ignored */
7123 rn = "MVPConf1";
7124 break;
7125 default:
7126 goto cp0_unimplemented;
7128 break;
7129 case 1:
7130 switch (sel) {
7131 case 0:
7132 /* ignored */
7133 rn = "Random";
7134 break;
7135 case 1:
7136 CP0_CHECK(ctx->insn_flags & ASE_MT);
7137 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7138 rn = "VPEControl";
7139 break;
7140 case 2:
7141 CP0_CHECK(ctx->insn_flags & ASE_MT);
7142 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7143 rn = "VPEConf0";
7144 break;
7145 case 3:
7146 CP0_CHECK(ctx->insn_flags & ASE_MT);
7147 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7148 rn = "VPEConf1";
7149 break;
7150 case 4:
7151 CP0_CHECK(ctx->insn_flags & ASE_MT);
7152 gen_helper_mtc0_yqmask(cpu_env, arg);
7153 rn = "YQMask";
7154 break;
7155 case 5:
7156 CP0_CHECK(ctx->insn_flags & ASE_MT);
7157 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7158 rn = "VPESchedule";
7159 break;
7160 case 6:
7161 CP0_CHECK(ctx->insn_flags & ASE_MT);
7162 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7163 rn = "VPEScheFBack";
7164 break;
7165 case 7:
7166 CP0_CHECK(ctx->insn_flags & ASE_MT);
7167 gen_helper_mtc0_vpeopt(cpu_env, arg);
7168 rn = "VPEOpt";
7169 break;
7170 default:
7171 goto cp0_unimplemented;
7173 break;
7174 case 2:
7175 switch (sel) {
7176 case 0:
7177 gen_helper_dmtc0_entrylo0(cpu_env, arg);
7178 rn = "EntryLo0";
7179 break;
7180 case 1:
7181 CP0_CHECK(ctx->insn_flags & ASE_MT);
7182 gen_helper_mtc0_tcstatus(cpu_env, arg);
7183 rn = "TCStatus";
7184 break;
7185 case 2:
7186 CP0_CHECK(ctx->insn_flags & ASE_MT);
7187 gen_helper_mtc0_tcbind(cpu_env, arg);
7188 rn = "TCBind";
7189 break;
7190 case 3:
7191 CP0_CHECK(ctx->insn_flags & ASE_MT);
7192 gen_helper_mtc0_tcrestart(cpu_env, arg);
7193 rn = "TCRestart";
7194 break;
7195 case 4:
7196 CP0_CHECK(ctx->insn_flags & ASE_MT);
7197 gen_helper_mtc0_tchalt(cpu_env, arg);
7198 rn = "TCHalt";
7199 break;
7200 case 5:
7201 CP0_CHECK(ctx->insn_flags & ASE_MT);
7202 gen_helper_mtc0_tccontext(cpu_env, arg);
7203 rn = "TCContext";
7204 break;
7205 case 6:
7206 CP0_CHECK(ctx->insn_flags & ASE_MT);
7207 gen_helper_mtc0_tcschedule(cpu_env, arg);
7208 rn = "TCSchedule";
7209 break;
7210 case 7:
7211 CP0_CHECK(ctx->insn_flags & ASE_MT);
7212 gen_helper_mtc0_tcschefback(cpu_env, arg);
7213 rn = "TCScheFBack";
7214 break;
7215 default:
7216 goto cp0_unimplemented;
7218 break;
7219 case 3:
7220 switch (sel) {
7221 case 0:
7222 gen_helper_dmtc0_entrylo1(cpu_env, arg);
7223 rn = "EntryLo1";
7224 break;
7225 default:
7226 goto cp0_unimplemented;
7228 break;
7229 case 4:
7230 switch (sel) {
7231 case 0:
7232 gen_helper_mtc0_context(cpu_env, arg);
7233 rn = "Context";
7234 break;
7235 case 1:
7236 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7237 rn = "ContextConfig";
7238 goto cp0_unimplemented;
7239 // break;
7240 case 2:
7241 CP0_CHECK(ctx->ulri);
7242 tcg_gen_st_tl(arg, cpu_env,
7243 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7244 rn = "UserLocal";
7245 break;
7246 default:
7247 goto cp0_unimplemented;
7249 break;
7250 case 5:
7251 switch (sel) {
7252 case 0:
7253 gen_helper_mtc0_pagemask(cpu_env, arg);
7254 rn = "PageMask";
7255 break;
7256 case 1:
7257 check_insn(ctx, ISA_MIPS32R2);
7258 gen_helper_mtc0_pagegrain(cpu_env, arg);
7259 rn = "PageGrain";
7260 break;
7261 default:
7262 goto cp0_unimplemented;
7264 break;
7265 case 6:
7266 switch (sel) {
7267 case 0:
7268 gen_helper_mtc0_wired(cpu_env, arg);
7269 rn = "Wired";
7270 break;
7271 case 1:
7272 check_insn(ctx, ISA_MIPS32R2);
7273 gen_helper_mtc0_srsconf0(cpu_env, arg);
7274 rn = "SRSConf0";
7275 break;
7276 case 2:
7277 check_insn(ctx, ISA_MIPS32R2);
7278 gen_helper_mtc0_srsconf1(cpu_env, arg);
7279 rn = "SRSConf1";
7280 break;
7281 case 3:
7282 check_insn(ctx, ISA_MIPS32R2);
7283 gen_helper_mtc0_srsconf2(cpu_env, arg);
7284 rn = "SRSConf2";
7285 break;
7286 case 4:
7287 check_insn(ctx, ISA_MIPS32R2);
7288 gen_helper_mtc0_srsconf3(cpu_env, arg);
7289 rn = "SRSConf3";
7290 break;
7291 case 5:
7292 check_insn(ctx, ISA_MIPS32R2);
7293 gen_helper_mtc0_srsconf4(cpu_env, arg);
7294 rn = "SRSConf4";
7295 break;
7296 default:
7297 goto cp0_unimplemented;
7299 break;
7300 case 7:
7301 switch (sel) {
7302 case 0:
7303 check_insn(ctx, ISA_MIPS32R2);
7304 gen_helper_mtc0_hwrena(cpu_env, arg);
7305 ctx->bstate = BS_STOP;
7306 rn = "HWREna";
7307 break;
7308 default:
7309 goto cp0_unimplemented;
7311 break;
7312 case 8:
7313 switch (sel) {
7314 case 0:
7315 /* ignored */
7316 rn = "BadVAddr";
7317 break;
7318 case 1:
7319 /* ignored */
7320 rn = "BadInstr";
7321 break;
7322 case 2:
7323 /* ignored */
7324 rn = "BadInstrP";
7325 break;
7326 default:
7327 goto cp0_unimplemented;
7329 break;
7330 case 9:
7331 switch (sel) {
7332 case 0:
7333 gen_helper_mtc0_count(cpu_env, arg);
7334 rn = "Count";
7335 break;
7336 /* 6,7 are implementation dependent */
7337 default:
7338 goto cp0_unimplemented;
7340 /* Stop translation as we may have switched the execution mode */
7341 ctx->bstate = BS_STOP;
7342 break;
7343 case 10:
7344 switch (sel) {
7345 case 0:
7346 gen_helper_mtc0_entryhi(cpu_env, arg);
7347 rn = "EntryHi";
7348 break;
7349 default:
7350 goto cp0_unimplemented;
7352 break;
7353 case 11:
7354 switch (sel) {
7355 case 0:
7356 gen_helper_mtc0_compare(cpu_env, arg);
7357 rn = "Compare";
7358 break;
7359 /* 6,7 are implementation dependent */
7360 default:
7361 goto cp0_unimplemented;
7363 /* Stop translation as we may have switched the execution mode */
7364 ctx->bstate = BS_STOP;
7365 break;
7366 case 12:
7367 switch (sel) {
7368 case 0:
7369 save_cpu_state(ctx, 1);
7370 gen_helper_mtc0_status(cpu_env, arg);
7371 /* BS_STOP isn't good enough here, hflags may have changed. */
7372 gen_save_pc(ctx->pc + 4);
7373 ctx->bstate = BS_EXCP;
7374 rn = "Status";
7375 break;
7376 case 1:
7377 check_insn(ctx, ISA_MIPS32R2);
7378 gen_helper_mtc0_intctl(cpu_env, arg);
7379 /* Stop translation as we may have switched the execution mode */
7380 ctx->bstate = BS_STOP;
7381 rn = "IntCtl";
7382 break;
7383 case 2:
7384 check_insn(ctx, ISA_MIPS32R2);
7385 gen_helper_mtc0_srsctl(cpu_env, arg);
7386 /* Stop translation as we may have switched the execution mode */
7387 ctx->bstate = BS_STOP;
7388 rn = "SRSCtl";
7389 break;
7390 case 3:
7391 check_insn(ctx, ISA_MIPS32R2);
7392 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7393 /* Stop translation as we may have switched the execution mode */
7394 ctx->bstate = BS_STOP;
7395 rn = "SRSMap";
7396 break;
7397 default:
7398 goto cp0_unimplemented;
7400 break;
7401 case 13:
7402 switch (sel) {
7403 case 0:
7404 save_cpu_state(ctx, 1);
7405 /* Mark as an IO operation because we may trigger a software
7406 interrupt. */
7407 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7408 gen_io_start();
7410 gen_helper_mtc0_cause(cpu_env, arg);
7411 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7412 gen_io_end();
7414 /* Stop translation as we may have triggered an intetrupt */
7415 ctx->bstate = BS_STOP;
7416 rn = "Cause";
7417 break;
7418 default:
7419 goto cp0_unimplemented;
7421 break;
7422 case 14:
7423 switch (sel) {
7424 case 0:
7425 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7426 rn = "EPC";
7427 break;
7428 default:
7429 goto cp0_unimplemented;
7431 break;
7432 case 15:
7433 switch (sel) {
7434 case 0:
7435 /* ignored */
7436 rn = "PRid";
7437 break;
7438 case 1:
7439 check_insn(ctx, ISA_MIPS32R2);
7440 gen_helper_mtc0_ebase(cpu_env, arg);
7441 rn = "EBase";
7442 break;
7443 default:
7444 goto cp0_unimplemented;
7446 break;
7447 case 16:
7448 switch (sel) {
7449 case 0:
7450 gen_helper_mtc0_config0(cpu_env, arg);
7451 rn = "Config";
7452 /* Stop translation as we may have switched the execution mode */
7453 ctx->bstate = BS_STOP;
7454 break;
7455 case 1:
7456 /* ignored, read only */
7457 rn = "Config1";
7458 break;
7459 case 2:
7460 gen_helper_mtc0_config2(cpu_env, arg);
7461 rn = "Config2";
7462 /* Stop translation as we may have switched the execution mode */
7463 ctx->bstate = BS_STOP;
7464 break;
7465 case 3:
7466 gen_helper_mtc0_config3(cpu_env, arg);
7467 rn = "Config3";
7468 /* Stop translation as we may have switched the execution mode */
7469 ctx->bstate = BS_STOP;
7470 break;
7471 case 4:
7472 /* currently ignored */
7473 rn = "Config4";
7474 break;
7475 case 5:
7476 gen_helper_mtc0_config5(cpu_env, arg);
7477 rn = "Config5";
7478 /* Stop translation as we may have switched the execution mode */
7479 ctx->bstate = BS_STOP;
7480 break;
7481 /* 6,7 are implementation dependent */
7482 default:
7483 rn = "Invalid config selector";
7484 goto cp0_unimplemented;
7486 break;
7487 case 17:
7488 switch (sel) {
7489 case 0:
7490 gen_helper_mtc0_lladdr(cpu_env, arg);
7491 rn = "LLAddr";
7492 break;
7493 default:
7494 goto cp0_unimplemented;
7496 break;
7497 case 18:
7498 switch (sel) {
7499 case 0 ... 7:
7500 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7501 rn = "WatchLo";
7502 break;
7503 default:
7504 goto cp0_unimplemented;
7506 break;
7507 case 19:
7508 switch (sel) {
7509 case 0 ... 7:
7510 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7511 rn = "WatchHi";
7512 break;
7513 default:
7514 goto cp0_unimplemented;
7516 break;
7517 case 20:
7518 switch (sel) {
7519 case 0:
7520 check_insn(ctx, ISA_MIPS3);
7521 gen_helper_mtc0_xcontext(cpu_env, arg);
7522 rn = "XContext";
7523 break;
7524 default:
7525 goto cp0_unimplemented;
7527 break;
7528 case 21:
7529 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7530 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7531 switch (sel) {
7532 case 0:
7533 gen_helper_mtc0_framemask(cpu_env, arg);
7534 rn = "Framemask";
7535 break;
7536 default:
7537 goto cp0_unimplemented;
7539 break;
7540 case 22:
7541 /* ignored */
7542 rn = "Diagnostic"; /* implementation dependent */
7543 break;
7544 case 23:
7545 switch (sel) {
7546 case 0:
7547 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7548 /* BS_STOP isn't good enough here, hflags may have changed. */
7549 gen_save_pc(ctx->pc + 4);
7550 ctx->bstate = BS_EXCP;
7551 rn = "Debug";
7552 break;
7553 case 1:
7554 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7555 /* Stop translation as we may have switched the execution mode */
7556 ctx->bstate = BS_STOP;
7557 rn = "TraceControl";
7558 // break;
7559 case 2:
7560 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7561 /* Stop translation as we may have switched the execution mode */
7562 ctx->bstate = BS_STOP;
7563 rn = "TraceControl2";
7564 // break;
7565 case 3:
7566 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7567 /* Stop translation as we may have switched the execution mode */
7568 ctx->bstate = BS_STOP;
7569 rn = "UserTraceData";
7570 // break;
7571 case 4:
7572 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7573 /* Stop translation as we may have switched the execution mode */
7574 ctx->bstate = BS_STOP;
7575 rn = "TraceBPC";
7576 // break;
7577 default:
7578 goto cp0_unimplemented;
7580 break;
7581 case 24:
7582 switch (sel) {
7583 case 0:
7584 /* EJTAG support */
7585 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7586 rn = "DEPC";
7587 break;
7588 default:
7589 goto cp0_unimplemented;
7591 break;
7592 case 25:
7593 switch (sel) {
7594 case 0:
7595 gen_helper_mtc0_performance0(cpu_env, arg);
7596 rn = "Performance0";
7597 break;
7598 case 1:
7599 // gen_helper_mtc0_performance1(cpu_env, arg);
7600 rn = "Performance1";
7601 // break;
7602 case 2:
7603 // gen_helper_mtc0_performance2(cpu_env, arg);
7604 rn = "Performance2";
7605 // break;
7606 case 3:
7607 // gen_helper_mtc0_performance3(cpu_env, arg);
7608 rn = "Performance3";
7609 // break;
7610 case 4:
7611 // gen_helper_mtc0_performance4(cpu_env, arg);
7612 rn = "Performance4";
7613 // break;
7614 case 5:
7615 // gen_helper_mtc0_performance5(cpu_env, arg);
7616 rn = "Performance5";
7617 // break;
7618 case 6:
7619 // gen_helper_mtc0_performance6(cpu_env, arg);
7620 rn = "Performance6";
7621 // break;
7622 case 7:
7623 // gen_helper_mtc0_performance7(cpu_env, arg);
7624 rn = "Performance7";
7625 // break;
7626 default:
7627 goto cp0_unimplemented;
7629 break;
7630 case 26:
7631 /* ignored */
7632 rn = "ECC";
7633 break;
7634 case 27:
7635 switch (sel) {
7636 case 0 ... 3:
7637 /* ignored */
7638 rn = "CacheErr";
7639 break;
7640 default:
7641 goto cp0_unimplemented;
7643 break;
7644 case 28:
7645 switch (sel) {
7646 case 0:
7647 case 2:
7648 case 4:
7649 case 6:
7650 gen_helper_mtc0_taglo(cpu_env, arg);
7651 rn = "TagLo";
7652 break;
7653 case 1:
7654 case 3:
7655 case 5:
7656 case 7:
7657 gen_helper_mtc0_datalo(cpu_env, arg);
7658 rn = "DataLo";
7659 break;
7660 default:
7661 goto cp0_unimplemented;
7663 break;
7664 case 29:
7665 switch (sel) {
7666 case 0:
7667 case 2:
7668 case 4:
7669 case 6:
7670 gen_helper_mtc0_taghi(cpu_env, arg);
7671 rn = "TagHi";
7672 break;
7673 case 1:
7674 case 3:
7675 case 5:
7676 case 7:
7677 gen_helper_mtc0_datahi(cpu_env, arg);
7678 rn = "DataHi";
7679 break;
7680 default:
7681 rn = "invalid sel";
7682 goto cp0_unimplemented;
7684 break;
7685 case 30:
7686 switch (sel) {
7687 case 0:
7688 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7689 rn = "ErrorEPC";
7690 break;
7691 default:
7692 goto cp0_unimplemented;
7694 break;
7695 case 31:
7696 switch (sel) {
7697 case 0:
7698 /* EJTAG support */
7699 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7700 rn = "DESAVE";
7701 break;
7702 case 2 ... 7:
7703 CP0_CHECK(ctx->kscrexist & (1 << sel));
7704 tcg_gen_st_tl(arg, cpu_env,
7705 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7706 rn = "KScratch";
7707 break;
7708 default:
7709 goto cp0_unimplemented;
7711 /* Stop translation as we may have switched the execution mode */
7712 ctx->bstate = BS_STOP;
7713 break;
7714 default:
7715 goto cp0_unimplemented;
7717 (void)rn; /* avoid a compiler warning */
7718 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7719 /* For simplicity assume that all writes can cause interrupts. */
7720 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7721 gen_io_end();
7722 ctx->bstate = BS_STOP;
7724 return;
7726 cp0_unimplemented:
7727 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7729 #endif /* TARGET_MIPS64 */
7731 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7732 int u, int sel, int h)
7734 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7735 TCGv t0 = tcg_temp_local_new();
7737 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7738 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7739 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7740 tcg_gen_movi_tl(t0, -1);
7741 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7742 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7743 tcg_gen_movi_tl(t0, -1);
7744 else if (u == 0) {
7745 switch (rt) {
7746 case 1:
7747 switch (sel) {
7748 case 1:
7749 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7750 break;
7751 case 2:
7752 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7753 break;
7754 default:
7755 goto die;
7756 break;
7758 break;
7759 case 2:
7760 switch (sel) {
7761 case 1:
7762 gen_helper_mftc0_tcstatus(t0, cpu_env);
7763 break;
7764 case 2:
7765 gen_helper_mftc0_tcbind(t0, cpu_env);
7766 break;
7767 case 3:
7768 gen_helper_mftc0_tcrestart(t0, cpu_env);
7769 break;
7770 case 4:
7771 gen_helper_mftc0_tchalt(t0, cpu_env);
7772 break;
7773 case 5:
7774 gen_helper_mftc0_tccontext(t0, cpu_env);
7775 break;
7776 case 6:
7777 gen_helper_mftc0_tcschedule(t0, cpu_env);
7778 break;
7779 case 7:
7780 gen_helper_mftc0_tcschefback(t0, cpu_env);
7781 break;
7782 default:
7783 gen_mfc0(ctx, t0, rt, sel);
7784 break;
7786 break;
7787 case 10:
7788 switch (sel) {
7789 case 0:
7790 gen_helper_mftc0_entryhi(t0, cpu_env);
7791 break;
7792 default:
7793 gen_mfc0(ctx, t0, rt, sel);
7794 break;
7796 case 12:
7797 switch (sel) {
7798 case 0:
7799 gen_helper_mftc0_status(t0, cpu_env);
7800 break;
7801 default:
7802 gen_mfc0(ctx, t0, rt, sel);
7803 break;
7805 case 13:
7806 switch (sel) {
7807 case 0:
7808 gen_helper_mftc0_cause(t0, cpu_env);
7809 break;
7810 default:
7811 goto die;
7812 break;
7814 break;
7815 case 14:
7816 switch (sel) {
7817 case 0:
7818 gen_helper_mftc0_epc(t0, cpu_env);
7819 break;
7820 default:
7821 goto die;
7822 break;
7824 break;
7825 case 15:
7826 switch (sel) {
7827 case 1:
7828 gen_helper_mftc0_ebase(t0, cpu_env);
7829 break;
7830 default:
7831 goto die;
7832 break;
7834 break;
7835 case 16:
7836 switch (sel) {
7837 case 0 ... 7:
7838 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7839 break;
7840 default:
7841 goto die;
7842 break;
7844 break;
7845 case 23:
7846 switch (sel) {
7847 case 0:
7848 gen_helper_mftc0_debug(t0, cpu_env);
7849 break;
7850 default:
7851 gen_mfc0(ctx, t0, rt, sel);
7852 break;
7854 break;
7855 default:
7856 gen_mfc0(ctx, t0, rt, sel);
7858 } else switch (sel) {
7859 /* GPR registers. */
7860 case 0:
7861 gen_helper_1e0i(mftgpr, t0, rt);
7862 break;
7863 /* Auxiliary CPU registers */
7864 case 1:
7865 switch (rt) {
7866 case 0:
7867 gen_helper_1e0i(mftlo, t0, 0);
7868 break;
7869 case 1:
7870 gen_helper_1e0i(mfthi, t0, 0);
7871 break;
7872 case 2:
7873 gen_helper_1e0i(mftacx, t0, 0);
7874 break;
7875 case 4:
7876 gen_helper_1e0i(mftlo, t0, 1);
7877 break;
7878 case 5:
7879 gen_helper_1e0i(mfthi, t0, 1);
7880 break;
7881 case 6:
7882 gen_helper_1e0i(mftacx, t0, 1);
7883 break;
7884 case 8:
7885 gen_helper_1e0i(mftlo, t0, 2);
7886 break;
7887 case 9:
7888 gen_helper_1e0i(mfthi, t0, 2);
7889 break;
7890 case 10:
7891 gen_helper_1e0i(mftacx, t0, 2);
7892 break;
7893 case 12:
7894 gen_helper_1e0i(mftlo, t0, 3);
7895 break;
7896 case 13:
7897 gen_helper_1e0i(mfthi, t0, 3);
7898 break;
7899 case 14:
7900 gen_helper_1e0i(mftacx, t0, 3);
7901 break;
7902 case 16:
7903 gen_helper_mftdsp(t0, cpu_env);
7904 break;
7905 default:
7906 goto die;
7908 break;
7909 /* Floating point (COP1). */
7910 case 2:
7911 /* XXX: For now we support only a single FPU context. */
7912 if (h == 0) {
7913 TCGv_i32 fp0 = tcg_temp_new_i32();
7915 gen_load_fpr32(ctx, fp0, rt);
7916 tcg_gen_ext_i32_tl(t0, fp0);
7917 tcg_temp_free_i32(fp0);
7918 } else {
7919 TCGv_i32 fp0 = tcg_temp_new_i32();
7921 gen_load_fpr32h(ctx, fp0, rt);
7922 tcg_gen_ext_i32_tl(t0, fp0);
7923 tcg_temp_free_i32(fp0);
7925 break;
7926 case 3:
7927 /* XXX: For now we support only a single FPU context. */
7928 gen_helper_1e0i(cfc1, t0, rt);
7929 break;
7930 /* COP2: Not implemented. */
7931 case 4:
7932 case 5:
7933 /* fall through */
7934 default:
7935 goto die;
7937 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7938 gen_store_gpr(t0, rd);
7939 tcg_temp_free(t0);
7940 return;
7942 die:
7943 tcg_temp_free(t0);
7944 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7945 generate_exception(ctx, EXCP_RI);
7948 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7949 int u, int sel, int h)
7951 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7952 TCGv t0 = tcg_temp_local_new();
7954 gen_load_gpr(t0, rt);
7955 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7956 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7957 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7958 /* NOP */ ;
7959 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7960 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7961 /* NOP */ ;
7962 else if (u == 0) {
7963 switch (rd) {
7964 case 1:
7965 switch (sel) {
7966 case 1:
7967 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7968 break;
7969 case 2:
7970 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7971 break;
7972 default:
7973 goto die;
7974 break;
7976 break;
7977 case 2:
7978 switch (sel) {
7979 case 1:
7980 gen_helper_mttc0_tcstatus(cpu_env, t0);
7981 break;
7982 case 2:
7983 gen_helper_mttc0_tcbind(cpu_env, t0);
7984 break;
7985 case 3:
7986 gen_helper_mttc0_tcrestart(cpu_env, t0);
7987 break;
7988 case 4:
7989 gen_helper_mttc0_tchalt(cpu_env, t0);
7990 break;
7991 case 5:
7992 gen_helper_mttc0_tccontext(cpu_env, t0);
7993 break;
7994 case 6:
7995 gen_helper_mttc0_tcschedule(cpu_env, t0);
7996 break;
7997 case 7:
7998 gen_helper_mttc0_tcschefback(cpu_env, t0);
7999 break;
8000 default:
8001 gen_mtc0(ctx, t0, rd, sel);
8002 break;
8004 break;
8005 case 10:
8006 switch (sel) {
8007 case 0:
8008 gen_helper_mttc0_entryhi(cpu_env, t0);
8009 break;
8010 default:
8011 gen_mtc0(ctx, t0, rd, sel);
8012 break;
8014 case 12:
8015 switch (sel) {
8016 case 0:
8017 gen_helper_mttc0_status(cpu_env, t0);
8018 break;
8019 default:
8020 gen_mtc0(ctx, t0, rd, sel);
8021 break;
8023 case 13:
8024 switch (sel) {
8025 case 0:
8026 gen_helper_mttc0_cause(cpu_env, t0);
8027 break;
8028 default:
8029 goto die;
8030 break;
8032 break;
8033 case 15:
8034 switch (sel) {
8035 case 1:
8036 gen_helper_mttc0_ebase(cpu_env, t0);
8037 break;
8038 default:
8039 goto die;
8040 break;
8042 break;
8043 case 23:
8044 switch (sel) {
8045 case 0:
8046 gen_helper_mttc0_debug(cpu_env, t0);
8047 break;
8048 default:
8049 gen_mtc0(ctx, t0, rd, sel);
8050 break;
8052 break;
8053 default:
8054 gen_mtc0(ctx, t0, rd, sel);
8056 } else switch (sel) {
8057 /* GPR registers. */
8058 case 0:
8059 gen_helper_0e1i(mttgpr, t0, rd);
8060 break;
8061 /* Auxiliary CPU registers */
8062 case 1:
8063 switch (rd) {
8064 case 0:
8065 gen_helper_0e1i(mttlo, t0, 0);
8066 break;
8067 case 1:
8068 gen_helper_0e1i(mtthi, t0, 0);
8069 break;
8070 case 2:
8071 gen_helper_0e1i(mttacx, t0, 0);
8072 break;
8073 case 4:
8074 gen_helper_0e1i(mttlo, t0, 1);
8075 break;
8076 case 5:
8077 gen_helper_0e1i(mtthi, t0, 1);
8078 break;
8079 case 6:
8080 gen_helper_0e1i(mttacx, t0, 1);
8081 break;
8082 case 8:
8083 gen_helper_0e1i(mttlo, t0, 2);
8084 break;
8085 case 9:
8086 gen_helper_0e1i(mtthi, t0, 2);
8087 break;
8088 case 10:
8089 gen_helper_0e1i(mttacx, t0, 2);
8090 break;
8091 case 12:
8092 gen_helper_0e1i(mttlo, t0, 3);
8093 break;
8094 case 13:
8095 gen_helper_0e1i(mtthi, t0, 3);
8096 break;
8097 case 14:
8098 gen_helper_0e1i(mttacx, t0, 3);
8099 break;
8100 case 16:
8101 gen_helper_mttdsp(cpu_env, t0);
8102 break;
8103 default:
8104 goto die;
8106 break;
8107 /* Floating point (COP1). */
8108 case 2:
8109 /* XXX: For now we support only a single FPU context. */
8110 if (h == 0) {
8111 TCGv_i32 fp0 = tcg_temp_new_i32();
8113 tcg_gen_trunc_tl_i32(fp0, t0);
8114 gen_store_fpr32(ctx, fp0, rd);
8115 tcg_temp_free_i32(fp0);
8116 } else {
8117 TCGv_i32 fp0 = tcg_temp_new_i32();
8119 tcg_gen_trunc_tl_i32(fp0, t0);
8120 gen_store_fpr32h(ctx, fp0, rd);
8121 tcg_temp_free_i32(fp0);
8123 break;
8124 case 3:
8125 /* XXX: For now we support only a single FPU context. */
8126 save_cpu_state(ctx, 1);
8128 TCGv_i32 fs_tmp = tcg_const_i32(rd);
8130 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8131 tcg_temp_free_i32(fs_tmp);
8133 /* Stop translation as we may have changed hflags */
8134 ctx->bstate = BS_STOP;
8135 break;
8136 /* COP2: Not implemented. */
8137 case 4:
8138 case 5:
8139 /* fall through */
8140 default:
8141 goto die;
8143 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8144 tcg_temp_free(t0);
8145 return;
8147 die:
8148 tcg_temp_free(t0);
8149 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8150 generate_exception(ctx, EXCP_RI);
8153 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
8155 const char *opn = "ldst";
8157 check_cp0_enabled(ctx);
8158 switch (opc) {
8159 case OPC_MFC0:
8160 if (rt == 0) {
8161 /* Treat as NOP. */
8162 return;
8164 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8165 opn = "mfc0";
8166 break;
8167 case OPC_MTC0:
8169 TCGv t0 = tcg_temp_new();
8171 gen_load_gpr(t0, rt);
8172 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8173 tcg_temp_free(t0);
8175 opn = "mtc0";
8176 break;
8177 #if defined(TARGET_MIPS64)
8178 case OPC_DMFC0:
8179 check_insn(ctx, ISA_MIPS3);
8180 if (rt == 0) {
8181 /* Treat as NOP. */
8182 return;
8184 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8185 opn = "dmfc0";
8186 break;
8187 case OPC_DMTC0:
8188 check_insn(ctx, ISA_MIPS3);
8190 TCGv t0 = tcg_temp_new();
8192 gen_load_gpr(t0, rt);
8193 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8194 tcg_temp_free(t0);
8196 opn = "dmtc0";
8197 break;
8198 #endif
8199 case OPC_MFHC0:
8200 check_mvh(ctx);
8201 if (rt == 0) {
8202 /* Treat as NOP. */
8203 return;
8205 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8206 opn = "mfhc0";
8207 break;
8208 case OPC_MTHC0:
8209 check_mvh(ctx);
8211 TCGv t0 = tcg_temp_new();
8212 gen_load_gpr(t0, rt);
8213 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8214 tcg_temp_free(t0);
8216 opn = "mthc0";
8217 break;
8218 case OPC_MFTR:
8219 check_insn(ctx, ASE_MT);
8220 if (rd == 0) {
8221 /* Treat as NOP. */
8222 return;
8224 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8225 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8226 opn = "mftr";
8227 break;
8228 case OPC_MTTR:
8229 check_insn(ctx, ASE_MT);
8230 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8231 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8232 opn = "mttr";
8233 break;
8234 case OPC_TLBWI:
8235 opn = "tlbwi";
8236 if (!env->tlb->helper_tlbwi)
8237 goto die;
8238 gen_helper_tlbwi(cpu_env);
8239 break;
8240 case OPC_TLBINV:
8241 opn = "tlbinv";
8242 if (ctx->ie >= 2) {
8243 if (!env->tlb->helper_tlbinv) {
8244 goto die;
8246 gen_helper_tlbinv(cpu_env);
8247 } /* treat as nop if TLBINV not supported */
8248 break;
8249 case OPC_TLBINVF:
8250 opn = "tlbinvf";
8251 if (ctx->ie >= 2) {
8252 if (!env->tlb->helper_tlbinvf) {
8253 goto die;
8255 gen_helper_tlbinvf(cpu_env);
8256 } /* treat as nop if TLBINV not supported */
8257 break;
8258 case OPC_TLBWR:
8259 opn = "tlbwr";
8260 if (!env->tlb->helper_tlbwr)
8261 goto die;
8262 gen_helper_tlbwr(cpu_env);
8263 break;
8264 case OPC_TLBP:
8265 opn = "tlbp";
8266 if (!env->tlb->helper_tlbp)
8267 goto die;
8268 gen_helper_tlbp(cpu_env);
8269 break;
8270 case OPC_TLBR:
8271 opn = "tlbr";
8272 if (!env->tlb->helper_tlbr)
8273 goto die;
8274 gen_helper_tlbr(cpu_env);
8275 break;
8276 case OPC_ERET: /* OPC_ERETNC */
8277 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8278 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8279 MIPS_DEBUG("CTI in delay / forbidden slot");
8280 goto die;
8281 } else {
8282 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8283 if (ctx->opcode & (1 << bit_shift)) {
8284 /* OPC_ERETNC */
8285 opn = "eretnc";
8286 check_insn(ctx, ISA_MIPS32R5);
8287 gen_helper_eretnc(cpu_env);
8288 } else {
8289 /* OPC_ERET */
8290 opn = "eret";
8291 check_insn(ctx, ISA_MIPS2);
8292 gen_helper_eret(cpu_env);
8294 ctx->bstate = BS_EXCP;
8296 break;
8297 case OPC_DERET:
8298 opn = "deret";
8299 check_insn(ctx, ISA_MIPS32);
8300 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8301 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8302 MIPS_DEBUG("CTI in delay / forbidden slot");
8303 goto die;
8305 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8306 MIPS_INVAL(opn);
8307 generate_exception(ctx, EXCP_RI);
8308 } else {
8309 gen_helper_deret(cpu_env);
8310 ctx->bstate = BS_EXCP;
8312 break;
8313 case OPC_WAIT:
8314 opn = "wait";
8315 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8316 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8317 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8318 MIPS_DEBUG("CTI in delay / forbidden slot");
8319 goto die;
8321 /* If we get an exception, we want to restart at next instruction */
8322 ctx->pc += 4;
8323 save_cpu_state(ctx, 1);
8324 ctx->pc -= 4;
8325 gen_helper_wait(cpu_env);
8326 ctx->bstate = BS_EXCP;
8327 break;
8328 default:
8329 die:
8330 MIPS_INVAL(opn);
8331 generate_exception(ctx, EXCP_RI);
8332 return;
8334 (void)opn; /* avoid a compiler warning */
8335 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
8337 #endif /* !CONFIG_USER_ONLY */
8339 /* CP1 Branches (before delay slot) */
8340 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8341 int32_t cc, int32_t offset)
8343 target_ulong btarget;
8344 const char *opn = "cp1 cond branch";
8345 TCGv_i32 t0 = tcg_temp_new_i32();
8347 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8348 MIPS_DEBUG("CTI in delay / forbidden slot");
8349 generate_exception(ctx, EXCP_RI);
8350 goto out;
8353 if (cc != 0)
8354 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8356 btarget = ctx->pc + 4 + offset;
8358 switch (op) {
8359 case OPC_BC1F:
8360 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8361 tcg_gen_not_i32(t0, t0);
8362 tcg_gen_andi_i32(t0, t0, 1);
8363 tcg_gen_extu_i32_tl(bcond, t0);
8364 opn = "bc1f";
8365 goto not_likely;
8366 case OPC_BC1FL:
8367 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8368 tcg_gen_not_i32(t0, t0);
8369 tcg_gen_andi_i32(t0, t0, 1);
8370 tcg_gen_extu_i32_tl(bcond, t0);
8371 opn = "bc1fl";
8372 goto likely;
8373 case OPC_BC1T:
8374 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8375 tcg_gen_andi_i32(t0, t0, 1);
8376 tcg_gen_extu_i32_tl(bcond, t0);
8377 opn = "bc1t";
8378 goto not_likely;
8379 case OPC_BC1TL:
8380 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8381 tcg_gen_andi_i32(t0, t0, 1);
8382 tcg_gen_extu_i32_tl(bcond, t0);
8383 opn = "bc1tl";
8384 likely:
8385 ctx->hflags |= MIPS_HFLAG_BL;
8386 break;
8387 case OPC_BC1FANY2:
8389 TCGv_i32 t1 = tcg_temp_new_i32();
8390 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8391 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8392 tcg_gen_nand_i32(t0, t0, t1);
8393 tcg_temp_free_i32(t1);
8394 tcg_gen_andi_i32(t0, t0, 1);
8395 tcg_gen_extu_i32_tl(bcond, t0);
8397 opn = "bc1any2f";
8398 goto not_likely;
8399 case OPC_BC1TANY2:
8401 TCGv_i32 t1 = tcg_temp_new_i32();
8402 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8403 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8404 tcg_gen_or_i32(t0, t0, t1);
8405 tcg_temp_free_i32(t1);
8406 tcg_gen_andi_i32(t0, t0, 1);
8407 tcg_gen_extu_i32_tl(bcond, t0);
8409 opn = "bc1any2t";
8410 goto not_likely;
8411 case OPC_BC1FANY4:
8413 TCGv_i32 t1 = tcg_temp_new_i32();
8414 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8415 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8416 tcg_gen_and_i32(t0, t0, t1);
8417 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8418 tcg_gen_and_i32(t0, t0, t1);
8419 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8420 tcg_gen_nand_i32(t0, t0, t1);
8421 tcg_temp_free_i32(t1);
8422 tcg_gen_andi_i32(t0, t0, 1);
8423 tcg_gen_extu_i32_tl(bcond, t0);
8425 opn = "bc1any4f";
8426 goto not_likely;
8427 case OPC_BC1TANY4:
8429 TCGv_i32 t1 = tcg_temp_new_i32();
8430 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8431 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8432 tcg_gen_or_i32(t0, t0, t1);
8433 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8434 tcg_gen_or_i32(t0, t0, t1);
8435 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8436 tcg_gen_or_i32(t0, t0, t1);
8437 tcg_temp_free_i32(t1);
8438 tcg_gen_andi_i32(t0, t0, 1);
8439 tcg_gen_extu_i32_tl(bcond, t0);
8441 opn = "bc1any4t";
8442 not_likely:
8443 ctx->hflags |= MIPS_HFLAG_BC;
8444 break;
8445 default:
8446 MIPS_INVAL(opn);
8447 generate_exception (ctx, EXCP_RI);
8448 goto out;
8450 (void)opn; /* avoid a compiler warning */
8451 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8452 ctx->hflags, btarget);
8453 ctx->btarget = btarget;
8454 ctx->hflags |= MIPS_HFLAG_BDS32;
8455 out:
8456 tcg_temp_free_i32(t0);
8459 /* R6 CP1 Branches */
8460 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8461 int32_t ft, int32_t offset,
8462 int delayslot_size)
8464 target_ulong btarget;
8465 const char *opn = "cp1 cond branch";
8466 TCGv_i64 t0 = tcg_temp_new_i64();
8468 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8469 #ifdef MIPS_DEBUG_DISAS
8470 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8471 "\n", ctx->pc);
8472 #endif
8473 generate_exception(ctx, EXCP_RI);
8474 goto out;
8477 gen_load_fpr64(ctx, t0, ft);
8478 tcg_gen_andi_i64(t0, t0, 1);
8480 btarget = addr_add(ctx, ctx->pc + 4, offset);
8482 switch (op) {
8483 case OPC_BC1EQZ:
8484 tcg_gen_xori_i64(t0, t0, 1);
8485 opn = "bc1eqz";
8486 ctx->hflags |= MIPS_HFLAG_BC;
8487 break;
8488 case OPC_BC1NEZ:
8489 /* t0 already set */
8490 opn = "bc1nez";
8491 ctx->hflags |= MIPS_HFLAG_BC;
8492 break;
8493 default:
8494 MIPS_INVAL(opn);
8495 generate_exception(ctx, EXCP_RI);
8496 goto out;
8499 tcg_gen_trunc_i64_tl(bcond, t0);
8501 (void)opn; /* avoid a compiler warning */
8502 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8503 ctx->hflags, btarget);
8504 ctx->btarget = btarget;
8506 switch (delayslot_size) {
8507 case 2:
8508 ctx->hflags |= MIPS_HFLAG_BDS16;
8509 break;
8510 case 4:
8511 ctx->hflags |= MIPS_HFLAG_BDS32;
8512 break;
8515 out:
8516 tcg_temp_free_i64(t0);
8519 /* Coprocessor 1 (FPU) */
8521 #define FOP(func, fmt) (((fmt) << 21) | (func))
8523 enum fopcode {
8524 OPC_ADD_S = FOP(0, FMT_S),
8525 OPC_SUB_S = FOP(1, FMT_S),
8526 OPC_MUL_S = FOP(2, FMT_S),
8527 OPC_DIV_S = FOP(3, FMT_S),
8528 OPC_SQRT_S = FOP(4, FMT_S),
8529 OPC_ABS_S = FOP(5, FMT_S),
8530 OPC_MOV_S = FOP(6, FMT_S),
8531 OPC_NEG_S = FOP(7, FMT_S),
8532 OPC_ROUND_L_S = FOP(8, FMT_S),
8533 OPC_TRUNC_L_S = FOP(9, FMT_S),
8534 OPC_CEIL_L_S = FOP(10, FMT_S),
8535 OPC_FLOOR_L_S = FOP(11, FMT_S),
8536 OPC_ROUND_W_S = FOP(12, FMT_S),
8537 OPC_TRUNC_W_S = FOP(13, FMT_S),
8538 OPC_CEIL_W_S = FOP(14, FMT_S),
8539 OPC_FLOOR_W_S = FOP(15, FMT_S),
8540 OPC_SEL_S = FOP(16, FMT_S),
8541 OPC_MOVCF_S = FOP(17, FMT_S),
8542 OPC_MOVZ_S = FOP(18, FMT_S),
8543 OPC_MOVN_S = FOP(19, FMT_S),
8544 OPC_SELEQZ_S = FOP(20, FMT_S),
8545 OPC_RECIP_S = FOP(21, FMT_S),
8546 OPC_RSQRT_S = FOP(22, FMT_S),
8547 OPC_SELNEZ_S = FOP(23, FMT_S),
8548 OPC_MADDF_S = FOP(24, FMT_S),
8549 OPC_MSUBF_S = FOP(25, FMT_S),
8550 OPC_RINT_S = FOP(26, FMT_S),
8551 OPC_CLASS_S = FOP(27, FMT_S),
8552 OPC_MIN_S = FOP(28, FMT_S),
8553 OPC_RECIP2_S = FOP(28, FMT_S),
8554 OPC_MINA_S = FOP(29, FMT_S),
8555 OPC_RECIP1_S = FOP(29, FMT_S),
8556 OPC_MAX_S = FOP(30, FMT_S),
8557 OPC_RSQRT1_S = FOP(30, FMT_S),
8558 OPC_MAXA_S = FOP(31, FMT_S),
8559 OPC_RSQRT2_S = FOP(31, FMT_S),
8560 OPC_CVT_D_S = FOP(33, FMT_S),
8561 OPC_CVT_W_S = FOP(36, FMT_S),
8562 OPC_CVT_L_S = FOP(37, FMT_S),
8563 OPC_CVT_PS_S = FOP(38, FMT_S),
8564 OPC_CMP_F_S = FOP (48, FMT_S),
8565 OPC_CMP_UN_S = FOP (49, FMT_S),
8566 OPC_CMP_EQ_S = FOP (50, FMT_S),
8567 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8568 OPC_CMP_OLT_S = FOP (52, FMT_S),
8569 OPC_CMP_ULT_S = FOP (53, FMT_S),
8570 OPC_CMP_OLE_S = FOP (54, FMT_S),
8571 OPC_CMP_ULE_S = FOP (55, FMT_S),
8572 OPC_CMP_SF_S = FOP (56, FMT_S),
8573 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8574 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8575 OPC_CMP_NGL_S = FOP (59, FMT_S),
8576 OPC_CMP_LT_S = FOP (60, FMT_S),
8577 OPC_CMP_NGE_S = FOP (61, FMT_S),
8578 OPC_CMP_LE_S = FOP (62, FMT_S),
8579 OPC_CMP_NGT_S = FOP (63, FMT_S),
8581 OPC_ADD_D = FOP(0, FMT_D),
8582 OPC_SUB_D = FOP(1, FMT_D),
8583 OPC_MUL_D = FOP(2, FMT_D),
8584 OPC_DIV_D = FOP(3, FMT_D),
8585 OPC_SQRT_D = FOP(4, FMT_D),
8586 OPC_ABS_D = FOP(5, FMT_D),
8587 OPC_MOV_D = FOP(6, FMT_D),
8588 OPC_NEG_D = FOP(7, FMT_D),
8589 OPC_ROUND_L_D = FOP(8, FMT_D),
8590 OPC_TRUNC_L_D = FOP(9, FMT_D),
8591 OPC_CEIL_L_D = FOP(10, FMT_D),
8592 OPC_FLOOR_L_D = FOP(11, FMT_D),
8593 OPC_ROUND_W_D = FOP(12, FMT_D),
8594 OPC_TRUNC_W_D = FOP(13, FMT_D),
8595 OPC_CEIL_W_D = FOP(14, FMT_D),
8596 OPC_FLOOR_W_D = FOP(15, FMT_D),
8597 OPC_SEL_D = FOP(16, FMT_D),
8598 OPC_MOVCF_D = FOP(17, FMT_D),
8599 OPC_MOVZ_D = FOP(18, FMT_D),
8600 OPC_MOVN_D = FOP(19, FMT_D),
8601 OPC_SELEQZ_D = FOP(20, FMT_D),
8602 OPC_RECIP_D = FOP(21, FMT_D),
8603 OPC_RSQRT_D = FOP(22, FMT_D),
8604 OPC_SELNEZ_D = FOP(23, FMT_D),
8605 OPC_MADDF_D = FOP(24, FMT_D),
8606 OPC_MSUBF_D = FOP(25, FMT_D),
8607 OPC_RINT_D = FOP(26, FMT_D),
8608 OPC_CLASS_D = FOP(27, FMT_D),
8609 OPC_MIN_D = FOP(28, FMT_D),
8610 OPC_RECIP2_D = FOP(28, FMT_D),
8611 OPC_MINA_D = FOP(29, FMT_D),
8612 OPC_RECIP1_D = FOP(29, FMT_D),
8613 OPC_MAX_D = FOP(30, FMT_D),
8614 OPC_RSQRT1_D = FOP(30, FMT_D),
8615 OPC_MAXA_D = FOP(31, FMT_D),
8616 OPC_RSQRT2_D = FOP(31, FMT_D),
8617 OPC_CVT_S_D = FOP(32, FMT_D),
8618 OPC_CVT_W_D = FOP(36, FMT_D),
8619 OPC_CVT_L_D = FOP(37, FMT_D),
8620 OPC_CMP_F_D = FOP (48, FMT_D),
8621 OPC_CMP_UN_D = FOP (49, FMT_D),
8622 OPC_CMP_EQ_D = FOP (50, FMT_D),
8623 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8624 OPC_CMP_OLT_D = FOP (52, FMT_D),
8625 OPC_CMP_ULT_D = FOP (53, FMT_D),
8626 OPC_CMP_OLE_D = FOP (54, FMT_D),
8627 OPC_CMP_ULE_D = FOP (55, FMT_D),
8628 OPC_CMP_SF_D = FOP (56, FMT_D),
8629 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8630 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8631 OPC_CMP_NGL_D = FOP (59, FMT_D),
8632 OPC_CMP_LT_D = FOP (60, FMT_D),
8633 OPC_CMP_NGE_D = FOP (61, FMT_D),
8634 OPC_CMP_LE_D = FOP (62, FMT_D),
8635 OPC_CMP_NGT_D = FOP (63, FMT_D),
8637 OPC_CVT_S_W = FOP(32, FMT_W),
8638 OPC_CVT_D_W = FOP(33, FMT_W),
8639 OPC_CVT_S_L = FOP(32, FMT_L),
8640 OPC_CVT_D_L = FOP(33, FMT_L),
8641 OPC_CVT_PS_PW = FOP(38, FMT_W),
8643 OPC_ADD_PS = FOP(0, FMT_PS),
8644 OPC_SUB_PS = FOP(1, FMT_PS),
8645 OPC_MUL_PS = FOP(2, FMT_PS),
8646 OPC_DIV_PS = FOP(3, FMT_PS),
8647 OPC_ABS_PS = FOP(5, FMT_PS),
8648 OPC_MOV_PS = FOP(6, FMT_PS),
8649 OPC_NEG_PS = FOP(7, FMT_PS),
8650 OPC_MOVCF_PS = FOP(17, FMT_PS),
8651 OPC_MOVZ_PS = FOP(18, FMT_PS),
8652 OPC_MOVN_PS = FOP(19, FMT_PS),
8653 OPC_ADDR_PS = FOP(24, FMT_PS),
8654 OPC_MULR_PS = FOP(26, FMT_PS),
8655 OPC_RECIP2_PS = FOP(28, FMT_PS),
8656 OPC_RECIP1_PS = FOP(29, FMT_PS),
8657 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8658 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8660 OPC_CVT_S_PU = FOP(32, FMT_PS),
8661 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8662 OPC_CVT_S_PL = FOP(40, FMT_PS),
8663 OPC_PLL_PS = FOP(44, FMT_PS),
8664 OPC_PLU_PS = FOP(45, FMT_PS),
8665 OPC_PUL_PS = FOP(46, FMT_PS),
8666 OPC_PUU_PS = FOP(47, FMT_PS),
8667 OPC_CMP_F_PS = FOP (48, FMT_PS),
8668 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8669 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8670 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8671 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8672 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8673 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8674 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8675 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8676 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8677 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8678 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8679 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8680 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8681 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8682 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8685 enum r6_f_cmp_op {
8686 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8687 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8688 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8689 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8690 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8691 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8692 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8693 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8694 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8695 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8696 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8697 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8698 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8699 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8700 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8701 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8702 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8703 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8704 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8705 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8706 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8707 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8709 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8710 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8711 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8712 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8713 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8714 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8715 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8716 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8717 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8718 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8719 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8720 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8721 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8722 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8723 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8724 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8725 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8726 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8727 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8728 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8729 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8730 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8732 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8734 const char *opn = "cp1 move";
8735 TCGv t0 = tcg_temp_new();
8737 switch (opc) {
8738 case OPC_MFC1:
8740 TCGv_i32 fp0 = tcg_temp_new_i32();
8742 gen_load_fpr32(ctx, fp0, fs);
8743 tcg_gen_ext_i32_tl(t0, fp0);
8744 tcg_temp_free_i32(fp0);
8746 gen_store_gpr(t0, rt);
8747 opn = "mfc1";
8748 break;
8749 case OPC_MTC1:
8750 gen_load_gpr(t0, rt);
8752 TCGv_i32 fp0 = tcg_temp_new_i32();
8754 tcg_gen_trunc_tl_i32(fp0, t0);
8755 gen_store_fpr32(ctx, fp0, fs);
8756 tcg_temp_free_i32(fp0);
8758 opn = "mtc1";
8759 break;
8760 case OPC_CFC1:
8761 gen_helper_1e0i(cfc1, t0, fs);
8762 gen_store_gpr(t0, rt);
8763 opn = "cfc1";
8764 break;
8765 case OPC_CTC1:
8766 gen_load_gpr(t0, rt);
8767 save_cpu_state(ctx, 1);
8769 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8771 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8772 tcg_temp_free_i32(fs_tmp);
8774 /* Stop translation as we may have changed hflags */
8775 ctx->bstate = BS_STOP;
8776 opn = "ctc1";
8777 break;
8778 #if defined(TARGET_MIPS64)
8779 case OPC_DMFC1:
8780 gen_load_fpr64(ctx, t0, fs);
8781 gen_store_gpr(t0, rt);
8782 opn = "dmfc1";
8783 break;
8784 case OPC_DMTC1:
8785 gen_load_gpr(t0, rt);
8786 gen_store_fpr64(ctx, t0, fs);
8787 opn = "dmtc1";
8788 break;
8789 #endif
8790 case OPC_MFHC1:
8792 TCGv_i32 fp0 = tcg_temp_new_i32();
8794 gen_load_fpr32h(ctx, fp0, fs);
8795 tcg_gen_ext_i32_tl(t0, fp0);
8796 tcg_temp_free_i32(fp0);
8798 gen_store_gpr(t0, rt);
8799 opn = "mfhc1";
8800 break;
8801 case OPC_MTHC1:
8802 gen_load_gpr(t0, rt);
8804 TCGv_i32 fp0 = tcg_temp_new_i32();
8806 tcg_gen_trunc_tl_i32(fp0, t0);
8807 gen_store_fpr32h(ctx, fp0, fs);
8808 tcg_temp_free_i32(fp0);
8810 opn = "mthc1";
8811 break;
8812 default:
8813 MIPS_INVAL(opn);
8814 generate_exception (ctx, EXCP_RI);
8815 goto out;
8817 (void)opn; /* avoid a compiler warning */
8818 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
8820 out:
8821 tcg_temp_free(t0);
8824 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8826 TCGLabel *l1;
8827 TCGCond cond;
8828 TCGv_i32 t0;
8830 if (rd == 0) {
8831 /* Treat as NOP. */
8832 return;
8835 if (tf)
8836 cond = TCG_COND_EQ;
8837 else
8838 cond = TCG_COND_NE;
8840 l1 = gen_new_label();
8841 t0 = tcg_temp_new_i32();
8842 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8843 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8844 tcg_temp_free_i32(t0);
8845 if (rs == 0) {
8846 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8847 } else {
8848 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8850 gen_set_label(l1);
8853 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
8854 int tf)
8856 int cond;
8857 TCGv_i32 t0 = tcg_temp_new_i32();
8858 TCGLabel *l1 = gen_new_label();
8860 if (tf)
8861 cond = TCG_COND_EQ;
8862 else
8863 cond = TCG_COND_NE;
8865 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8866 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8867 gen_load_fpr32(ctx, t0, fs);
8868 gen_store_fpr32(ctx, t0, fd);
8869 gen_set_label(l1);
8870 tcg_temp_free_i32(t0);
8873 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8875 int cond;
8876 TCGv_i32 t0 = tcg_temp_new_i32();
8877 TCGv_i64 fp0;
8878 TCGLabel *l1 = gen_new_label();
8880 if (tf)
8881 cond = TCG_COND_EQ;
8882 else
8883 cond = TCG_COND_NE;
8885 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8886 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8887 tcg_temp_free_i32(t0);
8888 fp0 = tcg_temp_new_i64();
8889 gen_load_fpr64(ctx, fp0, fs);
8890 gen_store_fpr64(ctx, fp0, fd);
8891 tcg_temp_free_i64(fp0);
8892 gen_set_label(l1);
8895 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8896 int cc, int tf)
8898 int cond;
8899 TCGv_i32 t0 = tcg_temp_new_i32();
8900 TCGLabel *l1 = gen_new_label();
8901 TCGLabel *l2 = gen_new_label();
8903 if (tf)
8904 cond = TCG_COND_EQ;
8905 else
8906 cond = TCG_COND_NE;
8908 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8909 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8910 gen_load_fpr32(ctx, t0, fs);
8911 gen_store_fpr32(ctx, t0, fd);
8912 gen_set_label(l1);
8914 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8915 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8916 gen_load_fpr32h(ctx, t0, fs);
8917 gen_store_fpr32h(ctx, t0, fd);
8918 tcg_temp_free_i32(t0);
8919 gen_set_label(l2);
8922 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8923 int fs)
8925 TCGv_i32 t1 = tcg_const_i32(0);
8926 TCGv_i32 fp0 = tcg_temp_new_i32();
8927 TCGv_i32 fp1 = tcg_temp_new_i32();
8928 TCGv_i32 fp2 = tcg_temp_new_i32();
8929 gen_load_fpr32(ctx, fp0, fd);
8930 gen_load_fpr32(ctx, fp1, ft);
8931 gen_load_fpr32(ctx, fp2, fs);
8933 switch (op1) {
8934 case OPC_SEL_S:
8935 tcg_gen_andi_i32(fp0, fp0, 1);
8936 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8937 break;
8938 case OPC_SELEQZ_S:
8939 tcg_gen_andi_i32(fp1, fp1, 1);
8940 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8941 break;
8942 case OPC_SELNEZ_S:
8943 tcg_gen_andi_i32(fp1, fp1, 1);
8944 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8945 break;
8946 default:
8947 MIPS_INVAL("gen_sel_s");
8948 generate_exception (ctx, EXCP_RI);
8949 break;
8952 gen_store_fpr32(ctx, fp0, fd);
8953 tcg_temp_free_i32(fp2);
8954 tcg_temp_free_i32(fp1);
8955 tcg_temp_free_i32(fp0);
8956 tcg_temp_free_i32(t1);
8959 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8960 int fs)
8962 TCGv_i64 t1 = tcg_const_i64(0);
8963 TCGv_i64 fp0 = tcg_temp_new_i64();
8964 TCGv_i64 fp1 = tcg_temp_new_i64();
8965 TCGv_i64 fp2 = tcg_temp_new_i64();
8966 gen_load_fpr64(ctx, fp0, fd);
8967 gen_load_fpr64(ctx, fp1, ft);
8968 gen_load_fpr64(ctx, fp2, fs);
8970 switch (op1) {
8971 case OPC_SEL_D:
8972 tcg_gen_andi_i64(fp0, fp0, 1);
8973 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8974 break;
8975 case OPC_SELEQZ_D:
8976 tcg_gen_andi_i64(fp1, fp1, 1);
8977 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8978 break;
8979 case OPC_SELNEZ_D:
8980 tcg_gen_andi_i64(fp1, fp1, 1);
8981 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8982 break;
8983 default:
8984 MIPS_INVAL("gen_sel_d");
8985 generate_exception (ctx, EXCP_RI);
8986 break;
8989 gen_store_fpr64(ctx, fp0, fd);
8990 tcg_temp_free_i64(fp2);
8991 tcg_temp_free_i64(fp1);
8992 tcg_temp_free_i64(fp0);
8993 tcg_temp_free_i64(t1);
8996 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8997 int ft, int fs, int fd, int cc)
8999 const char *opn = "farith";
9000 const char *condnames[] = {
9001 "c.f",
9002 "c.un",
9003 "c.eq",
9004 "c.ueq",
9005 "c.olt",
9006 "c.ult",
9007 "c.ole",
9008 "c.ule",
9009 "c.sf",
9010 "c.ngle",
9011 "c.seq",
9012 "c.ngl",
9013 "c.lt",
9014 "c.nge",
9015 "c.le",
9016 "c.ngt",
9018 const char *condnames_abs[] = {
9019 "cabs.f",
9020 "cabs.un",
9021 "cabs.eq",
9022 "cabs.ueq",
9023 "cabs.olt",
9024 "cabs.ult",
9025 "cabs.ole",
9026 "cabs.ule",
9027 "cabs.sf",
9028 "cabs.ngle",
9029 "cabs.seq",
9030 "cabs.ngl",
9031 "cabs.lt",
9032 "cabs.nge",
9033 "cabs.le",
9034 "cabs.ngt",
9036 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
9037 uint32_t func = ctx->opcode & 0x3f;
9038 switch (op1) {
9039 case OPC_ADD_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_add_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 = "add.s";
9052 optype = BINOP;
9053 break;
9054 case OPC_SUB_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_sub_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 = "sub.s";
9067 optype = BINOP;
9068 break;
9069 case OPC_MUL_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_mul_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 = "mul.s";
9082 optype = BINOP;
9083 break;
9084 case OPC_DIV_S:
9086 TCGv_i32 fp0 = tcg_temp_new_i32();
9087 TCGv_i32 fp1 = tcg_temp_new_i32();
9089 gen_load_fpr32(ctx, fp0, fs);
9090 gen_load_fpr32(ctx, fp1, ft);
9091 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
9092 tcg_temp_free_i32(fp1);
9093 gen_store_fpr32(ctx, fp0, fd);
9094 tcg_temp_free_i32(fp0);
9096 opn = "div.s";
9097 optype = BINOP;
9098 break;
9099 case OPC_SQRT_S:
9101 TCGv_i32 fp0 = tcg_temp_new_i32();
9103 gen_load_fpr32(ctx, fp0, fs);
9104 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
9105 gen_store_fpr32(ctx, fp0, fd);
9106 tcg_temp_free_i32(fp0);
9108 opn = "sqrt.s";
9109 break;
9110 case OPC_ABS_S:
9112 TCGv_i32 fp0 = tcg_temp_new_i32();
9114 gen_load_fpr32(ctx, fp0, fs);
9115 gen_helper_float_abs_s(fp0, fp0);
9116 gen_store_fpr32(ctx, fp0, fd);
9117 tcg_temp_free_i32(fp0);
9119 opn = "abs.s";
9120 break;
9121 case OPC_MOV_S:
9123 TCGv_i32 fp0 = tcg_temp_new_i32();
9125 gen_load_fpr32(ctx, fp0, fs);
9126 gen_store_fpr32(ctx, fp0, fd);
9127 tcg_temp_free_i32(fp0);
9129 opn = "mov.s";
9130 break;
9131 case OPC_NEG_S:
9133 TCGv_i32 fp0 = tcg_temp_new_i32();
9135 gen_load_fpr32(ctx, fp0, fs);
9136 gen_helper_float_chs_s(fp0, fp0);
9137 gen_store_fpr32(ctx, fp0, fd);
9138 tcg_temp_free_i32(fp0);
9140 opn = "neg.s";
9141 break;
9142 case OPC_ROUND_L_S:
9143 check_cp1_64bitmode(ctx);
9145 TCGv_i32 fp32 = tcg_temp_new_i32();
9146 TCGv_i64 fp64 = tcg_temp_new_i64();
9148 gen_load_fpr32(ctx, fp32, fs);
9149 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
9150 tcg_temp_free_i32(fp32);
9151 gen_store_fpr64(ctx, fp64, fd);
9152 tcg_temp_free_i64(fp64);
9154 opn = "round.l.s";
9155 break;
9156 case OPC_TRUNC_L_S:
9157 check_cp1_64bitmode(ctx);
9159 TCGv_i32 fp32 = tcg_temp_new_i32();
9160 TCGv_i64 fp64 = tcg_temp_new_i64();
9162 gen_load_fpr32(ctx, fp32, fs);
9163 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
9164 tcg_temp_free_i32(fp32);
9165 gen_store_fpr64(ctx, fp64, fd);
9166 tcg_temp_free_i64(fp64);
9168 opn = "trunc.l.s";
9169 break;
9170 case OPC_CEIL_L_S:
9171 check_cp1_64bitmode(ctx);
9173 TCGv_i32 fp32 = tcg_temp_new_i32();
9174 TCGv_i64 fp64 = tcg_temp_new_i64();
9176 gen_load_fpr32(ctx, fp32, fs);
9177 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
9178 tcg_temp_free_i32(fp32);
9179 gen_store_fpr64(ctx, fp64, fd);
9180 tcg_temp_free_i64(fp64);
9182 opn = "ceil.l.s";
9183 break;
9184 case OPC_FLOOR_L_S:
9185 check_cp1_64bitmode(ctx);
9187 TCGv_i32 fp32 = tcg_temp_new_i32();
9188 TCGv_i64 fp64 = tcg_temp_new_i64();
9190 gen_load_fpr32(ctx, fp32, fs);
9191 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
9192 tcg_temp_free_i32(fp32);
9193 gen_store_fpr64(ctx, fp64, fd);
9194 tcg_temp_free_i64(fp64);
9196 opn = "floor.l.s";
9197 break;
9198 case OPC_ROUND_W_S:
9200 TCGv_i32 fp0 = tcg_temp_new_i32();
9202 gen_load_fpr32(ctx, fp0, fs);
9203 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
9204 gen_store_fpr32(ctx, fp0, fd);
9205 tcg_temp_free_i32(fp0);
9207 opn = "round.w.s";
9208 break;
9209 case OPC_TRUNC_W_S:
9211 TCGv_i32 fp0 = tcg_temp_new_i32();
9213 gen_load_fpr32(ctx, fp0, fs);
9214 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
9215 gen_store_fpr32(ctx, fp0, fd);
9216 tcg_temp_free_i32(fp0);
9218 opn = "trunc.w.s";
9219 break;
9220 case OPC_CEIL_W_S:
9222 TCGv_i32 fp0 = tcg_temp_new_i32();
9224 gen_load_fpr32(ctx, fp0, fs);
9225 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
9226 gen_store_fpr32(ctx, fp0, fd);
9227 tcg_temp_free_i32(fp0);
9229 opn = "ceil.w.s";
9230 break;
9231 case OPC_FLOOR_W_S:
9233 TCGv_i32 fp0 = tcg_temp_new_i32();
9235 gen_load_fpr32(ctx, fp0, fs);
9236 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
9237 gen_store_fpr32(ctx, fp0, fd);
9238 tcg_temp_free_i32(fp0);
9240 opn = "floor.w.s";
9241 break;
9242 case OPC_SEL_S:
9243 check_insn(ctx, ISA_MIPS32R6);
9244 gen_sel_s(ctx, op1, fd, ft, fs);
9245 opn = "sel.s";
9246 break;
9247 case OPC_SELEQZ_S:
9248 check_insn(ctx, ISA_MIPS32R6);
9249 gen_sel_s(ctx, op1, fd, ft, fs);
9250 opn = "seleqz.s";
9251 break;
9252 case OPC_SELNEZ_S:
9253 check_insn(ctx, ISA_MIPS32R6);
9254 gen_sel_s(ctx, op1, fd, ft, fs);
9255 opn = "selnez.s";
9256 break;
9257 case OPC_MOVCF_S:
9258 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9259 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9260 opn = "movcf.s";
9261 break;
9262 case OPC_MOVZ_S:
9263 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9265 TCGLabel *l1 = gen_new_label();
9266 TCGv_i32 fp0;
9268 if (ft != 0) {
9269 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9271 fp0 = tcg_temp_new_i32();
9272 gen_load_fpr32(ctx, fp0, fs);
9273 gen_store_fpr32(ctx, fp0, fd);
9274 tcg_temp_free_i32(fp0);
9275 gen_set_label(l1);
9277 opn = "movz.s";
9278 break;
9279 case OPC_MOVN_S:
9280 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9282 TCGLabel *l1 = gen_new_label();
9283 TCGv_i32 fp0;
9285 if (ft != 0) {
9286 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9287 fp0 = tcg_temp_new_i32();
9288 gen_load_fpr32(ctx, fp0, fs);
9289 gen_store_fpr32(ctx, fp0, fd);
9290 tcg_temp_free_i32(fp0);
9291 gen_set_label(l1);
9294 opn = "movn.s";
9295 break;
9296 case OPC_RECIP_S:
9297 check_cop1x(ctx);
9299 TCGv_i32 fp0 = tcg_temp_new_i32();
9301 gen_load_fpr32(ctx, fp0, fs);
9302 gen_helper_float_recip_s(fp0, cpu_env, fp0);
9303 gen_store_fpr32(ctx, fp0, fd);
9304 tcg_temp_free_i32(fp0);
9306 opn = "recip.s";
9307 break;
9308 case OPC_RSQRT_S:
9309 check_cop1x(ctx);
9311 TCGv_i32 fp0 = tcg_temp_new_i32();
9313 gen_load_fpr32(ctx, fp0, fs);
9314 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
9315 gen_store_fpr32(ctx, fp0, fd);
9316 tcg_temp_free_i32(fp0);
9318 opn = "rsqrt.s";
9319 break;
9320 case OPC_MADDF_S:
9321 check_insn(ctx, ISA_MIPS32R6);
9323 TCGv_i32 fp0 = tcg_temp_new_i32();
9324 TCGv_i32 fp1 = tcg_temp_new_i32();
9325 TCGv_i32 fp2 = tcg_temp_new_i32();
9326 gen_load_fpr32(ctx, fp0, fs);
9327 gen_load_fpr32(ctx, fp1, ft);
9328 gen_load_fpr32(ctx, fp2, fd);
9329 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
9330 gen_store_fpr32(ctx, fp2, fd);
9331 tcg_temp_free_i32(fp2);
9332 tcg_temp_free_i32(fp1);
9333 tcg_temp_free_i32(fp0);
9334 opn = "maddf.s";
9336 break;
9337 case OPC_MSUBF_S:
9338 check_insn(ctx, ISA_MIPS32R6);
9340 TCGv_i32 fp0 = tcg_temp_new_i32();
9341 TCGv_i32 fp1 = tcg_temp_new_i32();
9342 TCGv_i32 fp2 = tcg_temp_new_i32();
9343 gen_load_fpr32(ctx, fp0, fs);
9344 gen_load_fpr32(ctx, fp1, ft);
9345 gen_load_fpr32(ctx, fp2, fd);
9346 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9347 gen_store_fpr32(ctx, fp2, fd);
9348 tcg_temp_free_i32(fp2);
9349 tcg_temp_free_i32(fp1);
9350 tcg_temp_free_i32(fp0);
9351 opn = "msubf.s";
9353 break;
9354 case OPC_RINT_S:
9355 check_insn(ctx, ISA_MIPS32R6);
9357 TCGv_i32 fp0 = tcg_temp_new_i32();
9358 gen_load_fpr32(ctx, fp0, fs);
9359 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9360 gen_store_fpr32(ctx, fp0, fd);
9361 tcg_temp_free_i32(fp0);
9362 opn = "rint.s";
9364 break;
9365 case OPC_CLASS_S:
9366 check_insn(ctx, ISA_MIPS32R6);
9368 TCGv_i32 fp0 = tcg_temp_new_i32();
9369 gen_load_fpr32(ctx, fp0, fs);
9370 gen_helper_float_class_s(fp0, fp0);
9371 gen_store_fpr32(ctx, fp0, fd);
9372 tcg_temp_free_i32(fp0);
9373 opn = "class.s";
9375 break;
9376 case OPC_MIN_S: /* OPC_RECIP2_S */
9377 if (ctx->insn_flags & ISA_MIPS32R6) {
9378 /* OPC_MIN_S */
9379 TCGv_i32 fp0 = tcg_temp_new_i32();
9380 TCGv_i32 fp1 = tcg_temp_new_i32();
9381 TCGv_i32 fp2 = tcg_temp_new_i32();
9382 gen_load_fpr32(ctx, fp0, fs);
9383 gen_load_fpr32(ctx, fp1, ft);
9384 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9385 gen_store_fpr32(ctx, fp2, fd);
9386 tcg_temp_free_i32(fp2);
9387 tcg_temp_free_i32(fp1);
9388 tcg_temp_free_i32(fp0);
9389 opn = "min.s";
9390 } else {
9391 /* OPC_RECIP2_S */
9392 check_cp1_64bitmode(ctx);
9394 TCGv_i32 fp0 = tcg_temp_new_i32();
9395 TCGv_i32 fp1 = tcg_temp_new_i32();
9397 gen_load_fpr32(ctx, fp0, fs);
9398 gen_load_fpr32(ctx, fp1, ft);
9399 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9400 tcg_temp_free_i32(fp1);
9401 gen_store_fpr32(ctx, fp0, fd);
9402 tcg_temp_free_i32(fp0);
9404 opn = "recip2.s";
9406 break;
9407 case OPC_MINA_S: /* OPC_RECIP1_S */
9408 if (ctx->insn_flags & ISA_MIPS32R6) {
9409 /* OPC_MINA_S */
9410 TCGv_i32 fp0 = tcg_temp_new_i32();
9411 TCGv_i32 fp1 = tcg_temp_new_i32();
9412 TCGv_i32 fp2 = tcg_temp_new_i32();
9413 gen_load_fpr32(ctx, fp0, fs);
9414 gen_load_fpr32(ctx, fp1, ft);
9415 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9416 gen_store_fpr32(ctx, fp2, fd);
9417 tcg_temp_free_i32(fp2);
9418 tcg_temp_free_i32(fp1);
9419 tcg_temp_free_i32(fp0);
9420 opn = "mina.s";
9421 } else {
9422 /* OPC_RECIP1_S */
9423 check_cp1_64bitmode(ctx);
9425 TCGv_i32 fp0 = tcg_temp_new_i32();
9427 gen_load_fpr32(ctx, fp0, fs);
9428 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9429 gen_store_fpr32(ctx, fp0, fd);
9430 tcg_temp_free_i32(fp0);
9432 opn = "recip1.s";
9434 break;
9435 case OPC_MAX_S: /* OPC_RSQRT1_S */
9436 if (ctx->insn_flags & ISA_MIPS32R6) {
9437 /* OPC_MAX_S */
9438 TCGv_i32 fp0 = tcg_temp_new_i32();
9439 TCGv_i32 fp1 = tcg_temp_new_i32();
9440 gen_load_fpr32(ctx, fp0, fs);
9441 gen_load_fpr32(ctx, fp1, ft);
9442 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9443 gen_store_fpr32(ctx, fp1, fd);
9444 tcg_temp_free_i32(fp1);
9445 tcg_temp_free_i32(fp0);
9446 opn = "max.s";
9447 } else {
9448 /* OPC_RSQRT1_S */
9449 check_cp1_64bitmode(ctx);
9451 TCGv_i32 fp0 = tcg_temp_new_i32();
9453 gen_load_fpr32(ctx, fp0, fs);
9454 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9455 gen_store_fpr32(ctx, fp0, fd);
9456 tcg_temp_free_i32(fp0);
9458 opn = "rsqrt1.s";
9460 break;
9461 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9462 if (ctx->insn_flags & ISA_MIPS32R6) {
9463 /* OPC_MAXA_S */
9464 TCGv_i32 fp0 = tcg_temp_new_i32();
9465 TCGv_i32 fp1 = tcg_temp_new_i32();
9466 gen_load_fpr32(ctx, fp0, fs);
9467 gen_load_fpr32(ctx, fp1, ft);
9468 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9469 gen_store_fpr32(ctx, fp1, fd);
9470 tcg_temp_free_i32(fp1);
9471 tcg_temp_free_i32(fp0);
9472 opn = "maxa.s";
9473 } else {
9474 /* OPC_RSQRT2_S */
9475 check_cp1_64bitmode(ctx);
9477 TCGv_i32 fp0 = tcg_temp_new_i32();
9478 TCGv_i32 fp1 = tcg_temp_new_i32();
9480 gen_load_fpr32(ctx, fp0, fs);
9481 gen_load_fpr32(ctx, fp1, ft);
9482 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9483 tcg_temp_free_i32(fp1);
9484 gen_store_fpr32(ctx, fp0, fd);
9485 tcg_temp_free_i32(fp0);
9487 opn = "rsqrt2.s";
9489 break;
9490 case OPC_CVT_D_S:
9491 check_cp1_registers(ctx, fd);
9493 TCGv_i32 fp32 = tcg_temp_new_i32();
9494 TCGv_i64 fp64 = tcg_temp_new_i64();
9496 gen_load_fpr32(ctx, fp32, fs);
9497 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9498 tcg_temp_free_i32(fp32);
9499 gen_store_fpr64(ctx, fp64, fd);
9500 tcg_temp_free_i64(fp64);
9502 opn = "cvt.d.s";
9503 break;
9504 case OPC_CVT_W_S:
9506 TCGv_i32 fp0 = tcg_temp_new_i32();
9508 gen_load_fpr32(ctx, fp0, fs);
9509 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
9510 gen_store_fpr32(ctx, fp0, fd);
9511 tcg_temp_free_i32(fp0);
9513 opn = "cvt.w.s";
9514 break;
9515 case OPC_CVT_L_S:
9516 check_cp1_64bitmode(ctx);
9518 TCGv_i32 fp32 = tcg_temp_new_i32();
9519 TCGv_i64 fp64 = tcg_temp_new_i64();
9521 gen_load_fpr32(ctx, fp32, fs);
9522 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
9523 tcg_temp_free_i32(fp32);
9524 gen_store_fpr64(ctx, fp64, fd);
9525 tcg_temp_free_i64(fp64);
9527 opn = "cvt.l.s";
9528 break;
9529 case OPC_CVT_PS_S:
9530 check_ps(ctx);
9532 TCGv_i64 fp64 = tcg_temp_new_i64();
9533 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9534 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9536 gen_load_fpr32(ctx, fp32_0, fs);
9537 gen_load_fpr32(ctx, fp32_1, ft);
9538 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9539 tcg_temp_free_i32(fp32_1);
9540 tcg_temp_free_i32(fp32_0);
9541 gen_store_fpr64(ctx, fp64, fd);
9542 tcg_temp_free_i64(fp64);
9544 opn = "cvt.ps.s";
9545 break;
9546 case OPC_CMP_F_S:
9547 case OPC_CMP_UN_S:
9548 case OPC_CMP_EQ_S:
9549 case OPC_CMP_UEQ_S:
9550 case OPC_CMP_OLT_S:
9551 case OPC_CMP_ULT_S:
9552 case OPC_CMP_OLE_S:
9553 case OPC_CMP_ULE_S:
9554 case OPC_CMP_SF_S:
9555 case OPC_CMP_NGLE_S:
9556 case OPC_CMP_SEQ_S:
9557 case OPC_CMP_NGL_S:
9558 case OPC_CMP_LT_S:
9559 case OPC_CMP_NGE_S:
9560 case OPC_CMP_LE_S:
9561 case OPC_CMP_NGT_S:
9562 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9563 if (ctx->opcode & (1 << 6)) {
9564 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9565 opn = condnames_abs[func-48];
9566 } else {
9567 gen_cmp_s(ctx, func-48, ft, fs, cc);
9568 opn = condnames[func-48];
9570 optype = CMPOP;
9571 break;
9572 case OPC_ADD_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_add_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 = "add.d";
9586 optype = BINOP;
9587 break;
9588 case OPC_SUB_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_sub_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 = "sub.d";
9602 optype = BINOP;
9603 break;
9604 case OPC_MUL_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_mul_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 = "mul.d";
9618 optype = BINOP;
9619 break;
9620 case OPC_DIV_D:
9621 check_cp1_registers(ctx, fs | ft | fd);
9623 TCGv_i64 fp0 = tcg_temp_new_i64();
9624 TCGv_i64 fp1 = tcg_temp_new_i64();
9626 gen_load_fpr64(ctx, fp0, fs);
9627 gen_load_fpr64(ctx, fp1, ft);
9628 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9629 tcg_temp_free_i64(fp1);
9630 gen_store_fpr64(ctx, fp0, fd);
9631 tcg_temp_free_i64(fp0);
9633 opn = "div.d";
9634 optype = BINOP;
9635 break;
9636 case OPC_SQRT_D:
9637 check_cp1_registers(ctx, fs | fd);
9639 TCGv_i64 fp0 = tcg_temp_new_i64();
9641 gen_load_fpr64(ctx, fp0, fs);
9642 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9643 gen_store_fpr64(ctx, fp0, fd);
9644 tcg_temp_free_i64(fp0);
9646 opn = "sqrt.d";
9647 break;
9648 case OPC_ABS_D:
9649 check_cp1_registers(ctx, fs | fd);
9651 TCGv_i64 fp0 = tcg_temp_new_i64();
9653 gen_load_fpr64(ctx, fp0, fs);
9654 gen_helper_float_abs_d(fp0, fp0);
9655 gen_store_fpr64(ctx, fp0, fd);
9656 tcg_temp_free_i64(fp0);
9658 opn = "abs.d";
9659 break;
9660 case OPC_MOV_D:
9661 check_cp1_registers(ctx, fs | fd);
9663 TCGv_i64 fp0 = tcg_temp_new_i64();
9665 gen_load_fpr64(ctx, fp0, fs);
9666 gen_store_fpr64(ctx, fp0, fd);
9667 tcg_temp_free_i64(fp0);
9669 opn = "mov.d";
9670 break;
9671 case OPC_NEG_D:
9672 check_cp1_registers(ctx, fs | fd);
9674 TCGv_i64 fp0 = tcg_temp_new_i64();
9676 gen_load_fpr64(ctx, fp0, fs);
9677 gen_helper_float_chs_d(fp0, fp0);
9678 gen_store_fpr64(ctx, fp0, fd);
9679 tcg_temp_free_i64(fp0);
9681 opn = "neg.d";
9682 break;
9683 case OPC_ROUND_L_D:
9684 check_cp1_64bitmode(ctx);
9686 TCGv_i64 fp0 = tcg_temp_new_i64();
9688 gen_load_fpr64(ctx, fp0, fs);
9689 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
9690 gen_store_fpr64(ctx, fp0, fd);
9691 tcg_temp_free_i64(fp0);
9693 opn = "round.l.d";
9694 break;
9695 case OPC_TRUNC_L_D:
9696 check_cp1_64bitmode(ctx);
9698 TCGv_i64 fp0 = tcg_temp_new_i64();
9700 gen_load_fpr64(ctx, fp0, fs);
9701 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
9702 gen_store_fpr64(ctx, fp0, fd);
9703 tcg_temp_free_i64(fp0);
9705 opn = "trunc.l.d";
9706 break;
9707 case OPC_CEIL_L_D:
9708 check_cp1_64bitmode(ctx);
9710 TCGv_i64 fp0 = tcg_temp_new_i64();
9712 gen_load_fpr64(ctx, fp0, fs);
9713 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
9714 gen_store_fpr64(ctx, fp0, fd);
9715 tcg_temp_free_i64(fp0);
9717 opn = "ceil.l.d";
9718 break;
9719 case OPC_FLOOR_L_D:
9720 check_cp1_64bitmode(ctx);
9722 TCGv_i64 fp0 = tcg_temp_new_i64();
9724 gen_load_fpr64(ctx, fp0, fs);
9725 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
9726 gen_store_fpr64(ctx, fp0, fd);
9727 tcg_temp_free_i64(fp0);
9729 opn = "floor.l.d";
9730 break;
9731 case OPC_ROUND_W_D:
9732 check_cp1_registers(ctx, fs);
9734 TCGv_i32 fp32 = tcg_temp_new_i32();
9735 TCGv_i64 fp64 = tcg_temp_new_i64();
9737 gen_load_fpr64(ctx, fp64, fs);
9738 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
9739 tcg_temp_free_i64(fp64);
9740 gen_store_fpr32(ctx, fp32, fd);
9741 tcg_temp_free_i32(fp32);
9743 opn = "round.w.d";
9744 break;
9745 case OPC_TRUNC_W_D:
9746 check_cp1_registers(ctx, fs);
9748 TCGv_i32 fp32 = tcg_temp_new_i32();
9749 TCGv_i64 fp64 = tcg_temp_new_i64();
9751 gen_load_fpr64(ctx, fp64, fs);
9752 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
9753 tcg_temp_free_i64(fp64);
9754 gen_store_fpr32(ctx, fp32, fd);
9755 tcg_temp_free_i32(fp32);
9757 opn = "trunc.w.d";
9758 break;
9759 case OPC_CEIL_W_D:
9760 check_cp1_registers(ctx, fs);
9762 TCGv_i32 fp32 = tcg_temp_new_i32();
9763 TCGv_i64 fp64 = tcg_temp_new_i64();
9765 gen_load_fpr64(ctx, fp64, fs);
9766 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
9767 tcg_temp_free_i64(fp64);
9768 gen_store_fpr32(ctx, fp32, fd);
9769 tcg_temp_free_i32(fp32);
9771 opn = "ceil.w.d";
9772 break;
9773 case OPC_FLOOR_W_D:
9774 check_cp1_registers(ctx, fs);
9776 TCGv_i32 fp32 = tcg_temp_new_i32();
9777 TCGv_i64 fp64 = tcg_temp_new_i64();
9779 gen_load_fpr64(ctx, fp64, fs);
9780 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
9781 tcg_temp_free_i64(fp64);
9782 gen_store_fpr32(ctx, fp32, fd);
9783 tcg_temp_free_i32(fp32);
9785 opn = "floor.w.d";
9786 break;
9787 case OPC_SEL_D:
9788 check_insn(ctx, ISA_MIPS32R6);
9789 gen_sel_d(ctx, op1, fd, ft, fs);
9790 opn = "sel.d";
9791 break;
9792 case OPC_SELEQZ_D:
9793 check_insn(ctx, ISA_MIPS32R6);
9794 gen_sel_d(ctx, op1, fd, ft, fs);
9795 opn = "seleqz.d";
9796 break;
9797 case OPC_SELNEZ_D:
9798 check_insn(ctx, ISA_MIPS32R6);
9799 gen_sel_d(ctx, op1, fd, ft, fs);
9800 opn = "selnez.d";
9801 break;
9802 case OPC_MOVCF_D:
9803 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9804 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9805 opn = "movcf.d";
9806 break;
9807 case OPC_MOVZ_D:
9808 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9810 TCGLabel *l1 = gen_new_label();
9811 TCGv_i64 fp0;
9813 if (ft != 0) {
9814 tcg_gen_brcondi_tl(TCG_COND_NE, 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);
9822 opn = "movz.d";
9823 break;
9824 case OPC_MOVN_D:
9825 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9827 TCGLabel *l1 = gen_new_label();
9828 TCGv_i64 fp0;
9830 if (ft != 0) {
9831 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9832 fp0 = tcg_temp_new_i64();
9833 gen_load_fpr64(ctx, fp0, fs);
9834 gen_store_fpr64(ctx, fp0, fd);
9835 tcg_temp_free_i64(fp0);
9836 gen_set_label(l1);
9839 opn = "movn.d";
9840 break;
9841 case OPC_RECIP_D:
9842 check_cp1_64bitmode(ctx);
9844 TCGv_i64 fp0 = tcg_temp_new_i64();
9846 gen_load_fpr64(ctx, fp0, fs);
9847 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9848 gen_store_fpr64(ctx, fp0, fd);
9849 tcg_temp_free_i64(fp0);
9851 opn = "recip.d";
9852 break;
9853 case OPC_RSQRT_D:
9854 check_cp1_64bitmode(ctx);
9856 TCGv_i64 fp0 = tcg_temp_new_i64();
9858 gen_load_fpr64(ctx, fp0, fs);
9859 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9860 gen_store_fpr64(ctx, fp0, fd);
9861 tcg_temp_free_i64(fp0);
9863 opn = "rsqrt.d";
9864 break;
9865 case OPC_MADDF_D:
9866 check_insn(ctx, ISA_MIPS32R6);
9868 TCGv_i64 fp0 = tcg_temp_new_i64();
9869 TCGv_i64 fp1 = tcg_temp_new_i64();
9870 TCGv_i64 fp2 = tcg_temp_new_i64();
9871 gen_load_fpr64(ctx, fp0, fs);
9872 gen_load_fpr64(ctx, fp1, ft);
9873 gen_load_fpr64(ctx, fp2, fd);
9874 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9875 gen_store_fpr64(ctx, fp2, fd);
9876 tcg_temp_free_i64(fp2);
9877 tcg_temp_free_i64(fp1);
9878 tcg_temp_free_i64(fp0);
9879 opn = "maddf.d";
9881 break;
9882 case OPC_MSUBF_D:
9883 check_insn(ctx, ISA_MIPS32R6);
9885 TCGv_i64 fp0 = tcg_temp_new_i64();
9886 TCGv_i64 fp1 = tcg_temp_new_i64();
9887 TCGv_i64 fp2 = tcg_temp_new_i64();
9888 gen_load_fpr64(ctx, fp0, fs);
9889 gen_load_fpr64(ctx, fp1, ft);
9890 gen_load_fpr64(ctx, fp2, fd);
9891 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9892 gen_store_fpr64(ctx, fp2, fd);
9893 tcg_temp_free_i64(fp2);
9894 tcg_temp_free_i64(fp1);
9895 tcg_temp_free_i64(fp0);
9896 opn = "msubf.d";
9898 break;
9899 case OPC_RINT_D:
9900 check_insn(ctx, ISA_MIPS32R6);
9902 TCGv_i64 fp0 = tcg_temp_new_i64();
9903 gen_load_fpr64(ctx, fp0, fs);
9904 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9905 gen_store_fpr64(ctx, fp0, fd);
9906 tcg_temp_free_i64(fp0);
9907 opn = "rint.d";
9909 break;
9910 case OPC_CLASS_D:
9911 check_insn(ctx, ISA_MIPS32R6);
9913 TCGv_i64 fp0 = tcg_temp_new_i64();
9914 gen_load_fpr64(ctx, fp0, fs);
9915 gen_helper_float_class_d(fp0, fp0);
9916 gen_store_fpr64(ctx, fp0, fd);
9917 tcg_temp_free_i64(fp0);
9918 opn = "class.d";
9920 break;
9921 case OPC_MIN_D: /* OPC_RECIP2_D */
9922 if (ctx->insn_flags & ISA_MIPS32R6) {
9923 /* OPC_MIN_D */
9924 TCGv_i64 fp0 = tcg_temp_new_i64();
9925 TCGv_i64 fp1 = tcg_temp_new_i64();
9926 gen_load_fpr64(ctx, fp0, fs);
9927 gen_load_fpr64(ctx, fp1, ft);
9928 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9929 gen_store_fpr64(ctx, fp1, fd);
9930 tcg_temp_free_i64(fp1);
9931 tcg_temp_free_i64(fp0);
9932 opn = "min.d";
9933 } else {
9934 /* OPC_RECIP2_D */
9935 check_cp1_64bitmode(ctx);
9937 TCGv_i64 fp0 = tcg_temp_new_i64();
9938 TCGv_i64 fp1 = tcg_temp_new_i64();
9940 gen_load_fpr64(ctx, fp0, fs);
9941 gen_load_fpr64(ctx, fp1, ft);
9942 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9943 tcg_temp_free_i64(fp1);
9944 gen_store_fpr64(ctx, fp0, fd);
9945 tcg_temp_free_i64(fp0);
9947 opn = "recip2.d";
9949 break;
9950 case OPC_MINA_D: /* OPC_RECIP1_D */
9951 if (ctx->insn_flags & ISA_MIPS32R6) {
9952 /* OPC_MINA_D */
9953 TCGv_i64 fp0 = tcg_temp_new_i64();
9954 TCGv_i64 fp1 = tcg_temp_new_i64();
9955 gen_load_fpr64(ctx, fp0, fs);
9956 gen_load_fpr64(ctx, fp1, ft);
9957 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9958 gen_store_fpr64(ctx, fp1, fd);
9959 tcg_temp_free_i64(fp1);
9960 tcg_temp_free_i64(fp0);
9961 opn = "mina.d";
9962 } else {
9963 /* OPC_RECIP1_D */
9964 check_cp1_64bitmode(ctx);
9966 TCGv_i64 fp0 = tcg_temp_new_i64();
9968 gen_load_fpr64(ctx, fp0, fs);
9969 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9970 gen_store_fpr64(ctx, fp0, fd);
9971 tcg_temp_free_i64(fp0);
9973 opn = "recip1.d";
9975 break;
9976 case OPC_MAX_D: /* OPC_RSQRT1_D */
9977 if (ctx->insn_flags & ISA_MIPS32R6) {
9978 /* OPC_MAX_D */
9979 TCGv_i64 fp0 = tcg_temp_new_i64();
9980 TCGv_i64 fp1 = tcg_temp_new_i64();
9981 gen_load_fpr64(ctx, fp0, fs);
9982 gen_load_fpr64(ctx, fp1, ft);
9983 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9984 gen_store_fpr64(ctx, fp1, fd);
9985 tcg_temp_free_i64(fp1);
9986 tcg_temp_free_i64(fp0);
9987 opn = "max.d";
9988 } else {
9989 /* OPC_RSQRT1_D */
9990 check_cp1_64bitmode(ctx);
9992 TCGv_i64 fp0 = tcg_temp_new_i64();
9994 gen_load_fpr64(ctx, fp0, fs);
9995 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9996 gen_store_fpr64(ctx, fp0, fd);
9997 tcg_temp_free_i64(fp0);
9999 opn = "rsqrt1.d";
10001 break;
10002 case OPC_MAXA_D: /* OPC_RSQRT2_D */
10003 if (ctx->insn_flags & ISA_MIPS32R6) {
10004 /* OPC_MAXA_D */
10005 TCGv_i64 fp0 = tcg_temp_new_i64();
10006 TCGv_i64 fp1 = tcg_temp_new_i64();
10007 gen_load_fpr64(ctx, fp0, fs);
10008 gen_load_fpr64(ctx, fp1, ft);
10009 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
10010 gen_store_fpr64(ctx, fp1, fd);
10011 tcg_temp_free_i64(fp1);
10012 tcg_temp_free_i64(fp0);
10013 opn = "maxa.d";
10014 } else {
10015 /* OPC_RSQRT2_D */
10016 check_cp1_64bitmode(ctx);
10018 TCGv_i64 fp0 = tcg_temp_new_i64();
10019 TCGv_i64 fp1 = tcg_temp_new_i64();
10021 gen_load_fpr64(ctx, fp0, fs);
10022 gen_load_fpr64(ctx, fp1, ft);
10023 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
10024 tcg_temp_free_i64(fp1);
10025 gen_store_fpr64(ctx, fp0, fd);
10026 tcg_temp_free_i64(fp0);
10028 opn = "rsqrt2.d";
10030 break;
10031 case OPC_CMP_F_D:
10032 case OPC_CMP_UN_D:
10033 case OPC_CMP_EQ_D:
10034 case OPC_CMP_UEQ_D:
10035 case OPC_CMP_OLT_D:
10036 case OPC_CMP_ULT_D:
10037 case OPC_CMP_OLE_D:
10038 case OPC_CMP_ULE_D:
10039 case OPC_CMP_SF_D:
10040 case OPC_CMP_NGLE_D:
10041 case OPC_CMP_SEQ_D:
10042 case OPC_CMP_NGL_D:
10043 case OPC_CMP_LT_D:
10044 case OPC_CMP_NGE_D:
10045 case OPC_CMP_LE_D:
10046 case OPC_CMP_NGT_D:
10047 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10048 if (ctx->opcode & (1 << 6)) {
10049 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
10050 opn = condnames_abs[func-48];
10051 } else {
10052 gen_cmp_d(ctx, func-48, ft, fs, cc);
10053 opn = condnames[func-48];
10055 optype = CMPOP;
10056 break;
10057 case OPC_CVT_S_D:
10058 check_cp1_registers(ctx, fs);
10060 TCGv_i32 fp32 = tcg_temp_new_i32();
10061 TCGv_i64 fp64 = tcg_temp_new_i64();
10063 gen_load_fpr64(ctx, fp64, fs);
10064 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
10065 tcg_temp_free_i64(fp64);
10066 gen_store_fpr32(ctx, fp32, fd);
10067 tcg_temp_free_i32(fp32);
10069 opn = "cvt.s.d";
10070 break;
10071 case OPC_CVT_W_D:
10072 check_cp1_registers(ctx, fs);
10074 TCGv_i32 fp32 = tcg_temp_new_i32();
10075 TCGv_i64 fp64 = tcg_temp_new_i64();
10077 gen_load_fpr64(ctx, fp64, fs);
10078 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
10079 tcg_temp_free_i64(fp64);
10080 gen_store_fpr32(ctx, fp32, fd);
10081 tcg_temp_free_i32(fp32);
10083 opn = "cvt.w.d";
10084 break;
10085 case OPC_CVT_L_D:
10086 check_cp1_64bitmode(ctx);
10088 TCGv_i64 fp0 = tcg_temp_new_i64();
10090 gen_load_fpr64(ctx, fp0, fs);
10091 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
10092 gen_store_fpr64(ctx, fp0, fd);
10093 tcg_temp_free_i64(fp0);
10095 opn = "cvt.l.d";
10096 break;
10097 case OPC_CVT_S_W:
10099 TCGv_i32 fp0 = tcg_temp_new_i32();
10101 gen_load_fpr32(ctx, fp0, fs);
10102 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
10103 gen_store_fpr32(ctx, fp0, fd);
10104 tcg_temp_free_i32(fp0);
10106 opn = "cvt.s.w";
10107 break;
10108 case OPC_CVT_D_W:
10109 check_cp1_registers(ctx, fd);
10111 TCGv_i32 fp32 = tcg_temp_new_i32();
10112 TCGv_i64 fp64 = tcg_temp_new_i64();
10114 gen_load_fpr32(ctx, fp32, fs);
10115 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
10116 tcg_temp_free_i32(fp32);
10117 gen_store_fpr64(ctx, fp64, fd);
10118 tcg_temp_free_i64(fp64);
10120 opn = "cvt.d.w";
10121 break;
10122 case OPC_CVT_S_L:
10123 check_cp1_64bitmode(ctx);
10125 TCGv_i32 fp32 = tcg_temp_new_i32();
10126 TCGv_i64 fp64 = tcg_temp_new_i64();
10128 gen_load_fpr64(ctx, fp64, fs);
10129 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
10130 tcg_temp_free_i64(fp64);
10131 gen_store_fpr32(ctx, fp32, fd);
10132 tcg_temp_free_i32(fp32);
10134 opn = "cvt.s.l";
10135 break;
10136 case OPC_CVT_D_L:
10137 check_cp1_64bitmode(ctx);
10139 TCGv_i64 fp0 = tcg_temp_new_i64();
10141 gen_load_fpr64(ctx, fp0, fs);
10142 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
10143 gen_store_fpr64(ctx, fp0, fd);
10144 tcg_temp_free_i64(fp0);
10146 opn = "cvt.d.l";
10147 break;
10148 case OPC_CVT_PS_PW:
10149 check_ps(ctx);
10151 TCGv_i64 fp0 = tcg_temp_new_i64();
10153 gen_load_fpr64(ctx, fp0, fs);
10154 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
10155 gen_store_fpr64(ctx, fp0, fd);
10156 tcg_temp_free_i64(fp0);
10158 opn = "cvt.ps.pw";
10159 break;
10160 case OPC_ADD_PS:
10161 check_ps(ctx);
10163 TCGv_i64 fp0 = tcg_temp_new_i64();
10164 TCGv_i64 fp1 = tcg_temp_new_i64();
10166 gen_load_fpr64(ctx, fp0, fs);
10167 gen_load_fpr64(ctx, fp1, ft);
10168 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
10169 tcg_temp_free_i64(fp1);
10170 gen_store_fpr64(ctx, fp0, fd);
10171 tcg_temp_free_i64(fp0);
10173 opn = "add.ps";
10174 break;
10175 case OPC_SUB_PS:
10176 check_ps(ctx);
10178 TCGv_i64 fp0 = tcg_temp_new_i64();
10179 TCGv_i64 fp1 = tcg_temp_new_i64();
10181 gen_load_fpr64(ctx, fp0, fs);
10182 gen_load_fpr64(ctx, fp1, ft);
10183 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
10184 tcg_temp_free_i64(fp1);
10185 gen_store_fpr64(ctx, fp0, fd);
10186 tcg_temp_free_i64(fp0);
10188 opn = "sub.ps";
10189 break;
10190 case OPC_MUL_PS:
10191 check_ps(ctx);
10193 TCGv_i64 fp0 = tcg_temp_new_i64();
10194 TCGv_i64 fp1 = tcg_temp_new_i64();
10196 gen_load_fpr64(ctx, fp0, fs);
10197 gen_load_fpr64(ctx, fp1, ft);
10198 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
10199 tcg_temp_free_i64(fp1);
10200 gen_store_fpr64(ctx, fp0, fd);
10201 tcg_temp_free_i64(fp0);
10203 opn = "mul.ps";
10204 break;
10205 case OPC_ABS_PS:
10206 check_ps(ctx);
10208 TCGv_i64 fp0 = tcg_temp_new_i64();
10210 gen_load_fpr64(ctx, fp0, fs);
10211 gen_helper_float_abs_ps(fp0, fp0);
10212 gen_store_fpr64(ctx, fp0, fd);
10213 tcg_temp_free_i64(fp0);
10215 opn = "abs.ps";
10216 break;
10217 case OPC_MOV_PS:
10218 check_ps(ctx);
10220 TCGv_i64 fp0 = tcg_temp_new_i64();
10222 gen_load_fpr64(ctx, fp0, fs);
10223 gen_store_fpr64(ctx, fp0, fd);
10224 tcg_temp_free_i64(fp0);
10226 opn = "mov.ps";
10227 break;
10228 case OPC_NEG_PS:
10229 check_ps(ctx);
10231 TCGv_i64 fp0 = tcg_temp_new_i64();
10233 gen_load_fpr64(ctx, fp0, fs);
10234 gen_helper_float_chs_ps(fp0, fp0);
10235 gen_store_fpr64(ctx, fp0, fd);
10236 tcg_temp_free_i64(fp0);
10238 opn = "neg.ps";
10239 break;
10240 case OPC_MOVCF_PS:
10241 check_ps(ctx);
10242 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10243 opn = "movcf.ps";
10244 break;
10245 case OPC_MOVZ_PS:
10246 check_ps(ctx);
10248 TCGLabel *l1 = gen_new_label();
10249 TCGv_i64 fp0;
10251 if (ft != 0)
10252 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10253 fp0 = tcg_temp_new_i64();
10254 gen_load_fpr64(ctx, fp0, fs);
10255 gen_store_fpr64(ctx, fp0, fd);
10256 tcg_temp_free_i64(fp0);
10257 gen_set_label(l1);
10259 opn = "movz.ps";
10260 break;
10261 case OPC_MOVN_PS:
10262 check_ps(ctx);
10264 TCGLabel *l1 = gen_new_label();
10265 TCGv_i64 fp0;
10267 if (ft != 0) {
10268 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10269 fp0 = tcg_temp_new_i64();
10270 gen_load_fpr64(ctx, fp0, fs);
10271 gen_store_fpr64(ctx, fp0, fd);
10272 tcg_temp_free_i64(fp0);
10273 gen_set_label(l1);
10276 opn = "movn.ps";
10277 break;
10278 case OPC_ADDR_PS:
10279 check_ps(ctx);
10281 TCGv_i64 fp0 = tcg_temp_new_i64();
10282 TCGv_i64 fp1 = tcg_temp_new_i64();
10284 gen_load_fpr64(ctx, fp0, ft);
10285 gen_load_fpr64(ctx, fp1, fs);
10286 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
10287 tcg_temp_free_i64(fp1);
10288 gen_store_fpr64(ctx, fp0, fd);
10289 tcg_temp_free_i64(fp0);
10291 opn = "addr.ps";
10292 break;
10293 case OPC_MULR_PS:
10294 check_ps(ctx);
10296 TCGv_i64 fp0 = tcg_temp_new_i64();
10297 TCGv_i64 fp1 = tcg_temp_new_i64();
10299 gen_load_fpr64(ctx, fp0, ft);
10300 gen_load_fpr64(ctx, fp1, fs);
10301 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
10302 tcg_temp_free_i64(fp1);
10303 gen_store_fpr64(ctx, fp0, fd);
10304 tcg_temp_free_i64(fp0);
10306 opn = "mulr.ps";
10307 break;
10308 case OPC_RECIP2_PS:
10309 check_ps(ctx);
10311 TCGv_i64 fp0 = tcg_temp_new_i64();
10312 TCGv_i64 fp1 = tcg_temp_new_i64();
10314 gen_load_fpr64(ctx, fp0, fs);
10315 gen_load_fpr64(ctx, fp1, ft);
10316 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
10317 tcg_temp_free_i64(fp1);
10318 gen_store_fpr64(ctx, fp0, fd);
10319 tcg_temp_free_i64(fp0);
10321 opn = "recip2.ps";
10322 break;
10323 case OPC_RECIP1_PS:
10324 check_ps(ctx);
10326 TCGv_i64 fp0 = tcg_temp_new_i64();
10328 gen_load_fpr64(ctx, fp0, fs);
10329 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
10330 gen_store_fpr64(ctx, fp0, fd);
10331 tcg_temp_free_i64(fp0);
10333 opn = "recip1.ps";
10334 break;
10335 case OPC_RSQRT1_PS:
10336 check_ps(ctx);
10338 TCGv_i64 fp0 = tcg_temp_new_i64();
10340 gen_load_fpr64(ctx, fp0, fs);
10341 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
10342 gen_store_fpr64(ctx, fp0, fd);
10343 tcg_temp_free_i64(fp0);
10345 opn = "rsqrt1.ps";
10346 break;
10347 case OPC_RSQRT2_PS:
10348 check_ps(ctx);
10350 TCGv_i64 fp0 = tcg_temp_new_i64();
10351 TCGv_i64 fp1 = tcg_temp_new_i64();
10353 gen_load_fpr64(ctx, fp0, fs);
10354 gen_load_fpr64(ctx, fp1, ft);
10355 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
10356 tcg_temp_free_i64(fp1);
10357 gen_store_fpr64(ctx, fp0, fd);
10358 tcg_temp_free_i64(fp0);
10360 opn = "rsqrt2.ps";
10361 break;
10362 case OPC_CVT_S_PU:
10363 check_cp1_64bitmode(ctx);
10365 TCGv_i32 fp0 = tcg_temp_new_i32();
10367 gen_load_fpr32h(ctx, fp0, fs);
10368 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
10369 gen_store_fpr32(ctx, fp0, fd);
10370 tcg_temp_free_i32(fp0);
10372 opn = "cvt.s.pu";
10373 break;
10374 case OPC_CVT_PW_PS:
10375 check_ps(ctx);
10377 TCGv_i64 fp0 = tcg_temp_new_i64();
10379 gen_load_fpr64(ctx, fp0, fs);
10380 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
10381 gen_store_fpr64(ctx, fp0, fd);
10382 tcg_temp_free_i64(fp0);
10384 opn = "cvt.pw.ps";
10385 break;
10386 case OPC_CVT_S_PL:
10387 check_cp1_64bitmode(ctx);
10389 TCGv_i32 fp0 = tcg_temp_new_i32();
10391 gen_load_fpr32(ctx, fp0, fs);
10392 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10393 gen_store_fpr32(ctx, fp0, fd);
10394 tcg_temp_free_i32(fp0);
10396 opn = "cvt.s.pl";
10397 break;
10398 case OPC_PLL_PS:
10399 check_ps(ctx);
10401 TCGv_i32 fp0 = tcg_temp_new_i32();
10402 TCGv_i32 fp1 = tcg_temp_new_i32();
10404 gen_load_fpr32(ctx, fp0, fs);
10405 gen_load_fpr32(ctx, fp1, ft);
10406 gen_store_fpr32h(ctx, fp0, fd);
10407 gen_store_fpr32(ctx, fp1, fd);
10408 tcg_temp_free_i32(fp0);
10409 tcg_temp_free_i32(fp1);
10411 opn = "pll.ps";
10412 break;
10413 case OPC_PLU_PS:
10414 check_ps(ctx);
10416 TCGv_i32 fp0 = tcg_temp_new_i32();
10417 TCGv_i32 fp1 = tcg_temp_new_i32();
10419 gen_load_fpr32(ctx, fp0, fs);
10420 gen_load_fpr32h(ctx, fp1, ft);
10421 gen_store_fpr32(ctx, fp1, fd);
10422 gen_store_fpr32h(ctx, fp0, fd);
10423 tcg_temp_free_i32(fp0);
10424 tcg_temp_free_i32(fp1);
10426 opn = "plu.ps";
10427 break;
10428 case OPC_PUL_PS:
10429 check_ps(ctx);
10431 TCGv_i32 fp0 = tcg_temp_new_i32();
10432 TCGv_i32 fp1 = tcg_temp_new_i32();
10434 gen_load_fpr32h(ctx, fp0, fs);
10435 gen_load_fpr32(ctx, fp1, ft);
10436 gen_store_fpr32(ctx, fp1, fd);
10437 gen_store_fpr32h(ctx, fp0, fd);
10438 tcg_temp_free_i32(fp0);
10439 tcg_temp_free_i32(fp1);
10441 opn = "pul.ps";
10442 break;
10443 case OPC_PUU_PS:
10444 check_ps(ctx);
10446 TCGv_i32 fp0 = tcg_temp_new_i32();
10447 TCGv_i32 fp1 = tcg_temp_new_i32();
10449 gen_load_fpr32h(ctx, fp0, fs);
10450 gen_load_fpr32h(ctx, fp1, ft);
10451 gen_store_fpr32(ctx, fp1, fd);
10452 gen_store_fpr32h(ctx, fp0, fd);
10453 tcg_temp_free_i32(fp0);
10454 tcg_temp_free_i32(fp1);
10456 opn = "puu.ps";
10457 break;
10458 case OPC_CMP_F_PS:
10459 case OPC_CMP_UN_PS:
10460 case OPC_CMP_EQ_PS:
10461 case OPC_CMP_UEQ_PS:
10462 case OPC_CMP_OLT_PS:
10463 case OPC_CMP_ULT_PS:
10464 case OPC_CMP_OLE_PS:
10465 case OPC_CMP_ULE_PS:
10466 case OPC_CMP_SF_PS:
10467 case OPC_CMP_NGLE_PS:
10468 case OPC_CMP_SEQ_PS:
10469 case OPC_CMP_NGL_PS:
10470 case OPC_CMP_LT_PS:
10471 case OPC_CMP_NGE_PS:
10472 case OPC_CMP_LE_PS:
10473 case OPC_CMP_NGT_PS:
10474 if (ctx->opcode & (1 << 6)) {
10475 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10476 opn = condnames_abs[func-48];
10477 } else {
10478 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10479 opn = condnames[func-48];
10481 optype = CMPOP;
10482 break;
10483 default:
10484 MIPS_INVAL(opn);
10485 generate_exception (ctx, EXCP_RI);
10486 return;
10488 (void)opn; /* avoid a compiler warning */
10489 switch (optype) {
10490 case BINOP:
10491 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
10492 break;
10493 case CMPOP:
10494 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
10495 break;
10496 default:
10497 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
10498 break;
10502 /* Coprocessor 3 (FPU) */
10503 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10504 int fd, int fs, int base, int index)
10506 const char *opn = "extended float load/store";
10507 int store = 0;
10508 TCGv t0 = tcg_temp_new();
10510 if (base == 0) {
10511 gen_load_gpr(t0, index);
10512 } else if (index == 0) {
10513 gen_load_gpr(t0, base);
10514 } else {
10515 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10517 /* Don't do NOP if destination is zero: we must perform the actual
10518 memory access. */
10519 switch (opc) {
10520 case OPC_LWXC1:
10521 check_cop1x(ctx);
10523 TCGv_i32 fp0 = tcg_temp_new_i32();
10525 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10526 tcg_gen_trunc_tl_i32(fp0, t0);
10527 gen_store_fpr32(ctx, fp0, fd);
10528 tcg_temp_free_i32(fp0);
10530 opn = "lwxc1";
10531 break;
10532 case OPC_LDXC1:
10533 check_cop1x(ctx);
10534 check_cp1_registers(ctx, fd);
10536 TCGv_i64 fp0 = tcg_temp_new_i64();
10537 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10538 gen_store_fpr64(ctx, fp0, fd);
10539 tcg_temp_free_i64(fp0);
10541 opn = "ldxc1";
10542 break;
10543 case OPC_LUXC1:
10544 check_cp1_64bitmode(ctx);
10545 tcg_gen_andi_tl(t0, t0, ~0x7);
10547 TCGv_i64 fp0 = tcg_temp_new_i64();
10549 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10550 gen_store_fpr64(ctx, fp0, fd);
10551 tcg_temp_free_i64(fp0);
10553 opn = "luxc1";
10554 break;
10555 case OPC_SWXC1:
10556 check_cop1x(ctx);
10558 TCGv_i32 fp0 = tcg_temp_new_i32();
10559 gen_load_fpr32(ctx, fp0, fs);
10560 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10561 tcg_temp_free_i32(fp0);
10563 opn = "swxc1";
10564 store = 1;
10565 break;
10566 case OPC_SDXC1:
10567 check_cop1x(ctx);
10568 check_cp1_registers(ctx, fs);
10570 TCGv_i64 fp0 = tcg_temp_new_i64();
10571 gen_load_fpr64(ctx, fp0, fs);
10572 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10573 tcg_temp_free_i64(fp0);
10575 opn = "sdxc1";
10576 store = 1;
10577 break;
10578 case OPC_SUXC1:
10579 check_cp1_64bitmode(ctx);
10580 tcg_gen_andi_tl(t0, t0, ~0x7);
10582 TCGv_i64 fp0 = tcg_temp_new_i64();
10583 gen_load_fpr64(ctx, fp0, fs);
10584 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10585 tcg_temp_free_i64(fp0);
10587 opn = "suxc1";
10588 store = 1;
10589 break;
10591 tcg_temp_free(t0);
10592 (void)opn; (void)store; /* avoid compiler warnings */
10593 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
10594 regnames[index], regnames[base]);
10597 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10598 int fd, int fr, int fs, int ft)
10600 const char *opn = "flt3_arith";
10602 switch (opc) {
10603 case OPC_ALNV_PS:
10604 check_ps(ctx);
10606 TCGv t0 = tcg_temp_local_new();
10607 TCGv_i32 fp = tcg_temp_new_i32();
10608 TCGv_i32 fph = tcg_temp_new_i32();
10609 TCGLabel *l1 = gen_new_label();
10610 TCGLabel *l2 = gen_new_label();
10612 gen_load_gpr(t0, fr);
10613 tcg_gen_andi_tl(t0, t0, 0x7);
10615 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10616 gen_load_fpr32(ctx, fp, fs);
10617 gen_load_fpr32h(ctx, fph, fs);
10618 gen_store_fpr32(ctx, fp, fd);
10619 gen_store_fpr32h(ctx, fph, fd);
10620 tcg_gen_br(l2);
10621 gen_set_label(l1);
10622 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10623 tcg_temp_free(t0);
10624 #ifdef TARGET_WORDS_BIGENDIAN
10625 gen_load_fpr32(ctx, fp, fs);
10626 gen_load_fpr32h(ctx, fph, ft);
10627 gen_store_fpr32h(ctx, fp, fd);
10628 gen_store_fpr32(ctx, fph, fd);
10629 #else
10630 gen_load_fpr32h(ctx, fph, fs);
10631 gen_load_fpr32(ctx, fp, ft);
10632 gen_store_fpr32(ctx, fph, fd);
10633 gen_store_fpr32h(ctx, fp, fd);
10634 #endif
10635 gen_set_label(l2);
10636 tcg_temp_free_i32(fp);
10637 tcg_temp_free_i32(fph);
10639 opn = "alnv.ps";
10640 break;
10641 case OPC_MADD_S:
10642 check_cop1x(ctx);
10644 TCGv_i32 fp0 = tcg_temp_new_i32();
10645 TCGv_i32 fp1 = tcg_temp_new_i32();
10646 TCGv_i32 fp2 = tcg_temp_new_i32();
10648 gen_load_fpr32(ctx, fp0, fs);
10649 gen_load_fpr32(ctx, fp1, ft);
10650 gen_load_fpr32(ctx, fp2, fr);
10651 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10652 tcg_temp_free_i32(fp0);
10653 tcg_temp_free_i32(fp1);
10654 gen_store_fpr32(ctx, fp2, fd);
10655 tcg_temp_free_i32(fp2);
10657 opn = "madd.s";
10658 break;
10659 case OPC_MADD_D:
10660 check_cop1x(ctx);
10661 check_cp1_registers(ctx, fd | fs | ft | fr);
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_d(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.d";
10677 break;
10678 case OPC_MADD_PS:
10679 check_ps(ctx);
10681 TCGv_i64 fp0 = tcg_temp_new_i64();
10682 TCGv_i64 fp1 = tcg_temp_new_i64();
10683 TCGv_i64 fp2 = tcg_temp_new_i64();
10685 gen_load_fpr64(ctx, fp0, fs);
10686 gen_load_fpr64(ctx, fp1, ft);
10687 gen_load_fpr64(ctx, fp2, fr);
10688 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10689 tcg_temp_free_i64(fp0);
10690 tcg_temp_free_i64(fp1);
10691 gen_store_fpr64(ctx, fp2, fd);
10692 tcg_temp_free_i64(fp2);
10694 opn = "madd.ps";
10695 break;
10696 case OPC_MSUB_S:
10697 check_cop1x(ctx);
10699 TCGv_i32 fp0 = tcg_temp_new_i32();
10700 TCGv_i32 fp1 = tcg_temp_new_i32();
10701 TCGv_i32 fp2 = tcg_temp_new_i32();
10703 gen_load_fpr32(ctx, fp0, fs);
10704 gen_load_fpr32(ctx, fp1, ft);
10705 gen_load_fpr32(ctx, fp2, fr);
10706 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10707 tcg_temp_free_i32(fp0);
10708 tcg_temp_free_i32(fp1);
10709 gen_store_fpr32(ctx, fp2, fd);
10710 tcg_temp_free_i32(fp2);
10712 opn = "msub.s";
10713 break;
10714 case OPC_MSUB_D:
10715 check_cop1x(ctx);
10716 check_cp1_registers(ctx, fd | fs | ft | fr);
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_d(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.d";
10732 break;
10733 case OPC_MSUB_PS:
10734 check_ps(ctx);
10736 TCGv_i64 fp0 = tcg_temp_new_i64();
10737 TCGv_i64 fp1 = tcg_temp_new_i64();
10738 TCGv_i64 fp2 = tcg_temp_new_i64();
10740 gen_load_fpr64(ctx, fp0, fs);
10741 gen_load_fpr64(ctx, fp1, ft);
10742 gen_load_fpr64(ctx, fp2, fr);
10743 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10744 tcg_temp_free_i64(fp0);
10745 tcg_temp_free_i64(fp1);
10746 gen_store_fpr64(ctx, fp2, fd);
10747 tcg_temp_free_i64(fp2);
10749 opn = "msub.ps";
10750 break;
10751 case OPC_NMADD_S:
10752 check_cop1x(ctx);
10754 TCGv_i32 fp0 = tcg_temp_new_i32();
10755 TCGv_i32 fp1 = tcg_temp_new_i32();
10756 TCGv_i32 fp2 = tcg_temp_new_i32();
10758 gen_load_fpr32(ctx, fp0, fs);
10759 gen_load_fpr32(ctx, fp1, ft);
10760 gen_load_fpr32(ctx, fp2, fr);
10761 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10762 tcg_temp_free_i32(fp0);
10763 tcg_temp_free_i32(fp1);
10764 gen_store_fpr32(ctx, fp2, fd);
10765 tcg_temp_free_i32(fp2);
10767 opn = "nmadd.s";
10768 break;
10769 case OPC_NMADD_D:
10770 check_cop1x(ctx);
10771 check_cp1_registers(ctx, fd | fs | ft | fr);
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_d(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.d";
10787 break;
10788 case OPC_NMADD_PS:
10789 check_ps(ctx);
10791 TCGv_i64 fp0 = tcg_temp_new_i64();
10792 TCGv_i64 fp1 = tcg_temp_new_i64();
10793 TCGv_i64 fp2 = tcg_temp_new_i64();
10795 gen_load_fpr64(ctx, fp0, fs);
10796 gen_load_fpr64(ctx, fp1, ft);
10797 gen_load_fpr64(ctx, fp2, fr);
10798 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10799 tcg_temp_free_i64(fp0);
10800 tcg_temp_free_i64(fp1);
10801 gen_store_fpr64(ctx, fp2, fd);
10802 tcg_temp_free_i64(fp2);
10804 opn = "nmadd.ps";
10805 break;
10806 case OPC_NMSUB_S:
10807 check_cop1x(ctx);
10809 TCGv_i32 fp0 = tcg_temp_new_i32();
10810 TCGv_i32 fp1 = tcg_temp_new_i32();
10811 TCGv_i32 fp2 = tcg_temp_new_i32();
10813 gen_load_fpr32(ctx, fp0, fs);
10814 gen_load_fpr32(ctx, fp1, ft);
10815 gen_load_fpr32(ctx, fp2, fr);
10816 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10817 tcg_temp_free_i32(fp0);
10818 tcg_temp_free_i32(fp1);
10819 gen_store_fpr32(ctx, fp2, fd);
10820 tcg_temp_free_i32(fp2);
10822 opn = "nmsub.s";
10823 break;
10824 case OPC_NMSUB_D:
10825 check_cop1x(ctx);
10826 check_cp1_registers(ctx, fd | fs | ft | fr);
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_d(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.d";
10842 break;
10843 case OPC_NMSUB_PS:
10844 check_ps(ctx);
10846 TCGv_i64 fp0 = tcg_temp_new_i64();
10847 TCGv_i64 fp1 = tcg_temp_new_i64();
10848 TCGv_i64 fp2 = tcg_temp_new_i64();
10850 gen_load_fpr64(ctx, fp0, fs);
10851 gen_load_fpr64(ctx, fp1, ft);
10852 gen_load_fpr64(ctx, fp2, fr);
10853 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10854 tcg_temp_free_i64(fp0);
10855 tcg_temp_free_i64(fp1);
10856 gen_store_fpr64(ctx, fp2, fd);
10857 tcg_temp_free_i64(fp2);
10859 opn = "nmsub.ps";
10860 break;
10861 default:
10862 MIPS_INVAL(opn);
10863 generate_exception (ctx, EXCP_RI);
10864 return;
10866 (void)opn; /* avoid a compiler warning */
10867 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
10868 fregnames[fs], fregnames[ft]);
10871 static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
10873 TCGv t0;
10875 #if !defined(CONFIG_USER_ONLY)
10876 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10877 Therefore only check the ISA in system mode. */
10878 check_insn(ctx, ISA_MIPS32R2);
10879 #endif
10880 t0 = tcg_temp_new();
10882 switch (rd) {
10883 case 0:
10884 save_cpu_state(ctx, 1);
10885 gen_helper_rdhwr_cpunum(t0, cpu_env);
10886 gen_store_gpr(t0, rt);
10887 break;
10888 case 1:
10889 save_cpu_state(ctx, 1);
10890 gen_helper_rdhwr_synci_step(t0, cpu_env);
10891 gen_store_gpr(t0, rt);
10892 break;
10893 case 2:
10894 save_cpu_state(ctx, 1);
10895 gen_helper_rdhwr_cc(t0, cpu_env);
10896 gen_store_gpr(t0, rt);
10897 break;
10898 case 3:
10899 save_cpu_state(ctx, 1);
10900 gen_helper_rdhwr_ccres(t0, cpu_env);
10901 gen_store_gpr(t0, rt);
10902 break;
10903 case 29:
10904 #if defined(CONFIG_USER_ONLY)
10905 tcg_gen_ld_tl(t0, cpu_env,
10906 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10907 gen_store_gpr(t0, rt);
10908 break;
10909 #else
10910 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10911 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10912 tcg_gen_ld_tl(t0, cpu_env,
10913 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10914 gen_store_gpr(t0, rt);
10915 } else {
10916 generate_exception(ctx, EXCP_RI);
10918 break;
10919 #endif
10920 default: /* Invalid */
10921 MIPS_INVAL("rdhwr");
10922 generate_exception(ctx, EXCP_RI);
10923 break;
10925 tcg_temp_free(t0);
10928 static inline void clear_branch_hflags(DisasContext *ctx)
10930 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10931 if (ctx->bstate == BS_NONE) {
10932 save_cpu_state(ctx, 0);
10933 } else {
10934 /* it is not safe to save ctx->hflags as hflags may be changed
10935 in execution time by the instruction in delay / forbidden slot. */
10936 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10940 static void gen_branch(DisasContext *ctx, int insn_bytes)
10942 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10943 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10944 /* Branches completion */
10945 clear_branch_hflags(ctx);
10946 ctx->bstate = BS_BRANCH;
10947 /* FIXME: Need to clear can_do_io. */
10948 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10949 case MIPS_HFLAG_FBNSLOT:
10950 MIPS_DEBUG("forbidden slot");
10951 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10952 break;
10953 case MIPS_HFLAG_B:
10954 /* unconditional branch */
10955 MIPS_DEBUG("unconditional branch");
10956 if (proc_hflags & MIPS_HFLAG_BX) {
10957 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10959 gen_goto_tb(ctx, 0, ctx->btarget);
10960 break;
10961 case MIPS_HFLAG_BL:
10962 /* blikely taken case */
10963 MIPS_DEBUG("blikely branch taken");
10964 gen_goto_tb(ctx, 0, ctx->btarget);
10965 break;
10966 case MIPS_HFLAG_BC:
10967 /* Conditional branch */
10968 MIPS_DEBUG("conditional branch");
10970 TCGLabel *l1 = gen_new_label();
10972 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10973 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10974 gen_set_label(l1);
10975 gen_goto_tb(ctx, 0, ctx->btarget);
10977 break;
10978 case MIPS_HFLAG_BR:
10979 /* unconditional branch to register */
10980 MIPS_DEBUG("branch to register");
10981 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10982 TCGv t0 = tcg_temp_new();
10983 TCGv_i32 t1 = tcg_temp_new_i32();
10985 tcg_gen_andi_tl(t0, btarget, 0x1);
10986 tcg_gen_trunc_tl_i32(t1, t0);
10987 tcg_temp_free(t0);
10988 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10989 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10990 tcg_gen_or_i32(hflags, hflags, t1);
10991 tcg_temp_free_i32(t1);
10993 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10994 } else {
10995 tcg_gen_mov_tl(cpu_PC, btarget);
10997 if (ctx->singlestep_enabled) {
10998 save_cpu_state(ctx, 0);
10999 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
11001 tcg_gen_exit_tb(0);
11002 break;
11003 default:
11004 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
11005 abort();
11010 /* Compact Branches */
11011 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
11012 int rs, int rt, int32_t offset)
11014 int bcond_compute = 0;
11015 TCGv t0 = tcg_temp_new();
11016 TCGv t1 = tcg_temp_new();
11017 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
11019 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11020 #ifdef MIPS_DEBUG_DISAS
11021 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11022 "\n", ctx->pc);
11023 #endif
11024 generate_exception(ctx, EXCP_RI);
11025 goto out;
11028 /* Load needed operands and calculate btarget */
11029 switch (opc) {
11030 /* compact branch */
11031 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11032 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11033 gen_load_gpr(t0, rs);
11034 gen_load_gpr(t1, rt);
11035 bcond_compute = 1;
11036 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11037 if (rs <= rt && rs == 0) {
11038 /* OPC_BEQZALC, OPC_BNEZALC */
11039 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11041 break;
11042 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11043 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11044 gen_load_gpr(t0, rs);
11045 gen_load_gpr(t1, rt);
11046 bcond_compute = 1;
11047 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11048 break;
11049 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11050 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11051 if (rs == 0 || rs == rt) {
11052 /* OPC_BLEZALC, OPC_BGEZALC */
11053 /* OPC_BGTZALC, OPC_BLTZALC */
11054 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11056 gen_load_gpr(t0, rs);
11057 gen_load_gpr(t1, rt);
11058 bcond_compute = 1;
11059 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11060 break;
11061 case OPC_BC:
11062 case OPC_BALC:
11063 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11064 break;
11065 case OPC_BEQZC:
11066 case OPC_BNEZC:
11067 if (rs != 0) {
11068 /* OPC_BEQZC, OPC_BNEZC */
11069 gen_load_gpr(t0, rs);
11070 bcond_compute = 1;
11071 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11072 } else {
11073 /* OPC_JIC, OPC_JIALC */
11074 TCGv tbase = tcg_temp_new();
11075 TCGv toffset = tcg_temp_new();
11077 gen_load_gpr(tbase, rt);
11078 tcg_gen_movi_tl(toffset, offset);
11079 gen_op_addr_add(ctx, btarget, tbase, toffset);
11080 tcg_temp_free(tbase);
11081 tcg_temp_free(toffset);
11083 break;
11084 default:
11085 MIPS_INVAL("Compact branch/jump");
11086 generate_exception(ctx, EXCP_RI);
11087 goto out;
11090 if (bcond_compute == 0) {
11091 /* Uncoditional compact branch */
11092 switch (opc) {
11093 case OPC_JIALC:
11094 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11095 /* Fallthrough */
11096 case OPC_JIC:
11097 ctx->hflags |= MIPS_HFLAG_BR;
11098 break;
11099 case OPC_BALC:
11100 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11101 /* Fallthrough */
11102 case OPC_BC:
11103 ctx->hflags |= MIPS_HFLAG_B;
11104 break;
11105 default:
11106 MIPS_INVAL("Compact branch/jump");
11107 generate_exception(ctx, EXCP_RI);
11108 goto out;
11111 /* Generating branch here as compact branches don't have delay slot */
11112 gen_branch(ctx, 4);
11113 } else {
11114 /* Conditional compact branch */
11115 TCGLabel *fs = gen_new_label();
11116 save_cpu_state(ctx, 0);
11118 switch (opc) {
11119 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11120 if (rs == 0 && rt != 0) {
11121 /* OPC_BLEZALC */
11122 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11123 } else if (rs != 0 && rt != 0 && rs == rt) {
11124 /* OPC_BGEZALC */
11125 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11126 } else {
11127 /* OPC_BGEUC */
11128 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
11130 break;
11131 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11132 if (rs == 0 && rt != 0) {
11133 /* OPC_BGTZALC */
11134 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11135 } else if (rs != 0 && rt != 0 && rs == rt) {
11136 /* OPC_BLTZALC */
11137 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11138 } else {
11139 /* OPC_BLTUC */
11140 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
11142 break;
11143 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11144 if (rs == 0 && rt != 0) {
11145 /* OPC_BLEZC */
11146 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11147 } else if (rs != 0 && rt != 0 && rs == rt) {
11148 /* OPC_BGEZC */
11149 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11150 } else {
11151 /* OPC_BGEC */
11152 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
11154 break;
11155 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11156 if (rs == 0 && rt != 0) {
11157 /* OPC_BGTZC */
11158 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11159 } else if (rs != 0 && rt != 0 && rs == rt) {
11160 /* OPC_BLTZC */
11161 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11162 } else {
11163 /* OPC_BLTC */
11164 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
11166 break;
11167 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11168 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11169 if (rs >= rt) {
11170 /* OPC_BOVC, OPC_BNVC */
11171 TCGv t2 = tcg_temp_new();
11172 TCGv t3 = tcg_temp_new();
11173 TCGv t4 = tcg_temp_new();
11174 TCGv input_overflow = tcg_temp_new();
11176 gen_load_gpr(t0, rs);
11177 gen_load_gpr(t1, rt);
11178 tcg_gen_ext32s_tl(t2, t0);
11179 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
11180 tcg_gen_ext32s_tl(t3, t1);
11181 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
11182 tcg_gen_or_tl(input_overflow, input_overflow, t4);
11184 tcg_gen_add_tl(t4, t2, t3);
11185 tcg_gen_ext32s_tl(t4, t4);
11186 tcg_gen_xor_tl(t2, t2, t3);
11187 tcg_gen_xor_tl(t3, t4, t3);
11188 tcg_gen_andc_tl(t2, t3, t2);
11189 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
11190 tcg_gen_or_tl(t4, t4, input_overflow);
11191 if (opc == OPC_BOVC) {
11192 /* OPC_BOVC */
11193 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
11194 } else {
11195 /* OPC_BNVC */
11196 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
11198 tcg_temp_free(input_overflow);
11199 tcg_temp_free(t4);
11200 tcg_temp_free(t3);
11201 tcg_temp_free(t2);
11202 } else if (rs < rt && rs == 0) {
11203 /* OPC_BEQZALC, OPC_BNEZALC */
11204 if (opc == OPC_BEQZALC) {
11205 /* OPC_BEQZALC */
11206 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
11207 } else {
11208 /* OPC_BNEZALC */
11209 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
11211 } else {
11212 /* OPC_BEQC, OPC_BNEC */
11213 if (opc == OPC_BEQC) {
11214 /* OPC_BEQC */
11215 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
11216 } else {
11217 /* OPC_BNEC */
11218 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
11221 break;
11222 case OPC_BEQZC:
11223 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
11224 break;
11225 case OPC_BNEZC:
11226 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
11227 break;
11228 default:
11229 MIPS_INVAL("Compact conditional branch/jump");
11230 generate_exception(ctx, EXCP_RI);
11231 goto out;
11234 /* Generating branch here as compact branches don't have delay slot */
11235 gen_goto_tb(ctx, 1, ctx->btarget);
11236 gen_set_label(fs);
11238 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
11239 MIPS_DEBUG("Compact conditional branch");
11242 out:
11243 tcg_temp_free(t0);
11244 tcg_temp_free(t1);
11247 /* ISA extensions (ASEs) */
11248 /* MIPS16 extension to MIPS32 */
11250 /* MIPS16 major opcodes */
11251 enum {
11252 M16_OPC_ADDIUSP = 0x00,
11253 M16_OPC_ADDIUPC = 0x01,
11254 M16_OPC_B = 0x02,
11255 M16_OPC_JAL = 0x03,
11256 M16_OPC_BEQZ = 0x04,
11257 M16_OPC_BNEQZ = 0x05,
11258 M16_OPC_SHIFT = 0x06,
11259 M16_OPC_LD = 0x07,
11260 M16_OPC_RRIA = 0x08,
11261 M16_OPC_ADDIU8 = 0x09,
11262 M16_OPC_SLTI = 0x0a,
11263 M16_OPC_SLTIU = 0x0b,
11264 M16_OPC_I8 = 0x0c,
11265 M16_OPC_LI = 0x0d,
11266 M16_OPC_CMPI = 0x0e,
11267 M16_OPC_SD = 0x0f,
11268 M16_OPC_LB = 0x10,
11269 M16_OPC_LH = 0x11,
11270 M16_OPC_LWSP = 0x12,
11271 M16_OPC_LW = 0x13,
11272 M16_OPC_LBU = 0x14,
11273 M16_OPC_LHU = 0x15,
11274 M16_OPC_LWPC = 0x16,
11275 M16_OPC_LWU = 0x17,
11276 M16_OPC_SB = 0x18,
11277 M16_OPC_SH = 0x19,
11278 M16_OPC_SWSP = 0x1a,
11279 M16_OPC_SW = 0x1b,
11280 M16_OPC_RRR = 0x1c,
11281 M16_OPC_RR = 0x1d,
11282 M16_OPC_EXTEND = 0x1e,
11283 M16_OPC_I64 = 0x1f
11286 /* I8 funct field */
11287 enum {
11288 I8_BTEQZ = 0x0,
11289 I8_BTNEZ = 0x1,
11290 I8_SWRASP = 0x2,
11291 I8_ADJSP = 0x3,
11292 I8_SVRS = 0x4,
11293 I8_MOV32R = 0x5,
11294 I8_MOVR32 = 0x7
11297 /* RRR f field */
11298 enum {
11299 RRR_DADDU = 0x0,
11300 RRR_ADDU = 0x1,
11301 RRR_DSUBU = 0x2,
11302 RRR_SUBU = 0x3
11305 /* RR funct field */
11306 enum {
11307 RR_JR = 0x00,
11308 RR_SDBBP = 0x01,
11309 RR_SLT = 0x02,
11310 RR_SLTU = 0x03,
11311 RR_SLLV = 0x04,
11312 RR_BREAK = 0x05,
11313 RR_SRLV = 0x06,
11314 RR_SRAV = 0x07,
11315 RR_DSRL = 0x08,
11316 RR_CMP = 0x0a,
11317 RR_NEG = 0x0b,
11318 RR_AND = 0x0c,
11319 RR_OR = 0x0d,
11320 RR_XOR = 0x0e,
11321 RR_NOT = 0x0f,
11322 RR_MFHI = 0x10,
11323 RR_CNVT = 0x11,
11324 RR_MFLO = 0x12,
11325 RR_DSRA = 0x13,
11326 RR_DSLLV = 0x14,
11327 RR_DSRLV = 0x16,
11328 RR_DSRAV = 0x17,
11329 RR_MULT = 0x18,
11330 RR_MULTU = 0x19,
11331 RR_DIV = 0x1a,
11332 RR_DIVU = 0x1b,
11333 RR_DMULT = 0x1c,
11334 RR_DMULTU = 0x1d,
11335 RR_DDIV = 0x1e,
11336 RR_DDIVU = 0x1f
11339 /* I64 funct field */
11340 enum {
11341 I64_LDSP = 0x0,
11342 I64_SDSP = 0x1,
11343 I64_SDRASP = 0x2,
11344 I64_DADJSP = 0x3,
11345 I64_LDPC = 0x4,
11346 I64_DADDIU5 = 0x5,
11347 I64_DADDIUPC = 0x6,
11348 I64_DADDIUSP = 0x7
11351 /* RR ry field for CNVT */
11352 enum {
11353 RR_RY_CNVT_ZEB = 0x0,
11354 RR_RY_CNVT_ZEH = 0x1,
11355 RR_RY_CNVT_ZEW = 0x2,
11356 RR_RY_CNVT_SEB = 0x4,
11357 RR_RY_CNVT_SEH = 0x5,
11358 RR_RY_CNVT_SEW = 0x6,
11361 static int xlat (int r)
11363 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11365 return map[r];
11368 static void gen_mips16_save (DisasContext *ctx,
11369 int xsregs, int aregs,
11370 int do_ra, int do_s0, int do_s1,
11371 int framesize)
11373 TCGv t0 = tcg_temp_new();
11374 TCGv t1 = tcg_temp_new();
11375 TCGv t2 = tcg_temp_new();
11376 int args, astatic;
11378 switch (aregs) {
11379 case 0:
11380 case 1:
11381 case 2:
11382 case 3:
11383 case 11:
11384 args = 0;
11385 break;
11386 case 4:
11387 case 5:
11388 case 6:
11389 case 7:
11390 args = 1;
11391 break;
11392 case 8:
11393 case 9:
11394 case 10:
11395 args = 2;
11396 break;
11397 case 12:
11398 case 13:
11399 args = 3;
11400 break;
11401 case 14:
11402 args = 4;
11403 break;
11404 default:
11405 generate_exception(ctx, EXCP_RI);
11406 return;
11409 switch (args) {
11410 case 4:
11411 gen_base_offset_addr(ctx, t0, 29, 12);
11412 gen_load_gpr(t1, 7);
11413 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11414 /* Fall through */
11415 case 3:
11416 gen_base_offset_addr(ctx, t0, 29, 8);
11417 gen_load_gpr(t1, 6);
11418 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11419 /* Fall through */
11420 case 2:
11421 gen_base_offset_addr(ctx, t0, 29, 4);
11422 gen_load_gpr(t1, 5);
11423 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11424 /* Fall through */
11425 case 1:
11426 gen_base_offset_addr(ctx, t0, 29, 0);
11427 gen_load_gpr(t1, 4);
11428 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11431 gen_load_gpr(t0, 29);
11433 #define DECR_AND_STORE(reg) do { \
11434 tcg_gen_movi_tl(t2, -4); \
11435 gen_op_addr_add(ctx, t0, t0, t2); \
11436 gen_load_gpr(t1, reg); \
11437 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
11438 } while (0)
11440 if (do_ra) {
11441 DECR_AND_STORE(31);
11444 switch (xsregs) {
11445 case 7:
11446 DECR_AND_STORE(30);
11447 /* Fall through */
11448 case 6:
11449 DECR_AND_STORE(23);
11450 /* Fall through */
11451 case 5:
11452 DECR_AND_STORE(22);
11453 /* Fall through */
11454 case 4:
11455 DECR_AND_STORE(21);
11456 /* Fall through */
11457 case 3:
11458 DECR_AND_STORE(20);
11459 /* Fall through */
11460 case 2:
11461 DECR_AND_STORE(19);
11462 /* Fall through */
11463 case 1:
11464 DECR_AND_STORE(18);
11467 if (do_s1) {
11468 DECR_AND_STORE(17);
11470 if (do_s0) {
11471 DECR_AND_STORE(16);
11474 switch (aregs) {
11475 case 0:
11476 case 4:
11477 case 8:
11478 case 12:
11479 case 14:
11480 astatic = 0;
11481 break;
11482 case 1:
11483 case 5:
11484 case 9:
11485 case 13:
11486 astatic = 1;
11487 break;
11488 case 2:
11489 case 6:
11490 case 10:
11491 astatic = 2;
11492 break;
11493 case 3:
11494 case 7:
11495 astatic = 3;
11496 break;
11497 case 11:
11498 astatic = 4;
11499 break;
11500 default:
11501 generate_exception(ctx, EXCP_RI);
11502 return;
11505 if (astatic > 0) {
11506 DECR_AND_STORE(7);
11507 if (astatic > 1) {
11508 DECR_AND_STORE(6);
11509 if (astatic > 2) {
11510 DECR_AND_STORE(5);
11511 if (astatic > 3) {
11512 DECR_AND_STORE(4);
11517 #undef DECR_AND_STORE
11519 tcg_gen_movi_tl(t2, -framesize);
11520 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11521 tcg_temp_free(t0);
11522 tcg_temp_free(t1);
11523 tcg_temp_free(t2);
11526 static void gen_mips16_restore (DisasContext *ctx,
11527 int xsregs, int aregs,
11528 int do_ra, int do_s0, int do_s1,
11529 int framesize)
11531 int astatic;
11532 TCGv t0 = tcg_temp_new();
11533 TCGv t1 = tcg_temp_new();
11534 TCGv t2 = tcg_temp_new();
11536 tcg_gen_movi_tl(t2, framesize);
11537 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11539 #define DECR_AND_LOAD(reg) do { \
11540 tcg_gen_movi_tl(t2, -4); \
11541 gen_op_addr_add(ctx, t0, t0, t2); \
11542 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11543 gen_store_gpr(t1, reg); \
11544 } while (0)
11546 if (do_ra) {
11547 DECR_AND_LOAD(31);
11550 switch (xsregs) {
11551 case 7:
11552 DECR_AND_LOAD(30);
11553 /* Fall through */
11554 case 6:
11555 DECR_AND_LOAD(23);
11556 /* Fall through */
11557 case 5:
11558 DECR_AND_LOAD(22);
11559 /* Fall through */
11560 case 4:
11561 DECR_AND_LOAD(21);
11562 /* Fall through */
11563 case 3:
11564 DECR_AND_LOAD(20);
11565 /* Fall through */
11566 case 2:
11567 DECR_AND_LOAD(19);
11568 /* Fall through */
11569 case 1:
11570 DECR_AND_LOAD(18);
11573 if (do_s1) {
11574 DECR_AND_LOAD(17);
11576 if (do_s0) {
11577 DECR_AND_LOAD(16);
11580 switch (aregs) {
11581 case 0:
11582 case 4:
11583 case 8:
11584 case 12:
11585 case 14:
11586 astatic = 0;
11587 break;
11588 case 1:
11589 case 5:
11590 case 9:
11591 case 13:
11592 astatic = 1;
11593 break;
11594 case 2:
11595 case 6:
11596 case 10:
11597 astatic = 2;
11598 break;
11599 case 3:
11600 case 7:
11601 astatic = 3;
11602 break;
11603 case 11:
11604 astatic = 4;
11605 break;
11606 default:
11607 generate_exception(ctx, EXCP_RI);
11608 return;
11611 if (astatic > 0) {
11612 DECR_AND_LOAD(7);
11613 if (astatic > 1) {
11614 DECR_AND_LOAD(6);
11615 if (astatic > 2) {
11616 DECR_AND_LOAD(5);
11617 if (astatic > 3) {
11618 DECR_AND_LOAD(4);
11623 #undef DECR_AND_LOAD
11625 tcg_gen_movi_tl(t2, framesize);
11626 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11627 tcg_temp_free(t0);
11628 tcg_temp_free(t1);
11629 tcg_temp_free(t2);
11632 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11633 int is_64_bit, int extended)
11635 TCGv t0;
11637 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11638 generate_exception(ctx, EXCP_RI);
11639 return;
11642 t0 = tcg_temp_new();
11644 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11645 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11646 if (!is_64_bit) {
11647 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11650 tcg_temp_free(t0);
11653 #if defined(TARGET_MIPS64)
11654 static void decode_i64_mips16 (DisasContext *ctx,
11655 int ry, int funct, int16_t offset,
11656 int extended)
11658 switch (funct) {
11659 case I64_LDSP:
11660 check_insn(ctx, ISA_MIPS3);
11661 check_mips_64(ctx);
11662 offset = extended ? offset : offset << 3;
11663 gen_ld(ctx, OPC_LD, ry, 29, offset);
11664 break;
11665 case I64_SDSP:
11666 check_insn(ctx, ISA_MIPS3);
11667 check_mips_64(ctx);
11668 offset = extended ? offset : offset << 3;
11669 gen_st(ctx, OPC_SD, ry, 29, offset);
11670 break;
11671 case I64_SDRASP:
11672 check_insn(ctx, ISA_MIPS3);
11673 check_mips_64(ctx);
11674 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11675 gen_st(ctx, OPC_SD, 31, 29, offset);
11676 break;
11677 case I64_DADJSP:
11678 check_insn(ctx, ISA_MIPS3);
11679 check_mips_64(ctx);
11680 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11681 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11682 break;
11683 case I64_LDPC:
11684 check_insn(ctx, ISA_MIPS3);
11685 check_mips_64(ctx);
11686 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11687 generate_exception(ctx, EXCP_RI);
11688 } else {
11689 offset = extended ? offset : offset << 3;
11690 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11692 break;
11693 case I64_DADDIU5:
11694 check_insn(ctx, ISA_MIPS3);
11695 check_mips_64(ctx);
11696 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11697 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11698 break;
11699 case I64_DADDIUPC:
11700 check_insn(ctx, ISA_MIPS3);
11701 check_mips_64(ctx);
11702 offset = extended ? offset : offset << 2;
11703 gen_addiupc(ctx, ry, offset, 1, extended);
11704 break;
11705 case I64_DADDIUSP:
11706 check_insn(ctx, ISA_MIPS3);
11707 check_mips_64(ctx);
11708 offset = extended ? offset : offset << 2;
11709 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11710 break;
11713 #endif
11715 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11717 int extend = cpu_lduw_code(env, ctx->pc + 2);
11718 int op, rx, ry, funct, sa;
11719 int16_t imm, offset;
11721 ctx->opcode = (ctx->opcode << 16) | extend;
11722 op = (ctx->opcode >> 11) & 0x1f;
11723 sa = (ctx->opcode >> 22) & 0x1f;
11724 funct = (ctx->opcode >> 8) & 0x7;
11725 rx = xlat((ctx->opcode >> 8) & 0x7);
11726 ry = xlat((ctx->opcode >> 5) & 0x7);
11727 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11728 | ((ctx->opcode >> 21) & 0x3f) << 5
11729 | (ctx->opcode & 0x1f));
11731 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11732 counterparts. */
11733 switch (op) {
11734 case M16_OPC_ADDIUSP:
11735 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11736 break;
11737 case M16_OPC_ADDIUPC:
11738 gen_addiupc(ctx, rx, imm, 0, 1);
11739 break;
11740 case M16_OPC_B:
11741 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11742 /* No delay slot, so just process as a normal instruction */
11743 break;
11744 case M16_OPC_BEQZ:
11745 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11746 /* No delay slot, so just process as a normal instruction */
11747 break;
11748 case M16_OPC_BNEQZ:
11749 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11750 /* No delay slot, so just process as a normal instruction */
11751 break;
11752 case M16_OPC_SHIFT:
11753 switch (ctx->opcode & 0x3) {
11754 case 0x0:
11755 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11756 break;
11757 case 0x1:
11758 #if defined(TARGET_MIPS64)
11759 check_mips_64(ctx);
11760 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11761 #else
11762 generate_exception(ctx, EXCP_RI);
11763 #endif
11764 break;
11765 case 0x2:
11766 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11767 break;
11768 case 0x3:
11769 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11770 break;
11772 break;
11773 #if defined(TARGET_MIPS64)
11774 case M16_OPC_LD:
11775 check_insn(ctx, ISA_MIPS3);
11776 check_mips_64(ctx);
11777 gen_ld(ctx, OPC_LD, ry, rx, offset);
11778 break;
11779 #endif
11780 case M16_OPC_RRIA:
11781 imm = ctx->opcode & 0xf;
11782 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11783 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11784 imm = (int16_t) (imm << 1) >> 1;
11785 if ((ctx->opcode >> 4) & 0x1) {
11786 #if defined(TARGET_MIPS64)
11787 check_mips_64(ctx);
11788 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11789 #else
11790 generate_exception(ctx, EXCP_RI);
11791 #endif
11792 } else {
11793 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11795 break;
11796 case M16_OPC_ADDIU8:
11797 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11798 break;
11799 case M16_OPC_SLTI:
11800 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11801 break;
11802 case M16_OPC_SLTIU:
11803 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11804 break;
11805 case M16_OPC_I8:
11806 switch (funct) {
11807 case I8_BTEQZ:
11808 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11809 break;
11810 case I8_BTNEZ:
11811 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11812 break;
11813 case I8_SWRASP:
11814 gen_st(ctx, OPC_SW, 31, 29, imm);
11815 break;
11816 case I8_ADJSP:
11817 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11818 break;
11819 case I8_SVRS:
11820 check_insn(ctx, ISA_MIPS32);
11822 int xsregs = (ctx->opcode >> 24) & 0x7;
11823 int aregs = (ctx->opcode >> 16) & 0xf;
11824 int do_ra = (ctx->opcode >> 6) & 0x1;
11825 int do_s0 = (ctx->opcode >> 5) & 0x1;
11826 int do_s1 = (ctx->opcode >> 4) & 0x1;
11827 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11828 | (ctx->opcode & 0xf)) << 3;
11830 if (ctx->opcode & (1 << 7)) {
11831 gen_mips16_save(ctx, xsregs, aregs,
11832 do_ra, do_s0, do_s1,
11833 framesize);
11834 } else {
11835 gen_mips16_restore(ctx, xsregs, aregs,
11836 do_ra, do_s0, do_s1,
11837 framesize);
11840 break;
11841 default:
11842 generate_exception(ctx, EXCP_RI);
11843 break;
11845 break;
11846 case M16_OPC_LI:
11847 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11848 break;
11849 case M16_OPC_CMPI:
11850 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11851 break;
11852 #if defined(TARGET_MIPS64)
11853 case M16_OPC_SD:
11854 check_insn(ctx, ISA_MIPS3);
11855 check_mips_64(ctx);
11856 gen_st(ctx, OPC_SD, ry, rx, offset);
11857 break;
11858 #endif
11859 case M16_OPC_LB:
11860 gen_ld(ctx, OPC_LB, ry, rx, offset);
11861 break;
11862 case M16_OPC_LH:
11863 gen_ld(ctx, OPC_LH, ry, rx, offset);
11864 break;
11865 case M16_OPC_LWSP:
11866 gen_ld(ctx, OPC_LW, rx, 29, offset);
11867 break;
11868 case M16_OPC_LW:
11869 gen_ld(ctx, OPC_LW, ry, rx, offset);
11870 break;
11871 case M16_OPC_LBU:
11872 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11873 break;
11874 case M16_OPC_LHU:
11875 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11876 break;
11877 case M16_OPC_LWPC:
11878 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11879 break;
11880 #if defined(TARGET_MIPS64)
11881 case M16_OPC_LWU:
11882 check_insn(ctx, ISA_MIPS3);
11883 check_mips_64(ctx);
11884 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11885 break;
11886 #endif
11887 case M16_OPC_SB:
11888 gen_st(ctx, OPC_SB, ry, rx, offset);
11889 break;
11890 case M16_OPC_SH:
11891 gen_st(ctx, OPC_SH, ry, rx, offset);
11892 break;
11893 case M16_OPC_SWSP:
11894 gen_st(ctx, OPC_SW, rx, 29, offset);
11895 break;
11896 case M16_OPC_SW:
11897 gen_st(ctx, OPC_SW, ry, rx, offset);
11898 break;
11899 #if defined(TARGET_MIPS64)
11900 case M16_OPC_I64:
11901 decode_i64_mips16(ctx, ry, funct, offset, 1);
11902 break;
11903 #endif
11904 default:
11905 generate_exception(ctx, EXCP_RI);
11906 break;
11909 return 4;
11912 static inline bool is_uhi(int sdbbp_code)
11914 #ifdef CONFIG_USER_ONLY
11915 return false;
11916 #else
11917 return semihosting_enabled() && sdbbp_code == 1;
11918 #endif
11921 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11923 int rx, ry;
11924 int sa;
11925 int op, cnvt_op, op1, offset;
11926 int funct;
11927 int n_bytes;
11929 op = (ctx->opcode >> 11) & 0x1f;
11930 sa = (ctx->opcode >> 2) & 0x7;
11931 sa = sa == 0 ? 8 : sa;
11932 rx = xlat((ctx->opcode >> 8) & 0x7);
11933 cnvt_op = (ctx->opcode >> 5) & 0x7;
11934 ry = xlat((ctx->opcode >> 5) & 0x7);
11935 op1 = offset = ctx->opcode & 0x1f;
11937 n_bytes = 2;
11939 switch (op) {
11940 case M16_OPC_ADDIUSP:
11942 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11944 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11946 break;
11947 case M16_OPC_ADDIUPC:
11948 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11949 break;
11950 case M16_OPC_B:
11951 offset = (ctx->opcode & 0x7ff) << 1;
11952 offset = (int16_t)(offset << 4) >> 4;
11953 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11954 /* No delay slot, so just process as a normal instruction */
11955 break;
11956 case M16_OPC_JAL:
11957 offset = cpu_lduw_code(env, ctx->pc + 2);
11958 offset = (((ctx->opcode & 0x1f) << 21)
11959 | ((ctx->opcode >> 5) & 0x1f) << 16
11960 | offset) << 2;
11961 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11962 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11963 n_bytes = 4;
11964 break;
11965 case M16_OPC_BEQZ:
11966 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11967 ((int8_t)ctx->opcode) << 1, 0);
11968 /* No delay slot, so just process as a normal instruction */
11969 break;
11970 case M16_OPC_BNEQZ:
11971 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11972 ((int8_t)ctx->opcode) << 1, 0);
11973 /* No delay slot, so just process as a normal instruction */
11974 break;
11975 case M16_OPC_SHIFT:
11976 switch (ctx->opcode & 0x3) {
11977 case 0x0:
11978 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11979 break;
11980 case 0x1:
11981 #if defined(TARGET_MIPS64)
11982 check_insn(ctx, ISA_MIPS3);
11983 check_mips_64(ctx);
11984 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11985 #else
11986 generate_exception(ctx, EXCP_RI);
11987 #endif
11988 break;
11989 case 0x2:
11990 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11991 break;
11992 case 0x3:
11993 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11994 break;
11996 break;
11997 #if defined(TARGET_MIPS64)
11998 case M16_OPC_LD:
11999 check_insn(ctx, ISA_MIPS3);
12000 check_mips_64(ctx);
12001 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
12002 break;
12003 #endif
12004 case M16_OPC_RRIA:
12006 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
12008 if ((ctx->opcode >> 4) & 1) {
12009 #if defined(TARGET_MIPS64)
12010 check_insn(ctx, ISA_MIPS3);
12011 check_mips_64(ctx);
12012 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12013 #else
12014 generate_exception(ctx, EXCP_RI);
12015 #endif
12016 } else {
12017 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12020 break;
12021 case M16_OPC_ADDIU8:
12023 int16_t imm = (int8_t) ctx->opcode;
12025 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12027 break;
12028 case M16_OPC_SLTI:
12030 int16_t imm = (uint8_t) ctx->opcode;
12031 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12033 break;
12034 case M16_OPC_SLTIU:
12036 int16_t imm = (uint8_t) ctx->opcode;
12037 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12039 break;
12040 case M16_OPC_I8:
12042 int reg32;
12044 funct = (ctx->opcode >> 8) & 0x7;
12045 switch (funct) {
12046 case I8_BTEQZ:
12047 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
12048 ((int8_t)ctx->opcode) << 1, 0);
12049 break;
12050 case I8_BTNEZ:
12051 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
12052 ((int8_t)ctx->opcode) << 1, 0);
12053 break;
12054 case I8_SWRASP:
12055 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
12056 break;
12057 case I8_ADJSP:
12058 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
12059 ((int8_t)ctx->opcode) << 3);
12060 break;
12061 case I8_SVRS:
12062 check_insn(ctx, ISA_MIPS32);
12064 int do_ra = ctx->opcode & (1 << 6);
12065 int do_s0 = ctx->opcode & (1 << 5);
12066 int do_s1 = ctx->opcode & (1 << 4);
12067 int framesize = ctx->opcode & 0xf;
12069 if (framesize == 0) {
12070 framesize = 128;
12071 } else {
12072 framesize = framesize << 3;
12075 if (ctx->opcode & (1 << 7)) {
12076 gen_mips16_save(ctx, 0, 0,
12077 do_ra, do_s0, do_s1, framesize);
12078 } else {
12079 gen_mips16_restore(ctx, 0, 0,
12080 do_ra, do_s0, do_s1, framesize);
12083 break;
12084 case I8_MOV32R:
12086 int rz = xlat(ctx->opcode & 0x7);
12088 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
12089 ((ctx->opcode >> 5) & 0x7);
12090 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
12092 break;
12093 case I8_MOVR32:
12094 reg32 = ctx->opcode & 0x1f;
12095 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
12096 break;
12097 default:
12098 generate_exception(ctx, EXCP_RI);
12099 break;
12102 break;
12103 case M16_OPC_LI:
12105 int16_t imm = (uint8_t) ctx->opcode;
12107 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
12109 break;
12110 case M16_OPC_CMPI:
12112 int16_t imm = (uint8_t) ctx->opcode;
12113 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
12115 break;
12116 #if defined(TARGET_MIPS64)
12117 case M16_OPC_SD:
12118 check_insn(ctx, ISA_MIPS3);
12119 check_mips_64(ctx);
12120 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
12121 break;
12122 #endif
12123 case M16_OPC_LB:
12124 gen_ld(ctx, OPC_LB, ry, rx, offset);
12125 break;
12126 case M16_OPC_LH:
12127 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
12128 break;
12129 case M16_OPC_LWSP:
12130 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12131 break;
12132 case M16_OPC_LW:
12133 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
12134 break;
12135 case M16_OPC_LBU:
12136 gen_ld(ctx, OPC_LBU, ry, rx, offset);
12137 break;
12138 case M16_OPC_LHU:
12139 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
12140 break;
12141 case M16_OPC_LWPC:
12142 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
12143 break;
12144 #if defined (TARGET_MIPS64)
12145 case M16_OPC_LWU:
12146 check_insn(ctx, ISA_MIPS3);
12147 check_mips_64(ctx);
12148 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
12149 break;
12150 #endif
12151 case M16_OPC_SB:
12152 gen_st(ctx, OPC_SB, ry, rx, offset);
12153 break;
12154 case M16_OPC_SH:
12155 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
12156 break;
12157 case M16_OPC_SWSP:
12158 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12159 break;
12160 case M16_OPC_SW:
12161 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
12162 break;
12163 case M16_OPC_RRR:
12165 int rz = xlat((ctx->opcode >> 2) & 0x7);
12166 int mips32_op;
12168 switch (ctx->opcode & 0x3) {
12169 case RRR_ADDU:
12170 mips32_op = OPC_ADDU;
12171 break;
12172 case RRR_SUBU:
12173 mips32_op = OPC_SUBU;
12174 break;
12175 #if defined(TARGET_MIPS64)
12176 case RRR_DADDU:
12177 mips32_op = OPC_DADDU;
12178 check_insn(ctx, ISA_MIPS3);
12179 check_mips_64(ctx);
12180 break;
12181 case RRR_DSUBU:
12182 mips32_op = OPC_DSUBU;
12183 check_insn(ctx, ISA_MIPS3);
12184 check_mips_64(ctx);
12185 break;
12186 #endif
12187 default:
12188 generate_exception(ctx, EXCP_RI);
12189 goto done;
12192 gen_arith(ctx, mips32_op, rz, rx, ry);
12193 done:
12196 break;
12197 case M16_OPC_RR:
12198 switch (op1) {
12199 case RR_JR:
12201 int nd = (ctx->opcode >> 7) & 0x1;
12202 int link = (ctx->opcode >> 6) & 0x1;
12203 int ra = (ctx->opcode >> 5) & 0x1;
12205 if (nd) {
12206 check_insn(ctx, ISA_MIPS32);
12209 if (link) {
12210 op = OPC_JALR;
12211 } else {
12212 op = OPC_JR;
12215 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
12216 (nd ? 0 : 2));
12218 break;
12219 case RR_SDBBP:
12220 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
12221 gen_helper_do_semihosting(cpu_env);
12222 } else {
12223 /* XXX: not clear which exception should be raised
12224 * when in debug mode...
12226 check_insn(ctx, ISA_MIPS32);
12227 generate_exception(ctx, EXCP_DBp);
12229 break;
12230 case RR_SLT:
12231 gen_slt(ctx, OPC_SLT, 24, rx, ry);
12232 break;
12233 case RR_SLTU:
12234 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
12235 break;
12236 case RR_BREAK:
12237 generate_exception(ctx, EXCP_BREAK);
12238 break;
12239 case RR_SLLV:
12240 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
12241 break;
12242 case RR_SRLV:
12243 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
12244 break;
12245 case RR_SRAV:
12246 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
12247 break;
12248 #if defined (TARGET_MIPS64)
12249 case RR_DSRL:
12250 check_insn(ctx, ISA_MIPS3);
12251 check_mips_64(ctx);
12252 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
12253 break;
12254 #endif
12255 case RR_CMP:
12256 gen_logic(ctx, OPC_XOR, 24, rx, ry);
12257 break;
12258 case RR_NEG:
12259 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
12260 break;
12261 case RR_AND:
12262 gen_logic(ctx, OPC_AND, rx, rx, ry);
12263 break;
12264 case RR_OR:
12265 gen_logic(ctx, OPC_OR, rx, rx, ry);
12266 break;
12267 case RR_XOR:
12268 gen_logic(ctx, OPC_XOR, rx, rx, ry);
12269 break;
12270 case RR_NOT:
12271 gen_logic(ctx, OPC_NOR, rx, ry, 0);
12272 break;
12273 case RR_MFHI:
12274 gen_HILO(ctx, OPC_MFHI, 0, rx);
12275 break;
12276 case RR_CNVT:
12277 check_insn(ctx, ISA_MIPS32);
12278 switch (cnvt_op) {
12279 case RR_RY_CNVT_ZEB:
12280 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12281 break;
12282 case RR_RY_CNVT_ZEH:
12283 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12284 break;
12285 case RR_RY_CNVT_SEB:
12286 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12287 break;
12288 case RR_RY_CNVT_SEH:
12289 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12290 break;
12291 #if defined (TARGET_MIPS64)
12292 case RR_RY_CNVT_ZEW:
12293 check_insn(ctx, ISA_MIPS64);
12294 check_mips_64(ctx);
12295 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12296 break;
12297 case RR_RY_CNVT_SEW:
12298 check_insn(ctx, ISA_MIPS64);
12299 check_mips_64(ctx);
12300 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12301 break;
12302 #endif
12303 default:
12304 generate_exception(ctx, EXCP_RI);
12305 break;
12307 break;
12308 case RR_MFLO:
12309 gen_HILO(ctx, OPC_MFLO, 0, rx);
12310 break;
12311 #if defined (TARGET_MIPS64)
12312 case RR_DSRA:
12313 check_insn(ctx, ISA_MIPS3);
12314 check_mips_64(ctx);
12315 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
12316 break;
12317 case RR_DSLLV:
12318 check_insn(ctx, ISA_MIPS3);
12319 check_mips_64(ctx);
12320 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
12321 break;
12322 case RR_DSRLV:
12323 check_insn(ctx, ISA_MIPS3);
12324 check_mips_64(ctx);
12325 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
12326 break;
12327 case RR_DSRAV:
12328 check_insn(ctx, ISA_MIPS3);
12329 check_mips_64(ctx);
12330 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
12331 break;
12332 #endif
12333 case RR_MULT:
12334 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
12335 break;
12336 case RR_MULTU:
12337 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
12338 break;
12339 case RR_DIV:
12340 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
12341 break;
12342 case RR_DIVU:
12343 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
12344 break;
12345 #if defined (TARGET_MIPS64)
12346 case RR_DMULT:
12347 check_insn(ctx, ISA_MIPS3);
12348 check_mips_64(ctx);
12349 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
12350 break;
12351 case RR_DMULTU:
12352 check_insn(ctx, ISA_MIPS3);
12353 check_mips_64(ctx);
12354 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
12355 break;
12356 case RR_DDIV:
12357 check_insn(ctx, ISA_MIPS3);
12358 check_mips_64(ctx);
12359 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
12360 break;
12361 case RR_DDIVU:
12362 check_insn(ctx, ISA_MIPS3);
12363 check_mips_64(ctx);
12364 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
12365 break;
12366 #endif
12367 default:
12368 generate_exception(ctx, EXCP_RI);
12369 break;
12371 break;
12372 case M16_OPC_EXTEND:
12373 decode_extended_mips16_opc(env, ctx);
12374 n_bytes = 4;
12375 break;
12376 #if defined(TARGET_MIPS64)
12377 case M16_OPC_I64:
12378 funct = (ctx->opcode >> 8) & 0x7;
12379 decode_i64_mips16(ctx, ry, funct, offset, 0);
12380 break;
12381 #endif
12382 default:
12383 generate_exception(ctx, EXCP_RI);
12384 break;
12387 return n_bytes;
12390 /* microMIPS extension to MIPS32/MIPS64 */
12393 * microMIPS32/microMIPS64 major opcodes
12395 * 1. MIPS Architecture for Programmers Volume II-B:
12396 * The microMIPS32 Instruction Set (Revision 3.05)
12398 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12400 * 2. MIPS Architecture For Programmers Volume II-A:
12401 * The MIPS64 Instruction Set (Revision 3.51)
12404 enum {
12405 POOL32A = 0x00,
12406 POOL16A = 0x01,
12407 LBU16 = 0x02,
12408 MOVE16 = 0x03,
12409 ADDI32 = 0x04,
12410 R6_LUI = 0x04,
12411 AUI = 0x04,
12412 LBU32 = 0x05,
12413 SB32 = 0x06,
12414 LB32 = 0x07,
12416 POOL32B = 0x08,
12417 POOL16B = 0x09,
12418 LHU16 = 0x0a,
12419 ANDI16 = 0x0b,
12420 ADDIU32 = 0x0c,
12421 LHU32 = 0x0d,
12422 SH32 = 0x0e,
12423 LH32 = 0x0f,
12425 POOL32I = 0x10,
12426 POOL16C = 0x11,
12427 LWSP16 = 0x12,
12428 POOL16D = 0x13,
12429 ORI32 = 0x14,
12430 POOL32F = 0x15,
12431 POOL32S = 0x16, /* MIPS64 */
12432 DADDIU32 = 0x17, /* MIPS64 */
12434 POOL32C = 0x18,
12435 LWGP16 = 0x19,
12436 LW16 = 0x1a,
12437 POOL16E = 0x1b,
12438 XORI32 = 0x1c,
12439 JALS32 = 0x1d,
12440 BOVC = 0x1d,
12441 BEQC = 0x1d,
12442 BEQZALC = 0x1d,
12443 ADDIUPC = 0x1e,
12444 PCREL = 0x1e,
12445 BNVC = 0x1f,
12446 BNEC = 0x1f,
12447 BNEZALC = 0x1f,
12449 R6_BEQZC = 0x20,
12450 JIC = 0x20,
12451 POOL16F = 0x21,
12452 SB16 = 0x22,
12453 BEQZ16 = 0x23,
12454 BEQZC16 = 0x23,
12455 SLTI32 = 0x24,
12456 BEQ32 = 0x25,
12457 BC = 0x25,
12458 SWC132 = 0x26,
12459 LWC132 = 0x27,
12461 /* 0x29 is reserved */
12462 RES_29 = 0x29,
12463 R6_BNEZC = 0x28,
12464 JIALC = 0x28,
12465 SH16 = 0x2a,
12466 BNEZ16 = 0x2b,
12467 BNEZC16 = 0x2b,
12468 SLTIU32 = 0x2c,
12469 BNE32 = 0x2d,
12470 BALC = 0x2d,
12471 SDC132 = 0x2e,
12472 LDC132 = 0x2f,
12474 /* 0x31 is reserved */
12475 RES_31 = 0x31,
12476 BLEZALC = 0x30,
12477 BGEZALC = 0x30,
12478 BGEUC = 0x30,
12479 SWSP16 = 0x32,
12480 B16 = 0x33,
12481 BC16 = 0x33,
12482 ANDI32 = 0x34,
12483 J32 = 0x35,
12484 BGTZC = 0x35,
12485 BLTZC = 0x35,
12486 BLTC = 0x35,
12487 SD32 = 0x36, /* MIPS64 */
12488 LD32 = 0x37, /* MIPS64 */
12490 /* 0x39 is reserved */
12491 RES_39 = 0x39,
12492 BGTZALC = 0x38,
12493 BLTZALC = 0x38,
12494 BLTUC = 0x38,
12495 SW16 = 0x3a,
12496 LI16 = 0x3b,
12497 JALX32 = 0x3c,
12498 JAL32 = 0x3d,
12499 BLEZC = 0x3d,
12500 BGEZC = 0x3d,
12501 BGEC = 0x3d,
12502 SW32 = 0x3e,
12503 LW32 = 0x3f
12506 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12507 enum {
12508 ADDIUPC_00 = 0x00,
12509 ADDIUPC_07 = 0x07,
12510 AUIPC = 0x1e,
12511 ALUIPC = 0x1f,
12512 LWPC_08 = 0x08,
12513 LWPC_0F = 0x0F,
12516 /* POOL32A encoding of minor opcode field */
12518 enum {
12519 /* These opcodes are distinguished only by bits 9..6; those bits are
12520 * what are recorded below. */
12521 SLL32 = 0x0,
12522 SRL32 = 0x1,
12523 SRA = 0x2,
12524 ROTR = 0x3,
12525 SELEQZ = 0x5,
12526 SELNEZ = 0x6,
12528 SLLV = 0x0,
12529 SRLV = 0x1,
12530 SRAV = 0x2,
12531 ROTRV = 0x3,
12532 ADD = 0x4,
12533 ADDU32 = 0x5,
12534 SUB = 0x6,
12535 SUBU32 = 0x7,
12536 MUL = 0x8,
12537 AND = 0x9,
12538 OR32 = 0xa,
12539 NOR = 0xb,
12540 XOR32 = 0xc,
12541 SLT = 0xd,
12542 SLTU = 0xe,
12544 MOVN = 0x0,
12545 R6_MUL = 0x0,
12546 MOVZ = 0x1,
12547 MUH = 0x1,
12548 MULU = 0x2,
12549 MUHU = 0x3,
12550 LWXS = 0x4,
12551 R6_DIV = 0x4,
12552 MOD = 0x5,
12553 R6_DIVU = 0x6,
12554 MODU = 0x7,
12556 /* The following can be distinguished by their lower 6 bits. */
12557 INS = 0x0c,
12558 LSA = 0x0f,
12559 ALIGN = 0x1f,
12560 EXT = 0x2c,
12561 POOL32AXF = 0x3c
12564 /* POOL32AXF encoding of minor opcode field extension */
12567 * 1. MIPS Architecture for Programmers Volume II-B:
12568 * The microMIPS32 Instruction Set (Revision 3.05)
12570 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12572 * 2. MIPS Architecture for Programmers VolumeIV-e:
12573 * The MIPS DSP Application-Specific Extension
12574 * to the microMIPS32 Architecture (Revision 2.34)
12576 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12579 enum {
12580 /* bits 11..6 */
12581 TEQ = 0x00,
12582 TGE = 0x08,
12583 TGEU = 0x10,
12584 TLT = 0x20,
12585 TLTU = 0x28,
12586 TNE = 0x30,
12588 MFC0 = 0x03,
12589 MTC0 = 0x0b,
12591 /* begin of microMIPS32 DSP */
12593 /* bits 13..12 for 0x01 */
12594 MFHI_ACC = 0x0,
12595 MFLO_ACC = 0x1,
12596 MTHI_ACC = 0x2,
12597 MTLO_ACC = 0x3,
12599 /* bits 13..12 for 0x2a */
12600 MADD_ACC = 0x0,
12601 MADDU_ACC = 0x1,
12602 MSUB_ACC = 0x2,
12603 MSUBU_ACC = 0x3,
12605 /* bits 13..12 for 0x32 */
12606 MULT_ACC = 0x0,
12607 MULTU_ACC = 0x1,
12609 /* end of microMIPS32 DSP */
12611 /* bits 15..12 for 0x2c */
12612 BITSWAP = 0x0,
12613 SEB = 0x2,
12614 SEH = 0x3,
12615 CLO = 0x4,
12616 CLZ = 0x5,
12617 RDHWR = 0x6,
12618 WSBH = 0x7,
12619 MULT = 0x8,
12620 MULTU = 0x9,
12621 DIV = 0xa,
12622 DIVU = 0xb,
12623 MADD = 0xc,
12624 MADDU = 0xd,
12625 MSUB = 0xe,
12626 MSUBU = 0xf,
12628 /* bits 15..12 for 0x34 */
12629 MFC2 = 0x4,
12630 MTC2 = 0x5,
12631 MFHC2 = 0x8,
12632 MTHC2 = 0x9,
12633 CFC2 = 0xc,
12634 CTC2 = 0xd,
12636 /* bits 15..12 for 0x3c */
12637 JALR = 0x0,
12638 JR = 0x0, /* alias */
12639 JALRC = 0x0,
12640 JRC = 0x0,
12641 JALR_HB = 0x1,
12642 JALRC_HB = 0x1,
12643 JALRS = 0x4,
12644 JALRS_HB = 0x5,
12646 /* bits 15..12 for 0x05 */
12647 RDPGPR = 0xe,
12648 WRPGPR = 0xf,
12650 /* bits 15..12 for 0x0d */
12651 TLBP = 0x0,
12652 TLBR = 0x1,
12653 TLBWI = 0x2,
12654 TLBWR = 0x3,
12655 TLBINV = 0x4,
12656 TLBINVF = 0x5,
12657 WAIT = 0x9,
12658 IRET = 0xd,
12659 DERET = 0xe,
12660 ERET = 0xf,
12662 /* bits 15..12 for 0x15 */
12663 DMT = 0x0,
12664 DVPE = 0x1,
12665 EMT = 0x2,
12666 EVPE = 0x3,
12668 /* bits 15..12 for 0x1d */
12669 DI = 0x4,
12670 EI = 0x5,
12672 /* bits 15..12 for 0x2d */
12673 SYNC = 0x6,
12674 SYSCALL = 0x8,
12675 SDBBP = 0xd,
12677 /* bits 15..12 for 0x35 */
12678 MFHI32 = 0x0,
12679 MFLO32 = 0x1,
12680 MTHI32 = 0x2,
12681 MTLO32 = 0x3,
12684 /* POOL32B encoding of minor opcode field (bits 15..12) */
12686 enum {
12687 LWC2 = 0x0,
12688 LWP = 0x1,
12689 LDP = 0x4,
12690 LWM32 = 0x5,
12691 CACHE = 0x6,
12692 LDM = 0x7,
12693 SWC2 = 0x8,
12694 SWP = 0x9,
12695 SDP = 0xc,
12696 SWM32 = 0xd,
12697 SDM = 0xf
12700 /* POOL32C encoding of minor opcode field (bits 15..12) */
12702 enum {
12703 LWL = 0x0,
12704 SWL = 0x8,
12705 LWR = 0x1,
12706 SWR = 0x9,
12707 PREF = 0x2,
12708 /* 0xa is reserved */
12709 LL = 0x3,
12710 SC = 0xb,
12711 LDL = 0x4,
12712 SDL = 0xc,
12713 LDR = 0x5,
12714 SDR = 0xd,
12715 /* 0x6 is reserved */
12716 LWU = 0xe,
12717 LLD = 0x7,
12718 SCD = 0xf
12721 /* POOL32F encoding of minor opcode field (bits 5..0) */
12723 enum {
12724 /* These are the bit 7..6 values */
12725 ADD_FMT = 0x0,
12727 SUB_FMT = 0x1,
12729 MUL_FMT = 0x2,
12731 DIV_FMT = 0x3,
12733 /* These are the bit 8..6 values */
12734 MOVN_FMT = 0x0,
12735 RSQRT2_FMT = 0x0,
12736 MOVF_FMT = 0x0,
12737 RINT_FMT = 0x0,
12738 SELNEZ_FMT = 0x0,
12740 MOVZ_FMT = 0x1,
12741 LWXC1 = 0x1,
12742 MOVT_FMT = 0x1,
12743 CLASS_FMT = 0x1,
12744 SELEQZ_FMT = 0x1,
12746 PLL_PS = 0x2,
12747 SWXC1 = 0x2,
12748 SEL_FMT = 0x2,
12750 PLU_PS = 0x3,
12751 LDXC1 = 0x3,
12753 MOVN_FMT_04 = 0x4,
12754 PUL_PS = 0x4,
12755 SDXC1 = 0x4,
12756 RECIP2_FMT = 0x4,
12758 MOVZ_FMT_05 = 0x05,
12759 PUU_PS = 0x5,
12760 LUXC1 = 0x5,
12762 CVT_PS_S = 0x6,
12763 SUXC1 = 0x6,
12764 ADDR_PS = 0x6,
12765 PREFX = 0x6,
12766 MADDF_FMT = 0x6,
12768 MULR_PS = 0x7,
12769 MSUBF_FMT = 0x7,
12771 MADD_S = 0x01,
12772 MADD_D = 0x09,
12773 MADD_PS = 0x11,
12774 ALNV_PS = 0x19,
12775 MSUB_S = 0x21,
12776 MSUB_D = 0x29,
12777 MSUB_PS = 0x31,
12779 NMADD_S = 0x02,
12780 NMADD_D = 0x0a,
12781 NMADD_PS = 0x12,
12782 NMSUB_S = 0x22,
12783 NMSUB_D = 0x2a,
12784 NMSUB_PS = 0x32,
12786 MIN_FMT = 0x3,
12787 MAX_FMT = 0xb,
12788 MINA_FMT = 0x23,
12789 MAXA_FMT = 0x2b,
12790 POOL32FXF = 0x3b,
12792 CABS_COND_FMT = 0x1c, /* MIPS3D */
12793 C_COND_FMT = 0x3c,
12795 CMP_CONDN_S = 0x5,
12796 CMP_CONDN_D = 0x15
12799 /* POOL32Fxf encoding of minor opcode extension field */
12801 enum {
12802 CVT_L = 0x04,
12803 RSQRT_FMT = 0x08,
12804 FLOOR_L = 0x0c,
12805 CVT_PW_PS = 0x1c,
12806 CVT_W = 0x24,
12807 SQRT_FMT = 0x28,
12808 FLOOR_W = 0x2c,
12809 CVT_PS_PW = 0x3c,
12810 CFC1 = 0x40,
12811 RECIP_FMT = 0x48,
12812 CEIL_L = 0x4c,
12813 CTC1 = 0x60,
12814 CEIL_W = 0x6c,
12815 MFC1 = 0x80,
12816 CVT_S_PL = 0x84,
12817 TRUNC_L = 0x8c,
12818 MTC1 = 0xa0,
12819 CVT_S_PU = 0xa4,
12820 TRUNC_W = 0xac,
12821 MFHC1 = 0xc0,
12822 ROUND_L = 0xcc,
12823 MTHC1 = 0xe0,
12824 ROUND_W = 0xec,
12826 MOV_FMT = 0x01,
12827 MOVF = 0x05,
12828 ABS_FMT = 0x0d,
12829 RSQRT1_FMT = 0x1d,
12830 MOVT = 0x25,
12831 NEG_FMT = 0x2d,
12832 CVT_D = 0x4d,
12833 RECIP1_FMT = 0x5d,
12834 CVT_S = 0x6d
12837 /* POOL32I encoding of minor opcode field (bits 25..21) */
12839 enum {
12840 BLTZ = 0x00,
12841 BLTZAL = 0x01,
12842 BGEZ = 0x02,
12843 BGEZAL = 0x03,
12844 BLEZ = 0x04,
12845 BNEZC = 0x05,
12846 BGTZ = 0x06,
12847 BEQZC = 0x07,
12848 TLTI = 0x08,
12849 BC1EQZC = 0x08,
12850 TGEI = 0x09,
12851 BC1NEZC = 0x09,
12852 TLTIU = 0x0a,
12853 BC2EQZC = 0x0a,
12854 TGEIU = 0x0b,
12855 BC2NEZC = 0x0a,
12856 TNEI = 0x0c,
12857 R6_SYNCI = 0x0c,
12858 LUI = 0x0d,
12859 TEQI = 0x0e,
12860 SYNCI = 0x10,
12861 BLTZALS = 0x11,
12862 BGEZALS = 0x13,
12863 BC2F = 0x14,
12864 BC2T = 0x15,
12865 BPOSGE64 = 0x1a,
12866 BPOSGE32 = 0x1b,
12867 /* These overlap and are distinguished by bit16 of the instruction */
12868 BC1F = 0x1c,
12869 BC1T = 0x1d,
12870 BC1ANY2F = 0x1c,
12871 BC1ANY2T = 0x1d,
12872 BC1ANY4F = 0x1e,
12873 BC1ANY4T = 0x1f
12876 /* POOL16A encoding of minor opcode field */
12878 enum {
12879 ADDU16 = 0x0,
12880 SUBU16 = 0x1
12883 /* POOL16B encoding of minor opcode field */
12885 enum {
12886 SLL16 = 0x0,
12887 SRL16 = 0x1
12890 /* POOL16C encoding of minor opcode field */
12892 enum {
12893 NOT16 = 0x00,
12894 XOR16 = 0x04,
12895 AND16 = 0x08,
12896 OR16 = 0x0c,
12897 LWM16 = 0x10,
12898 SWM16 = 0x14,
12899 JR16 = 0x18,
12900 JRC16 = 0x1a,
12901 JALR16 = 0x1c,
12902 JALR16S = 0x1e,
12903 MFHI16 = 0x20,
12904 MFLO16 = 0x24,
12905 BREAK16 = 0x28,
12906 SDBBP16 = 0x2c,
12907 JRADDIUSP = 0x30
12910 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
12912 enum {
12913 R6_NOT16 = 0x00,
12914 R6_AND16 = 0x01,
12915 R6_LWM16 = 0x02,
12916 R6_JRC16 = 0x03,
12917 MOVEP = 0x04,
12918 MOVEP_07 = 0x07,
12919 R6_XOR16 = 0x08,
12920 R6_OR16 = 0x09,
12921 R6_SWM16 = 0x0a,
12922 JALRC16 = 0x0b,
12923 MOVEP_0C = 0x0c,
12924 MOVEP_0F = 0x0f,
12925 JRCADDIUSP = 0x13,
12926 R6_BREAK16 = 0x1b,
12927 R6_SDBBP16 = 0x3b
12930 /* POOL16D encoding of minor opcode field */
12932 enum {
12933 ADDIUS5 = 0x0,
12934 ADDIUSP = 0x1
12937 /* POOL16E encoding of minor opcode field */
12939 enum {
12940 ADDIUR2 = 0x0,
12941 ADDIUR1SP = 0x1
12944 static int mmreg (int r)
12946 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12948 return map[r];
12951 /* Used for 16-bit store instructions. */
12952 static int mmreg2 (int r)
12954 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12956 return map[r];
12959 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12960 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12961 #define uMIPS_RS2(op) uMIPS_RS(op)
12962 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12963 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12964 #define uMIPS_RS5(op) (op & 0x1f)
12966 /* Signed immediate */
12967 #define SIMM(op, start, width) \
12968 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12969 << (32-width)) \
12970 >> (32-width))
12971 /* Zero-extended immediate */
12972 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12974 static void gen_addiur1sp(DisasContext *ctx)
12976 int rd = mmreg(uMIPS_RD(ctx->opcode));
12978 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12981 static void gen_addiur2(DisasContext *ctx)
12983 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12984 int rd = mmreg(uMIPS_RD(ctx->opcode));
12985 int rs = mmreg(uMIPS_RS(ctx->opcode));
12987 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12990 static void gen_addiusp(DisasContext *ctx)
12992 int encoded = ZIMM(ctx->opcode, 1, 9);
12993 int decoded;
12995 if (encoded <= 1) {
12996 decoded = 256 + encoded;
12997 } else if (encoded <= 255) {
12998 decoded = encoded;
12999 } else if (encoded <= 509) {
13000 decoded = encoded - 512;
13001 } else {
13002 decoded = encoded - 768;
13005 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
13008 static void gen_addius5(DisasContext *ctx)
13010 int imm = SIMM(ctx->opcode, 1, 4);
13011 int rd = (ctx->opcode >> 5) & 0x1f;
13013 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
13016 static void gen_andi16(DisasContext *ctx)
13018 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
13019 31, 32, 63, 64, 255, 32768, 65535 };
13020 int rd = mmreg(uMIPS_RD(ctx->opcode));
13021 int rs = mmreg(uMIPS_RS(ctx->opcode));
13022 int encoded = ZIMM(ctx->opcode, 0, 4);
13024 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
13027 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
13028 int base, int16_t offset)
13030 const char *opn = "ldst_multiple";
13031 TCGv t0, t1;
13032 TCGv_i32 t2;
13034 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13035 generate_exception(ctx, EXCP_RI);
13036 return;
13039 t0 = tcg_temp_new();
13041 gen_base_offset_addr(ctx, t0, base, offset);
13043 t1 = tcg_const_tl(reglist);
13044 t2 = tcg_const_i32(ctx->mem_idx);
13046 save_cpu_state(ctx, 1);
13047 switch (opc) {
13048 case LWM32:
13049 gen_helper_lwm(cpu_env, t0, t1, t2);
13050 opn = "lwm";
13051 break;
13052 case SWM32:
13053 gen_helper_swm(cpu_env, t0, t1, t2);
13054 opn = "swm";
13055 break;
13056 #ifdef TARGET_MIPS64
13057 case LDM:
13058 gen_helper_ldm(cpu_env, t0, t1, t2);
13059 opn = "ldm";
13060 break;
13061 case SDM:
13062 gen_helper_sdm(cpu_env, t0, t1, t2);
13063 opn = "sdm";
13064 break;
13065 #endif
13067 (void)opn;
13068 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
13069 tcg_temp_free(t0);
13070 tcg_temp_free(t1);
13071 tcg_temp_free_i32(t2);
13075 static void gen_pool16c_insn(DisasContext *ctx)
13077 int rd = mmreg((ctx->opcode >> 3) & 0x7);
13078 int rs = mmreg(ctx->opcode & 0x7);
13080 switch (((ctx->opcode) >> 4) & 0x3f) {
13081 case NOT16 + 0:
13082 case NOT16 + 1:
13083 case NOT16 + 2:
13084 case NOT16 + 3:
13085 gen_logic(ctx, OPC_NOR, rd, rs, 0);
13086 break;
13087 case XOR16 + 0:
13088 case XOR16 + 1:
13089 case XOR16 + 2:
13090 case XOR16 + 3:
13091 gen_logic(ctx, OPC_XOR, rd, rd, rs);
13092 break;
13093 case AND16 + 0:
13094 case AND16 + 1:
13095 case AND16 + 2:
13096 case AND16 + 3:
13097 gen_logic(ctx, OPC_AND, rd, rd, rs);
13098 break;
13099 case OR16 + 0:
13100 case OR16 + 1:
13101 case OR16 + 2:
13102 case OR16 + 3:
13103 gen_logic(ctx, OPC_OR, rd, rd, rs);
13104 break;
13105 case LWM16 + 0:
13106 case LWM16 + 1:
13107 case LWM16 + 2:
13108 case LWM16 + 3:
13110 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13111 int offset = ZIMM(ctx->opcode, 0, 4);
13113 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
13114 29, offset << 2);
13116 break;
13117 case SWM16 + 0:
13118 case SWM16 + 1:
13119 case SWM16 + 2:
13120 case SWM16 + 3:
13122 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13123 int offset = ZIMM(ctx->opcode, 0, 4);
13125 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
13126 29, offset << 2);
13128 break;
13129 case JR16 + 0:
13130 case JR16 + 1:
13132 int reg = ctx->opcode & 0x1f;
13134 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
13136 break;
13137 case JRC16 + 0:
13138 case JRC16 + 1:
13140 int reg = ctx->opcode & 0x1f;
13141 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
13142 /* Let normal delay slot handling in our caller take us
13143 to the branch target. */
13145 break;
13146 case JALR16 + 0:
13147 case JALR16 + 1:
13148 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
13149 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13150 break;
13151 case JALR16S + 0:
13152 case JALR16S + 1:
13153 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
13154 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13155 break;
13156 case MFHI16 + 0:
13157 case MFHI16 + 1:
13158 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
13159 break;
13160 case MFLO16 + 0:
13161 case MFLO16 + 1:
13162 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
13163 break;
13164 case BREAK16:
13165 generate_exception(ctx, EXCP_BREAK);
13166 break;
13167 case SDBBP16:
13168 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
13169 gen_helper_do_semihosting(cpu_env);
13170 } else {
13171 /* XXX: not clear which exception should be raised
13172 * when in debug mode...
13174 check_insn(ctx, ISA_MIPS32);
13175 generate_exception(ctx, EXCP_DBp);
13177 break;
13178 case JRADDIUSP + 0:
13179 case JRADDIUSP + 1:
13181 int imm = ZIMM(ctx->opcode, 0, 5);
13182 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13183 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13184 /* Let normal delay slot handling in our caller take us
13185 to the branch target. */
13187 break;
13188 default:
13189 generate_exception(ctx, EXCP_RI);
13190 break;
13194 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
13195 int enc_rs)
13197 int rd, rs, re, rt;
13198 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
13199 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
13200 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
13201 rd = rd_enc[enc_dest];
13202 re = re_enc[enc_dest];
13203 rs = rs_rt_enc[enc_rs];
13204 rt = rs_rt_enc[enc_rt];
13205 if (rs) {
13206 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
13207 } else {
13208 tcg_gen_movi_tl(cpu_gpr[rd], 0);
13210 if (rt) {
13211 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
13212 } else {
13213 tcg_gen_movi_tl(cpu_gpr[re], 0);
13217 static void gen_pool16c_r6_insn(DisasContext *ctx)
13219 int rt = mmreg((ctx->opcode >> 7) & 0x7);
13220 int rs = mmreg((ctx->opcode >> 4) & 0x7);
13222 switch (ctx->opcode & 0xf) {
13223 case R6_NOT16:
13224 gen_logic(ctx, OPC_NOR, rt, rs, 0);
13225 break;
13226 case R6_AND16:
13227 gen_logic(ctx, OPC_AND, rt, rt, rs);
13228 break;
13229 case R6_LWM16:
13231 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13232 int offset = extract32(ctx->opcode, 4, 4);
13233 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
13235 break;
13236 case R6_JRC16: /* JRCADDIUSP */
13237 if ((ctx->opcode >> 4) & 1) {
13238 /* JRCADDIUSP */
13239 int imm = extract32(ctx->opcode, 5, 5);
13240 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13241 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13242 } else {
13243 /* JRC16 */
13244 int rs = extract32(ctx->opcode, 5, 5);
13245 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
13247 break;
13248 case MOVEP ... MOVEP_07:
13249 case MOVEP_0C ... MOVEP_0F:
13251 int enc_dest = uMIPS_RD(ctx->opcode);
13252 int enc_rt = uMIPS_RS2(ctx->opcode);
13253 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
13254 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
13256 break;
13257 case R6_XOR16:
13258 gen_logic(ctx, OPC_XOR, rt, rt, rs);
13259 break;
13260 case R6_OR16:
13261 gen_logic(ctx, OPC_OR, rt, rt, rs);
13262 break;
13263 case R6_SWM16:
13265 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13266 int offset = extract32(ctx->opcode, 4, 4);
13267 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
13269 break;
13270 case JALRC16: /* BREAK16, SDBBP16 */
13271 switch (ctx->opcode & 0x3f) {
13272 case JALRC16:
13273 case JALRC16 + 0x20:
13274 /* JALRC16 */
13275 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
13276 31, 0, 0);
13277 break;
13278 case R6_BREAK16:
13279 /* BREAK16 */
13280 generate_exception(ctx, EXCP_BREAK);
13281 break;
13282 case R6_SDBBP16:
13283 /* SDBBP16 */
13284 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
13285 gen_helper_do_semihosting(cpu_env);
13286 } else {
13287 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13288 generate_exception(ctx, EXCP_RI);
13289 } else {
13290 generate_exception(ctx, EXCP_DBp);
13293 break;
13295 break;
13296 default:
13297 generate_exception(ctx, EXCP_RI);
13298 break;
13302 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
13304 TCGv t0 = tcg_temp_new();
13305 TCGv t1 = tcg_temp_new();
13307 gen_load_gpr(t0, base);
13309 if (index != 0) {
13310 gen_load_gpr(t1, index);
13311 tcg_gen_shli_tl(t1, t1, 2);
13312 gen_op_addr_add(ctx, t0, t1, t0);
13315 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13316 gen_store_gpr(t1, rd);
13318 tcg_temp_free(t0);
13319 tcg_temp_free(t1);
13322 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
13323 int base, int16_t offset)
13325 const char *opn = "ldst_pair";
13326 TCGv t0, t1;
13328 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
13329 generate_exception(ctx, EXCP_RI);
13330 return;
13333 t0 = tcg_temp_new();
13334 t1 = tcg_temp_new();
13336 gen_base_offset_addr(ctx, t0, base, offset);
13338 switch (opc) {
13339 case LWP:
13340 if (rd == base) {
13341 generate_exception(ctx, EXCP_RI);
13342 return;
13344 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13345 gen_store_gpr(t1, rd);
13346 tcg_gen_movi_tl(t1, 4);
13347 gen_op_addr_add(ctx, t0, t0, t1);
13348 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13349 gen_store_gpr(t1, rd+1);
13350 opn = "lwp";
13351 break;
13352 case SWP:
13353 gen_load_gpr(t1, rd);
13354 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13355 tcg_gen_movi_tl(t1, 4);
13356 gen_op_addr_add(ctx, t0, t0, t1);
13357 gen_load_gpr(t1, rd+1);
13358 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13359 opn = "swp";
13360 break;
13361 #ifdef TARGET_MIPS64
13362 case LDP:
13363 if (rd == base) {
13364 generate_exception(ctx, EXCP_RI);
13365 return;
13367 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13368 gen_store_gpr(t1, rd);
13369 tcg_gen_movi_tl(t1, 8);
13370 gen_op_addr_add(ctx, t0, t0, t1);
13371 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13372 gen_store_gpr(t1, rd+1);
13373 opn = "ldp";
13374 break;
13375 case SDP:
13376 gen_load_gpr(t1, rd);
13377 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13378 tcg_gen_movi_tl(t1, 8);
13379 gen_op_addr_add(ctx, t0, t0, t1);
13380 gen_load_gpr(t1, rd+1);
13381 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13382 opn = "sdp";
13383 break;
13384 #endif
13386 (void)opn; /* avoid a compiler warning */
13387 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
13388 tcg_temp_free(t0);
13389 tcg_temp_free(t1);
13392 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
13394 int extension = (ctx->opcode >> 6) & 0x3f;
13395 int minor = (ctx->opcode >> 12) & 0xf;
13396 uint32_t mips32_op;
13398 switch (extension) {
13399 case TEQ:
13400 mips32_op = OPC_TEQ;
13401 goto do_trap;
13402 case TGE:
13403 mips32_op = OPC_TGE;
13404 goto do_trap;
13405 case TGEU:
13406 mips32_op = OPC_TGEU;
13407 goto do_trap;
13408 case TLT:
13409 mips32_op = OPC_TLT;
13410 goto do_trap;
13411 case TLTU:
13412 mips32_op = OPC_TLTU;
13413 goto do_trap;
13414 case TNE:
13415 mips32_op = OPC_TNE;
13416 do_trap:
13417 gen_trap(ctx, mips32_op, rs, rt, -1);
13418 break;
13419 #ifndef CONFIG_USER_ONLY
13420 case MFC0:
13421 case MFC0 + 32:
13422 check_cp0_enabled(ctx);
13423 if (rt == 0) {
13424 /* Treat as NOP. */
13425 break;
13427 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
13428 break;
13429 case MTC0:
13430 case MTC0 + 32:
13431 check_cp0_enabled(ctx);
13433 TCGv t0 = tcg_temp_new();
13435 gen_load_gpr(t0, rt);
13436 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
13437 tcg_temp_free(t0);
13439 break;
13440 #endif
13441 case 0x2a:
13442 switch (minor & 3) {
13443 case MADD_ACC:
13444 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
13445 break;
13446 case MADDU_ACC:
13447 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
13448 break;
13449 case MSUB_ACC:
13450 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
13451 break;
13452 case MSUBU_ACC:
13453 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
13454 break;
13455 default:
13456 goto pool32axf_invalid;
13458 break;
13459 case 0x32:
13460 switch (minor & 3) {
13461 case MULT_ACC:
13462 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
13463 break;
13464 case MULTU_ACC:
13465 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
13466 break;
13467 default:
13468 goto pool32axf_invalid;
13470 break;
13471 case 0x2c:
13472 switch (minor) {
13473 case BITSWAP:
13474 check_insn(ctx, ISA_MIPS32R6);
13475 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
13476 break;
13477 case SEB:
13478 gen_bshfl(ctx, OPC_SEB, rs, rt);
13479 break;
13480 case SEH:
13481 gen_bshfl(ctx, OPC_SEH, rs, rt);
13482 break;
13483 case CLO:
13484 mips32_op = OPC_CLO;
13485 goto do_cl;
13486 case CLZ:
13487 mips32_op = OPC_CLZ;
13488 do_cl:
13489 check_insn(ctx, ISA_MIPS32);
13490 gen_cl(ctx, mips32_op, rt, rs);
13491 break;
13492 case RDHWR:
13493 gen_rdhwr(ctx, rt, rs);
13494 break;
13495 case WSBH:
13496 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13497 break;
13498 case MULT:
13499 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13500 mips32_op = OPC_MULT;
13501 goto do_mul;
13502 case MULTU:
13503 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13504 mips32_op = OPC_MULTU;
13505 goto do_mul;
13506 case DIV:
13507 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13508 mips32_op = OPC_DIV;
13509 goto do_div;
13510 case DIVU:
13511 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13512 mips32_op = OPC_DIVU;
13513 goto do_div;
13514 do_div:
13515 check_insn(ctx, ISA_MIPS32);
13516 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13517 break;
13518 case MADD:
13519 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13520 mips32_op = OPC_MADD;
13521 goto do_mul;
13522 case MADDU:
13523 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13524 mips32_op = OPC_MADDU;
13525 goto do_mul;
13526 case MSUB:
13527 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13528 mips32_op = OPC_MSUB;
13529 goto do_mul;
13530 case MSUBU:
13531 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13532 mips32_op = OPC_MSUBU;
13533 do_mul:
13534 check_insn(ctx, ISA_MIPS32);
13535 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13536 break;
13537 default:
13538 goto pool32axf_invalid;
13540 break;
13541 case 0x34:
13542 switch (minor) {
13543 case MFC2:
13544 case MTC2:
13545 case MFHC2:
13546 case MTHC2:
13547 case CFC2:
13548 case CTC2:
13549 generate_exception_err(ctx, EXCP_CpU, 2);
13550 break;
13551 default:
13552 goto pool32axf_invalid;
13554 break;
13555 case 0x3c:
13556 switch (minor) {
13557 case JALR: /* JALRC */
13558 case JALR_HB: /* JALRC_HB */
13559 if (ctx->insn_flags & ISA_MIPS32R6) {
13560 /* JALRC, JALRC_HB */
13561 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13562 } else {
13563 /* JALR, JALR_HB */
13564 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13565 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13567 break;
13568 case JALRS:
13569 case JALRS_HB:
13570 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13571 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13572 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13573 break;
13574 default:
13575 goto pool32axf_invalid;
13577 break;
13578 case 0x05:
13579 switch (minor) {
13580 case RDPGPR:
13581 check_cp0_enabled(ctx);
13582 check_insn(ctx, ISA_MIPS32R2);
13583 gen_load_srsgpr(rs, rt);
13584 break;
13585 case WRPGPR:
13586 check_cp0_enabled(ctx);
13587 check_insn(ctx, ISA_MIPS32R2);
13588 gen_store_srsgpr(rs, rt);
13589 break;
13590 default:
13591 goto pool32axf_invalid;
13593 break;
13594 #ifndef CONFIG_USER_ONLY
13595 case 0x0d:
13596 switch (minor) {
13597 case TLBP:
13598 mips32_op = OPC_TLBP;
13599 goto do_cp0;
13600 case TLBR:
13601 mips32_op = OPC_TLBR;
13602 goto do_cp0;
13603 case TLBWI:
13604 mips32_op = OPC_TLBWI;
13605 goto do_cp0;
13606 case TLBWR:
13607 mips32_op = OPC_TLBWR;
13608 goto do_cp0;
13609 case TLBINV:
13610 mips32_op = OPC_TLBINV;
13611 goto do_cp0;
13612 case TLBINVF:
13613 mips32_op = OPC_TLBINVF;
13614 goto do_cp0;
13615 case WAIT:
13616 mips32_op = OPC_WAIT;
13617 goto do_cp0;
13618 case DERET:
13619 mips32_op = OPC_DERET;
13620 goto do_cp0;
13621 case ERET:
13622 mips32_op = OPC_ERET;
13623 do_cp0:
13624 gen_cp0(env, ctx, mips32_op, rt, rs);
13625 break;
13626 default:
13627 goto pool32axf_invalid;
13629 break;
13630 case 0x1d:
13631 switch (minor) {
13632 case DI:
13633 check_cp0_enabled(ctx);
13635 TCGv t0 = tcg_temp_new();
13637 save_cpu_state(ctx, 1);
13638 gen_helper_di(t0, cpu_env);
13639 gen_store_gpr(t0, rs);
13640 /* Stop translation as we may have switched the execution mode */
13641 ctx->bstate = BS_STOP;
13642 tcg_temp_free(t0);
13644 break;
13645 case EI:
13646 check_cp0_enabled(ctx);
13648 TCGv t0 = tcg_temp_new();
13650 save_cpu_state(ctx, 1);
13651 gen_helper_ei(t0, cpu_env);
13652 gen_store_gpr(t0, rs);
13653 /* Stop translation as we may have switched the execution mode */
13654 ctx->bstate = BS_STOP;
13655 tcg_temp_free(t0);
13657 break;
13658 default:
13659 goto pool32axf_invalid;
13661 break;
13662 #endif
13663 case 0x2d:
13664 switch (minor) {
13665 case SYNC:
13666 /* NOP */
13667 break;
13668 case SYSCALL:
13669 generate_exception(ctx, EXCP_SYSCALL);
13670 ctx->bstate = BS_STOP;
13671 break;
13672 case SDBBP:
13673 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
13674 gen_helper_do_semihosting(cpu_env);
13675 } else {
13676 check_insn(ctx, ISA_MIPS32);
13677 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13678 generate_exception(ctx, EXCP_RI);
13679 } else {
13680 generate_exception(ctx, EXCP_DBp);
13683 break;
13684 default:
13685 goto pool32axf_invalid;
13687 break;
13688 case 0x01:
13689 switch (minor & 3) {
13690 case MFHI_ACC:
13691 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
13692 break;
13693 case MFLO_ACC:
13694 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
13695 break;
13696 case MTHI_ACC:
13697 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
13698 break;
13699 case MTLO_ACC:
13700 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
13701 break;
13702 default:
13703 goto pool32axf_invalid;
13705 break;
13706 case 0x35:
13707 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13708 switch (minor) {
13709 case MFHI32:
13710 gen_HILO(ctx, OPC_MFHI, 0, rs);
13711 break;
13712 case MFLO32:
13713 gen_HILO(ctx, OPC_MFLO, 0, rs);
13714 break;
13715 case MTHI32:
13716 gen_HILO(ctx, OPC_MTHI, 0, rs);
13717 break;
13718 case MTLO32:
13719 gen_HILO(ctx, OPC_MTLO, 0, rs);
13720 break;
13721 default:
13722 goto pool32axf_invalid;
13724 break;
13725 default:
13726 pool32axf_invalid:
13727 MIPS_INVAL("pool32axf");
13728 generate_exception(ctx, EXCP_RI);
13729 break;
13733 /* Values for microMIPS fmt field. Variable-width, depending on which
13734 formats the instruction supports. */
13736 enum {
13737 FMT_SD_S = 0,
13738 FMT_SD_D = 1,
13740 FMT_SDPS_S = 0,
13741 FMT_SDPS_D = 1,
13742 FMT_SDPS_PS = 2,
13744 FMT_SWL_S = 0,
13745 FMT_SWL_W = 1,
13746 FMT_SWL_L = 2,
13748 FMT_DWL_D = 0,
13749 FMT_DWL_W = 1,
13750 FMT_DWL_L = 2
13753 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
13755 int extension = (ctx->opcode >> 6) & 0x3ff;
13756 uint32_t mips32_op;
13758 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
13759 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
13760 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
13762 switch (extension) {
13763 case FLOAT_1BIT_FMT(CFC1, 0):
13764 mips32_op = OPC_CFC1;
13765 goto do_cp1;
13766 case FLOAT_1BIT_FMT(CTC1, 0):
13767 mips32_op = OPC_CTC1;
13768 goto do_cp1;
13769 case FLOAT_1BIT_FMT(MFC1, 0):
13770 mips32_op = OPC_MFC1;
13771 goto do_cp1;
13772 case FLOAT_1BIT_FMT(MTC1, 0):
13773 mips32_op = OPC_MTC1;
13774 goto do_cp1;
13775 case FLOAT_1BIT_FMT(MFHC1, 0):
13776 mips32_op = OPC_MFHC1;
13777 goto do_cp1;
13778 case FLOAT_1BIT_FMT(MTHC1, 0):
13779 mips32_op = OPC_MTHC1;
13780 do_cp1:
13781 gen_cp1(ctx, mips32_op, rt, rs);
13782 break;
13784 /* Reciprocal square root */
13785 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
13786 mips32_op = OPC_RSQRT_S;
13787 goto do_unaryfp;
13788 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
13789 mips32_op = OPC_RSQRT_D;
13790 goto do_unaryfp;
13792 /* Square root */
13793 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
13794 mips32_op = OPC_SQRT_S;
13795 goto do_unaryfp;
13796 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
13797 mips32_op = OPC_SQRT_D;
13798 goto do_unaryfp;
13800 /* Reciprocal */
13801 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
13802 mips32_op = OPC_RECIP_S;
13803 goto do_unaryfp;
13804 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
13805 mips32_op = OPC_RECIP_D;
13806 goto do_unaryfp;
13808 /* Floor */
13809 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
13810 mips32_op = OPC_FLOOR_L_S;
13811 goto do_unaryfp;
13812 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
13813 mips32_op = OPC_FLOOR_L_D;
13814 goto do_unaryfp;
13815 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
13816 mips32_op = OPC_FLOOR_W_S;
13817 goto do_unaryfp;
13818 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
13819 mips32_op = OPC_FLOOR_W_D;
13820 goto do_unaryfp;
13822 /* Ceiling */
13823 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
13824 mips32_op = OPC_CEIL_L_S;
13825 goto do_unaryfp;
13826 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
13827 mips32_op = OPC_CEIL_L_D;
13828 goto do_unaryfp;
13829 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
13830 mips32_op = OPC_CEIL_W_S;
13831 goto do_unaryfp;
13832 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
13833 mips32_op = OPC_CEIL_W_D;
13834 goto do_unaryfp;
13836 /* Truncation */
13837 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
13838 mips32_op = OPC_TRUNC_L_S;
13839 goto do_unaryfp;
13840 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
13841 mips32_op = OPC_TRUNC_L_D;
13842 goto do_unaryfp;
13843 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
13844 mips32_op = OPC_TRUNC_W_S;
13845 goto do_unaryfp;
13846 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
13847 mips32_op = OPC_TRUNC_W_D;
13848 goto do_unaryfp;
13850 /* Round */
13851 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
13852 mips32_op = OPC_ROUND_L_S;
13853 goto do_unaryfp;
13854 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
13855 mips32_op = OPC_ROUND_L_D;
13856 goto do_unaryfp;
13857 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
13858 mips32_op = OPC_ROUND_W_S;
13859 goto do_unaryfp;
13860 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
13861 mips32_op = OPC_ROUND_W_D;
13862 goto do_unaryfp;
13864 /* Integer to floating-point conversion */
13865 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
13866 mips32_op = OPC_CVT_L_S;
13867 goto do_unaryfp;
13868 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
13869 mips32_op = OPC_CVT_L_D;
13870 goto do_unaryfp;
13871 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
13872 mips32_op = OPC_CVT_W_S;
13873 goto do_unaryfp;
13874 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
13875 mips32_op = OPC_CVT_W_D;
13876 goto do_unaryfp;
13878 /* Paired-foo conversions */
13879 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
13880 mips32_op = OPC_CVT_S_PL;
13881 goto do_unaryfp;
13882 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13883 mips32_op = OPC_CVT_S_PU;
13884 goto do_unaryfp;
13885 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13886 mips32_op = OPC_CVT_PW_PS;
13887 goto do_unaryfp;
13888 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13889 mips32_op = OPC_CVT_PS_PW;
13890 goto do_unaryfp;
13892 /* Floating-point moves */
13893 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13894 mips32_op = OPC_MOV_S;
13895 goto do_unaryfp;
13896 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13897 mips32_op = OPC_MOV_D;
13898 goto do_unaryfp;
13899 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13900 mips32_op = OPC_MOV_PS;
13901 goto do_unaryfp;
13903 /* Absolute value */
13904 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13905 mips32_op = OPC_ABS_S;
13906 goto do_unaryfp;
13907 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13908 mips32_op = OPC_ABS_D;
13909 goto do_unaryfp;
13910 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13911 mips32_op = OPC_ABS_PS;
13912 goto do_unaryfp;
13914 /* Negation */
13915 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13916 mips32_op = OPC_NEG_S;
13917 goto do_unaryfp;
13918 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13919 mips32_op = OPC_NEG_D;
13920 goto do_unaryfp;
13921 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13922 mips32_op = OPC_NEG_PS;
13923 goto do_unaryfp;
13925 /* Reciprocal square root step */
13926 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13927 mips32_op = OPC_RSQRT1_S;
13928 goto do_unaryfp;
13929 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13930 mips32_op = OPC_RSQRT1_D;
13931 goto do_unaryfp;
13932 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13933 mips32_op = OPC_RSQRT1_PS;
13934 goto do_unaryfp;
13936 /* Reciprocal step */
13937 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13938 mips32_op = OPC_RECIP1_S;
13939 goto do_unaryfp;
13940 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13941 mips32_op = OPC_RECIP1_S;
13942 goto do_unaryfp;
13943 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13944 mips32_op = OPC_RECIP1_PS;
13945 goto do_unaryfp;
13947 /* Conversions from double */
13948 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13949 mips32_op = OPC_CVT_D_S;
13950 goto do_unaryfp;
13951 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13952 mips32_op = OPC_CVT_D_W;
13953 goto do_unaryfp;
13954 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13955 mips32_op = OPC_CVT_D_L;
13956 goto do_unaryfp;
13958 /* Conversions from single */
13959 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13960 mips32_op = OPC_CVT_S_D;
13961 goto do_unaryfp;
13962 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13963 mips32_op = OPC_CVT_S_W;
13964 goto do_unaryfp;
13965 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13966 mips32_op = OPC_CVT_S_L;
13967 do_unaryfp:
13968 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13969 break;
13971 /* Conditional moves on floating-point codes */
13972 case COND_FLOAT_MOV(MOVT, 0):
13973 case COND_FLOAT_MOV(MOVT, 1):
13974 case COND_FLOAT_MOV(MOVT, 2):
13975 case COND_FLOAT_MOV(MOVT, 3):
13976 case COND_FLOAT_MOV(MOVT, 4):
13977 case COND_FLOAT_MOV(MOVT, 5):
13978 case COND_FLOAT_MOV(MOVT, 6):
13979 case COND_FLOAT_MOV(MOVT, 7):
13980 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13981 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13982 break;
13983 case COND_FLOAT_MOV(MOVF, 0):
13984 case COND_FLOAT_MOV(MOVF, 1):
13985 case COND_FLOAT_MOV(MOVF, 2):
13986 case COND_FLOAT_MOV(MOVF, 3):
13987 case COND_FLOAT_MOV(MOVF, 4):
13988 case COND_FLOAT_MOV(MOVF, 5):
13989 case COND_FLOAT_MOV(MOVF, 6):
13990 case COND_FLOAT_MOV(MOVF, 7):
13991 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13992 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13993 break;
13994 default:
13995 MIPS_INVAL("pool32fxf");
13996 generate_exception(ctx, EXCP_RI);
13997 break;
14001 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
14003 int32_t offset;
14004 uint16_t insn;
14005 int rt, rs, rd, rr;
14006 int16_t imm;
14007 uint32_t op, minor, mips32_op;
14008 uint32_t cond, fmt, cc;
14010 insn = cpu_lduw_code(env, ctx->pc + 2);
14011 ctx->opcode = (ctx->opcode << 16) | insn;
14013 rt = (ctx->opcode >> 21) & 0x1f;
14014 rs = (ctx->opcode >> 16) & 0x1f;
14015 rd = (ctx->opcode >> 11) & 0x1f;
14016 rr = (ctx->opcode >> 6) & 0x1f;
14017 imm = (int16_t) ctx->opcode;
14019 op = (ctx->opcode >> 26) & 0x3f;
14020 switch (op) {
14021 case POOL32A:
14022 minor = ctx->opcode & 0x3f;
14023 switch (minor) {
14024 case 0x00:
14025 minor = (ctx->opcode >> 6) & 0xf;
14026 switch (minor) {
14027 case SLL32:
14028 mips32_op = OPC_SLL;
14029 goto do_shifti;
14030 case SRA:
14031 mips32_op = OPC_SRA;
14032 goto do_shifti;
14033 case SRL32:
14034 mips32_op = OPC_SRL;
14035 goto do_shifti;
14036 case ROTR:
14037 mips32_op = OPC_ROTR;
14038 do_shifti:
14039 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
14040 break;
14041 case SELEQZ:
14042 check_insn(ctx, ISA_MIPS32R6);
14043 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
14044 break;
14045 case SELNEZ:
14046 check_insn(ctx, ISA_MIPS32R6);
14047 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
14048 break;
14049 default:
14050 goto pool32a_invalid;
14052 break;
14053 case 0x10:
14054 minor = (ctx->opcode >> 6) & 0xf;
14055 switch (minor) {
14056 /* Arithmetic */
14057 case ADD:
14058 mips32_op = OPC_ADD;
14059 goto do_arith;
14060 case ADDU32:
14061 mips32_op = OPC_ADDU;
14062 goto do_arith;
14063 case SUB:
14064 mips32_op = OPC_SUB;
14065 goto do_arith;
14066 case SUBU32:
14067 mips32_op = OPC_SUBU;
14068 goto do_arith;
14069 case MUL:
14070 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14071 mips32_op = OPC_MUL;
14072 do_arith:
14073 gen_arith(ctx, mips32_op, rd, rs, rt);
14074 break;
14075 /* Shifts */
14076 case SLLV:
14077 mips32_op = OPC_SLLV;
14078 goto do_shift;
14079 case SRLV:
14080 mips32_op = OPC_SRLV;
14081 goto do_shift;
14082 case SRAV:
14083 mips32_op = OPC_SRAV;
14084 goto do_shift;
14085 case ROTRV:
14086 mips32_op = OPC_ROTRV;
14087 do_shift:
14088 gen_shift(ctx, mips32_op, rd, rs, rt);
14089 break;
14090 /* Logical operations */
14091 case AND:
14092 mips32_op = OPC_AND;
14093 goto do_logic;
14094 case OR32:
14095 mips32_op = OPC_OR;
14096 goto do_logic;
14097 case NOR:
14098 mips32_op = OPC_NOR;
14099 goto do_logic;
14100 case XOR32:
14101 mips32_op = OPC_XOR;
14102 do_logic:
14103 gen_logic(ctx, mips32_op, rd, rs, rt);
14104 break;
14105 /* Set less than */
14106 case SLT:
14107 mips32_op = OPC_SLT;
14108 goto do_slt;
14109 case SLTU:
14110 mips32_op = OPC_SLTU;
14111 do_slt:
14112 gen_slt(ctx, mips32_op, rd, rs, rt);
14113 break;
14114 default:
14115 goto pool32a_invalid;
14117 break;
14118 case 0x18:
14119 minor = (ctx->opcode >> 6) & 0xf;
14120 switch (minor) {
14121 /* Conditional moves */
14122 case MOVN: /* MUL */
14123 if (ctx->insn_flags & ISA_MIPS32R6) {
14124 /* MUL */
14125 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
14126 } else {
14127 /* MOVN */
14128 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
14130 break;
14131 case MOVZ: /* MUH */
14132 if (ctx->insn_flags & ISA_MIPS32R6) {
14133 /* MUH */
14134 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
14135 } else {
14136 /* MOVZ */
14137 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
14139 break;
14140 case MULU:
14141 check_insn(ctx, ISA_MIPS32R6);
14142 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
14143 break;
14144 case MUHU:
14145 check_insn(ctx, ISA_MIPS32R6);
14146 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
14147 break;
14148 case LWXS: /* DIV */
14149 if (ctx->insn_flags & ISA_MIPS32R6) {
14150 /* DIV */
14151 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
14152 } else {
14153 /* LWXS */
14154 gen_ldxs(ctx, rs, rt, rd);
14156 break;
14157 case MOD:
14158 check_insn(ctx, ISA_MIPS32R6);
14159 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
14160 break;
14161 case R6_DIVU:
14162 check_insn(ctx, ISA_MIPS32R6);
14163 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
14164 break;
14165 case MODU:
14166 check_insn(ctx, ISA_MIPS32R6);
14167 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
14168 break;
14169 default:
14170 goto pool32a_invalid;
14172 break;
14173 case INS:
14174 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
14175 return;
14176 case LSA:
14177 check_insn(ctx, ISA_MIPS32R6);
14178 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
14179 extract32(ctx->opcode, 9, 2));
14180 break;
14181 case ALIGN:
14182 check_insn(ctx, ISA_MIPS32R6);
14183 gen_align(ctx, OPC_ALIGN, rd, rs, rt,
14184 extract32(ctx->opcode, 9, 2));
14185 break;
14186 case EXT:
14187 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
14188 return;
14189 case POOL32AXF:
14190 gen_pool32axf(env, ctx, rt, rs);
14191 break;
14192 case 0x07:
14193 generate_exception(ctx, EXCP_BREAK);
14194 break;
14195 default:
14196 pool32a_invalid:
14197 MIPS_INVAL("pool32a");
14198 generate_exception(ctx, EXCP_RI);
14199 break;
14201 break;
14202 case POOL32B:
14203 minor = (ctx->opcode >> 12) & 0xf;
14204 switch (minor) {
14205 case CACHE:
14206 check_cp0_enabled(ctx);
14207 /* Treat as no-op. */
14208 break;
14209 case LWC2:
14210 case SWC2:
14211 /* COP2: Not implemented. */
14212 generate_exception_err(ctx, EXCP_CpU, 2);
14213 break;
14214 #ifdef TARGET_MIPS64
14215 case LDP:
14216 case SDP:
14217 check_insn(ctx, ISA_MIPS3);
14218 check_mips_64(ctx);
14219 /* Fallthrough */
14220 #endif
14221 case LWP:
14222 case SWP:
14223 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14224 break;
14225 #ifdef TARGET_MIPS64
14226 case LDM:
14227 case SDM:
14228 check_insn(ctx, ISA_MIPS3);
14229 check_mips_64(ctx);
14230 /* Fallthrough */
14231 #endif
14232 case LWM32:
14233 case SWM32:
14234 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14235 break;
14236 default:
14237 MIPS_INVAL("pool32b");
14238 generate_exception(ctx, EXCP_RI);
14239 break;
14241 break;
14242 case POOL32F:
14243 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14244 minor = ctx->opcode & 0x3f;
14245 check_cp1_enabled(ctx);
14246 switch (minor) {
14247 case ALNV_PS:
14248 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14249 mips32_op = OPC_ALNV_PS;
14250 goto do_madd;
14251 case MADD_S:
14252 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14253 mips32_op = OPC_MADD_S;
14254 goto do_madd;
14255 case MADD_D:
14256 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14257 mips32_op = OPC_MADD_D;
14258 goto do_madd;
14259 case MADD_PS:
14260 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14261 mips32_op = OPC_MADD_PS;
14262 goto do_madd;
14263 case MSUB_S:
14264 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14265 mips32_op = OPC_MSUB_S;
14266 goto do_madd;
14267 case MSUB_D:
14268 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14269 mips32_op = OPC_MSUB_D;
14270 goto do_madd;
14271 case MSUB_PS:
14272 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14273 mips32_op = OPC_MSUB_PS;
14274 goto do_madd;
14275 case NMADD_S:
14276 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14277 mips32_op = OPC_NMADD_S;
14278 goto do_madd;
14279 case NMADD_D:
14280 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14281 mips32_op = OPC_NMADD_D;
14282 goto do_madd;
14283 case NMADD_PS:
14284 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14285 mips32_op = OPC_NMADD_PS;
14286 goto do_madd;
14287 case NMSUB_S:
14288 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14289 mips32_op = OPC_NMSUB_S;
14290 goto do_madd;
14291 case NMSUB_D:
14292 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14293 mips32_op = OPC_NMSUB_D;
14294 goto do_madd;
14295 case NMSUB_PS:
14296 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14297 mips32_op = OPC_NMSUB_PS;
14298 do_madd:
14299 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
14300 break;
14301 case CABS_COND_FMT:
14302 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14303 cond = (ctx->opcode >> 6) & 0xf;
14304 cc = (ctx->opcode >> 13) & 0x7;
14305 fmt = (ctx->opcode >> 10) & 0x3;
14306 switch (fmt) {
14307 case 0x0:
14308 gen_cmpabs_s(ctx, cond, rt, rs, cc);
14309 break;
14310 case 0x1:
14311 gen_cmpabs_d(ctx, cond, rt, rs, cc);
14312 break;
14313 case 0x2:
14314 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
14315 break;
14316 default:
14317 goto pool32f_invalid;
14319 break;
14320 case C_COND_FMT:
14321 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14322 cond = (ctx->opcode >> 6) & 0xf;
14323 cc = (ctx->opcode >> 13) & 0x7;
14324 fmt = (ctx->opcode >> 10) & 0x3;
14325 switch (fmt) {
14326 case 0x0:
14327 gen_cmp_s(ctx, cond, rt, rs, cc);
14328 break;
14329 case 0x1:
14330 gen_cmp_d(ctx, cond, rt, rs, cc);
14331 break;
14332 case 0x2:
14333 gen_cmp_ps(ctx, cond, rt, rs, cc);
14334 break;
14335 default:
14336 goto pool32f_invalid;
14338 break;
14339 case CMP_CONDN_S:
14340 check_insn(ctx, ISA_MIPS32R6);
14341 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14342 break;
14343 case CMP_CONDN_D:
14344 check_insn(ctx, ISA_MIPS32R6);
14345 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14346 break;
14347 case POOL32FXF:
14348 gen_pool32fxf(ctx, rt, rs);
14349 break;
14350 case 0x00:
14351 /* PLL foo */
14352 switch ((ctx->opcode >> 6) & 0x7) {
14353 case PLL_PS:
14354 mips32_op = OPC_PLL_PS;
14355 goto do_ps;
14356 case PLU_PS:
14357 mips32_op = OPC_PLU_PS;
14358 goto do_ps;
14359 case PUL_PS:
14360 mips32_op = OPC_PUL_PS;
14361 goto do_ps;
14362 case PUU_PS:
14363 mips32_op = OPC_PUU_PS;
14364 goto do_ps;
14365 case CVT_PS_S:
14366 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14367 mips32_op = OPC_CVT_PS_S;
14368 do_ps:
14369 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14370 break;
14371 default:
14372 goto pool32f_invalid;
14374 break;
14375 case MIN_FMT:
14376 check_insn(ctx, ISA_MIPS32R6);
14377 switch ((ctx->opcode >> 9) & 0x3) {
14378 case FMT_SDPS_S:
14379 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
14380 break;
14381 case FMT_SDPS_D:
14382 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
14383 break;
14384 default:
14385 goto pool32f_invalid;
14387 break;
14388 case 0x08:
14389 /* [LS][WDU]XC1 */
14390 switch ((ctx->opcode >> 6) & 0x7) {
14391 case LWXC1:
14392 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14393 mips32_op = OPC_LWXC1;
14394 goto do_ldst_cp1;
14395 case SWXC1:
14396 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14397 mips32_op = OPC_SWXC1;
14398 goto do_ldst_cp1;
14399 case LDXC1:
14400 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14401 mips32_op = OPC_LDXC1;
14402 goto do_ldst_cp1;
14403 case SDXC1:
14404 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14405 mips32_op = OPC_SDXC1;
14406 goto do_ldst_cp1;
14407 case LUXC1:
14408 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14409 mips32_op = OPC_LUXC1;
14410 goto do_ldst_cp1;
14411 case SUXC1:
14412 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14413 mips32_op = OPC_SUXC1;
14414 do_ldst_cp1:
14415 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
14416 break;
14417 default:
14418 goto pool32f_invalid;
14420 break;
14421 case MAX_FMT:
14422 check_insn(ctx, ISA_MIPS32R6);
14423 switch ((ctx->opcode >> 9) & 0x3) {
14424 case FMT_SDPS_S:
14425 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
14426 break;
14427 case FMT_SDPS_D:
14428 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
14429 break;
14430 default:
14431 goto pool32f_invalid;
14433 break;
14434 case 0x18:
14435 /* 3D insns */
14436 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14437 fmt = (ctx->opcode >> 9) & 0x3;
14438 switch ((ctx->opcode >> 6) & 0x7) {
14439 case RSQRT2_FMT:
14440 switch (fmt) {
14441 case FMT_SDPS_S:
14442 mips32_op = OPC_RSQRT2_S;
14443 goto do_3d;
14444 case FMT_SDPS_D:
14445 mips32_op = OPC_RSQRT2_D;
14446 goto do_3d;
14447 case FMT_SDPS_PS:
14448 mips32_op = OPC_RSQRT2_PS;
14449 goto do_3d;
14450 default:
14451 goto pool32f_invalid;
14453 break;
14454 case RECIP2_FMT:
14455 switch (fmt) {
14456 case FMT_SDPS_S:
14457 mips32_op = OPC_RECIP2_S;
14458 goto do_3d;
14459 case FMT_SDPS_D:
14460 mips32_op = OPC_RECIP2_D;
14461 goto do_3d;
14462 case FMT_SDPS_PS:
14463 mips32_op = OPC_RECIP2_PS;
14464 goto do_3d;
14465 default:
14466 goto pool32f_invalid;
14468 break;
14469 case ADDR_PS:
14470 mips32_op = OPC_ADDR_PS;
14471 goto do_3d;
14472 case MULR_PS:
14473 mips32_op = OPC_MULR_PS;
14474 do_3d:
14475 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14476 break;
14477 default:
14478 goto pool32f_invalid;
14480 break;
14481 case 0x20:
14482 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
14483 cc = (ctx->opcode >> 13) & 0x7;
14484 fmt = (ctx->opcode >> 9) & 0x3;
14485 switch ((ctx->opcode >> 6) & 0x7) {
14486 case MOVF_FMT: /* RINT_FMT */
14487 if (ctx->insn_flags & ISA_MIPS32R6) {
14488 /* RINT_FMT */
14489 switch (fmt) {
14490 case FMT_SDPS_S:
14491 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14492 break;
14493 case FMT_SDPS_D:
14494 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14495 break;
14496 default:
14497 goto pool32f_invalid;
14499 } else {
14500 /* MOVF_FMT */
14501 switch (fmt) {
14502 case FMT_SDPS_S:
14503 gen_movcf_s(ctx, rs, rt, cc, 0);
14504 break;
14505 case FMT_SDPS_D:
14506 gen_movcf_d(ctx, rs, rt, cc, 0);
14507 break;
14508 case FMT_SDPS_PS:
14509 check_ps(ctx);
14510 gen_movcf_ps(ctx, rs, rt, cc, 0);
14511 break;
14512 default:
14513 goto pool32f_invalid;
14516 break;
14517 case MOVT_FMT: /* CLASS_FMT */
14518 if (ctx->insn_flags & ISA_MIPS32R6) {
14519 /* CLASS_FMT */
14520 switch (fmt) {
14521 case FMT_SDPS_S:
14522 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14523 break;
14524 case FMT_SDPS_D:
14525 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14526 break;
14527 default:
14528 goto pool32f_invalid;
14530 } else {
14531 /* MOVT_FMT */
14532 switch (fmt) {
14533 case FMT_SDPS_S:
14534 gen_movcf_s(ctx, rs, rt, cc, 1);
14535 break;
14536 case FMT_SDPS_D:
14537 gen_movcf_d(ctx, rs, rt, cc, 1);
14538 break;
14539 case FMT_SDPS_PS:
14540 check_ps(ctx);
14541 gen_movcf_ps(ctx, rs, rt, cc, 1);
14542 break;
14543 default:
14544 goto pool32f_invalid;
14547 break;
14548 case PREFX:
14549 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14550 break;
14551 default:
14552 goto pool32f_invalid;
14554 break;
14555 #define FINSN_3ARG_SDPS(prfx) \
14556 switch ((ctx->opcode >> 8) & 0x3) { \
14557 case FMT_SDPS_S: \
14558 mips32_op = OPC_##prfx##_S; \
14559 goto do_fpop; \
14560 case FMT_SDPS_D: \
14561 mips32_op = OPC_##prfx##_D; \
14562 goto do_fpop; \
14563 case FMT_SDPS_PS: \
14564 check_ps(ctx); \
14565 mips32_op = OPC_##prfx##_PS; \
14566 goto do_fpop; \
14567 default: \
14568 goto pool32f_invalid; \
14570 case MINA_FMT:
14571 check_insn(ctx, ISA_MIPS32R6);
14572 switch ((ctx->opcode >> 9) & 0x3) {
14573 case FMT_SDPS_S:
14574 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14575 break;
14576 case FMT_SDPS_D:
14577 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14578 break;
14579 default:
14580 goto pool32f_invalid;
14582 break;
14583 case MAXA_FMT:
14584 check_insn(ctx, ISA_MIPS32R6);
14585 switch ((ctx->opcode >> 9) & 0x3) {
14586 case FMT_SDPS_S:
14587 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14588 break;
14589 case FMT_SDPS_D:
14590 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14591 break;
14592 default:
14593 goto pool32f_invalid;
14595 break;
14596 case 0x30:
14597 /* regular FP ops */
14598 switch ((ctx->opcode >> 6) & 0x3) {
14599 case ADD_FMT:
14600 FINSN_3ARG_SDPS(ADD);
14601 break;
14602 case SUB_FMT:
14603 FINSN_3ARG_SDPS(SUB);
14604 break;
14605 case MUL_FMT:
14606 FINSN_3ARG_SDPS(MUL);
14607 break;
14608 case DIV_FMT:
14609 fmt = (ctx->opcode >> 8) & 0x3;
14610 if (fmt == 1) {
14611 mips32_op = OPC_DIV_D;
14612 } else if (fmt == 0) {
14613 mips32_op = OPC_DIV_S;
14614 } else {
14615 goto pool32f_invalid;
14617 goto do_fpop;
14618 default:
14619 goto pool32f_invalid;
14621 break;
14622 case 0x38:
14623 /* cmovs */
14624 switch ((ctx->opcode >> 6) & 0x7) {
14625 case MOVN_FMT: /* SELNEZ_FMT */
14626 if (ctx->insn_flags & ISA_MIPS32R6) {
14627 /* SELNEZ_FMT */
14628 switch ((ctx->opcode >> 9) & 0x3) {
14629 case FMT_SDPS_S:
14630 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14631 break;
14632 case FMT_SDPS_D:
14633 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
14634 break;
14635 default:
14636 goto pool32f_invalid;
14638 } else {
14639 /* MOVN_FMT */
14640 FINSN_3ARG_SDPS(MOVN);
14642 break;
14643 case MOVN_FMT_04:
14644 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14645 FINSN_3ARG_SDPS(MOVN);
14646 break;
14647 case MOVZ_FMT: /* SELEQZ_FMT */
14648 if (ctx->insn_flags & ISA_MIPS32R6) {
14649 /* SELEQZ_FMT */
14650 switch ((ctx->opcode >> 9) & 0x3) {
14651 case FMT_SDPS_S:
14652 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
14653 break;
14654 case FMT_SDPS_D:
14655 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
14656 break;
14657 default:
14658 goto pool32f_invalid;
14660 } else {
14661 /* MOVZ_FMT */
14662 FINSN_3ARG_SDPS(MOVZ);
14664 break;
14665 case MOVZ_FMT_05:
14666 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14667 FINSN_3ARG_SDPS(MOVZ);
14668 break;
14669 case SEL_FMT:
14670 check_insn(ctx, ISA_MIPS32R6);
14671 switch ((ctx->opcode >> 9) & 0x3) {
14672 case FMT_SDPS_S:
14673 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
14674 break;
14675 case FMT_SDPS_D:
14676 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
14677 break;
14678 default:
14679 goto pool32f_invalid;
14681 break;
14682 case MADDF_FMT:
14683 check_insn(ctx, ISA_MIPS32R6);
14684 switch ((ctx->opcode >> 9) & 0x3) {
14685 case FMT_SDPS_S:
14686 mips32_op = OPC_MADDF_S;
14687 goto do_fpop;
14688 case FMT_SDPS_D:
14689 mips32_op = OPC_MADDF_D;
14690 goto do_fpop;
14691 default:
14692 goto pool32f_invalid;
14694 break;
14695 case MSUBF_FMT:
14696 check_insn(ctx, ISA_MIPS32R6);
14697 switch ((ctx->opcode >> 9) & 0x3) {
14698 case FMT_SDPS_S:
14699 mips32_op = OPC_MSUBF_S;
14700 goto do_fpop;
14701 case FMT_SDPS_D:
14702 mips32_op = OPC_MSUBF_D;
14703 goto do_fpop;
14704 default:
14705 goto pool32f_invalid;
14707 break;
14708 default:
14709 goto pool32f_invalid;
14711 break;
14712 do_fpop:
14713 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14714 break;
14715 default:
14716 pool32f_invalid:
14717 MIPS_INVAL("pool32f");
14718 generate_exception(ctx, EXCP_RI);
14719 break;
14721 } else {
14722 generate_exception_err(ctx, EXCP_CpU, 1);
14724 break;
14725 case POOL32I:
14726 minor = (ctx->opcode >> 21) & 0x1f;
14727 switch (minor) {
14728 case BLTZ:
14729 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14730 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
14731 break;
14732 case BLTZAL:
14733 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14734 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
14735 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14736 break;
14737 case BLTZALS:
14738 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14739 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
14740 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14741 break;
14742 case BGEZ:
14743 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14744 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
14745 break;
14746 case BGEZAL:
14747 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14748 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
14749 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14750 break;
14751 case BGEZALS:
14752 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14753 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
14754 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14755 break;
14756 case BLEZ:
14757 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14758 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
14759 break;
14760 case BGTZ:
14761 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14762 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
14763 break;
14765 /* Traps */
14766 case TLTI: /* BC1EQZC */
14767 if (ctx->insn_flags & ISA_MIPS32R6) {
14768 /* BC1EQZC */
14769 check_cp1_enabled(ctx);
14770 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
14771 } else {
14772 /* TLTI */
14773 mips32_op = OPC_TLTI;
14774 goto do_trapi;
14776 break;
14777 case TGEI: /* BC1NEZC */
14778 if (ctx->insn_flags & ISA_MIPS32R6) {
14779 /* BC1NEZC */
14780 check_cp1_enabled(ctx);
14781 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
14782 } else {
14783 /* TGEI */
14784 mips32_op = OPC_TGEI;
14785 goto do_trapi;
14787 break;
14788 case TLTIU:
14789 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14790 mips32_op = OPC_TLTIU;
14791 goto do_trapi;
14792 case TGEIU:
14793 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14794 mips32_op = OPC_TGEIU;
14795 goto do_trapi;
14796 case TNEI: /* SYNCI */
14797 if (ctx->insn_flags & ISA_MIPS32R6) {
14798 /* SYNCI */
14799 /* Break the TB to be able to sync copied instructions
14800 immediately */
14801 ctx->bstate = BS_STOP;
14802 } else {
14803 /* TNEI */
14804 mips32_op = OPC_TNEI;
14805 goto do_trapi;
14807 break;
14808 case TEQI:
14809 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14810 mips32_op = OPC_TEQI;
14811 do_trapi:
14812 gen_trap(ctx, mips32_op, rs, -1, imm);
14813 break;
14815 case BNEZC:
14816 case BEQZC:
14817 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14818 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
14819 4, rs, 0, imm << 1, 0);
14820 /* Compact branches don't have a delay slot, so just let
14821 the normal delay slot handling take us to the branch
14822 target. */
14823 break;
14824 case LUI:
14825 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14826 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
14827 break;
14828 case SYNCI:
14829 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14830 /* Break the TB to be able to sync copied instructions
14831 immediately */
14832 ctx->bstate = BS_STOP;
14833 break;
14834 case BC2F:
14835 case BC2T:
14836 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14837 /* COP2: Not implemented. */
14838 generate_exception_err(ctx, EXCP_CpU, 2);
14839 break;
14840 case BC1F:
14841 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14842 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
14843 goto do_cp1branch;
14844 case BC1T:
14845 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14846 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
14847 goto do_cp1branch;
14848 case BC1ANY4F:
14849 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14850 mips32_op = OPC_BC1FANY4;
14851 goto do_cp1mips3d;
14852 case BC1ANY4T:
14853 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14854 mips32_op = OPC_BC1TANY4;
14855 do_cp1mips3d:
14856 check_cop1x(ctx);
14857 check_insn(ctx, ASE_MIPS3D);
14858 /* Fall through */
14859 do_cp1branch:
14860 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14861 check_cp1_enabled(ctx);
14862 gen_compute_branch1(ctx, mips32_op,
14863 (ctx->opcode >> 18) & 0x7, imm << 1);
14864 } else {
14865 generate_exception_err(ctx, EXCP_CpU, 1);
14867 break;
14868 case BPOSGE64:
14869 case BPOSGE32:
14870 /* MIPS DSP: not implemented */
14871 /* Fall through */
14872 default:
14873 MIPS_INVAL("pool32i");
14874 generate_exception(ctx, EXCP_RI);
14875 break;
14877 break;
14878 case POOL32C:
14879 minor = (ctx->opcode >> 12) & 0xf;
14880 offset = sextract32(ctx->opcode, 0,
14881 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
14882 switch (minor) {
14883 case LWL:
14884 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14885 mips32_op = OPC_LWL;
14886 goto do_ld_lr;
14887 case SWL:
14888 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14889 mips32_op = OPC_SWL;
14890 goto do_st_lr;
14891 case LWR:
14892 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14893 mips32_op = OPC_LWR;
14894 goto do_ld_lr;
14895 case SWR:
14896 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14897 mips32_op = OPC_SWR;
14898 goto do_st_lr;
14899 #if defined(TARGET_MIPS64)
14900 case LDL:
14901 check_insn(ctx, ISA_MIPS3);
14902 check_mips_64(ctx);
14903 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14904 mips32_op = OPC_LDL;
14905 goto do_ld_lr;
14906 case SDL:
14907 check_insn(ctx, ISA_MIPS3);
14908 check_mips_64(ctx);
14909 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14910 mips32_op = OPC_SDL;
14911 goto do_st_lr;
14912 case LDR:
14913 check_insn(ctx, ISA_MIPS3);
14914 check_mips_64(ctx);
14915 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14916 mips32_op = OPC_LDR;
14917 goto do_ld_lr;
14918 case SDR:
14919 check_insn(ctx, ISA_MIPS3);
14920 check_mips_64(ctx);
14921 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14922 mips32_op = OPC_SDR;
14923 goto do_st_lr;
14924 case LWU:
14925 check_insn(ctx, ISA_MIPS3);
14926 check_mips_64(ctx);
14927 mips32_op = OPC_LWU;
14928 goto do_ld_lr;
14929 case LLD:
14930 check_insn(ctx, ISA_MIPS3);
14931 check_mips_64(ctx);
14932 mips32_op = OPC_LLD;
14933 goto do_ld_lr;
14934 #endif
14935 case LL:
14936 mips32_op = OPC_LL;
14937 goto do_ld_lr;
14938 do_ld_lr:
14939 gen_ld(ctx, mips32_op, rt, rs, offset);
14940 break;
14941 do_st_lr:
14942 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
14943 break;
14944 case SC:
14945 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
14946 break;
14947 #if defined(TARGET_MIPS64)
14948 case SCD:
14949 check_insn(ctx, ISA_MIPS3);
14950 check_mips_64(ctx);
14951 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
14952 break;
14953 #endif
14954 case PREF:
14955 /* Treat as no-op */
14956 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
14957 /* hint codes 24-31 are reserved and signal RI */
14958 generate_exception(ctx, EXCP_RI);
14960 break;
14961 default:
14962 MIPS_INVAL("pool32c");
14963 generate_exception(ctx, EXCP_RI);
14964 break;
14966 break;
14967 case ADDI32: /* AUI, LUI */
14968 if (ctx->insn_flags & ISA_MIPS32R6) {
14969 /* AUI, LUI */
14970 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
14971 } else {
14972 /* ADDI32 */
14973 mips32_op = OPC_ADDI;
14974 goto do_addi;
14976 break;
14977 case ADDIU32:
14978 mips32_op = OPC_ADDIU;
14979 do_addi:
14980 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
14981 break;
14983 /* Logical operations */
14984 case ORI32:
14985 mips32_op = OPC_ORI;
14986 goto do_logici;
14987 case XORI32:
14988 mips32_op = OPC_XORI;
14989 goto do_logici;
14990 case ANDI32:
14991 mips32_op = OPC_ANDI;
14992 do_logici:
14993 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
14994 break;
14996 /* Set less than immediate */
14997 case SLTI32:
14998 mips32_op = OPC_SLTI;
14999 goto do_slti;
15000 case SLTIU32:
15001 mips32_op = OPC_SLTIU;
15002 do_slti:
15003 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
15004 break;
15005 case JALX32:
15006 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15007 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15008 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
15009 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15010 break;
15011 case JALS32: /* BOVC, BEQC, BEQZALC */
15012 if (ctx->insn_flags & ISA_MIPS32R6) {
15013 if (rs >= rt) {
15014 /* BOVC */
15015 mips32_op = OPC_BOVC;
15016 } else if (rs < rt && rs == 0) {
15017 /* BEQZALC */
15018 mips32_op = OPC_BEQZALC;
15019 } else {
15020 /* BEQC */
15021 mips32_op = OPC_BEQC;
15023 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15024 } else {
15025 /* JALS32 */
15026 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
15027 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
15028 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15030 break;
15031 case BEQ32: /* BC */
15032 if (ctx->insn_flags & ISA_MIPS32R6) {
15033 /* BC */
15034 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
15035 sextract32(ctx->opcode << 1, 0, 27));
15036 } else {
15037 /* BEQ32 */
15038 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
15040 break;
15041 case BNE32: /* BALC */
15042 if (ctx->insn_flags & ISA_MIPS32R6) {
15043 /* BALC */
15044 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
15045 sextract32(ctx->opcode << 1, 0, 27));
15046 } else {
15047 /* BNE32 */
15048 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
15050 break;
15051 case J32: /* BGTZC, BLTZC, BLTC */
15052 if (ctx->insn_flags & ISA_MIPS32R6) {
15053 if (rs == 0 && rt != 0) {
15054 /* BGTZC */
15055 mips32_op = OPC_BGTZC;
15056 } else if (rs != 0 && rt != 0 && rs == rt) {
15057 /* BLTZC */
15058 mips32_op = OPC_BLTZC;
15059 } else {
15060 /* BLTC */
15061 mips32_op = OPC_BLTC;
15063 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15064 } else {
15065 /* J32 */
15066 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
15067 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15069 break;
15070 case JAL32: /* BLEZC, BGEZC, BGEC */
15071 if (ctx->insn_flags & ISA_MIPS32R6) {
15072 if (rs == 0 && rt != 0) {
15073 /* BLEZC */
15074 mips32_op = OPC_BLEZC;
15075 } else if (rs != 0 && rt != 0 && rs == rt) {
15076 /* BGEZC */
15077 mips32_op = OPC_BGEZC;
15078 } else {
15079 /* BGEC */
15080 mips32_op = OPC_BGEC;
15082 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15083 } else {
15084 /* JAL32 */
15085 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
15086 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15087 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15089 break;
15090 /* Floating point (COP1) */
15091 case LWC132:
15092 mips32_op = OPC_LWC1;
15093 goto do_cop1;
15094 case LDC132:
15095 mips32_op = OPC_LDC1;
15096 goto do_cop1;
15097 case SWC132:
15098 mips32_op = OPC_SWC1;
15099 goto do_cop1;
15100 case SDC132:
15101 mips32_op = OPC_SDC1;
15102 do_cop1:
15103 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
15104 break;
15105 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15106 if (ctx->insn_flags & ISA_MIPS32R6) {
15107 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15108 switch ((ctx->opcode >> 16) & 0x1f) {
15109 case ADDIUPC_00 ... ADDIUPC_07:
15110 gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
15111 break;
15112 case AUIPC:
15113 gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
15114 break;
15115 case ALUIPC:
15116 gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
15117 break;
15118 case LWPC_08 ... LWPC_0F:
15119 gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
15120 break;
15121 default:
15122 generate_exception(ctx, EXCP_RI);
15123 break;
15125 } else {
15126 /* ADDIUPC */
15127 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
15128 int offset = SIMM(ctx->opcode, 0, 23) << 2;
15130 gen_addiupc(ctx, reg, offset, 0, 0);
15132 break;
15133 case BNVC: /* BNEC, BNEZALC */
15134 check_insn(ctx, ISA_MIPS32R6);
15135 if (rs >= rt) {
15136 /* BNVC */
15137 mips32_op = OPC_BNVC;
15138 } else if (rs < rt && rs == 0) {
15139 /* BNEZALC */
15140 mips32_op = OPC_BNEZALC;
15141 } else {
15142 /* BNEC */
15143 mips32_op = OPC_BNEC;
15145 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15146 break;
15147 case R6_BNEZC: /* JIALC */
15148 check_insn(ctx, ISA_MIPS32R6);
15149 if (rt != 0) {
15150 /* BNEZC */
15151 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
15152 sextract32(ctx->opcode << 1, 0, 22));
15153 } else {
15154 /* JIALC */
15155 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
15157 break;
15158 case R6_BEQZC: /* JIC */
15159 check_insn(ctx, ISA_MIPS32R6);
15160 if (rt != 0) {
15161 /* BEQZC */
15162 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
15163 sextract32(ctx->opcode << 1, 0, 22));
15164 } else {
15165 /* JIC */
15166 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
15168 break;
15169 case BLEZALC: /* BGEZALC, BGEUC */
15170 check_insn(ctx, ISA_MIPS32R6);
15171 if (rs == 0 && rt != 0) {
15172 /* BLEZALC */
15173 mips32_op = OPC_BLEZALC;
15174 } else if (rs != 0 && rt != 0 && rs == rt) {
15175 /* BGEZALC */
15176 mips32_op = OPC_BGEZALC;
15177 } else {
15178 /* BGEUC */
15179 mips32_op = OPC_BGEUC;
15181 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15182 break;
15183 case BGTZALC: /* BLTZALC, BLTUC */
15184 check_insn(ctx, ISA_MIPS32R6);
15185 if (rs == 0 && rt != 0) {
15186 /* BGTZALC */
15187 mips32_op = OPC_BGTZALC;
15188 } else if (rs != 0 && rt != 0 && rs == rt) {
15189 /* BLTZALC */
15190 mips32_op = OPC_BLTZALC;
15191 } else {
15192 /* BLTUC */
15193 mips32_op = OPC_BLTUC;
15195 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15196 break;
15197 /* Loads and stores */
15198 case LB32:
15199 mips32_op = OPC_LB;
15200 goto do_ld;
15201 case LBU32:
15202 mips32_op = OPC_LBU;
15203 goto do_ld;
15204 case LH32:
15205 mips32_op = OPC_LH;
15206 goto do_ld;
15207 case LHU32:
15208 mips32_op = OPC_LHU;
15209 goto do_ld;
15210 case LW32:
15211 mips32_op = OPC_LW;
15212 goto do_ld;
15213 #ifdef TARGET_MIPS64
15214 case LD32:
15215 check_insn(ctx, ISA_MIPS3);
15216 check_mips_64(ctx);
15217 mips32_op = OPC_LD;
15218 goto do_ld;
15219 case SD32:
15220 check_insn(ctx, ISA_MIPS3);
15221 check_mips_64(ctx);
15222 mips32_op = OPC_SD;
15223 goto do_st;
15224 #endif
15225 case SB32:
15226 mips32_op = OPC_SB;
15227 goto do_st;
15228 case SH32:
15229 mips32_op = OPC_SH;
15230 goto do_st;
15231 case SW32:
15232 mips32_op = OPC_SW;
15233 goto do_st;
15234 do_ld:
15235 gen_ld(ctx, mips32_op, rt, rs, imm);
15236 break;
15237 do_st:
15238 gen_st(ctx, mips32_op, rt, rs, imm);
15239 break;
15240 default:
15241 generate_exception(ctx, EXCP_RI);
15242 break;
15246 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
15248 uint32_t op;
15250 /* make sure instructions are on a halfword boundary */
15251 if (ctx->pc & 0x1) {
15252 env->CP0_BadVAddr = ctx->pc;
15253 generate_exception(ctx, EXCP_AdEL);
15254 ctx->bstate = BS_STOP;
15255 return 2;
15258 op = (ctx->opcode >> 10) & 0x3f;
15259 /* Enforce properly-sized instructions in a delay slot */
15260 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
15261 switch (op & 0x7) { /* MSB-3..MSB-5 */
15262 case 0:
15263 /* POOL32A, POOL32B, POOL32I, POOL32C */
15264 case 4:
15265 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
15266 case 5:
15267 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
15268 case 6:
15269 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
15270 case 7:
15271 /* LB32, LH32, LWC132, LDC132, LW32 */
15272 if (ctx->hflags & MIPS_HFLAG_BDS16) {
15273 generate_exception(ctx, EXCP_RI);
15274 /* Just stop translation; the user is confused. */
15275 ctx->bstate = BS_STOP;
15276 return 2;
15278 break;
15279 case 1:
15280 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
15281 case 2:
15282 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
15283 case 3:
15284 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
15285 if (ctx->hflags & MIPS_HFLAG_BDS32) {
15286 generate_exception(ctx, EXCP_RI);
15287 /* Just stop translation; the user is confused. */
15288 ctx->bstate = BS_STOP;
15289 return 2;
15291 break;
15295 switch (op) {
15296 case POOL16A:
15298 int rd = mmreg(uMIPS_RD(ctx->opcode));
15299 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
15300 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
15301 uint32_t opc = 0;
15303 switch (ctx->opcode & 0x1) {
15304 case ADDU16:
15305 opc = OPC_ADDU;
15306 break;
15307 case SUBU16:
15308 opc = OPC_SUBU;
15309 break;
15311 if (ctx->insn_flags & ISA_MIPS32R6) {
15312 /* In the Release 6 the register number location in
15313 * the instruction encoding has changed.
15315 gen_arith(ctx, opc, rs1, rd, rs2);
15316 } else {
15317 gen_arith(ctx, opc, rd, rs1, rs2);
15320 break;
15321 case POOL16B:
15323 int rd = mmreg(uMIPS_RD(ctx->opcode));
15324 int rs = mmreg(uMIPS_RS(ctx->opcode));
15325 int amount = (ctx->opcode >> 1) & 0x7;
15326 uint32_t opc = 0;
15327 amount = amount == 0 ? 8 : amount;
15329 switch (ctx->opcode & 0x1) {
15330 case SLL16:
15331 opc = OPC_SLL;
15332 break;
15333 case SRL16:
15334 opc = OPC_SRL;
15335 break;
15338 gen_shift_imm(ctx, opc, rd, rs, amount);
15340 break;
15341 case POOL16C:
15342 if (ctx->insn_flags & ISA_MIPS32R6) {
15343 gen_pool16c_r6_insn(ctx);
15344 } else {
15345 gen_pool16c_insn(ctx);
15347 break;
15348 case LWGP16:
15350 int rd = mmreg(uMIPS_RD(ctx->opcode));
15351 int rb = 28; /* GP */
15352 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
15354 gen_ld(ctx, OPC_LW, rd, rb, offset);
15356 break;
15357 case POOL16F:
15358 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15359 if (ctx->opcode & 1) {
15360 generate_exception(ctx, EXCP_RI);
15361 } else {
15362 /* MOVEP */
15363 int enc_dest = uMIPS_RD(ctx->opcode);
15364 int enc_rt = uMIPS_RS2(ctx->opcode);
15365 int enc_rs = uMIPS_RS1(ctx->opcode);
15366 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15368 break;
15369 case LBU16:
15371 int rd = mmreg(uMIPS_RD(ctx->opcode));
15372 int rb = mmreg(uMIPS_RS(ctx->opcode));
15373 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15374 offset = (offset == 0xf ? -1 : offset);
15376 gen_ld(ctx, OPC_LBU, rd, rb, offset);
15378 break;
15379 case LHU16:
15381 int rd = mmreg(uMIPS_RD(ctx->opcode));
15382 int rb = mmreg(uMIPS_RS(ctx->opcode));
15383 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15385 gen_ld(ctx, OPC_LHU, rd, rb, offset);
15387 break;
15388 case LWSP16:
15390 int rd = (ctx->opcode >> 5) & 0x1f;
15391 int rb = 29; /* SP */
15392 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15394 gen_ld(ctx, OPC_LW, rd, rb, offset);
15396 break;
15397 case LW16:
15399 int rd = mmreg(uMIPS_RD(ctx->opcode));
15400 int rb = mmreg(uMIPS_RS(ctx->opcode));
15401 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15403 gen_ld(ctx, OPC_LW, rd, rb, offset);
15405 break;
15406 case SB16:
15408 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15409 int rb = mmreg(uMIPS_RS(ctx->opcode));
15410 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15412 gen_st(ctx, OPC_SB, rd, rb, offset);
15414 break;
15415 case SH16:
15417 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15418 int rb = mmreg(uMIPS_RS(ctx->opcode));
15419 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15421 gen_st(ctx, OPC_SH, rd, rb, offset);
15423 break;
15424 case SWSP16:
15426 int rd = (ctx->opcode >> 5) & 0x1f;
15427 int rb = 29; /* SP */
15428 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15430 gen_st(ctx, OPC_SW, rd, rb, offset);
15432 break;
15433 case SW16:
15435 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15436 int rb = mmreg(uMIPS_RS(ctx->opcode));
15437 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15439 gen_st(ctx, OPC_SW, rd, rb, offset);
15441 break;
15442 case MOVE16:
15444 int rd = uMIPS_RD5(ctx->opcode);
15445 int rs = uMIPS_RS5(ctx->opcode);
15447 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
15449 break;
15450 case ANDI16:
15451 gen_andi16(ctx);
15452 break;
15453 case POOL16D:
15454 switch (ctx->opcode & 0x1) {
15455 case ADDIUS5:
15456 gen_addius5(ctx);
15457 break;
15458 case ADDIUSP:
15459 gen_addiusp(ctx);
15460 break;
15462 break;
15463 case POOL16E:
15464 switch (ctx->opcode & 0x1) {
15465 case ADDIUR2:
15466 gen_addiur2(ctx);
15467 break;
15468 case ADDIUR1SP:
15469 gen_addiur1sp(ctx);
15470 break;
15472 break;
15473 case B16: /* BC16 */
15474 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
15475 sextract32(ctx->opcode, 0, 10) << 1,
15476 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15477 break;
15478 case BNEZ16: /* BNEZC16 */
15479 case BEQZ16: /* BEQZC16 */
15480 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
15481 mmreg(uMIPS_RD(ctx->opcode)),
15482 0, sextract32(ctx->opcode, 0, 7) << 1,
15483 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15485 break;
15486 case LI16:
15488 int reg = mmreg(uMIPS_RD(ctx->opcode));
15489 int imm = ZIMM(ctx->opcode, 0, 7);
15491 imm = (imm == 0x7f ? -1 : imm);
15492 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15494 break;
15495 case RES_29:
15496 case RES_31:
15497 case RES_39:
15498 generate_exception(ctx, EXCP_RI);
15499 break;
15500 default:
15501 decode_micromips32_opc(env, ctx);
15502 return 4;
15505 return 2;
15508 /* SmartMIPS extension to MIPS32 */
15510 #if defined(TARGET_MIPS64)
15512 /* MDMX extension to MIPS64 */
15514 #endif
15516 /* MIPSDSP functions. */
15517 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
15518 int rd, int base, int offset)
15520 const char *opn = "ldx";
15521 TCGv t0;
15523 check_dsp(ctx);
15524 t0 = tcg_temp_new();
15526 if (base == 0) {
15527 gen_load_gpr(t0, offset);
15528 } else if (offset == 0) {
15529 gen_load_gpr(t0, base);
15530 } else {
15531 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
15534 switch (opc) {
15535 case OPC_LBUX:
15536 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
15537 gen_store_gpr(t0, rd);
15538 opn = "lbux";
15539 break;
15540 case OPC_LHX:
15541 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
15542 gen_store_gpr(t0, rd);
15543 opn = "lhx";
15544 break;
15545 case OPC_LWX:
15546 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
15547 gen_store_gpr(t0, rd);
15548 opn = "lwx";
15549 break;
15550 #if defined(TARGET_MIPS64)
15551 case OPC_LDX:
15552 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
15553 gen_store_gpr(t0, rd);
15554 opn = "ldx";
15555 break;
15556 #endif
15558 (void)opn; /* avoid a compiler warning */
15559 MIPS_DEBUG("%s %s, %s(%s)", opn,
15560 regnames[rd], regnames[offset], regnames[base]);
15561 tcg_temp_free(t0);
15564 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
15565 int ret, int v1, int v2)
15567 const char *opn = "mipsdsp arith";
15568 TCGv v1_t;
15569 TCGv v2_t;
15571 if (ret == 0) {
15572 /* Treat as NOP. */
15573 MIPS_DEBUG("NOP");
15574 return;
15577 v1_t = tcg_temp_new();
15578 v2_t = tcg_temp_new();
15580 gen_load_gpr(v1_t, v1);
15581 gen_load_gpr(v2_t, v2);
15583 switch (op1) {
15584 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
15585 case OPC_MULT_G_2E:
15586 check_dspr2(ctx);
15587 switch (op2) {
15588 case OPC_ADDUH_QB:
15589 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
15590 break;
15591 case OPC_ADDUH_R_QB:
15592 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15593 break;
15594 case OPC_ADDQH_PH:
15595 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
15596 break;
15597 case OPC_ADDQH_R_PH:
15598 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15599 break;
15600 case OPC_ADDQH_W:
15601 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
15602 break;
15603 case OPC_ADDQH_R_W:
15604 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15605 break;
15606 case OPC_SUBUH_QB:
15607 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
15608 break;
15609 case OPC_SUBUH_R_QB:
15610 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15611 break;
15612 case OPC_SUBQH_PH:
15613 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
15614 break;
15615 case OPC_SUBQH_R_PH:
15616 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15617 break;
15618 case OPC_SUBQH_W:
15619 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
15620 break;
15621 case OPC_SUBQH_R_W:
15622 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15623 break;
15625 break;
15626 case OPC_ABSQ_S_PH_DSP:
15627 switch (op2) {
15628 case OPC_ABSQ_S_QB:
15629 check_dspr2(ctx);
15630 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
15631 break;
15632 case OPC_ABSQ_S_PH:
15633 check_dsp(ctx);
15634 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
15635 break;
15636 case OPC_ABSQ_S_W:
15637 check_dsp(ctx);
15638 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
15639 break;
15640 case OPC_PRECEQ_W_PHL:
15641 check_dsp(ctx);
15642 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
15643 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15644 break;
15645 case OPC_PRECEQ_W_PHR:
15646 check_dsp(ctx);
15647 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
15648 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
15649 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15650 break;
15651 case OPC_PRECEQU_PH_QBL:
15652 check_dsp(ctx);
15653 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
15654 break;
15655 case OPC_PRECEQU_PH_QBR:
15656 check_dsp(ctx);
15657 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
15658 break;
15659 case OPC_PRECEQU_PH_QBLA:
15660 check_dsp(ctx);
15661 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
15662 break;
15663 case OPC_PRECEQU_PH_QBRA:
15664 check_dsp(ctx);
15665 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
15666 break;
15667 case OPC_PRECEU_PH_QBL:
15668 check_dsp(ctx);
15669 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
15670 break;
15671 case OPC_PRECEU_PH_QBR:
15672 check_dsp(ctx);
15673 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
15674 break;
15675 case OPC_PRECEU_PH_QBLA:
15676 check_dsp(ctx);
15677 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
15678 break;
15679 case OPC_PRECEU_PH_QBRA:
15680 check_dsp(ctx);
15681 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
15682 break;
15684 break;
15685 case OPC_ADDU_QB_DSP:
15686 switch (op2) {
15687 case OPC_ADDQ_PH:
15688 check_dsp(ctx);
15689 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15690 break;
15691 case OPC_ADDQ_S_PH:
15692 check_dsp(ctx);
15693 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15694 break;
15695 case OPC_ADDQ_S_W:
15696 check_dsp(ctx);
15697 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15698 break;
15699 case OPC_ADDU_QB:
15700 check_dsp(ctx);
15701 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15702 break;
15703 case OPC_ADDU_S_QB:
15704 check_dsp(ctx);
15705 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15706 break;
15707 case OPC_ADDU_PH:
15708 check_dspr2(ctx);
15709 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15710 break;
15711 case OPC_ADDU_S_PH:
15712 check_dspr2(ctx);
15713 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15714 break;
15715 case OPC_SUBQ_PH:
15716 check_dsp(ctx);
15717 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15718 break;
15719 case OPC_SUBQ_S_PH:
15720 check_dsp(ctx);
15721 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15722 break;
15723 case OPC_SUBQ_S_W:
15724 check_dsp(ctx);
15725 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15726 break;
15727 case OPC_SUBU_QB:
15728 check_dsp(ctx);
15729 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15730 break;
15731 case OPC_SUBU_S_QB:
15732 check_dsp(ctx);
15733 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15734 break;
15735 case OPC_SUBU_PH:
15736 check_dspr2(ctx);
15737 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15738 break;
15739 case OPC_SUBU_S_PH:
15740 check_dspr2(ctx);
15741 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15742 break;
15743 case OPC_ADDSC:
15744 check_dsp(ctx);
15745 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15746 break;
15747 case OPC_ADDWC:
15748 check_dsp(ctx);
15749 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15750 break;
15751 case OPC_MODSUB:
15752 check_dsp(ctx);
15753 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
15754 break;
15755 case OPC_RADDU_W_QB:
15756 check_dsp(ctx);
15757 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
15758 break;
15760 break;
15761 case OPC_CMPU_EQ_QB_DSP:
15762 switch (op2) {
15763 case OPC_PRECR_QB_PH:
15764 check_dspr2(ctx);
15765 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15766 break;
15767 case OPC_PRECRQ_QB_PH:
15768 check_dsp(ctx);
15769 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15770 break;
15771 case OPC_PRECR_SRA_PH_W:
15772 check_dspr2(ctx);
15774 TCGv_i32 sa_t = tcg_const_i32(v2);
15775 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
15776 cpu_gpr[ret]);
15777 tcg_temp_free_i32(sa_t);
15778 break;
15780 case OPC_PRECR_SRA_R_PH_W:
15781 check_dspr2(ctx);
15783 TCGv_i32 sa_t = tcg_const_i32(v2);
15784 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
15785 cpu_gpr[ret]);
15786 tcg_temp_free_i32(sa_t);
15787 break;
15789 case OPC_PRECRQ_PH_W:
15790 check_dsp(ctx);
15791 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
15792 break;
15793 case OPC_PRECRQ_RS_PH_W:
15794 check_dsp(ctx);
15795 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15796 break;
15797 case OPC_PRECRQU_S_QB_PH:
15798 check_dsp(ctx);
15799 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15800 break;
15802 break;
15803 #ifdef TARGET_MIPS64
15804 case OPC_ABSQ_S_QH_DSP:
15805 switch (op2) {
15806 case OPC_PRECEQ_L_PWL:
15807 check_dsp(ctx);
15808 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
15809 break;
15810 case OPC_PRECEQ_L_PWR:
15811 check_dsp(ctx);
15812 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
15813 break;
15814 case OPC_PRECEQ_PW_QHL:
15815 check_dsp(ctx);
15816 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
15817 break;
15818 case OPC_PRECEQ_PW_QHR:
15819 check_dsp(ctx);
15820 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
15821 break;
15822 case OPC_PRECEQ_PW_QHLA:
15823 check_dsp(ctx);
15824 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
15825 break;
15826 case OPC_PRECEQ_PW_QHRA:
15827 check_dsp(ctx);
15828 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
15829 break;
15830 case OPC_PRECEQU_QH_OBL:
15831 check_dsp(ctx);
15832 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
15833 break;
15834 case OPC_PRECEQU_QH_OBR:
15835 check_dsp(ctx);
15836 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
15837 break;
15838 case OPC_PRECEQU_QH_OBLA:
15839 check_dsp(ctx);
15840 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
15841 break;
15842 case OPC_PRECEQU_QH_OBRA:
15843 check_dsp(ctx);
15844 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
15845 break;
15846 case OPC_PRECEU_QH_OBL:
15847 check_dsp(ctx);
15848 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
15849 break;
15850 case OPC_PRECEU_QH_OBR:
15851 check_dsp(ctx);
15852 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
15853 break;
15854 case OPC_PRECEU_QH_OBLA:
15855 check_dsp(ctx);
15856 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
15857 break;
15858 case OPC_PRECEU_QH_OBRA:
15859 check_dsp(ctx);
15860 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
15861 break;
15862 case OPC_ABSQ_S_OB:
15863 check_dspr2(ctx);
15864 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
15865 break;
15866 case OPC_ABSQ_S_PW:
15867 check_dsp(ctx);
15868 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
15869 break;
15870 case OPC_ABSQ_S_QH:
15871 check_dsp(ctx);
15872 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
15873 break;
15875 break;
15876 case OPC_ADDU_OB_DSP:
15877 switch (op2) {
15878 case OPC_RADDU_L_OB:
15879 check_dsp(ctx);
15880 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
15881 break;
15882 case OPC_SUBQ_PW:
15883 check_dsp(ctx);
15884 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15885 break;
15886 case OPC_SUBQ_S_PW:
15887 check_dsp(ctx);
15888 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15889 break;
15890 case OPC_SUBQ_QH:
15891 check_dsp(ctx);
15892 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15893 break;
15894 case OPC_SUBQ_S_QH:
15895 check_dsp(ctx);
15896 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15897 break;
15898 case OPC_SUBU_OB:
15899 check_dsp(ctx);
15900 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15901 break;
15902 case OPC_SUBU_S_OB:
15903 check_dsp(ctx);
15904 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15905 break;
15906 case OPC_SUBU_QH:
15907 check_dspr2(ctx);
15908 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15909 break;
15910 case OPC_SUBU_S_QH:
15911 check_dspr2(ctx);
15912 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15913 break;
15914 case OPC_SUBUH_OB:
15915 check_dspr2(ctx);
15916 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
15917 break;
15918 case OPC_SUBUH_R_OB:
15919 check_dspr2(ctx);
15920 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15921 break;
15922 case OPC_ADDQ_PW:
15923 check_dsp(ctx);
15924 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15925 break;
15926 case OPC_ADDQ_S_PW:
15927 check_dsp(ctx);
15928 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15929 break;
15930 case OPC_ADDQ_QH:
15931 check_dsp(ctx);
15932 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15933 break;
15934 case OPC_ADDQ_S_QH:
15935 check_dsp(ctx);
15936 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15937 break;
15938 case OPC_ADDU_OB:
15939 check_dsp(ctx);
15940 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15941 break;
15942 case OPC_ADDU_S_OB:
15943 check_dsp(ctx);
15944 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15945 break;
15946 case OPC_ADDU_QH:
15947 check_dspr2(ctx);
15948 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15949 break;
15950 case OPC_ADDU_S_QH:
15951 check_dspr2(ctx);
15952 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15953 break;
15954 case OPC_ADDUH_OB:
15955 check_dspr2(ctx);
15956 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
15957 break;
15958 case OPC_ADDUH_R_OB:
15959 check_dspr2(ctx);
15960 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15961 break;
15963 break;
15964 case OPC_CMPU_EQ_OB_DSP:
15965 switch (op2) {
15966 case OPC_PRECR_OB_QH:
15967 check_dspr2(ctx);
15968 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15969 break;
15970 case OPC_PRECR_SRA_QH_PW:
15971 check_dspr2(ctx);
15973 TCGv_i32 ret_t = tcg_const_i32(ret);
15974 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
15975 tcg_temp_free_i32(ret_t);
15976 break;
15978 case OPC_PRECR_SRA_R_QH_PW:
15979 check_dspr2(ctx);
15981 TCGv_i32 sa_v = tcg_const_i32(ret);
15982 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
15983 tcg_temp_free_i32(sa_v);
15984 break;
15986 case OPC_PRECRQ_OB_QH:
15987 check_dsp(ctx);
15988 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15989 break;
15990 case OPC_PRECRQ_PW_L:
15991 check_dsp(ctx);
15992 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
15993 break;
15994 case OPC_PRECRQ_QH_PW:
15995 check_dsp(ctx);
15996 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
15997 break;
15998 case OPC_PRECRQ_RS_QH_PW:
15999 check_dsp(ctx);
16000 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16001 break;
16002 case OPC_PRECRQU_S_OB_QH:
16003 check_dsp(ctx);
16004 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16005 break;
16007 break;
16008 #endif
16011 tcg_temp_free(v1_t);
16012 tcg_temp_free(v2_t);
16014 (void)opn; /* avoid a compiler warning */
16015 MIPS_DEBUG("%s", opn);
16018 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
16019 int ret, int v1, int v2)
16021 uint32_t op2;
16022 const char *opn = "mipsdsp shift";
16023 TCGv t0;
16024 TCGv v1_t;
16025 TCGv v2_t;
16027 if (ret == 0) {
16028 /* Treat as NOP. */
16029 MIPS_DEBUG("NOP");
16030 return;
16033 t0 = tcg_temp_new();
16034 v1_t = tcg_temp_new();
16035 v2_t = tcg_temp_new();
16037 tcg_gen_movi_tl(t0, v1);
16038 gen_load_gpr(v1_t, v1);
16039 gen_load_gpr(v2_t, v2);
16041 switch (opc) {
16042 case OPC_SHLL_QB_DSP:
16044 op2 = MASK_SHLL_QB(ctx->opcode);
16045 switch (op2) {
16046 case OPC_SHLL_QB:
16047 check_dsp(ctx);
16048 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
16049 break;
16050 case OPC_SHLLV_QB:
16051 check_dsp(ctx);
16052 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16053 break;
16054 case OPC_SHLL_PH:
16055 check_dsp(ctx);
16056 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
16057 break;
16058 case OPC_SHLLV_PH:
16059 check_dsp(ctx);
16060 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16061 break;
16062 case OPC_SHLL_S_PH:
16063 check_dsp(ctx);
16064 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
16065 break;
16066 case OPC_SHLLV_S_PH:
16067 check_dsp(ctx);
16068 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16069 break;
16070 case OPC_SHLL_S_W:
16071 check_dsp(ctx);
16072 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
16073 break;
16074 case OPC_SHLLV_S_W:
16075 check_dsp(ctx);
16076 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16077 break;
16078 case OPC_SHRL_QB:
16079 check_dsp(ctx);
16080 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
16081 break;
16082 case OPC_SHRLV_QB:
16083 check_dsp(ctx);
16084 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
16085 break;
16086 case OPC_SHRL_PH:
16087 check_dspr2(ctx);
16088 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
16089 break;
16090 case OPC_SHRLV_PH:
16091 check_dspr2(ctx);
16092 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
16093 break;
16094 case OPC_SHRA_QB:
16095 check_dspr2(ctx);
16096 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
16097 break;
16098 case OPC_SHRA_R_QB:
16099 check_dspr2(ctx);
16100 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
16101 break;
16102 case OPC_SHRAV_QB:
16103 check_dspr2(ctx);
16104 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
16105 break;
16106 case OPC_SHRAV_R_QB:
16107 check_dspr2(ctx);
16108 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
16109 break;
16110 case OPC_SHRA_PH:
16111 check_dsp(ctx);
16112 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
16113 break;
16114 case OPC_SHRA_R_PH:
16115 check_dsp(ctx);
16116 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
16117 break;
16118 case OPC_SHRAV_PH:
16119 check_dsp(ctx);
16120 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
16121 break;
16122 case OPC_SHRAV_R_PH:
16123 check_dsp(ctx);
16124 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
16125 break;
16126 case OPC_SHRA_R_W:
16127 check_dsp(ctx);
16128 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
16129 break;
16130 case OPC_SHRAV_R_W:
16131 check_dsp(ctx);
16132 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
16133 break;
16134 default: /* Invalid */
16135 MIPS_INVAL("MASK SHLL.QB");
16136 generate_exception(ctx, EXCP_RI);
16137 break;
16139 break;
16141 #ifdef TARGET_MIPS64
16142 case OPC_SHLL_OB_DSP:
16143 op2 = MASK_SHLL_OB(ctx->opcode);
16144 switch (op2) {
16145 case OPC_SHLL_PW:
16146 check_dsp(ctx);
16147 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
16148 break;
16149 case OPC_SHLLV_PW:
16150 check_dsp(ctx);
16151 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16152 break;
16153 case OPC_SHLL_S_PW:
16154 check_dsp(ctx);
16155 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
16156 break;
16157 case OPC_SHLLV_S_PW:
16158 check_dsp(ctx);
16159 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16160 break;
16161 case OPC_SHLL_OB:
16162 check_dsp(ctx);
16163 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
16164 break;
16165 case OPC_SHLLV_OB:
16166 check_dsp(ctx);
16167 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16168 break;
16169 case OPC_SHLL_QH:
16170 check_dsp(ctx);
16171 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
16172 break;
16173 case OPC_SHLLV_QH:
16174 check_dsp(ctx);
16175 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16176 break;
16177 case OPC_SHLL_S_QH:
16178 check_dsp(ctx);
16179 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
16180 break;
16181 case OPC_SHLLV_S_QH:
16182 check_dsp(ctx);
16183 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16184 break;
16185 case OPC_SHRA_OB:
16186 check_dspr2(ctx);
16187 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
16188 break;
16189 case OPC_SHRAV_OB:
16190 check_dspr2(ctx);
16191 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
16192 break;
16193 case OPC_SHRA_R_OB:
16194 check_dspr2(ctx);
16195 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
16196 break;
16197 case OPC_SHRAV_R_OB:
16198 check_dspr2(ctx);
16199 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
16200 break;
16201 case OPC_SHRA_PW:
16202 check_dsp(ctx);
16203 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
16204 break;
16205 case OPC_SHRAV_PW:
16206 check_dsp(ctx);
16207 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
16208 break;
16209 case OPC_SHRA_R_PW:
16210 check_dsp(ctx);
16211 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
16212 break;
16213 case OPC_SHRAV_R_PW:
16214 check_dsp(ctx);
16215 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
16216 break;
16217 case OPC_SHRA_QH:
16218 check_dsp(ctx);
16219 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
16220 break;
16221 case OPC_SHRAV_QH:
16222 check_dsp(ctx);
16223 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
16224 break;
16225 case OPC_SHRA_R_QH:
16226 check_dsp(ctx);
16227 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
16228 break;
16229 case OPC_SHRAV_R_QH:
16230 check_dsp(ctx);
16231 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
16232 break;
16233 case OPC_SHRL_OB:
16234 check_dsp(ctx);
16235 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
16236 break;
16237 case OPC_SHRLV_OB:
16238 check_dsp(ctx);
16239 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
16240 break;
16241 case OPC_SHRL_QH:
16242 check_dspr2(ctx);
16243 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
16244 break;
16245 case OPC_SHRLV_QH:
16246 check_dspr2(ctx);
16247 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
16248 break;
16249 default: /* Invalid */
16250 MIPS_INVAL("MASK SHLL.OB");
16251 generate_exception(ctx, EXCP_RI);
16252 break;
16254 break;
16255 #endif
16258 tcg_temp_free(t0);
16259 tcg_temp_free(v1_t);
16260 tcg_temp_free(v2_t);
16261 (void)opn; /* avoid a compiler warning */
16262 MIPS_DEBUG("%s", opn);
16265 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
16266 int ret, int v1, int v2, int check_ret)
16268 const char *opn = "mipsdsp multiply";
16269 TCGv_i32 t0;
16270 TCGv v1_t;
16271 TCGv v2_t;
16273 if ((ret == 0) && (check_ret == 1)) {
16274 /* Treat as NOP. */
16275 MIPS_DEBUG("NOP");
16276 return;
16279 t0 = tcg_temp_new_i32();
16280 v1_t = tcg_temp_new();
16281 v2_t = tcg_temp_new();
16283 tcg_gen_movi_i32(t0, ret);
16284 gen_load_gpr(v1_t, v1);
16285 gen_load_gpr(v2_t, v2);
16287 switch (op1) {
16288 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
16289 * the same mask and op1. */
16290 case OPC_MULT_G_2E:
16291 check_dspr2(ctx);
16292 switch (op2) {
16293 case OPC_MUL_PH:
16294 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16295 break;
16296 case OPC_MUL_S_PH:
16297 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16298 break;
16299 case OPC_MULQ_S_W:
16300 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16301 break;
16302 case OPC_MULQ_RS_W:
16303 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16304 break;
16306 break;
16307 case OPC_DPA_W_PH_DSP:
16308 switch (op2) {
16309 case OPC_DPAU_H_QBL:
16310 check_dsp(ctx);
16311 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
16312 break;
16313 case OPC_DPAU_H_QBR:
16314 check_dsp(ctx);
16315 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
16316 break;
16317 case OPC_DPSU_H_QBL:
16318 check_dsp(ctx);
16319 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
16320 break;
16321 case OPC_DPSU_H_QBR:
16322 check_dsp(ctx);
16323 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
16324 break;
16325 case OPC_DPA_W_PH:
16326 check_dspr2(ctx);
16327 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
16328 break;
16329 case OPC_DPAX_W_PH:
16330 check_dspr2(ctx);
16331 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
16332 break;
16333 case OPC_DPAQ_S_W_PH:
16334 check_dsp(ctx);
16335 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16336 break;
16337 case OPC_DPAQX_S_W_PH:
16338 check_dspr2(ctx);
16339 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16340 break;
16341 case OPC_DPAQX_SA_W_PH:
16342 check_dspr2(ctx);
16343 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16344 break;
16345 case OPC_DPS_W_PH:
16346 check_dspr2(ctx);
16347 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
16348 break;
16349 case OPC_DPSX_W_PH:
16350 check_dspr2(ctx);
16351 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
16352 break;
16353 case OPC_DPSQ_S_W_PH:
16354 check_dsp(ctx);
16355 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16356 break;
16357 case OPC_DPSQX_S_W_PH:
16358 check_dspr2(ctx);
16359 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16360 break;
16361 case OPC_DPSQX_SA_W_PH:
16362 check_dspr2(ctx);
16363 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16364 break;
16365 case OPC_MULSAQ_S_W_PH:
16366 check_dsp(ctx);
16367 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16368 break;
16369 case OPC_DPAQ_SA_L_W:
16370 check_dsp(ctx);
16371 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16372 break;
16373 case OPC_DPSQ_SA_L_W:
16374 check_dsp(ctx);
16375 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16376 break;
16377 case OPC_MAQ_S_W_PHL:
16378 check_dsp(ctx);
16379 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
16380 break;
16381 case OPC_MAQ_S_W_PHR:
16382 check_dsp(ctx);
16383 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
16384 break;
16385 case OPC_MAQ_SA_W_PHL:
16386 check_dsp(ctx);
16387 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
16388 break;
16389 case OPC_MAQ_SA_W_PHR:
16390 check_dsp(ctx);
16391 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
16392 break;
16393 case OPC_MULSA_W_PH:
16394 check_dspr2(ctx);
16395 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
16396 break;
16398 break;
16399 #ifdef TARGET_MIPS64
16400 case OPC_DPAQ_W_QH_DSP:
16402 int ac = ret & 0x03;
16403 tcg_gen_movi_i32(t0, ac);
16405 switch (op2) {
16406 case OPC_DMADD:
16407 check_dsp(ctx);
16408 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
16409 break;
16410 case OPC_DMADDU:
16411 check_dsp(ctx);
16412 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
16413 break;
16414 case OPC_DMSUB:
16415 check_dsp(ctx);
16416 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
16417 break;
16418 case OPC_DMSUBU:
16419 check_dsp(ctx);
16420 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
16421 break;
16422 case OPC_DPA_W_QH:
16423 check_dspr2(ctx);
16424 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
16425 break;
16426 case OPC_DPAQ_S_W_QH:
16427 check_dsp(ctx);
16428 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16429 break;
16430 case OPC_DPAQ_SA_L_PW:
16431 check_dsp(ctx);
16432 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16433 break;
16434 case OPC_DPAU_H_OBL:
16435 check_dsp(ctx);
16436 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
16437 break;
16438 case OPC_DPAU_H_OBR:
16439 check_dsp(ctx);
16440 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
16441 break;
16442 case OPC_DPS_W_QH:
16443 check_dspr2(ctx);
16444 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
16445 break;
16446 case OPC_DPSQ_S_W_QH:
16447 check_dsp(ctx);
16448 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16449 break;
16450 case OPC_DPSQ_SA_L_PW:
16451 check_dsp(ctx);
16452 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16453 break;
16454 case OPC_DPSU_H_OBL:
16455 check_dsp(ctx);
16456 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
16457 break;
16458 case OPC_DPSU_H_OBR:
16459 check_dsp(ctx);
16460 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
16461 break;
16462 case OPC_MAQ_S_L_PWL:
16463 check_dsp(ctx);
16464 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
16465 break;
16466 case OPC_MAQ_S_L_PWR:
16467 check_dsp(ctx);
16468 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
16469 break;
16470 case OPC_MAQ_S_W_QHLL:
16471 check_dsp(ctx);
16472 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
16473 break;
16474 case OPC_MAQ_SA_W_QHLL:
16475 check_dsp(ctx);
16476 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
16477 break;
16478 case OPC_MAQ_S_W_QHLR:
16479 check_dsp(ctx);
16480 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
16481 break;
16482 case OPC_MAQ_SA_W_QHLR:
16483 check_dsp(ctx);
16484 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
16485 break;
16486 case OPC_MAQ_S_W_QHRL:
16487 check_dsp(ctx);
16488 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
16489 break;
16490 case OPC_MAQ_SA_W_QHRL:
16491 check_dsp(ctx);
16492 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
16493 break;
16494 case OPC_MAQ_S_W_QHRR:
16495 check_dsp(ctx);
16496 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
16497 break;
16498 case OPC_MAQ_SA_W_QHRR:
16499 check_dsp(ctx);
16500 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
16501 break;
16502 case OPC_MULSAQ_S_L_PW:
16503 check_dsp(ctx);
16504 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
16505 break;
16506 case OPC_MULSAQ_S_W_QH:
16507 check_dsp(ctx);
16508 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16509 break;
16512 break;
16513 #endif
16514 case OPC_ADDU_QB_DSP:
16515 switch (op2) {
16516 case OPC_MULEU_S_PH_QBL:
16517 check_dsp(ctx);
16518 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16519 break;
16520 case OPC_MULEU_S_PH_QBR:
16521 check_dsp(ctx);
16522 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16523 break;
16524 case OPC_MULQ_RS_PH:
16525 check_dsp(ctx);
16526 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16527 break;
16528 case OPC_MULEQ_S_W_PHL:
16529 check_dsp(ctx);
16530 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16531 break;
16532 case OPC_MULEQ_S_W_PHR:
16533 check_dsp(ctx);
16534 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16535 break;
16536 case OPC_MULQ_S_PH:
16537 check_dspr2(ctx);
16538 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16539 break;
16541 break;
16542 #ifdef TARGET_MIPS64
16543 case OPC_ADDU_OB_DSP:
16544 switch (op2) {
16545 case OPC_MULEQ_S_PW_QHL:
16546 check_dsp(ctx);
16547 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16548 break;
16549 case OPC_MULEQ_S_PW_QHR:
16550 check_dsp(ctx);
16551 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16552 break;
16553 case OPC_MULEU_S_QH_OBL:
16554 check_dsp(ctx);
16555 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16556 break;
16557 case OPC_MULEU_S_QH_OBR:
16558 check_dsp(ctx);
16559 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16560 break;
16561 case OPC_MULQ_RS_QH:
16562 check_dsp(ctx);
16563 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16564 break;
16566 break;
16567 #endif
16570 tcg_temp_free_i32(t0);
16571 tcg_temp_free(v1_t);
16572 tcg_temp_free(v2_t);
16574 (void)opn; /* avoid a compiler warning */
16575 MIPS_DEBUG("%s", opn);
16579 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16580 int ret, int val)
16582 const char *opn = "mipsdsp Bit/ Manipulation";
16583 int16_t imm;
16584 TCGv t0;
16585 TCGv val_t;
16587 if (ret == 0) {
16588 /* Treat as NOP. */
16589 MIPS_DEBUG("NOP");
16590 return;
16593 t0 = tcg_temp_new();
16594 val_t = tcg_temp_new();
16595 gen_load_gpr(val_t, val);
16597 switch (op1) {
16598 case OPC_ABSQ_S_PH_DSP:
16599 switch (op2) {
16600 case OPC_BITREV:
16601 check_dsp(ctx);
16602 gen_helper_bitrev(cpu_gpr[ret], val_t);
16603 break;
16604 case OPC_REPL_QB:
16605 check_dsp(ctx);
16607 target_long result;
16608 imm = (ctx->opcode >> 16) & 0xFF;
16609 result = (uint32_t)imm << 24 |
16610 (uint32_t)imm << 16 |
16611 (uint32_t)imm << 8 |
16612 (uint32_t)imm;
16613 result = (int32_t)result;
16614 tcg_gen_movi_tl(cpu_gpr[ret], result);
16616 break;
16617 case OPC_REPLV_QB:
16618 check_dsp(ctx);
16619 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16620 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16621 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16622 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16623 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16624 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16625 break;
16626 case OPC_REPL_PH:
16627 check_dsp(ctx);
16629 imm = (ctx->opcode >> 16) & 0x03FF;
16630 imm = (int16_t)(imm << 6) >> 6;
16631 tcg_gen_movi_tl(cpu_gpr[ret], \
16632 (target_long)((int32_t)imm << 16 | \
16633 (uint16_t)imm));
16635 break;
16636 case OPC_REPLV_PH:
16637 check_dsp(ctx);
16638 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16639 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16640 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16641 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16642 break;
16644 break;
16645 #ifdef TARGET_MIPS64
16646 case OPC_ABSQ_S_QH_DSP:
16647 switch (op2) {
16648 case OPC_REPL_OB:
16649 check_dsp(ctx);
16651 target_long temp;
16653 imm = (ctx->opcode >> 16) & 0xFF;
16654 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
16655 temp = (temp << 16) | temp;
16656 temp = (temp << 32) | temp;
16657 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16658 break;
16660 case OPC_REPL_PW:
16661 check_dsp(ctx);
16663 target_long temp;
16665 imm = (ctx->opcode >> 16) & 0x03FF;
16666 imm = (int16_t)(imm << 6) >> 6;
16667 temp = ((target_long)imm << 32) \
16668 | ((target_long)imm & 0xFFFFFFFF);
16669 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16670 break;
16672 case OPC_REPL_QH:
16673 check_dsp(ctx);
16675 target_long temp;
16677 imm = (ctx->opcode >> 16) & 0x03FF;
16678 imm = (int16_t)(imm << 6) >> 6;
16680 temp = ((uint64_t)(uint16_t)imm << 48) |
16681 ((uint64_t)(uint16_t)imm << 32) |
16682 ((uint64_t)(uint16_t)imm << 16) |
16683 (uint64_t)(uint16_t)imm;
16684 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16685 break;
16687 case OPC_REPLV_OB:
16688 check_dsp(ctx);
16689 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16690 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16691 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16692 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16693 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16694 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16695 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16696 break;
16697 case OPC_REPLV_PW:
16698 check_dsp(ctx);
16699 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
16700 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16701 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16702 break;
16703 case OPC_REPLV_QH:
16704 check_dsp(ctx);
16705 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16706 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16707 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16708 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16709 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16710 break;
16712 break;
16713 #endif
16715 tcg_temp_free(t0);
16716 tcg_temp_free(val_t);
16718 (void)opn; /* avoid a compiler warning */
16719 MIPS_DEBUG("%s", opn);
16722 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
16723 uint32_t op1, uint32_t op2,
16724 int ret, int v1, int v2, int check_ret)
16726 const char *opn = "mipsdsp add compare pick";
16727 TCGv t1;
16728 TCGv v1_t;
16729 TCGv v2_t;
16731 if ((ret == 0) && (check_ret == 1)) {
16732 /* Treat as NOP. */
16733 MIPS_DEBUG("NOP");
16734 return;
16737 t1 = tcg_temp_new();
16738 v1_t = tcg_temp_new();
16739 v2_t = tcg_temp_new();
16741 gen_load_gpr(v1_t, v1);
16742 gen_load_gpr(v2_t, v2);
16744 switch (op1) {
16745 case OPC_CMPU_EQ_QB_DSP:
16746 switch (op2) {
16747 case OPC_CMPU_EQ_QB:
16748 check_dsp(ctx);
16749 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
16750 break;
16751 case OPC_CMPU_LT_QB:
16752 check_dsp(ctx);
16753 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
16754 break;
16755 case OPC_CMPU_LE_QB:
16756 check_dsp(ctx);
16757 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
16758 break;
16759 case OPC_CMPGU_EQ_QB:
16760 check_dsp(ctx);
16761 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
16762 break;
16763 case OPC_CMPGU_LT_QB:
16764 check_dsp(ctx);
16765 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
16766 break;
16767 case OPC_CMPGU_LE_QB:
16768 check_dsp(ctx);
16769 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
16770 break;
16771 case OPC_CMPGDU_EQ_QB:
16772 check_dspr2(ctx);
16773 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
16774 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16775 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16776 tcg_gen_shli_tl(t1, t1, 24);
16777 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16778 break;
16779 case OPC_CMPGDU_LT_QB:
16780 check_dspr2(ctx);
16781 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
16782 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16783 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16784 tcg_gen_shli_tl(t1, t1, 24);
16785 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16786 break;
16787 case OPC_CMPGDU_LE_QB:
16788 check_dspr2(ctx);
16789 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
16790 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16791 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16792 tcg_gen_shli_tl(t1, t1, 24);
16793 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16794 break;
16795 case OPC_CMP_EQ_PH:
16796 check_dsp(ctx);
16797 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
16798 break;
16799 case OPC_CMP_LT_PH:
16800 check_dsp(ctx);
16801 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
16802 break;
16803 case OPC_CMP_LE_PH:
16804 check_dsp(ctx);
16805 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
16806 break;
16807 case OPC_PICK_QB:
16808 check_dsp(ctx);
16809 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16810 break;
16811 case OPC_PICK_PH:
16812 check_dsp(ctx);
16813 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16814 break;
16815 case OPC_PACKRL_PH:
16816 check_dsp(ctx);
16817 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
16818 break;
16820 break;
16821 #ifdef TARGET_MIPS64
16822 case OPC_CMPU_EQ_OB_DSP:
16823 switch (op2) {
16824 case OPC_CMP_EQ_PW:
16825 check_dsp(ctx);
16826 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
16827 break;
16828 case OPC_CMP_LT_PW:
16829 check_dsp(ctx);
16830 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
16831 break;
16832 case OPC_CMP_LE_PW:
16833 check_dsp(ctx);
16834 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
16835 break;
16836 case OPC_CMP_EQ_QH:
16837 check_dsp(ctx);
16838 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
16839 break;
16840 case OPC_CMP_LT_QH:
16841 check_dsp(ctx);
16842 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
16843 break;
16844 case OPC_CMP_LE_QH:
16845 check_dsp(ctx);
16846 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
16847 break;
16848 case OPC_CMPGDU_EQ_OB:
16849 check_dspr2(ctx);
16850 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16851 break;
16852 case OPC_CMPGDU_LT_OB:
16853 check_dspr2(ctx);
16854 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16855 break;
16856 case OPC_CMPGDU_LE_OB:
16857 check_dspr2(ctx);
16858 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16859 break;
16860 case OPC_CMPGU_EQ_OB:
16861 check_dsp(ctx);
16862 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
16863 break;
16864 case OPC_CMPGU_LT_OB:
16865 check_dsp(ctx);
16866 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
16867 break;
16868 case OPC_CMPGU_LE_OB:
16869 check_dsp(ctx);
16870 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
16871 break;
16872 case OPC_CMPU_EQ_OB:
16873 check_dsp(ctx);
16874 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
16875 break;
16876 case OPC_CMPU_LT_OB:
16877 check_dsp(ctx);
16878 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
16879 break;
16880 case OPC_CMPU_LE_OB:
16881 check_dsp(ctx);
16882 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
16883 break;
16884 case OPC_PACKRL_PW:
16885 check_dsp(ctx);
16886 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
16887 break;
16888 case OPC_PICK_OB:
16889 check_dsp(ctx);
16890 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16891 break;
16892 case OPC_PICK_PW:
16893 check_dsp(ctx);
16894 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16895 break;
16896 case OPC_PICK_QH:
16897 check_dsp(ctx);
16898 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16899 break;
16901 break;
16902 #endif
16905 tcg_temp_free(t1);
16906 tcg_temp_free(v1_t);
16907 tcg_temp_free(v2_t);
16909 (void)opn; /* avoid a compiler warning */
16910 MIPS_DEBUG("%s", opn);
16913 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
16914 uint32_t op1, int rt, int rs, int sa)
16916 const char *opn = "mipsdsp append/dappend";
16917 TCGv t0;
16919 check_dspr2(ctx);
16921 if (rt == 0) {
16922 /* Treat as NOP. */
16923 MIPS_DEBUG("NOP");
16924 return;
16927 t0 = tcg_temp_new();
16928 gen_load_gpr(t0, rs);
16930 switch (op1) {
16931 case OPC_APPEND_DSP:
16932 switch (MASK_APPEND(ctx->opcode)) {
16933 case OPC_APPEND:
16934 if (sa != 0) {
16935 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
16937 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16938 break;
16939 case OPC_PREPEND:
16940 if (sa != 0) {
16941 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
16942 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16943 tcg_gen_shli_tl(t0, t0, 32 - sa);
16944 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16946 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16947 break;
16948 case OPC_BALIGN:
16949 sa &= 3;
16950 if (sa != 0 && sa != 2) {
16951 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16952 tcg_gen_ext32u_tl(t0, t0);
16953 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
16954 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16956 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16957 break;
16958 default: /* Invalid */
16959 MIPS_INVAL("MASK APPEND");
16960 generate_exception(ctx, EXCP_RI);
16961 break;
16963 break;
16964 #ifdef TARGET_MIPS64
16965 case OPC_DAPPEND_DSP:
16966 switch (MASK_DAPPEND(ctx->opcode)) {
16967 case OPC_DAPPEND:
16968 if (sa != 0) {
16969 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
16971 break;
16972 case OPC_PREPENDD:
16973 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
16974 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
16975 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
16976 break;
16977 case OPC_PREPENDW:
16978 if (sa != 0) {
16979 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16980 tcg_gen_shli_tl(t0, t0, 64 - sa);
16981 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16983 break;
16984 case OPC_DBALIGN:
16985 sa &= 7;
16986 if (sa != 0 && sa != 2 && sa != 4) {
16987 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16988 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
16989 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16991 break;
16992 default: /* Invalid */
16993 MIPS_INVAL("MASK DAPPEND");
16994 generate_exception(ctx, EXCP_RI);
16995 break;
16997 break;
16998 #endif
17000 tcg_temp_free(t0);
17001 (void)opn; /* avoid a compiler warning */
17002 MIPS_DEBUG("%s", opn);
17005 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
17006 int ret, int v1, int v2, int check_ret)
17009 const char *opn = "mipsdsp accumulator";
17010 TCGv t0;
17011 TCGv t1;
17012 TCGv v1_t;
17013 TCGv v2_t;
17014 int16_t imm;
17016 if ((ret == 0) && (check_ret == 1)) {
17017 /* Treat as NOP. */
17018 MIPS_DEBUG("NOP");
17019 return;
17022 t0 = tcg_temp_new();
17023 t1 = tcg_temp_new();
17024 v1_t = tcg_temp_new();
17025 v2_t = tcg_temp_new();
17027 gen_load_gpr(v1_t, v1);
17028 gen_load_gpr(v2_t, v2);
17030 switch (op1) {
17031 case OPC_EXTR_W_DSP:
17032 check_dsp(ctx);
17033 switch (op2) {
17034 case OPC_EXTR_W:
17035 tcg_gen_movi_tl(t0, v2);
17036 tcg_gen_movi_tl(t1, v1);
17037 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
17038 break;
17039 case OPC_EXTR_R_W:
17040 tcg_gen_movi_tl(t0, v2);
17041 tcg_gen_movi_tl(t1, v1);
17042 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
17043 break;
17044 case OPC_EXTR_RS_W:
17045 tcg_gen_movi_tl(t0, v2);
17046 tcg_gen_movi_tl(t1, v1);
17047 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
17048 break;
17049 case OPC_EXTR_S_H:
17050 tcg_gen_movi_tl(t0, v2);
17051 tcg_gen_movi_tl(t1, v1);
17052 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17053 break;
17054 case OPC_EXTRV_S_H:
17055 tcg_gen_movi_tl(t0, v2);
17056 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
17057 break;
17058 case OPC_EXTRV_W:
17059 tcg_gen_movi_tl(t0, v2);
17060 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17061 break;
17062 case OPC_EXTRV_R_W:
17063 tcg_gen_movi_tl(t0, v2);
17064 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17065 break;
17066 case OPC_EXTRV_RS_W:
17067 tcg_gen_movi_tl(t0, v2);
17068 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17069 break;
17070 case OPC_EXTP:
17071 tcg_gen_movi_tl(t0, v2);
17072 tcg_gen_movi_tl(t1, v1);
17073 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
17074 break;
17075 case OPC_EXTPV:
17076 tcg_gen_movi_tl(t0, v2);
17077 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
17078 break;
17079 case OPC_EXTPDP:
17080 tcg_gen_movi_tl(t0, v2);
17081 tcg_gen_movi_tl(t1, v1);
17082 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
17083 break;
17084 case OPC_EXTPDPV:
17085 tcg_gen_movi_tl(t0, v2);
17086 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
17087 break;
17088 case OPC_SHILO:
17089 imm = (ctx->opcode >> 20) & 0x3F;
17090 tcg_gen_movi_tl(t0, ret);
17091 tcg_gen_movi_tl(t1, imm);
17092 gen_helper_shilo(t0, t1, cpu_env);
17093 break;
17094 case OPC_SHILOV:
17095 tcg_gen_movi_tl(t0, ret);
17096 gen_helper_shilo(t0, v1_t, cpu_env);
17097 break;
17098 case OPC_MTHLIP:
17099 tcg_gen_movi_tl(t0, ret);
17100 gen_helper_mthlip(t0, v1_t, cpu_env);
17101 break;
17102 case OPC_WRDSP:
17103 imm = (ctx->opcode >> 11) & 0x3FF;
17104 tcg_gen_movi_tl(t0, imm);
17105 gen_helper_wrdsp(v1_t, t0, cpu_env);
17106 break;
17107 case OPC_RDDSP:
17108 imm = (ctx->opcode >> 16) & 0x03FF;
17109 tcg_gen_movi_tl(t0, imm);
17110 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
17111 break;
17113 break;
17114 #ifdef TARGET_MIPS64
17115 case OPC_DEXTR_W_DSP:
17116 check_dsp(ctx);
17117 switch (op2) {
17118 case OPC_DMTHLIP:
17119 tcg_gen_movi_tl(t0, ret);
17120 gen_helper_dmthlip(v1_t, t0, cpu_env);
17121 break;
17122 case OPC_DSHILO:
17124 int shift = (ctx->opcode >> 19) & 0x7F;
17125 int ac = (ctx->opcode >> 11) & 0x03;
17126 tcg_gen_movi_tl(t0, shift);
17127 tcg_gen_movi_tl(t1, ac);
17128 gen_helper_dshilo(t0, t1, cpu_env);
17129 break;
17131 case OPC_DSHILOV:
17133 int ac = (ctx->opcode >> 11) & 0x03;
17134 tcg_gen_movi_tl(t0, ac);
17135 gen_helper_dshilo(v1_t, t0, cpu_env);
17136 break;
17138 case OPC_DEXTP:
17139 tcg_gen_movi_tl(t0, v2);
17140 tcg_gen_movi_tl(t1, v1);
17142 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
17143 break;
17144 case OPC_DEXTPV:
17145 tcg_gen_movi_tl(t0, v2);
17146 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
17147 break;
17148 case OPC_DEXTPDP:
17149 tcg_gen_movi_tl(t0, v2);
17150 tcg_gen_movi_tl(t1, v1);
17151 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
17152 break;
17153 case OPC_DEXTPDPV:
17154 tcg_gen_movi_tl(t0, v2);
17155 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
17156 break;
17157 case OPC_DEXTR_L:
17158 tcg_gen_movi_tl(t0, v2);
17159 tcg_gen_movi_tl(t1, v1);
17160 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
17161 break;
17162 case OPC_DEXTR_R_L:
17163 tcg_gen_movi_tl(t0, v2);
17164 tcg_gen_movi_tl(t1, v1);
17165 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
17166 break;
17167 case OPC_DEXTR_RS_L:
17168 tcg_gen_movi_tl(t0, v2);
17169 tcg_gen_movi_tl(t1, v1);
17170 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
17171 break;
17172 case OPC_DEXTR_W:
17173 tcg_gen_movi_tl(t0, v2);
17174 tcg_gen_movi_tl(t1, v1);
17175 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
17176 break;
17177 case OPC_DEXTR_R_W:
17178 tcg_gen_movi_tl(t0, v2);
17179 tcg_gen_movi_tl(t1, v1);
17180 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
17181 break;
17182 case OPC_DEXTR_RS_W:
17183 tcg_gen_movi_tl(t0, v2);
17184 tcg_gen_movi_tl(t1, v1);
17185 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
17186 break;
17187 case OPC_DEXTR_S_H:
17188 tcg_gen_movi_tl(t0, v2);
17189 tcg_gen_movi_tl(t1, v1);
17190 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17191 break;
17192 case OPC_DEXTRV_S_H:
17193 tcg_gen_movi_tl(t0, v2);
17194 tcg_gen_movi_tl(t1, v1);
17195 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17196 break;
17197 case OPC_DEXTRV_L:
17198 tcg_gen_movi_tl(t0, v2);
17199 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17200 break;
17201 case OPC_DEXTRV_R_L:
17202 tcg_gen_movi_tl(t0, v2);
17203 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17204 break;
17205 case OPC_DEXTRV_RS_L:
17206 tcg_gen_movi_tl(t0, v2);
17207 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17208 break;
17209 case OPC_DEXTRV_W:
17210 tcg_gen_movi_tl(t0, v2);
17211 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17212 break;
17213 case OPC_DEXTRV_R_W:
17214 tcg_gen_movi_tl(t0, v2);
17215 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17216 break;
17217 case OPC_DEXTRV_RS_W:
17218 tcg_gen_movi_tl(t0, v2);
17219 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17220 break;
17222 break;
17223 #endif
17226 tcg_temp_free(t0);
17227 tcg_temp_free(t1);
17228 tcg_temp_free(v1_t);
17229 tcg_temp_free(v2_t);
17231 (void)opn; /* avoid a compiler warning */
17232 MIPS_DEBUG("%s", opn);
17235 /* End MIPSDSP functions. */
17237 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
17239 int rs, rt, rd, sa;
17240 uint32_t op1, op2;
17242 rs = (ctx->opcode >> 21) & 0x1f;
17243 rt = (ctx->opcode >> 16) & 0x1f;
17244 rd = (ctx->opcode >> 11) & 0x1f;
17245 sa = (ctx->opcode >> 6) & 0x1f;
17247 op1 = MASK_SPECIAL(ctx->opcode);
17248 switch (op1) {
17249 case OPC_LSA:
17250 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
17251 break;
17252 case OPC_MULT ... OPC_DIVU:
17253 op2 = MASK_R6_MULDIV(ctx->opcode);
17254 switch (op2) {
17255 case R6_OPC_MUL:
17256 case R6_OPC_MUH:
17257 case R6_OPC_MULU:
17258 case R6_OPC_MUHU:
17259 case R6_OPC_DIV:
17260 case R6_OPC_MOD:
17261 case R6_OPC_DIVU:
17262 case R6_OPC_MODU:
17263 gen_r6_muldiv(ctx, op2, rd, rs, rt);
17264 break;
17265 default:
17266 MIPS_INVAL("special_r6 muldiv");
17267 generate_exception(ctx, EXCP_RI);
17268 break;
17270 break;
17271 case OPC_SELEQZ:
17272 case OPC_SELNEZ:
17273 gen_cond_move(ctx, op1, rd, rs, rt);
17274 break;
17275 case R6_OPC_CLO:
17276 case R6_OPC_CLZ:
17277 if (rt == 0 && sa == 1) {
17278 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17279 We need additionally to check other fields */
17280 gen_cl(ctx, op1, rd, rs);
17281 } else {
17282 generate_exception(ctx, EXCP_RI);
17284 break;
17285 case R6_OPC_SDBBP:
17286 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17287 gen_helper_do_semihosting(cpu_env);
17288 } else {
17289 if (ctx->hflags & MIPS_HFLAG_SBRI) {
17290 generate_exception(ctx, EXCP_RI);
17291 } else {
17292 generate_exception(ctx, EXCP_DBp);
17295 break;
17296 #if defined(TARGET_MIPS64)
17297 case OPC_DLSA:
17298 check_mips_64(ctx);
17299 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
17300 break;
17301 case R6_OPC_DCLO:
17302 case R6_OPC_DCLZ:
17303 if (rt == 0 && sa == 1) {
17304 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17305 We need additionally to check other fields */
17306 check_mips_64(ctx);
17307 gen_cl(ctx, op1, rd, rs);
17308 } else {
17309 generate_exception(ctx, EXCP_RI);
17311 break;
17312 case OPC_DMULT ... OPC_DDIVU:
17313 op2 = MASK_R6_MULDIV(ctx->opcode);
17314 switch (op2) {
17315 case R6_OPC_DMUL:
17316 case R6_OPC_DMUH:
17317 case R6_OPC_DMULU:
17318 case R6_OPC_DMUHU:
17319 case R6_OPC_DDIV:
17320 case R6_OPC_DMOD:
17321 case R6_OPC_DDIVU:
17322 case R6_OPC_DMODU:
17323 check_mips_64(ctx);
17324 gen_r6_muldiv(ctx, op2, rd, rs, rt);
17325 break;
17326 default:
17327 MIPS_INVAL("special_r6 muldiv");
17328 generate_exception(ctx, EXCP_RI);
17329 break;
17331 break;
17332 #endif
17333 default: /* Invalid */
17334 MIPS_INVAL("special_r6");
17335 generate_exception(ctx, EXCP_RI);
17336 break;
17340 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
17342 int rs, rt, rd, sa;
17343 uint32_t op1;
17345 rs = (ctx->opcode >> 21) & 0x1f;
17346 rt = (ctx->opcode >> 16) & 0x1f;
17347 rd = (ctx->opcode >> 11) & 0x1f;
17348 sa = (ctx->opcode >> 6) & 0x1f;
17350 op1 = MASK_SPECIAL(ctx->opcode);
17351 switch (op1) {
17352 case OPC_MOVN: /* Conditional move */
17353 case OPC_MOVZ:
17354 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
17355 INSN_LOONGSON2E | INSN_LOONGSON2F);
17356 gen_cond_move(ctx, op1, rd, rs, rt);
17357 break;
17358 case OPC_MFHI: /* Move from HI/LO */
17359 case OPC_MFLO:
17360 gen_HILO(ctx, op1, rs & 3, rd);
17361 break;
17362 case OPC_MTHI:
17363 case OPC_MTLO: /* Move to HI/LO */
17364 gen_HILO(ctx, op1, rd & 3, rs);
17365 break;
17366 case OPC_MOVCI:
17367 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
17368 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17369 check_cp1_enabled(ctx);
17370 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
17371 (ctx->opcode >> 16) & 1);
17372 } else {
17373 generate_exception_err(ctx, EXCP_CpU, 1);
17375 break;
17376 case OPC_MULT:
17377 case OPC_MULTU:
17378 if (sa) {
17379 check_insn(ctx, INSN_VR54XX);
17380 op1 = MASK_MUL_VR54XX(ctx->opcode);
17381 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
17382 } else {
17383 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17385 break;
17386 case OPC_DIV:
17387 case OPC_DIVU:
17388 gen_muldiv(ctx, op1, 0, rs, rt);
17389 break;
17390 #if defined(TARGET_MIPS64)
17391 case OPC_DMULT ... OPC_DDIVU:
17392 check_insn(ctx, ISA_MIPS3);
17393 check_mips_64(ctx);
17394 gen_muldiv(ctx, op1, 0, rs, rt);
17395 break;
17396 #endif
17397 case OPC_JR:
17398 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17399 break;
17400 case OPC_SPIM:
17401 #ifdef MIPS_STRICT_STANDARD
17402 MIPS_INVAL("SPIM");
17403 generate_exception(ctx, EXCP_RI);
17404 #else
17405 /* Implemented as RI exception for now. */
17406 MIPS_INVAL("spim (unofficial)");
17407 generate_exception(ctx, EXCP_RI);
17408 #endif
17409 break;
17410 default: /* Invalid */
17411 MIPS_INVAL("special_legacy");
17412 generate_exception(ctx, EXCP_RI);
17413 break;
17417 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
17419 int rs, rt, rd, sa;
17420 uint32_t op1;
17422 rs = (ctx->opcode >> 21) & 0x1f;
17423 rt = (ctx->opcode >> 16) & 0x1f;
17424 rd = (ctx->opcode >> 11) & 0x1f;
17425 sa = (ctx->opcode >> 6) & 0x1f;
17427 op1 = MASK_SPECIAL(ctx->opcode);
17428 switch (op1) {
17429 case OPC_SLL: /* Shift with immediate */
17430 if (sa == 5 && rd == 0 &&
17431 rs == 0 && rt == 0) { /* PAUSE */
17432 if ((ctx->insn_flags & ISA_MIPS32R6) &&
17433 (ctx->hflags & MIPS_HFLAG_BMASK)) {
17434 MIPS_DEBUG("CTI in delay / forbidden slot");
17435 generate_exception(ctx, EXCP_RI);
17436 break;
17439 /* Fallthrough */
17440 case OPC_SRA:
17441 gen_shift_imm(ctx, op1, rd, rt, sa);
17442 break;
17443 case OPC_SRL:
17444 switch ((ctx->opcode >> 21) & 0x1f) {
17445 case 1:
17446 /* rotr is decoded as srl on non-R2 CPUs */
17447 if (ctx->insn_flags & ISA_MIPS32R2) {
17448 op1 = OPC_ROTR;
17450 /* Fallthrough */
17451 case 0:
17452 gen_shift_imm(ctx, op1, rd, rt, sa);
17453 break;
17454 default:
17455 generate_exception(ctx, EXCP_RI);
17456 break;
17458 break;
17459 case OPC_ADD ... OPC_SUBU:
17460 gen_arith(ctx, op1, rd, rs, rt);
17461 break;
17462 case OPC_SLLV: /* Shifts */
17463 case OPC_SRAV:
17464 gen_shift(ctx, op1, rd, rs, rt);
17465 break;
17466 case OPC_SRLV:
17467 switch ((ctx->opcode >> 6) & 0x1f) {
17468 case 1:
17469 /* rotrv is decoded as srlv on non-R2 CPUs */
17470 if (ctx->insn_flags & ISA_MIPS32R2) {
17471 op1 = OPC_ROTRV;
17473 /* Fallthrough */
17474 case 0:
17475 gen_shift(ctx, op1, rd, rs, rt);
17476 break;
17477 default:
17478 generate_exception(ctx, EXCP_RI);
17479 break;
17481 break;
17482 case OPC_SLT: /* Set on less than */
17483 case OPC_SLTU:
17484 gen_slt(ctx, op1, rd, rs, rt);
17485 break;
17486 case OPC_AND: /* Logic*/
17487 case OPC_OR:
17488 case OPC_NOR:
17489 case OPC_XOR:
17490 gen_logic(ctx, op1, rd, rs, rt);
17491 break;
17492 case OPC_JALR:
17493 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17494 break;
17495 case OPC_TGE ... OPC_TEQ: /* Traps */
17496 case OPC_TNE:
17497 check_insn(ctx, ISA_MIPS2);
17498 gen_trap(ctx, op1, rs, rt, -1);
17499 break;
17500 case OPC_LSA: /* OPC_PMON */
17501 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17502 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17503 decode_opc_special_r6(env, ctx);
17504 } else {
17505 /* Pmon entry point, also R4010 selsl */
17506 #ifdef MIPS_STRICT_STANDARD
17507 MIPS_INVAL("PMON / selsl");
17508 generate_exception(ctx, EXCP_RI);
17509 #else
17510 gen_helper_0e0i(pmon, sa);
17511 #endif
17513 break;
17514 case OPC_SYSCALL:
17515 generate_exception(ctx, EXCP_SYSCALL);
17516 ctx->bstate = BS_STOP;
17517 break;
17518 case OPC_BREAK:
17519 generate_exception(ctx, EXCP_BREAK);
17520 break;
17521 case OPC_SYNC:
17522 check_insn(ctx, ISA_MIPS2);
17523 /* Treat as NOP. */
17524 break;
17526 #if defined(TARGET_MIPS64)
17527 /* MIPS64 specific opcodes */
17528 case OPC_DSLL:
17529 case OPC_DSRA:
17530 case OPC_DSLL32:
17531 case OPC_DSRA32:
17532 check_insn(ctx, ISA_MIPS3);
17533 check_mips_64(ctx);
17534 gen_shift_imm(ctx, op1, rd, rt, sa);
17535 break;
17536 case OPC_DSRL:
17537 switch ((ctx->opcode >> 21) & 0x1f) {
17538 case 1:
17539 /* drotr is decoded as dsrl on non-R2 CPUs */
17540 if (ctx->insn_flags & ISA_MIPS32R2) {
17541 op1 = OPC_DROTR;
17543 /* Fallthrough */
17544 case 0:
17545 check_insn(ctx, ISA_MIPS3);
17546 check_mips_64(ctx);
17547 gen_shift_imm(ctx, op1, rd, rt, sa);
17548 break;
17549 default:
17550 generate_exception(ctx, EXCP_RI);
17551 break;
17553 break;
17554 case OPC_DSRL32:
17555 switch ((ctx->opcode >> 21) & 0x1f) {
17556 case 1:
17557 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
17558 if (ctx->insn_flags & ISA_MIPS32R2) {
17559 op1 = OPC_DROTR32;
17561 /* Fallthrough */
17562 case 0:
17563 check_insn(ctx, ISA_MIPS3);
17564 check_mips_64(ctx);
17565 gen_shift_imm(ctx, op1, rd, rt, sa);
17566 break;
17567 default:
17568 generate_exception(ctx, EXCP_RI);
17569 break;
17571 break;
17572 case OPC_DADD ... OPC_DSUBU:
17573 check_insn(ctx, ISA_MIPS3);
17574 check_mips_64(ctx);
17575 gen_arith(ctx, op1, rd, rs, rt);
17576 break;
17577 case OPC_DSLLV:
17578 case OPC_DSRAV:
17579 check_insn(ctx, ISA_MIPS3);
17580 check_mips_64(ctx);
17581 gen_shift(ctx, op1, rd, rs, rt);
17582 break;
17583 case OPC_DSRLV:
17584 switch ((ctx->opcode >> 6) & 0x1f) {
17585 case 1:
17586 /* drotrv is decoded as dsrlv on non-R2 CPUs */
17587 if (ctx->insn_flags & ISA_MIPS32R2) {
17588 op1 = OPC_DROTRV;
17590 /* Fallthrough */
17591 case 0:
17592 check_insn(ctx, ISA_MIPS3);
17593 check_mips_64(ctx);
17594 gen_shift(ctx, op1, rd, rs, rt);
17595 break;
17596 default:
17597 generate_exception(ctx, EXCP_RI);
17598 break;
17600 break;
17601 case OPC_DLSA:
17602 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17603 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17604 decode_opc_special_r6(env, ctx);
17606 break;
17607 #endif
17608 default:
17609 if (ctx->insn_flags & ISA_MIPS32R6) {
17610 decode_opc_special_r6(env, ctx);
17611 } else {
17612 decode_opc_special_legacy(env, ctx);
17617 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
17619 int rs, rt, rd;
17620 uint32_t op1;
17622 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17624 rs = (ctx->opcode >> 21) & 0x1f;
17625 rt = (ctx->opcode >> 16) & 0x1f;
17626 rd = (ctx->opcode >> 11) & 0x1f;
17628 op1 = MASK_SPECIAL2(ctx->opcode);
17629 switch (op1) {
17630 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
17631 case OPC_MSUB ... OPC_MSUBU:
17632 check_insn(ctx, ISA_MIPS32);
17633 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17634 break;
17635 case OPC_MUL:
17636 gen_arith(ctx, op1, rd, rs, rt);
17637 break;
17638 case OPC_DIV_G_2F:
17639 case OPC_DIVU_G_2F:
17640 case OPC_MULT_G_2F:
17641 case OPC_MULTU_G_2F:
17642 case OPC_MOD_G_2F:
17643 case OPC_MODU_G_2F:
17644 check_insn(ctx, INSN_LOONGSON2F);
17645 gen_loongson_integer(ctx, op1, rd, rs, rt);
17646 break;
17647 case OPC_CLO:
17648 case OPC_CLZ:
17649 check_insn(ctx, ISA_MIPS32);
17650 gen_cl(ctx, op1, rd, rs);
17651 break;
17652 case OPC_SDBBP:
17653 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17654 gen_helper_do_semihosting(cpu_env);
17655 } else {
17656 /* XXX: not clear which exception should be raised
17657 * when in debug mode...
17659 check_insn(ctx, ISA_MIPS32);
17660 generate_exception(ctx, EXCP_DBp);
17662 break;
17663 #if defined(TARGET_MIPS64)
17664 case OPC_DCLO:
17665 case OPC_DCLZ:
17666 check_insn(ctx, ISA_MIPS64);
17667 check_mips_64(ctx);
17668 gen_cl(ctx, op1, rd, rs);
17669 break;
17670 case OPC_DMULT_G_2F:
17671 case OPC_DMULTU_G_2F:
17672 case OPC_DDIV_G_2F:
17673 case OPC_DDIVU_G_2F:
17674 case OPC_DMOD_G_2F:
17675 case OPC_DMODU_G_2F:
17676 check_insn(ctx, INSN_LOONGSON2F);
17677 gen_loongson_integer(ctx, op1, rd, rs, rt);
17678 break;
17679 #endif
17680 default: /* Invalid */
17681 MIPS_INVAL("special2_legacy");
17682 generate_exception(ctx, EXCP_RI);
17683 break;
17687 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
17689 int rs, rt, rd, sa;
17690 uint32_t op1, op2;
17691 int16_t imm;
17693 rs = (ctx->opcode >> 21) & 0x1f;
17694 rt = (ctx->opcode >> 16) & 0x1f;
17695 rd = (ctx->opcode >> 11) & 0x1f;
17696 sa = (ctx->opcode >> 6) & 0x1f;
17697 imm = (int16_t)ctx->opcode >> 7;
17699 op1 = MASK_SPECIAL3(ctx->opcode);
17700 switch (op1) {
17701 case R6_OPC_PREF:
17702 if (rt >= 24) {
17703 /* hint codes 24-31 are reserved and signal RI */
17704 generate_exception(ctx, EXCP_RI);
17706 /* Treat as NOP. */
17707 break;
17708 case R6_OPC_CACHE:
17709 /* Treat as NOP. */
17710 break;
17711 case R6_OPC_SC:
17712 gen_st_cond(ctx, op1, rt, rs, imm);
17713 break;
17714 case R6_OPC_LL:
17715 gen_ld(ctx, op1, rt, rs, imm);
17716 break;
17717 case OPC_BSHFL:
17719 if (rd == 0) {
17720 /* Treat as NOP. */
17721 break;
17723 op2 = MASK_BSHFL(ctx->opcode);
17724 switch (op2) {
17725 case OPC_ALIGN ... OPC_ALIGN_END:
17726 gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3);
17727 break;
17728 case OPC_BITSWAP:
17729 gen_bitswap(ctx, op2, rd, rt);
17730 break;
17733 break;
17734 #if defined(TARGET_MIPS64)
17735 case R6_OPC_SCD:
17736 gen_st_cond(ctx, op1, rt, rs, imm);
17737 break;
17738 case R6_OPC_LLD:
17739 gen_ld(ctx, op1, rt, rs, imm);
17740 break;
17741 case OPC_DBSHFL:
17742 check_mips_64(ctx);
17744 if (rd == 0) {
17745 /* Treat as NOP. */
17746 break;
17748 op2 = MASK_DBSHFL(ctx->opcode);
17749 switch (op2) {
17750 case OPC_DALIGN ... OPC_DALIGN_END:
17751 gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7);
17752 break;
17753 case OPC_DBITSWAP:
17754 gen_bitswap(ctx, op2, rd, rt);
17755 break;
17759 break;
17760 #endif
17761 default: /* Invalid */
17762 MIPS_INVAL("special3_r6");
17763 generate_exception(ctx, EXCP_RI);
17764 break;
17768 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
17770 int rs, rt, rd;
17771 uint32_t op1, op2;
17773 rs = (ctx->opcode >> 21) & 0x1f;
17774 rt = (ctx->opcode >> 16) & 0x1f;
17775 rd = (ctx->opcode >> 11) & 0x1f;
17777 op1 = MASK_SPECIAL3(ctx->opcode);
17778 switch (op1) {
17779 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
17780 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
17781 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
17782 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
17783 * the same mask and op1. */
17784 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
17785 op2 = MASK_ADDUH_QB(ctx->opcode);
17786 switch (op2) {
17787 case OPC_ADDUH_QB:
17788 case OPC_ADDUH_R_QB:
17789 case OPC_ADDQH_PH:
17790 case OPC_ADDQH_R_PH:
17791 case OPC_ADDQH_W:
17792 case OPC_ADDQH_R_W:
17793 case OPC_SUBUH_QB:
17794 case OPC_SUBUH_R_QB:
17795 case OPC_SUBQH_PH:
17796 case OPC_SUBQH_R_PH:
17797 case OPC_SUBQH_W:
17798 case OPC_SUBQH_R_W:
17799 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17800 break;
17801 case OPC_MUL_PH:
17802 case OPC_MUL_S_PH:
17803 case OPC_MULQ_S_W:
17804 case OPC_MULQ_RS_W:
17805 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17806 break;
17807 default:
17808 MIPS_INVAL("MASK ADDUH.QB");
17809 generate_exception(ctx, EXCP_RI);
17810 break;
17812 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
17813 gen_loongson_integer(ctx, op1, rd, rs, rt);
17814 } else {
17815 generate_exception(ctx, EXCP_RI);
17817 break;
17818 case OPC_LX_DSP:
17819 op2 = MASK_LX(ctx->opcode);
17820 switch (op2) {
17821 #if defined(TARGET_MIPS64)
17822 case OPC_LDX:
17823 #endif
17824 case OPC_LBUX:
17825 case OPC_LHX:
17826 case OPC_LWX:
17827 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
17828 break;
17829 default: /* Invalid */
17830 MIPS_INVAL("MASK LX");
17831 generate_exception(ctx, EXCP_RI);
17832 break;
17834 break;
17835 case OPC_ABSQ_S_PH_DSP:
17836 op2 = MASK_ABSQ_S_PH(ctx->opcode);
17837 switch (op2) {
17838 case OPC_ABSQ_S_QB:
17839 case OPC_ABSQ_S_PH:
17840 case OPC_ABSQ_S_W:
17841 case OPC_PRECEQ_W_PHL:
17842 case OPC_PRECEQ_W_PHR:
17843 case OPC_PRECEQU_PH_QBL:
17844 case OPC_PRECEQU_PH_QBR:
17845 case OPC_PRECEQU_PH_QBLA:
17846 case OPC_PRECEQU_PH_QBRA:
17847 case OPC_PRECEU_PH_QBL:
17848 case OPC_PRECEU_PH_QBR:
17849 case OPC_PRECEU_PH_QBLA:
17850 case OPC_PRECEU_PH_QBRA:
17851 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17852 break;
17853 case OPC_BITREV:
17854 case OPC_REPL_QB:
17855 case OPC_REPLV_QB:
17856 case OPC_REPL_PH:
17857 case OPC_REPLV_PH:
17858 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17859 break;
17860 default:
17861 MIPS_INVAL("MASK ABSQ_S.PH");
17862 generate_exception(ctx, EXCP_RI);
17863 break;
17865 break;
17866 case OPC_ADDU_QB_DSP:
17867 op2 = MASK_ADDU_QB(ctx->opcode);
17868 switch (op2) {
17869 case OPC_ADDQ_PH:
17870 case OPC_ADDQ_S_PH:
17871 case OPC_ADDQ_S_W:
17872 case OPC_ADDU_QB:
17873 case OPC_ADDU_S_QB:
17874 case OPC_ADDU_PH:
17875 case OPC_ADDU_S_PH:
17876 case OPC_SUBQ_PH:
17877 case OPC_SUBQ_S_PH:
17878 case OPC_SUBQ_S_W:
17879 case OPC_SUBU_QB:
17880 case OPC_SUBU_S_QB:
17881 case OPC_SUBU_PH:
17882 case OPC_SUBU_S_PH:
17883 case OPC_ADDSC:
17884 case OPC_ADDWC:
17885 case OPC_MODSUB:
17886 case OPC_RADDU_W_QB:
17887 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17888 break;
17889 case OPC_MULEU_S_PH_QBL:
17890 case OPC_MULEU_S_PH_QBR:
17891 case OPC_MULQ_RS_PH:
17892 case OPC_MULEQ_S_W_PHL:
17893 case OPC_MULEQ_S_W_PHR:
17894 case OPC_MULQ_S_PH:
17895 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17896 break;
17897 default: /* Invalid */
17898 MIPS_INVAL("MASK ADDU.QB");
17899 generate_exception(ctx, EXCP_RI);
17900 break;
17903 break;
17904 case OPC_CMPU_EQ_QB_DSP:
17905 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
17906 switch (op2) {
17907 case OPC_PRECR_SRA_PH_W:
17908 case OPC_PRECR_SRA_R_PH_W:
17909 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17910 break;
17911 case OPC_PRECR_QB_PH:
17912 case OPC_PRECRQ_QB_PH:
17913 case OPC_PRECRQ_PH_W:
17914 case OPC_PRECRQ_RS_PH_W:
17915 case OPC_PRECRQU_S_QB_PH:
17916 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17917 break;
17918 case OPC_CMPU_EQ_QB:
17919 case OPC_CMPU_LT_QB:
17920 case OPC_CMPU_LE_QB:
17921 case OPC_CMP_EQ_PH:
17922 case OPC_CMP_LT_PH:
17923 case OPC_CMP_LE_PH:
17924 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17925 break;
17926 case OPC_CMPGU_EQ_QB:
17927 case OPC_CMPGU_LT_QB:
17928 case OPC_CMPGU_LE_QB:
17929 case OPC_CMPGDU_EQ_QB:
17930 case OPC_CMPGDU_LT_QB:
17931 case OPC_CMPGDU_LE_QB:
17932 case OPC_PICK_QB:
17933 case OPC_PICK_PH:
17934 case OPC_PACKRL_PH:
17935 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17936 break;
17937 default: /* Invalid */
17938 MIPS_INVAL("MASK CMPU.EQ.QB");
17939 generate_exception(ctx, EXCP_RI);
17940 break;
17942 break;
17943 case OPC_SHLL_QB_DSP:
17944 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17945 break;
17946 case OPC_DPA_W_PH_DSP:
17947 op2 = MASK_DPA_W_PH(ctx->opcode);
17948 switch (op2) {
17949 case OPC_DPAU_H_QBL:
17950 case OPC_DPAU_H_QBR:
17951 case OPC_DPSU_H_QBL:
17952 case OPC_DPSU_H_QBR:
17953 case OPC_DPA_W_PH:
17954 case OPC_DPAX_W_PH:
17955 case OPC_DPAQ_S_W_PH:
17956 case OPC_DPAQX_S_W_PH:
17957 case OPC_DPAQX_SA_W_PH:
17958 case OPC_DPS_W_PH:
17959 case OPC_DPSX_W_PH:
17960 case OPC_DPSQ_S_W_PH:
17961 case OPC_DPSQX_S_W_PH:
17962 case OPC_DPSQX_SA_W_PH:
17963 case OPC_MULSAQ_S_W_PH:
17964 case OPC_DPAQ_SA_L_W:
17965 case OPC_DPSQ_SA_L_W:
17966 case OPC_MAQ_S_W_PHL:
17967 case OPC_MAQ_S_W_PHR:
17968 case OPC_MAQ_SA_W_PHL:
17969 case OPC_MAQ_SA_W_PHR:
17970 case OPC_MULSA_W_PH:
17971 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17972 break;
17973 default: /* Invalid */
17974 MIPS_INVAL("MASK DPAW.PH");
17975 generate_exception(ctx, EXCP_RI);
17976 break;
17978 break;
17979 case OPC_INSV_DSP:
17980 op2 = MASK_INSV(ctx->opcode);
17981 switch (op2) {
17982 case OPC_INSV:
17983 check_dsp(ctx);
17985 TCGv t0, t1;
17987 if (rt == 0) {
17988 MIPS_DEBUG("NOP");
17989 break;
17992 t0 = tcg_temp_new();
17993 t1 = tcg_temp_new();
17995 gen_load_gpr(t0, rt);
17996 gen_load_gpr(t1, rs);
17998 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
18000 tcg_temp_free(t0);
18001 tcg_temp_free(t1);
18002 break;
18004 default: /* Invalid */
18005 MIPS_INVAL("MASK INSV");
18006 generate_exception(ctx, EXCP_RI);
18007 break;
18009 break;
18010 case OPC_APPEND_DSP:
18011 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
18012 break;
18013 case OPC_EXTR_W_DSP:
18014 op2 = MASK_EXTR_W(ctx->opcode);
18015 switch (op2) {
18016 case OPC_EXTR_W:
18017 case OPC_EXTR_R_W:
18018 case OPC_EXTR_RS_W:
18019 case OPC_EXTR_S_H:
18020 case OPC_EXTRV_S_H:
18021 case OPC_EXTRV_W:
18022 case OPC_EXTRV_R_W:
18023 case OPC_EXTRV_RS_W:
18024 case OPC_EXTP:
18025 case OPC_EXTPV:
18026 case OPC_EXTPDP:
18027 case OPC_EXTPDPV:
18028 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
18029 break;
18030 case OPC_RDDSP:
18031 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
18032 break;
18033 case OPC_SHILO:
18034 case OPC_SHILOV:
18035 case OPC_MTHLIP:
18036 case OPC_WRDSP:
18037 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
18038 break;
18039 default: /* Invalid */
18040 MIPS_INVAL("MASK EXTR.W");
18041 generate_exception(ctx, EXCP_RI);
18042 break;
18044 break;
18045 #if defined(TARGET_MIPS64)
18046 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
18047 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
18048 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
18049 check_insn(ctx, INSN_LOONGSON2E);
18050 gen_loongson_integer(ctx, op1, rd, rs, rt);
18051 break;
18052 case OPC_ABSQ_S_QH_DSP:
18053 op2 = MASK_ABSQ_S_QH(ctx->opcode);
18054 switch (op2) {
18055 case OPC_PRECEQ_L_PWL:
18056 case OPC_PRECEQ_L_PWR:
18057 case OPC_PRECEQ_PW_QHL:
18058 case OPC_PRECEQ_PW_QHR:
18059 case OPC_PRECEQ_PW_QHLA:
18060 case OPC_PRECEQ_PW_QHRA:
18061 case OPC_PRECEQU_QH_OBL:
18062 case OPC_PRECEQU_QH_OBR:
18063 case OPC_PRECEQU_QH_OBLA:
18064 case OPC_PRECEQU_QH_OBRA:
18065 case OPC_PRECEU_QH_OBL:
18066 case OPC_PRECEU_QH_OBR:
18067 case OPC_PRECEU_QH_OBLA:
18068 case OPC_PRECEU_QH_OBRA:
18069 case OPC_ABSQ_S_OB:
18070 case OPC_ABSQ_S_PW:
18071 case OPC_ABSQ_S_QH:
18072 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18073 break;
18074 case OPC_REPL_OB:
18075 case OPC_REPL_PW:
18076 case OPC_REPL_QH:
18077 case OPC_REPLV_OB:
18078 case OPC_REPLV_PW:
18079 case OPC_REPLV_QH:
18080 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
18081 break;
18082 default: /* Invalid */
18083 MIPS_INVAL("MASK ABSQ_S.QH");
18084 generate_exception(ctx, EXCP_RI);
18085 break;
18087 break;
18088 case OPC_ADDU_OB_DSP:
18089 op2 = MASK_ADDU_OB(ctx->opcode);
18090 switch (op2) {
18091 case OPC_RADDU_L_OB:
18092 case OPC_SUBQ_PW:
18093 case OPC_SUBQ_S_PW:
18094 case OPC_SUBQ_QH:
18095 case OPC_SUBQ_S_QH:
18096 case OPC_SUBU_OB:
18097 case OPC_SUBU_S_OB:
18098 case OPC_SUBU_QH:
18099 case OPC_SUBU_S_QH:
18100 case OPC_SUBUH_OB:
18101 case OPC_SUBUH_R_OB:
18102 case OPC_ADDQ_PW:
18103 case OPC_ADDQ_S_PW:
18104 case OPC_ADDQ_QH:
18105 case OPC_ADDQ_S_QH:
18106 case OPC_ADDU_OB:
18107 case OPC_ADDU_S_OB:
18108 case OPC_ADDU_QH:
18109 case OPC_ADDU_S_QH:
18110 case OPC_ADDUH_OB:
18111 case OPC_ADDUH_R_OB:
18112 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18113 break;
18114 case OPC_MULEQ_S_PW_QHL:
18115 case OPC_MULEQ_S_PW_QHR:
18116 case OPC_MULEU_S_QH_OBL:
18117 case OPC_MULEU_S_QH_OBR:
18118 case OPC_MULQ_RS_QH:
18119 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
18120 break;
18121 default: /* Invalid */
18122 MIPS_INVAL("MASK ADDU.OB");
18123 generate_exception(ctx, EXCP_RI);
18124 break;
18126 break;
18127 case OPC_CMPU_EQ_OB_DSP:
18128 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
18129 switch (op2) {
18130 case OPC_PRECR_SRA_QH_PW:
18131 case OPC_PRECR_SRA_R_QH_PW:
18132 /* Return value is rt. */
18133 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
18134 break;
18135 case OPC_PRECR_OB_QH:
18136 case OPC_PRECRQ_OB_QH:
18137 case OPC_PRECRQ_PW_L:
18138 case OPC_PRECRQ_QH_PW:
18139 case OPC_PRECRQ_RS_QH_PW:
18140 case OPC_PRECRQU_S_OB_QH:
18141 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18142 break;
18143 case OPC_CMPU_EQ_OB:
18144 case OPC_CMPU_LT_OB:
18145 case OPC_CMPU_LE_OB:
18146 case OPC_CMP_EQ_QH:
18147 case OPC_CMP_LT_QH:
18148 case OPC_CMP_LE_QH:
18149 case OPC_CMP_EQ_PW:
18150 case OPC_CMP_LT_PW:
18151 case OPC_CMP_LE_PW:
18152 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
18153 break;
18154 case OPC_CMPGDU_EQ_OB:
18155 case OPC_CMPGDU_LT_OB:
18156 case OPC_CMPGDU_LE_OB:
18157 case OPC_CMPGU_EQ_OB:
18158 case OPC_CMPGU_LT_OB:
18159 case OPC_CMPGU_LE_OB:
18160 case OPC_PACKRL_PW:
18161 case OPC_PICK_OB:
18162 case OPC_PICK_PW:
18163 case OPC_PICK_QH:
18164 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
18165 break;
18166 default: /* Invalid */
18167 MIPS_INVAL("MASK CMPU_EQ.OB");
18168 generate_exception(ctx, EXCP_RI);
18169 break;
18171 break;
18172 case OPC_DAPPEND_DSP:
18173 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
18174 break;
18175 case OPC_DEXTR_W_DSP:
18176 op2 = MASK_DEXTR_W(ctx->opcode);
18177 switch (op2) {
18178 case OPC_DEXTP:
18179 case OPC_DEXTPDP:
18180 case OPC_DEXTPDPV:
18181 case OPC_DEXTPV:
18182 case OPC_DEXTR_L:
18183 case OPC_DEXTR_R_L:
18184 case OPC_DEXTR_RS_L:
18185 case OPC_DEXTR_W:
18186 case OPC_DEXTR_R_W:
18187 case OPC_DEXTR_RS_W:
18188 case OPC_DEXTR_S_H:
18189 case OPC_DEXTRV_L:
18190 case OPC_DEXTRV_R_L:
18191 case OPC_DEXTRV_RS_L:
18192 case OPC_DEXTRV_S_H:
18193 case OPC_DEXTRV_W:
18194 case OPC_DEXTRV_R_W:
18195 case OPC_DEXTRV_RS_W:
18196 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
18197 break;
18198 case OPC_DMTHLIP:
18199 case OPC_DSHILO:
18200 case OPC_DSHILOV:
18201 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
18202 break;
18203 default: /* Invalid */
18204 MIPS_INVAL("MASK EXTR.W");
18205 generate_exception(ctx, EXCP_RI);
18206 break;
18208 break;
18209 case OPC_DPAQ_W_QH_DSP:
18210 op2 = MASK_DPAQ_W_QH(ctx->opcode);
18211 switch (op2) {
18212 case OPC_DPAU_H_OBL:
18213 case OPC_DPAU_H_OBR:
18214 case OPC_DPSU_H_OBL:
18215 case OPC_DPSU_H_OBR:
18216 case OPC_DPA_W_QH:
18217 case OPC_DPAQ_S_W_QH:
18218 case OPC_DPS_W_QH:
18219 case OPC_DPSQ_S_W_QH:
18220 case OPC_MULSAQ_S_W_QH:
18221 case OPC_DPAQ_SA_L_PW:
18222 case OPC_DPSQ_SA_L_PW:
18223 case OPC_MULSAQ_S_L_PW:
18224 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
18225 break;
18226 case OPC_MAQ_S_W_QHLL:
18227 case OPC_MAQ_S_W_QHLR:
18228 case OPC_MAQ_S_W_QHRL:
18229 case OPC_MAQ_S_W_QHRR:
18230 case OPC_MAQ_SA_W_QHLL:
18231 case OPC_MAQ_SA_W_QHLR:
18232 case OPC_MAQ_SA_W_QHRL:
18233 case OPC_MAQ_SA_W_QHRR:
18234 case OPC_MAQ_S_L_PWL:
18235 case OPC_MAQ_S_L_PWR:
18236 case OPC_DMADD:
18237 case OPC_DMADDU:
18238 case OPC_DMSUB:
18239 case OPC_DMSUBU:
18240 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
18241 break;
18242 default: /* Invalid */
18243 MIPS_INVAL("MASK DPAQ.W.QH");
18244 generate_exception(ctx, EXCP_RI);
18245 break;
18247 break;
18248 case OPC_DINSV_DSP:
18249 op2 = MASK_INSV(ctx->opcode);
18250 switch (op2) {
18251 case OPC_DINSV:
18253 TCGv t0, t1;
18255 if (rt == 0) {
18256 MIPS_DEBUG("NOP");
18257 break;
18259 check_dsp(ctx);
18261 t0 = tcg_temp_new();
18262 t1 = tcg_temp_new();
18264 gen_load_gpr(t0, rt);
18265 gen_load_gpr(t1, rs);
18267 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
18269 tcg_temp_free(t0);
18270 tcg_temp_free(t1);
18271 break;
18273 default: /* Invalid */
18274 MIPS_INVAL("MASK DINSV");
18275 generate_exception(ctx, EXCP_RI);
18276 break;
18278 break;
18279 case OPC_SHLL_OB_DSP:
18280 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
18281 break;
18282 #endif
18283 default: /* Invalid */
18284 MIPS_INVAL("special3_legacy");
18285 generate_exception(ctx, EXCP_RI);
18286 break;
18290 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
18292 int rs, rt, rd, sa;
18293 uint32_t op1, op2;
18295 rs = (ctx->opcode >> 21) & 0x1f;
18296 rt = (ctx->opcode >> 16) & 0x1f;
18297 rd = (ctx->opcode >> 11) & 0x1f;
18298 sa = (ctx->opcode >> 6) & 0x1f;
18300 op1 = MASK_SPECIAL3(ctx->opcode);
18301 switch (op1) {
18302 case OPC_EXT:
18303 case OPC_INS:
18304 check_insn(ctx, ISA_MIPS32R2);
18305 gen_bitops(ctx, op1, rt, rs, sa, rd);
18306 break;
18307 case OPC_BSHFL:
18308 op2 = MASK_BSHFL(ctx->opcode);
18309 switch (op2) {
18310 case OPC_ALIGN ... OPC_ALIGN_END:
18311 case OPC_BITSWAP:
18312 check_insn(ctx, ISA_MIPS32R6);
18313 decode_opc_special3_r6(env, ctx);
18314 break;
18315 default:
18316 check_insn(ctx, ISA_MIPS32R2);
18317 gen_bshfl(ctx, op2, rt, rd);
18318 break;
18320 break;
18321 #if defined(TARGET_MIPS64)
18322 case OPC_DEXTM ... OPC_DEXT:
18323 case OPC_DINSM ... OPC_DINS:
18324 check_insn(ctx, ISA_MIPS64R2);
18325 check_mips_64(ctx);
18326 gen_bitops(ctx, op1, rt, rs, sa, rd);
18327 break;
18328 case OPC_DBSHFL:
18329 op2 = MASK_DBSHFL(ctx->opcode);
18330 switch (op2) {
18331 case OPC_DALIGN ... OPC_DALIGN_END:
18332 case OPC_DBITSWAP:
18333 check_insn(ctx, ISA_MIPS32R6);
18334 decode_opc_special3_r6(env, ctx);
18335 break;
18336 default:
18337 check_insn(ctx, ISA_MIPS64R2);
18338 check_mips_64(ctx);
18339 op2 = MASK_DBSHFL(ctx->opcode);
18340 gen_bshfl(ctx, op2, rt, rd);
18341 break;
18343 break;
18344 #endif
18345 case OPC_RDHWR:
18346 gen_rdhwr(ctx, rt, rd);
18347 break;
18348 case OPC_FORK:
18349 check_insn(ctx, ASE_MT);
18351 TCGv t0 = tcg_temp_new();
18352 TCGv t1 = tcg_temp_new();
18354 gen_load_gpr(t0, rt);
18355 gen_load_gpr(t1, rs);
18356 gen_helper_fork(t0, t1);
18357 tcg_temp_free(t0);
18358 tcg_temp_free(t1);
18360 break;
18361 case OPC_YIELD:
18362 check_insn(ctx, ASE_MT);
18364 TCGv t0 = tcg_temp_new();
18366 save_cpu_state(ctx, 1);
18367 gen_load_gpr(t0, rs);
18368 gen_helper_yield(t0, cpu_env, t0);
18369 gen_store_gpr(t0, rd);
18370 tcg_temp_free(t0);
18372 break;
18373 default:
18374 if (ctx->insn_flags & ISA_MIPS32R6) {
18375 decode_opc_special3_r6(env, ctx);
18376 } else {
18377 decode_opc_special3_legacy(env, ctx);
18382 /* MIPS SIMD Architecture (MSA) */
18383 static inline int check_msa_access(DisasContext *ctx)
18385 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
18386 !(ctx->hflags & MIPS_HFLAG_F64))) {
18387 generate_exception(ctx, EXCP_RI);
18388 return 0;
18391 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
18392 if (ctx->insn_flags & ASE_MSA) {
18393 generate_exception(ctx, EXCP_MSADIS);
18394 return 0;
18395 } else {
18396 generate_exception(ctx, EXCP_RI);
18397 return 0;
18400 return 1;
18403 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
18405 /* generates tcg ops to check if any element is 0 */
18406 /* Note this function only works with MSA_WRLEN = 128 */
18407 uint64_t eval_zero_or_big = 0;
18408 uint64_t eval_big = 0;
18409 TCGv_i64 t0 = tcg_temp_new_i64();
18410 TCGv_i64 t1 = tcg_temp_new_i64();
18411 switch (df) {
18412 case DF_BYTE:
18413 eval_zero_or_big = 0x0101010101010101ULL;
18414 eval_big = 0x8080808080808080ULL;
18415 break;
18416 case DF_HALF:
18417 eval_zero_or_big = 0x0001000100010001ULL;
18418 eval_big = 0x8000800080008000ULL;
18419 break;
18420 case DF_WORD:
18421 eval_zero_or_big = 0x0000000100000001ULL;
18422 eval_big = 0x8000000080000000ULL;
18423 break;
18424 case DF_DOUBLE:
18425 eval_zero_or_big = 0x0000000000000001ULL;
18426 eval_big = 0x8000000000000000ULL;
18427 break;
18429 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
18430 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
18431 tcg_gen_andi_i64(t0, t0, eval_big);
18432 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
18433 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
18434 tcg_gen_andi_i64(t1, t1, eval_big);
18435 tcg_gen_or_i64(t0, t0, t1);
18436 /* if all bits are zero then all elements are not zero */
18437 /* if some bit is non-zero then some element is zero */
18438 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
18439 tcg_gen_trunc_i64_tl(tresult, t0);
18440 tcg_temp_free_i64(t0);
18441 tcg_temp_free_i64(t1);
18444 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
18446 uint8_t df = (ctx->opcode >> 21) & 0x3;
18447 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18448 int64_t s16 = (int16_t)ctx->opcode;
18450 check_msa_access(ctx);
18452 if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
18453 MIPS_DEBUG("CTI in delay / forbidden slot");
18454 generate_exception(ctx, EXCP_RI);
18455 return;
18457 switch (op1) {
18458 case OPC_BZ_V:
18459 case OPC_BNZ_V:
18461 TCGv_i64 t0 = tcg_temp_new_i64();
18462 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
18463 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
18464 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
18465 tcg_gen_trunc_i64_tl(bcond, t0);
18466 tcg_temp_free_i64(t0);
18468 break;
18469 case OPC_BZ_B:
18470 case OPC_BZ_H:
18471 case OPC_BZ_W:
18472 case OPC_BZ_D:
18473 gen_check_zero_element(bcond, df, wt);
18474 break;
18475 case OPC_BNZ_B:
18476 case OPC_BNZ_H:
18477 case OPC_BNZ_W:
18478 case OPC_BNZ_D:
18479 gen_check_zero_element(bcond, df, wt);
18480 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
18481 break;
18484 ctx->btarget = ctx->pc + (s16 << 2) + 4;
18486 ctx->hflags |= MIPS_HFLAG_BC;
18487 ctx->hflags |= MIPS_HFLAG_BDS32;
18490 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
18492 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
18493 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
18494 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18495 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18497 TCGv_i32 twd = tcg_const_i32(wd);
18498 TCGv_i32 tws = tcg_const_i32(ws);
18499 TCGv_i32 ti8 = tcg_const_i32(i8);
18501 switch (MASK_MSA_I8(ctx->opcode)) {
18502 case OPC_ANDI_B:
18503 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
18504 break;
18505 case OPC_ORI_B:
18506 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
18507 break;
18508 case OPC_NORI_B:
18509 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
18510 break;
18511 case OPC_XORI_B:
18512 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
18513 break;
18514 case OPC_BMNZI_B:
18515 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
18516 break;
18517 case OPC_BMZI_B:
18518 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
18519 break;
18520 case OPC_BSELI_B:
18521 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
18522 break;
18523 case OPC_SHF_B:
18524 case OPC_SHF_H:
18525 case OPC_SHF_W:
18527 uint8_t df = (ctx->opcode >> 24) & 0x3;
18528 if (df == DF_DOUBLE) {
18529 generate_exception(ctx, EXCP_RI);
18530 } else {
18531 TCGv_i32 tdf = tcg_const_i32(df);
18532 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
18533 tcg_temp_free_i32(tdf);
18536 break;
18537 default:
18538 MIPS_INVAL("MSA instruction");
18539 generate_exception(ctx, EXCP_RI);
18540 break;
18543 tcg_temp_free_i32(twd);
18544 tcg_temp_free_i32(tws);
18545 tcg_temp_free_i32(ti8);
18548 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
18550 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18551 uint8_t df = (ctx->opcode >> 21) & 0x3;
18552 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
18553 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
18554 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18555 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18557 TCGv_i32 tdf = tcg_const_i32(df);
18558 TCGv_i32 twd = tcg_const_i32(wd);
18559 TCGv_i32 tws = tcg_const_i32(ws);
18560 TCGv_i32 timm = tcg_temp_new_i32();
18561 tcg_gen_movi_i32(timm, u5);
18563 switch (MASK_MSA_I5(ctx->opcode)) {
18564 case OPC_ADDVI_df:
18565 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
18566 break;
18567 case OPC_SUBVI_df:
18568 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
18569 break;
18570 case OPC_MAXI_S_df:
18571 tcg_gen_movi_i32(timm, s5);
18572 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
18573 break;
18574 case OPC_MAXI_U_df:
18575 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
18576 break;
18577 case OPC_MINI_S_df:
18578 tcg_gen_movi_i32(timm, s5);
18579 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
18580 break;
18581 case OPC_MINI_U_df:
18582 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
18583 break;
18584 case OPC_CEQI_df:
18585 tcg_gen_movi_i32(timm, s5);
18586 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
18587 break;
18588 case OPC_CLTI_S_df:
18589 tcg_gen_movi_i32(timm, s5);
18590 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
18591 break;
18592 case OPC_CLTI_U_df:
18593 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
18594 break;
18595 case OPC_CLEI_S_df:
18596 tcg_gen_movi_i32(timm, s5);
18597 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
18598 break;
18599 case OPC_CLEI_U_df:
18600 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
18601 break;
18602 case OPC_LDI_df:
18604 int32_t s10 = sextract32(ctx->opcode, 11, 10);
18605 tcg_gen_movi_i32(timm, s10);
18606 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
18608 break;
18609 default:
18610 MIPS_INVAL("MSA instruction");
18611 generate_exception(ctx, EXCP_RI);
18612 break;
18615 tcg_temp_free_i32(tdf);
18616 tcg_temp_free_i32(twd);
18617 tcg_temp_free_i32(tws);
18618 tcg_temp_free_i32(timm);
18621 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
18623 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18624 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
18625 uint32_t df = 0, m = 0;
18626 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18627 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18629 TCGv_i32 tdf;
18630 TCGv_i32 tm;
18631 TCGv_i32 twd;
18632 TCGv_i32 tws;
18634 if ((dfm & 0x40) == 0x00) {
18635 m = dfm & 0x3f;
18636 df = DF_DOUBLE;
18637 } else if ((dfm & 0x60) == 0x40) {
18638 m = dfm & 0x1f;
18639 df = DF_WORD;
18640 } else if ((dfm & 0x70) == 0x60) {
18641 m = dfm & 0x0f;
18642 df = DF_HALF;
18643 } else if ((dfm & 0x78) == 0x70) {
18644 m = dfm & 0x7;
18645 df = DF_BYTE;
18646 } else {
18647 generate_exception(ctx, EXCP_RI);
18648 return;
18651 tdf = tcg_const_i32(df);
18652 tm = tcg_const_i32(m);
18653 twd = tcg_const_i32(wd);
18654 tws = tcg_const_i32(ws);
18656 switch (MASK_MSA_BIT(ctx->opcode)) {
18657 case OPC_SLLI_df:
18658 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
18659 break;
18660 case OPC_SRAI_df:
18661 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
18662 break;
18663 case OPC_SRLI_df:
18664 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
18665 break;
18666 case OPC_BCLRI_df:
18667 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
18668 break;
18669 case OPC_BSETI_df:
18670 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
18671 break;
18672 case OPC_BNEGI_df:
18673 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
18674 break;
18675 case OPC_BINSLI_df:
18676 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
18677 break;
18678 case OPC_BINSRI_df:
18679 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
18680 break;
18681 case OPC_SAT_S_df:
18682 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
18683 break;
18684 case OPC_SAT_U_df:
18685 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
18686 break;
18687 case OPC_SRARI_df:
18688 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
18689 break;
18690 case OPC_SRLRI_df:
18691 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
18692 break;
18693 default:
18694 MIPS_INVAL("MSA instruction");
18695 generate_exception(ctx, EXCP_RI);
18696 break;
18699 tcg_temp_free_i32(tdf);
18700 tcg_temp_free_i32(tm);
18701 tcg_temp_free_i32(twd);
18702 tcg_temp_free_i32(tws);
18705 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
18707 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18708 uint8_t df = (ctx->opcode >> 21) & 0x3;
18709 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18710 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18711 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18713 TCGv_i32 tdf = tcg_const_i32(df);
18714 TCGv_i32 twd = tcg_const_i32(wd);
18715 TCGv_i32 tws = tcg_const_i32(ws);
18716 TCGv_i32 twt = tcg_const_i32(wt);
18718 switch (MASK_MSA_3R(ctx->opcode)) {
18719 case OPC_SLL_df:
18720 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
18721 break;
18722 case OPC_ADDV_df:
18723 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
18724 break;
18725 case OPC_CEQ_df:
18726 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
18727 break;
18728 case OPC_ADD_A_df:
18729 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
18730 break;
18731 case OPC_SUBS_S_df:
18732 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
18733 break;
18734 case OPC_MULV_df:
18735 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
18736 break;
18737 case OPC_SLD_df:
18738 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
18739 break;
18740 case OPC_VSHF_df:
18741 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
18742 break;
18743 case OPC_SRA_df:
18744 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
18745 break;
18746 case OPC_SUBV_df:
18747 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
18748 break;
18749 case OPC_ADDS_A_df:
18750 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
18751 break;
18752 case OPC_SUBS_U_df:
18753 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
18754 break;
18755 case OPC_MADDV_df:
18756 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
18757 break;
18758 case OPC_SPLAT_df:
18759 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
18760 break;
18761 case OPC_SRAR_df:
18762 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
18763 break;
18764 case OPC_SRL_df:
18765 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
18766 break;
18767 case OPC_MAX_S_df:
18768 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
18769 break;
18770 case OPC_CLT_S_df:
18771 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
18772 break;
18773 case OPC_ADDS_S_df:
18774 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
18775 break;
18776 case OPC_SUBSUS_U_df:
18777 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
18778 break;
18779 case OPC_MSUBV_df:
18780 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
18781 break;
18782 case OPC_PCKEV_df:
18783 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
18784 break;
18785 case OPC_SRLR_df:
18786 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
18787 break;
18788 case OPC_BCLR_df:
18789 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
18790 break;
18791 case OPC_MAX_U_df:
18792 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
18793 break;
18794 case OPC_CLT_U_df:
18795 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
18796 break;
18797 case OPC_ADDS_U_df:
18798 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
18799 break;
18800 case OPC_SUBSUU_S_df:
18801 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
18802 break;
18803 case OPC_PCKOD_df:
18804 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
18805 break;
18806 case OPC_BSET_df:
18807 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
18808 break;
18809 case OPC_MIN_S_df:
18810 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
18811 break;
18812 case OPC_CLE_S_df:
18813 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
18814 break;
18815 case OPC_AVE_S_df:
18816 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
18817 break;
18818 case OPC_ASUB_S_df:
18819 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
18820 break;
18821 case OPC_DIV_S_df:
18822 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
18823 break;
18824 case OPC_ILVL_df:
18825 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
18826 break;
18827 case OPC_BNEG_df:
18828 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
18829 break;
18830 case OPC_MIN_U_df:
18831 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
18832 break;
18833 case OPC_CLE_U_df:
18834 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
18835 break;
18836 case OPC_AVE_U_df:
18837 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
18838 break;
18839 case OPC_ASUB_U_df:
18840 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
18841 break;
18842 case OPC_DIV_U_df:
18843 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
18844 break;
18845 case OPC_ILVR_df:
18846 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
18847 break;
18848 case OPC_BINSL_df:
18849 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
18850 break;
18851 case OPC_MAX_A_df:
18852 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
18853 break;
18854 case OPC_AVER_S_df:
18855 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
18856 break;
18857 case OPC_MOD_S_df:
18858 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
18859 break;
18860 case OPC_ILVEV_df:
18861 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
18862 break;
18863 case OPC_BINSR_df:
18864 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
18865 break;
18866 case OPC_MIN_A_df:
18867 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
18868 break;
18869 case OPC_AVER_U_df:
18870 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
18871 break;
18872 case OPC_MOD_U_df:
18873 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
18874 break;
18875 case OPC_ILVOD_df:
18876 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
18877 break;
18879 case OPC_DOTP_S_df:
18880 case OPC_DOTP_U_df:
18881 case OPC_DPADD_S_df:
18882 case OPC_DPADD_U_df:
18883 case OPC_DPSUB_S_df:
18884 case OPC_HADD_S_df:
18885 case OPC_DPSUB_U_df:
18886 case OPC_HADD_U_df:
18887 case OPC_HSUB_S_df:
18888 case OPC_HSUB_U_df:
18889 if (df == DF_BYTE) {
18890 generate_exception(ctx, EXCP_RI);
18892 switch (MASK_MSA_3R(ctx->opcode)) {
18893 case OPC_DOTP_S_df:
18894 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
18895 break;
18896 case OPC_DOTP_U_df:
18897 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
18898 break;
18899 case OPC_DPADD_S_df:
18900 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
18901 break;
18902 case OPC_DPADD_U_df:
18903 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
18904 break;
18905 case OPC_DPSUB_S_df:
18906 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
18907 break;
18908 case OPC_HADD_S_df:
18909 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
18910 break;
18911 case OPC_DPSUB_U_df:
18912 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
18913 break;
18914 case OPC_HADD_U_df:
18915 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
18916 break;
18917 case OPC_HSUB_S_df:
18918 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
18919 break;
18920 case OPC_HSUB_U_df:
18921 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
18922 break;
18924 break;
18925 default:
18926 MIPS_INVAL("MSA instruction");
18927 generate_exception(ctx, EXCP_RI);
18928 break;
18930 tcg_temp_free_i32(twd);
18931 tcg_temp_free_i32(tws);
18932 tcg_temp_free_i32(twt);
18933 tcg_temp_free_i32(tdf);
18936 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
18938 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
18939 uint8_t source = (ctx->opcode >> 11) & 0x1f;
18940 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
18941 TCGv telm = tcg_temp_new();
18942 TCGv_i32 tsr = tcg_const_i32(source);
18943 TCGv_i32 tdt = tcg_const_i32(dest);
18945 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
18946 case OPC_CTCMSA:
18947 gen_load_gpr(telm, source);
18948 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
18949 break;
18950 case OPC_CFCMSA:
18951 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
18952 gen_store_gpr(telm, dest);
18953 break;
18954 case OPC_MOVE_V:
18955 gen_helper_msa_move_v(cpu_env, tdt, tsr);
18956 break;
18957 default:
18958 MIPS_INVAL("MSA instruction");
18959 generate_exception(ctx, EXCP_RI);
18960 break;
18963 tcg_temp_free(telm);
18964 tcg_temp_free_i32(tdt);
18965 tcg_temp_free_i32(tsr);
18968 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
18969 uint32_t n)
18971 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18972 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18973 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18975 TCGv_i32 tws = tcg_const_i32(ws);
18976 TCGv_i32 twd = tcg_const_i32(wd);
18977 TCGv_i32 tn = tcg_const_i32(n);
18978 TCGv_i32 tdf = tcg_const_i32(df);
18980 switch (MASK_MSA_ELM(ctx->opcode)) {
18981 case OPC_SLDI_df:
18982 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
18983 break;
18984 case OPC_SPLATI_df:
18985 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
18986 break;
18987 case OPC_INSVE_df:
18988 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
18989 break;
18990 case OPC_COPY_S_df:
18991 case OPC_COPY_U_df:
18992 case OPC_INSERT_df:
18993 #if !defined(TARGET_MIPS64)
18994 /* Double format valid only for MIPS64 */
18995 if (df == DF_DOUBLE) {
18996 generate_exception(ctx, EXCP_RI);
18997 break;
18999 #endif
19000 switch (MASK_MSA_ELM(ctx->opcode)) {
19001 case OPC_COPY_S_df:
19002 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
19003 break;
19004 case OPC_COPY_U_df:
19005 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
19006 break;
19007 case OPC_INSERT_df:
19008 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
19009 break;
19011 break;
19012 default:
19013 MIPS_INVAL("MSA instruction");
19014 generate_exception(ctx, EXCP_RI);
19016 tcg_temp_free_i32(twd);
19017 tcg_temp_free_i32(tws);
19018 tcg_temp_free_i32(tn);
19019 tcg_temp_free_i32(tdf);
19022 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
19024 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
19025 uint32_t df = 0, n = 0;
19027 if ((dfn & 0x30) == 0x00) {
19028 n = dfn & 0x0f;
19029 df = DF_BYTE;
19030 } else if ((dfn & 0x38) == 0x20) {
19031 n = dfn & 0x07;
19032 df = DF_HALF;
19033 } else if ((dfn & 0x3c) == 0x30) {
19034 n = dfn & 0x03;
19035 df = DF_WORD;
19036 } else if ((dfn & 0x3e) == 0x38) {
19037 n = dfn & 0x01;
19038 df = DF_DOUBLE;
19039 } else if (dfn == 0x3E) {
19040 /* CTCMSA, CFCMSA, MOVE.V */
19041 gen_msa_elm_3e(env, ctx);
19042 return;
19043 } else {
19044 generate_exception(ctx, EXCP_RI);
19045 return;
19048 gen_msa_elm_df(env, ctx, df, n);
19051 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
19053 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
19054 uint8_t df = (ctx->opcode >> 21) & 0x1;
19055 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19056 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19057 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19059 TCGv_i32 twd = tcg_const_i32(wd);
19060 TCGv_i32 tws = tcg_const_i32(ws);
19061 TCGv_i32 twt = tcg_const_i32(wt);
19062 TCGv_i32 tdf = tcg_temp_new_i32();
19064 /* adjust df value for floating-point instruction */
19065 tcg_gen_movi_i32(tdf, df + 2);
19067 switch (MASK_MSA_3RF(ctx->opcode)) {
19068 case OPC_FCAF_df:
19069 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
19070 break;
19071 case OPC_FADD_df:
19072 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
19073 break;
19074 case OPC_FCUN_df:
19075 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
19076 break;
19077 case OPC_FSUB_df:
19078 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
19079 break;
19080 case OPC_FCOR_df:
19081 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
19082 break;
19083 case OPC_FCEQ_df:
19084 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
19085 break;
19086 case OPC_FMUL_df:
19087 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
19088 break;
19089 case OPC_FCUNE_df:
19090 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
19091 break;
19092 case OPC_FCUEQ_df:
19093 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
19094 break;
19095 case OPC_FDIV_df:
19096 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
19097 break;
19098 case OPC_FCNE_df:
19099 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
19100 break;
19101 case OPC_FCLT_df:
19102 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
19103 break;
19104 case OPC_FMADD_df:
19105 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
19106 break;
19107 case OPC_MUL_Q_df:
19108 tcg_gen_movi_i32(tdf, df + 1);
19109 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
19110 break;
19111 case OPC_FCULT_df:
19112 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
19113 break;
19114 case OPC_FMSUB_df:
19115 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
19116 break;
19117 case OPC_MADD_Q_df:
19118 tcg_gen_movi_i32(tdf, df + 1);
19119 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
19120 break;
19121 case OPC_FCLE_df:
19122 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
19123 break;
19124 case OPC_MSUB_Q_df:
19125 tcg_gen_movi_i32(tdf, df + 1);
19126 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
19127 break;
19128 case OPC_FCULE_df:
19129 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
19130 break;
19131 case OPC_FEXP2_df:
19132 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
19133 break;
19134 case OPC_FSAF_df:
19135 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
19136 break;
19137 case OPC_FEXDO_df:
19138 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
19139 break;
19140 case OPC_FSUN_df:
19141 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
19142 break;
19143 case OPC_FSOR_df:
19144 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
19145 break;
19146 case OPC_FSEQ_df:
19147 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
19148 break;
19149 case OPC_FTQ_df:
19150 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
19151 break;
19152 case OPC_FSUNE_df:
19153 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
19154 break;
19155 case OPC_FSUEQ_df:
19156 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
19157 break;
19158 case OPC_FSNE_df:
19159 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
19160 break;
19161 case OPC_FSLT_df:
19162 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
19163 break;
19164 case OPC_FMIN_df:
19165 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
19166 break;
19167 case OPC_MULR_Q_df:
19168 tcg_gen_movi_i32(tdf, df + 1);
19169 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
19170 break;
19171 case OPC_FSULT_df:
19172 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
19173 break;
19174 case OPC_FMIN_A_df:
19175 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
19176 break;
19177 case OPC_MADDR_Q_df:
19178 tcg_gen_movi_i32(tdf, df + 1);
19179 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
19180 break;
19181 case OPC_FSLE_df:
19182 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
19183 break;
19184 case OPC_FMAX_df:
19185 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
19186 break;
19187 case OPC_MSUBR_Q_df:
19188 tcg_gen_movi_i32(tdf, df + 1);
19189 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
19190 break;
19191 case OPC_FSULE_df:
19192 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
19193 break;
19194 case OPC_FMAX_A_df:
19195 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
19196 break;
19197 default:
19198 MIPS_INVAL("MSA instruction");
19199 generate_exception(ctx, EXCP_RI);
19200 break;
19203 tcg_temp_free_i32(twd);
19204 tcg_temp_free_i32(tws);
19205 tcg_temp_free_i32(twt);
19206 tcg_temp_free_i32(tdf);
19209 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
19211 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
19212 (op & (0x7 << 18)))
19213 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19214 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19215 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19216 uint8_t df = (ctx->opcode >> 16) & 0x3;
19217 TCGv_i32 twd = tcg_const_i32(wd);
19218 TCGv_i32 tws = tcg_const_i32(ws);
19219 TCGv_i32 twt = tcg_const_i32(wt);
19220 TCGv_i32 tdf = tcg_const_i32(df);
19222 switch (MASK_MSA_2R(ctx->opcode)) {
19223 case OPC_FILL_df:
19224 #if !defined(TARGET_MIPS64)
19225 /* Double format valid only for MIPS64 */
19226 if (df == DF_DOUBLE) {
19227 generate_exception(ctx, EXCP_RI);
19228 break;
19230 #endif
19231 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
19232 break;
19233 case OPC_PCNT_df:
19234 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
19235 break;
19236 case OPC_NLOC_df:
19237 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
19238 break;
19239 case OPC_NLZC_df:
19240 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
19241 break;
19242 default:
19243 MIPS_INVAL("MSA instruction");
19244 generate_exception(ctx, EXCP_RI);
19245 break;
19248 tcg_temp_free_i32(twd);
19249 tcg_temp_free_i32(tws);
19250 tcg_temp_free_i32(twt);
19251 tcg_temp_free_i32(tdf);
19254 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
19256 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
19257 (op & (0xf << 17)))
19258 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19259 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19260 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19261 uint8_t df = (ctx->opcode >> 16) & 0x1;
19262 TCGv_i32 twd = tcg_const_i32(wd);
19263 TCGv_i32 tws = tcg_const_i32(ws);
19264 TCGv_i32 twt = tcg_const_i32(wt);
19265 /* adjust df value for floating-point instruction */
19266 TCGv_i32 tdf = tcg_const_i32(df + 2);
19268 switch (MASK_MSA_2RF(ctx->opcode)) {
19269 case OPC_FCLASS_df:
19270 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
19271 break;
19272 case OPC_FTRUNC_S_df:
19273 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
19274 break;
19275 case OPC_FTRUNC_U_df:
19276 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
19277 break;
19278 case OPC_FSQRT_df:
19279 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
19280 break;
19281 case OPC_FRSQRT_df:
19282 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
19283 break;
19284 case OPC_FRCP_df:
19285 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
19286 break;
19287 case OPC_FRINT_df:
19288 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
19289 break;
19290 case OPC_FLOG2_df:
19291 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
19292 break;
19293 case OPC_FEXUPL_df:
19294 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
19295 break;
19296 case OPC_FEXUPR_df:
19297 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
19298 break;
19299 case OPC_FFQL_df:
19300 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
19301 break;
19302 case OPC_FFQR_df:
19303 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
19304 break;
19305 case OPC_FTINT_S_df:
19306 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
19307 break;
19308 case OPC_FTINT_U_df:
19309 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
19310 break;
19311 case OPC_FFINT_S_df:
19312 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
19313 break;
19314 case OPC_FFINT_U_df:
19315 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
19316 break;
19319 tcg_temp_free_i32(twd);
19320 tcg_temp_free_i32(tws);
19321 tcg_temp_free_i32(twt);
19322 tcg_temp_free_i32(tdf);
19325 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
19327 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
19328 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19329 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19330 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19331 TCGv_i32 twd = tcg_const_i32(wd);
19332 TCGv_i32 tws = tcg_const_i32(ws);
19333 TCGv_i32 twt = tcg_const_i32(wt);
19335 switch (MASK_MSA_VEC(ctx->opcode)) {
19336 case OPC_AND_V:
19337 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
19338 break;
19339 case OPC_OR_V:
19340 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
19341 break;
19342 case OPC_NOR_V:
19343 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
19344 break;
19345 case OPC_XOR_V:
19346 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
19347 break;
19348 case OPC_BMNZ_V:
19349 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
19350 break;
19351 case OPC_BMZ_V:
19352 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
19353 break;
19354 case OPC_BSEL_V:
19355 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
19356 break;
19357 default:
19358 MIPS_INVAL("MSA instruction");
19359 generate_exception(ctx, EXCP_RI);
19360 break;
19363 tcg_temp_free_i32(twd);
19364 tcg_temp_free_i32(tws);
19365 tcg_temp_free_i32(twt);
19368 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
19370 switch (MASK_MSA_VEC(ctx->opcode)) {
19371 case OPC_AND_V:
19372 case OPC_OR_V:
19373 case OPC_NOR_V:
19374 case OPC_XOR_V:
19375 case OPC_BMNZ_V:
19376 case OPC_BMZ_V:
19377 case OPC_BSEL_V:
19378 gen_msa_vec_v(env, ctx);
19379 break;
19380 case OPC_MSA_2R:
19381 gen_msa_2r(env, ctx);
19382 break;
19383 case OPC_MSA_2RF:
19384 gen_msa_2rf(env, ctx);
19385 break;
19386 default:
19387 MIPS_INVAL("MSA instruction");
19388 generate_exception(ctx, EXCP_RI);
19389 break;
19393 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
19395 uint32_t opcode = ctx->opcode;
19396 check_insn(ctx, ASE_MSA);
19397 check_msa_access(ctx);
19399 switch (MASK_MSA_MINOR(opcode)) {
19400 case OPC_MSA_I8_00:
19401 case OPC_MSA_I8_01:
19402 case OPC_MSA_I8_02:
19403 gen_msa_i8(env, ctx);
19404 break;
19405 case OPC_MSA_I5_06:
19406 case OPC_MSA_I5_07:
19407 gen_msa_i5(env, ctx);
19408 break;
19409 case OPC_MSA_BIT_09:
19410 case OPC_MSA_BIT_0A:
19411 gen_msa_bit(env, ctx);
19412 break;
19413 case OPC_MSA_3R_0D:
19414 case OPC_MSA_3R_0E:
19415 case OPC_MSA_3R_0F:
19416 case OPC_MSA_3R_10:
19417 case OPC_MSA_3R_11:
19418 case OPC_MSA_3R_12:
19419 case OPC_MSA_3R_13:
19420 case OPC_MSA_3R_14:
19421 case OPC_MSA_3R_15:
19422 gen_msa_3r(env, ctx);
19423 break;
19424 case OPC_MSA_ELM:
19425 gen_msa_elm(env, ctx);
19426 break;
19427 case OPC_MSA_3RF_1A:
19428 case OPC_MSA_3RF_1B:
19429 case OPC_MSA_3RF_1C:
19430 gen_msa_3rf(env, ctx);
19431 break;
19432 case OPC_MSA_VEC:
19433 gen_msa_vec(env, ctx);
19434 break;
19435 case OPC_LD_B:
19436 case OPC_LD_H:
19437 case OPC_LD_W:
19438 case OPC_LD_D:
19439 case OPC_ST_B:
19440 case OPC_ST_H:
19441 case OPC_ST_W:
19442 case OPC_ST_D:
19444 int32_t s10 = sextract32(ctx->opcode, 16, 10);
19445 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
19446 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19447 uint8_t df = (ctx->opcode >> 0) & 0x3;
19449 TCGv_i32 twd = tcg_const_i32(wd);
19450 TCGv taddr = tcg_temp_new();
19451 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
19453 switch (MASK_MSA_MINOR(opcode)) {
19454 case OPC_LD_B:
19455 gen_helper_msa_ld_b(cpu_env, twd, taddr);
19456 break;
19457 case OPC_LD_H:
19458 gen_helper_msa_ld_h(cpu_env, twd, taddr);
19459 break;
19460 case OPC_LD_W:
19461 gen_helper_msa_ld_w(cpu_env, twd, taddr);
19462 break;
19463 case OPC_LD_D:
19464 gen_helper_msa_ld_d(cpu_env, twd, taddr);
19465 break;
19466 case OPC_ST_B:
19467 gen_helper_msa_st_b(cpu_env, twd, taddr);
19468 break;
19469 case OPC_ST_H:
19470 gen_helper_msa_st_h(cpu_env, twd, taddr);
19471 break;
19472 case OPC_ST_W:
19473 gen_helper_msa_st_w(cpu_env, twd, taddr);
19474 break;
19475 case OPC_ST_D:
19476 gen_helper_msa_st_d(cpu_env, twd, taddr);
19477 break;
19480 tcg_temp_free_i32(twd);
19481 tcg_temp_free(taddr);
19483 break;
19484 default:
19485 MIPS_INVAL("MSA instruction");
19486 generate_exception(ctx, EXCP_RI);
19487 break;
19492 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
19494 int32_t offset;
19495 int rs, rt, rd, sa;
19496 uint32_t op, op1;
19497 int16_t imm;
19499 /* make sure instructions are on a word boundary */
19500 if (ctx->pc & 0x3) {
19501 env->CP0_BadVAddr = ctx->pc;
19502 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
19503 ctx->bstate = BS_STOP;
19504 return;
19507 /* Handle blikely not taken case */
19508 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
19509 TCGLabel *l1 = gen_new_label();
19511 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
19512 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
19513 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
19514 gen_goto_tb(ctx, 1, ctx->pc + 4);
19515 gen_set_label(l1);
19518 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
19519 tcg_gen_debug_insn_start(ctx->pc);
19522 op = MASK_OP_MAJOR(ctx->opcode);
19523 rs = (ctx->opcode >> 21) & 0x1f;
19524 rt = (ctx->opcode >> 16) & 0x1f;
19525 rd = (ctx->opcode >> 11) & 0x1f;
19526 sa = (ctx->opcode >> 6) & 0x1f;
19527 imm = (int16_t)ctx->opcode;
19528 switch (op) {
19529 case OPC_SPECIAL:
19530 decode_opc_special(env, ctx);
19531 break;
19532 case OPC_SPECIAL2:
19533 decode_opc_special2_legacy(env, ctx);
19534 break;
19535 case OPC_SPECIAL3:
19536 decode_opc_special3(env, ctx);
19537 break;
19538 case OPC_REGIMM:
19539 op1 = MASK_REGIMM(ctx->opcode);
19540 switch (op1) {
19541 case OPC_BLTZL: /* REGIMM branches */
19542 case OPC_BGEZL:
19543 case OPC_BLTZALL:
19544 case OPC_BGEZALL:
19545 check_insn(ctx, ISA_MIPS2);
19546 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19547 /* Fallthrough */
19548 case OPC_BLTZ:
19549 case OPC_BGEZ:
19550 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19551 break;
19552 case OPC_BLTZAL:
19553 case OPC_BGEZAL:
19554 if (ctx->insn_flags & ISA_MIPS32R6) {
19555 if (rs == 0) {
19556 /* OPC_NAL, OPC_BAL */
19557 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
19558 } else {
19559 generate_exception(ctx, EXCP_RI);
19561 } else {
19562 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19564 break;
19565 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
19566 case OPC_TNEI:
19567 check_insn(ctx, ISA_MIPS2);
19568 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19569 gen_trap(ctx, op1, rs, -1, imm);
19570 break;
19571 case OPC_SYNCI:
19572 check_insn(ctx, ISA_MIPS32R2);
19573 /* Break the TB to be able to sync copied instructions
19574 immediately */
19575 ctx->bstate = BS_STOP;
19576 break;
19577 case OPC_BPOSGE32: /* MIPS DSP branch */
19578 #if defined(TARGET_MIPS64)
19579 case OPC_BPOSGE64:
19580 #endif
19581 check_dsp(ctx);
19582 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
19583 break;
19584 #if defined(TARGET_MIPS64)
19585 case OPC_DAHI:
19586 check_insn(ctx, ISA_MIPS32R6);
19587 check_mips_64(ctx);
19588 if (rs != 0) {
19589 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
19591 MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm);
19592 break;
19593 case OPC_DATI:
19594 check_insn(ctx, ISA_MIPS32R6);
19595 check_mips_64(ctx);
19596 if (rs != 0) {
19597 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
19599 MIPS_DEBUG("dati %s, %04x", regnames[rs], imm);
19600 break;
19601 #endif
19602 default: /* Invalid */
19603 MIPS_INVAL("regimm");
19604 generate_exception(ctx, EXCP_RI);
19605 break;
19607 break;
19608 case OPC_CP0:
19609 check_cp0_enabled(ctx);
19610 op1 = MASK_CP0(ctx->opcode);
19611 switch (op1) {
19612 case OPC_MFC0:
19613 case OPC_MTC0:
19614 case OPC_MFTR:
19615 case OPC_MTTR:
19616 case OPC_MFHC0:
19617 case OPC_MTHC0:
19618 #if defined(TARGET_MIPS64)
19619 case OPC_DMFC0:
19620 case OPC_DMTC0:
19621 #endif
19622 #ifndef CONFIG_USER_ONLY
19623 gen_cp0(env, ctx, op1, rt, rd);
19624 #endif /* !CONFIG_USER_ONLY */
19625 break;
19626 case OPC_C0_FIRST ... OPC_C0_LAST:
19627 #ifndef CONFIG_USER_ONLY
19628 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
19629 #endif /* !CONFIG_USER_ONLY */
19630 break;
19631 case OPC_MFMC0:
19632 #ifndef CONFIG_USER_ONLY
19634 uint32_t op2;
19635 TCGv t0 = tcg_temp_new();
19637 op2 = MASK_MFMC0(ctx->opcode);
19638 switch (op2) {
19639 case OPC_DMT:
19640 check_insn(ctx, ASE_MT);
19641 gen_helper_dmt(t0);
19642 gen_store_gpr(t0, rt);
19643 break;
19644 case OPC_EMT:
19645 check_insn(ctx, ASE_MT);
19646 gen_helper_emt(t0);
19647 gen_store_gpr(t0, rt);
19648 break;
19649 case OPC_DVPE:
19650 check_insn(ctx, ASE_MT);
19651 gen_helper_dvpe(t0, cpu_env);
19652 gen_store_gpr(t0, rt);
19653 break;
19654 case OPC_EVPE:
19655 check_insn(ctx, ASE_MT);
19656 gen_helper_evpe(t0, cpu_env);
19657 gen_store_gpr(t0, rt);
19658 break;
19659 case OPC_DI:
19660 check_insn(ctx, ISA_MIPS32R2);
19661 save_cpu_state(ctx, 1);
19662 gen_helper_di(t0, cpu_env);
19663 gen_store_gpr(t0, rt);
19664 /* Stop translation as we may have switched
19665 the execution mode. */
19666 ctx->bstate = BS_STOP;
19667 break;
19668 case OPC_EI:
19669 check_insn(ctx, ISA_MIPS32R2);
19670 save_cpu_state(ctx, 1);
19671 gen_helper_ei(t0, cpu_env);
19672 gen_store_gpr(t0, rt);
19673 /* Stop translation as we may have switched
19674 the execution mode. */
19675 ctx->bstate = BS_STOP;
19676 break;
19677 default: /* Invalid */
19678 MIPS_INVAL("mfmc0");
19679 generate_exception(ctx, EXCP_RI);
19680 break;
19682 tcg_temp_free(t0);
19684 #endif /* !CONFIG_USER_ONLY */
19685 break;
19686 case OPC_RDPGPR:
19687 check_insn(ctx, ISA_MIPS32R2);
19688 gen_load_srsgpr(rt, rd);
19689 break;
19690 case OPC_WRPGPR:
19691 check_insn(ctx, ISA_MIPS32R2);
19692 gen_store_srsgpr(rt, rd);
19693 break;
19694 default:
19695 MIPS_INVAL("cp0");
19696 generate_exception(ctx, EXCP_RI);
19697 break;
19699 break;
19700 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
19701 if (ctx->insn_flags & ISA_MIPS32R6) {
19702 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
19703 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19704 } else {
19705 /* OPC_ADDI */
19706 /* Arithmetic with immediate opcode */
19707 gen_arith_imm(ctx, op, rt, rs, imm);
19709 break;
19710 case OPC_ADDIU:
19711 gen_arith_imm(ctx, op, rt, rs, imm);
19712 break;
19713 case OPC_SLTI: /* Set on less than with immediate opcode */
19714 case OPC_SLTIU:
19715 gen_slt_imm(ctx, op, rt, rs, imm);
19716 break;
19717 case OPC_ANDI: /* Arithmetic with immediate opcode */
19718 case OPC_LUI: /* OPC_AUI */
19719 case OPC_ORI:
19720 case OPC_XORI:
19721 gen_logic_imm(ctx, op, rt, rs, imm);
19722 break;
19723 case OPC_J ... OPC_JAL: /* Jump */
19724 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19725 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19726 break;
19727 /* Branch */
19728 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
19729 if (ctx->insn_flags & ISA_MIPS32R6) {
19730 if (rt == 0) {
19731 generate_exception(ctx, EXCP_RI);
19732 break;
19734 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
19735 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19736 } else {
19737 /* OPC_BLEZL */
19738 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19740 break;
19741 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
19742 if (ctx->insn_flags & ISA_MIPS32R6) {
19743 if (rt == 0) {
19744 generate_exception(ctx, EXCP_RI);
19745 break;
19747 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
19748 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19749 } else {
19750 /* OPC_BGTZL */
19751 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19753 break;
19754 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
19755 if (rt == 0) {
19756 /* OPC_BLEZ */
19757 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19758 } else {
19759 check_insn(ctx, ISA_MIPS32R6);
19760 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
19761 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19763 break;
19764 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
19765 if (rt == 0) {
19766 /* OPC_BGTZ */
19767 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19768 } else {
19769 check_insn(ctx, ISA_MIPS32R6);
19770 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
19771 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19773 break;
19774 case OPC_BEQL:
19775 case OPC_BNEL:
19776 check_insn(ctx, ISA_MIPS2);
19777 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19778 /* Fallthrough */
19779 case OPC_BEQ:
19780 case OPC_BNE:
19781 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19782 break;
19783 case OPC_LL: /* Load and stores */
19784 check_insn(ctx, ISA_MIPS2);
19785 /* Fallthrough */
19786 case OPC_LWL:
19787 case OPC_LWR:
19788 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19789 /* Fallthrough */
19790 case OPC_LB ... OPC_LH:
19791 case OPC_LW ... OPC_LHU:
19792 gen_ld(ctx, op, rt, rs, imm);
19793 break;
19794 case OPC_SWL:
19795 case OPC_SWR:
19796 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19797 /* fall through */
19798 case OPC_SB ... OPC_SH:
19799 case OPC_SW:
19800 gen_st(ctx, op, rt, rs, imm);
19801 break;
19802 case OPC_SC:
19803 check_insn(ctx, ISA_MIPS2);
19804 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19805 gen_st_cond(ctx, op, rt, rs, imm);
19806 break;
19807 case OPC_CACHE:
19808 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19809 check_cp0_enabled(ctx);
19810 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
19811 /* Treat as NOP. */
19812 break;
19813 case OPC_PREF:
19814 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19815 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
19816 /* Treat as NOP. */
19817 break;
19819 /* Floating point (COP1). */
19820 case OPC_LWC1:
19821 case OPC_LDC1:
19822 case OPC_SWC1:
19823 case OPC_SDC1:
19824 gen_cop1_ldst(ctx, op, rt, rs, imm);
19825 break;
19827 case OPC_CP1:
19828 op1 = MASK_CP1(ctx->opcode);
19830 switch (op1) {
19831 case OPC_MFHC1:
19832 case OPC_MTHC1:
19833 check_cp1_enabled(ctx);
19834 check_insn(ctx, ISA_MIPS32R2);
19835 case OPC_MFC1:
19836 case OPC_CFC1:
19837 case OPC_MTC1:
19838 case OPC_CTC1:
19839 check_cp1_enabled(ctx);
19840 gen_cp1(ctx, op1, rt, rd);
19841 break;
19842 #if defined(TARGET_MIPS64)
19843 case OPC_DMFC1:
19844 case OPC_DMTC1:
19845 check_cp1_enabled(ctx);
19846 check_insn(ctx, ISA_MIPS3);
19847 check_mips_64(ctx);
19848 gen_cp1(ctx, op1, rt, rd);
19849 break;
19850 #endif
19851 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
19852 check_cp1_enabled(ctx);
19853 if (ctx->insn_flags & ISA_MIPS32R6) {
19854 /* OPC_BC1EQZ */
19855 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19856 rt, imm << 2, 4);
19857 } else {
19858 /* OPC_BC1ANY2 */
19859 check_cop1x(ctx);
19860 check_insn(ctx, ASE_MIPS3D);
19861 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19862 (rt >> 2) & 0x7, imm << 2);
19864 break;
19865 case OPC_BC1NEZ:
19866 check_cp1_enabled(ctx);
19867 check_insn(ctx, ISA_MIPS32R6);
19868 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19869 rt, imm << 2, 4);
19870 break;
19871 case OPC_BC1ANY4:
19872 check_cp1_enabled(ctx);
19873 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19874 check_cop1x(ctx);
19875 check_insn(ctx, ASE_MIPS3D);
19876 /* fall through */
19877 case OPC_BC1:
19878 check_cp1_enabled(ctx);
19879 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19880 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19881 (rt >> 2) & 0x7, imm << 2);
19882 break;
19883 case OPC_PS_FMT:
19884 check_ps(ctx);
19885 /* fall through */
19886 case OPC_S_FMT:
19887 case OPC_D_FMT:
19888 check_cp1_enabled(ctx);
19889 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19890 (imm >> 8) & 0x7);
19891 break;
19892 case OPC_W_FMT:
19893 case OPC_L_FMT:
19895 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
19896 check_cp1_enabled(ctx);
19897 if (ctx->insn_flags & ISA_MIPS32R6) {
19898 switch (r6_op) {
19899 case R6_OPC_CMP_AF_S:
19900 case R6_OPC_CMP_UN_S:
19901 case R6_OPC_CMP_EQ_S:
19902 case R6_OPC_CMP_UEQ_S:
19903 case R6_OPC_CMP_LT_S:
19904 case R6_OPC_CMP_ULT_S:
19905 case R6_OPC_CMP_LE_S:
19906 case R6_OPC_CMP_ULE_S:
19907 case R6_OPC_CMP_SAF_S:
19908 case R6_OPC_CMP_SUN_S:
19909 case R6_OPC_CMP_SEQ_S:
19910 case R6_OPC_CMP_SEUQ_S:
19911 case R6_OPC_CMP_SLT_S:
19912 case R6_OPC_CMP_SULT_S:
19913 case R6_OPC_CMP_SLE_S:
19914 case R6_OPC_CMP_SULE_S:
19915 case R6_OPC_CMP_OR_S:
19916 case R6_OPC_CMP_UNE_S:
19917 case R6_OPC_CMP_NE_S:
19918 case R6_OPC_CMP_SOR_S:
19919 case R6_OPC_CMP_SUNE_S:
19920 case R6_OPC_CMP_SNE_S:
19921 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19922 break;
19923 case R6_OPC_CMP_AF_D:
19924 case R6_OPC_CMP_UN_D:
19925 case R6_OPC_CMP_EQ_D:
19926 case R6_OPC_CMP_UEQ_D:
19927 case R6_OPC_CMP_LT_D:
19928 case R6_OPC_CMP_ULT_D:
19929 case R6_OPC_CMP_LE_D:
19930 case R6_OPC_CMP_ULE_D:
19931 case R6_OPC_CMP_SAF_D:
19932 case R6_OPC_CMP_SUN_D:
19933 case R6_OPC_CMP_SEQ_D:
19934 case R6_OPC_CMP_SEUQ_D:
19935 case R6_OPC_CMP_SLT_D:
19936 case R6_OPC_CMP_SULT_D:
19937 case R6_OPC_CMP_SLE_D:
19938 case R6_OPC_CMP_SULE_D:
19939 case R6_OPC_CMP_OR_D:
19940 case R6_OPC_CMP_UNE_D:
19941 case R6_OPC_CMP_NE_D:
19942 case R6_OPC_CMP_SOR_D:
19943 case R6_OPC_CMP_SUNE_D:
19944 case R6_OPC_CMP_SNE_D:
19945 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19946 break;
19947 default:
19948 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
19949 rt, rd, sa, (imm >> 8) & 0x7);
19951 break;
19953 } else {
19954 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19955 (imm >> 8) & 0x7);
19957 break;
19959 case OPC_BZ_V:
19960 case OPC_BNZ_V:
19961 case OPC_BZ_B:
19962 case OPC_BZ_H:
19963 case OPC_BZ_W:
19964 case OPC_BZ_D:
19965 case OPC_BNZ_B:
19966 case OPC_BNZ_H:
19967 case OPC_BNZ_W:
19968 case OPC_BNZ_D:
19969 check_insn(ctx, ASE_MSA);
19970 gen_msa_branch(env, ctx, op1);
19971 break;
19972 default:
19973 MIPS_INVAL("cp1");
19974 generate_exception(ctx, EXCP_RI);
19975 break;
19977 break;
19979 /* Compact branches [R6] and COP2 [non-R6] */
19980 case OPC_BC: /* OPC_LWC2 */
19981 case OPC_BALC: /* OPC_SWC2 */
19982 if (ctx->insn_flags & ISA_MIPS32R6) {
19983 /* OPC_BC, OPC_BALC */
19984 gen_compute_compact_branch(ctx, op, 0, 0,
19985 sextract32(ctx->opcode << 2, 0, 28));
19986 } else {
19987 /* OPC_LWC2, OPC_SWC2 */
19988 /* COP2: Not implemented. */
19989 generate_exception_err(ctx, EXCP_CpU, 2);
19991 break;
19992 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
19993 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
19994 if (ctx->insn_flags & ISA_MIPS32R6) {
19995 if (rs != 0) {
19996 /* OPC_BEQZC, OPC_BNEZC */
19997 gen_compute_compact_branch(ctx, op, rs, 0,
19998 sextract32(ctx->opcode << 2, 0, 23));
19999 } else {
20000 /* OPC_JIC, OPC_JIALC */
20001 gen_compute_compact_branch(ctx, op, 0, rt, imm);
20003 } else {
20004 /* OPC_LWC2, OPC_SWC2 */
20005 /* COP2: Not implemented. */
20006 generate_exception_err(ctx, EXCP_CpU, 2);
20008 break;
20009 case OPC_CP2:
20010 check_insn(ctx, INSN_LOONGSON2F);
20011 /* Note that these instructions use different fields. */
20012 gen_loongson_multimedia(ctx, sa, rd, rt);
20013 break;
20015 case OPC_CP3:
20016 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20017 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20018 check_cp1_enabled(ctx);
20019 op1 = MASK_CP3(ctx->opcode);
20020 switch (op1) {
20021 case OPC_LUXC1:
20022 case OPC_SUXC1:
20023 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
20024 /* Fallthrough */
20025 case OPC_LWXC1:
20026 case OPC_LDXC1:
20027 case OPC_SWXC1:
20028 case OPC_SDXC1:
20029 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20030 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
20031 break;
20032 case OPC_PREFX:
20033 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20034 /* Treat as NOP. */
20035 break;
20036 case OPC_ALNV_PS:
20037 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
20038 /* Fallthrough */
20039 case OPC_MADD_S:
20040 case OPC_MADD_D:
20041 case OPC_MADD_PS:
20042 case OPC_MSUB_S:
20043 case OPC_MSUB_D:
20044 case OPC_MSUB_PS:
20045 case OPC_NMADD_S:
20046 case OPC_NMADD_D:
20047 case OPC_NMADD_PS:
20048 case OPC_NMSUB_S:
20049 case OPC_NMSUB_D:
20050 case OPC_NMSUB_PS:
20051 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20052 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
20053 break;
20054 default:
20055 MIPS_INVAL("cp3");
20056 generate_exception (ctx, EXCP_RI);
20057 break;
20059 } else {
20060 generate_exception_err(ctx, EXCP_CpU, 1);
20062 break;
20064 #if defined(TARGET_MIPS64)
20065 /* MIPS64 opcodes */
20066 case OPC_LDL ... OPC_LDR:
20067 case OPC_LLD:
20068 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20069 /* fall through */
20070 case OPC_LWU:
20071 case OPC_LD:
20072 check_insn(ctx, ISA_MIPS3);
20073 check_mips_64(ctx);
20074 gen_ld(ctx, op, rt, rs, imm);
20075 break;
20076 case OPC_SDL ... OPC_SDR:
20077 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20078 /* fall through */
20079 case OPC_SD:
20080 check_insn(ctx, ISA_MIPS3);
20081 check_mips_64(ctx);
20082 gen_st(ctx, op, rt, rs, imm);
20083 break;
20084 case OPC_SCD:
20085 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20086 check_insn(ctx, ISA_MIPS3);
20087 check_mips_64(ctx);
20088 gen_st_cond(ctx, op, rt, rs, imm);
20089 break;
20090 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
20091 if (ctx->insn_flags & ISA_MIPS32R6) {
20092 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
20093 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
20094 } else {
20095 /* OPC_DADDI */
20096 check_insn(ctx, ISA_MIPS3);
20097 check_mips_64(ctx);
20098 gen_arith_imm(ctx, op, rt, rs, imm);
20100 break;
20101 case OPC_DADDIU:
20102 check_insn(ctx, ISA_MIPS3);
20103 check_mips_64(ctx);
20104 gen_arith_imm(ctx, op, rt, rs, imm);
20105 break;
20106 #else
20107 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
20108 if (ctx->insn_flags & ISA_MIPS32R6) {
20109 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
20110 } else {
20111 MIPS_INVAL("major opcode");
20112 generate_exception(ctx, EXCP_RI);
20114 break;
20115 #endif
20116 case OPC_DAUI: /* OPC_JALX */
20117 if (ctx->insn_flags & ISA_MIPS32R6) {
20118 #if defined(TARGET_MIPS64)
20119 /* OPC_DAUI */
20120 check_mips_64(ctx);
20121 if (rt != 0) {
20122 TCGv t0 = tcg_temp_new();
20123 gen_load_gpr(t0, rs);
20124 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
20125 tcg_temp_free(t0);
20127 MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm);
20128 #else
20129 generate_exception(ctx, EXCP_RI);
20130 MIPS_INVAL("major opcode");
20131 #endif
20132 } else {
20133 /* OPC_JALX */
20134 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
20135 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
20136 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
20138 break;
20139 case OPC_MSA: /* OPC_MDMX */
20140 /* MDMX: Not implemented. */
20141 gen_msa(env, ctx);
20142 break;
20143 case OPC_PCREL:
20144 check_insn(ctx, ISA_MIPS32R6);
20145 gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
20146 break;
20147 default: /* Invalid */
20148 MIPS_INVAL("major opcode");
20149 generate_exception(ctx, EXCP_RI);
20150 break;
20154 static inline void
20155 gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
20156 bool search_pc)
20158 CPUState *cs = CPU(cpu);
20159 CPUMIPSState *env = &cpu->env;
20160 DisasContext ctx;
20161 target_ulong pc_start;
20162 target_ulong next_page_start;
20163 CPUBreakpoint *bp;
20164 int j, lj = -1;
20165 int num_insns;
20166 int max_insns;
20167 int insn_bytes;
20168 int is_slot;
20170 if (search_pc)
20171 qemu_log("search pc %d\n", search_pc);
20173 pc_start = tb->pc;
20174 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
20175 ctx.pc = pc_start;
20176 ctx.saved_pc = -1;
20177 ctx.singlestep_enabled = cs->singlestep_enabled;
20178 ctx.insn_flags = env->insn_flags;
20179 ctx.CP0_Config1 = env->CP0_Config1;
20180 ctx.tb = tb;
20181 ctx.bstate = BS_NONE;
20182 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
20183 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
20184 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
20185 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
20186 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
20187 ctx.PAMask = env->PAMask;
20188 ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
20189 ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
20190 /* Restore delay slot state from the tb context. */
20191 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
20192 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
20193 ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
20194 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
20195 restore_cpu_state(env, &ctx);
20196 #ifdef CONFIG_USER_ONLY
20197 ctx.mem_idx = MIPS_HFLAG_UM;
20198 #else
20199 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
20200 #endif
20201 ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
20202 MO_UNALN : MO_ALIGN;
20203 num_insns = 0;
20204 max_insns = tb->cflags & CF_COUNT_MASK;
20205 if (max_insns == 0)
20206 max_insns = CF_COUNT_MASK;
20207 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
20208 gen_tb_start(tb);
20209 while (ctx.bstate == BS_NONE) {
20210 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
20211 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
20212 if (bp->pc == ctx.pc) {
20213 save_cpu_state(&ctx, 1);
20214 ctx.bstate = BS_BRANCH;
20215 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
20216 /* Include the breakpoint location or the tb won't
20217 * be flushed when it must be. */
20218 ctx.pc += 4;
20219 goto done_generating;
20224 if (search_pc) {
20225 j = tcg_op_buf_count();
20226 if (lj < j) {
20227 lj++;
20228 while (lj < j)
20229 tcg_ctx.gen_opc_instr_start[lj++] = 0;
20231 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
20232 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
20233 gen_opc_btarget[lj] = ctx.btarget;
20234 tcg_ctx.gen_opc_instr_start[lj] = 1;
20235 tcg_ctx.gen_opc_icount[lj] = num_insns;
20237 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
20238 gen_io_start();
20240 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
20241 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
20242 ctx.opcode = cpu_ldl_code(env, ctx.pc);
20243 insn_bytes = 4;
20244 decode_opc(env, &ctx);
20245 } else if (ctx.insn_flags & ASE_MICROMIPS) {
20246 ctx.opcode = cpu_lduw_code(env, ctx.pc);
20247 insn_bytes = decode_micromips_opc(env, &ctx);
20248 } else if (ctx.insn_flags & ASE_MIPS16) {
20249 ctx.opcode = cpu_lduw_code(env, ctx.pc);
20250 insn_bytes = decode_mips16_opc(env, &ctx);
20251 } else {
20252 generate_exception(&ctx, EXCP_RI);
20253 ctx.bstate = BS_STOP;
20254 break;
20257 if (ctx.hflags & MIPS_HFLAG_BMASK) {
20258 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
20259 MIPS_HFLAG_FBNSLOT))) {
20260 /* force to generate branch as there is neither delay nor
20261 forbidden slot */
20262 is_slot = 1;
20264 if ((ctx.hflags & MIPS_HFLAG_M16) &&
20265 (ctx.hflags & MIPS_HFLAG_FBNSLOT)) {
20266 /* Force to generate branch as microMIPS R6 doesn't restrict
20267 branches in the forbidden slot. */
20268 is_slot = 1;
20271 if (is_slot) {
20272 gen_branch(&ctx, insn_bytes);
20274 ctx.pc += insn_bytes;
20276 num_insns++;
20278 /* Execute a branch and its delay slot as a single instruction.
20279 This is what GDB expects and is consistent with what the
20280 hardware does (e.g. if a delay slot instruction faults, the
20281 reported PC is the PC of the branch). */
20282 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
20283 break;
20286 if (ctx.pc >= next_page_start) {
20287 break;
20290 if (tcg_op_buf_full()) {
20291 break;
20294 if (num_insns >= max_insns)
20295 break;
20297 if (singlestep)
20298 break;
20300 if (tb->cflags & CF_LAST_IO) {
20301 gen_io_end();
20303 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
20304 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
20305 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
20306 } else {
20307 switch (ctx.bstate) {
20308 case BS_STOP:
20309 gen_goto_tb(&ctx, 0, ctx.pc);
20310 break;
20311 case BS_NONE:
20312 save_cpu_state(&ctx, 0);
20313 gen_goto_tb(&ctx, 0, ctx.pc);
20314 break;
20315 case BS_EXCP:
20316 tcg_gen_exit_tb(0);
20317 break;
20318 case BS_BRANCH:
20319 default:
20320 break;
20323 done_generating:
20324 gen_tb_end(tb, num_insns);
20326 if (search_pc) {
20327 j = tcg_op_buf_count();
20328 lj++;
20329 while (lj <= j)
20330 tcg_ctx.gen_opc_instr_start[lj++] = 0;
20331 } else {
20332 tb->size = ctx.pc - pc_start;
20333 tb->icount = num_insns;
20335 #ifdef DEBUG_DISAS
20336 LOG_DISAS("\n");
20337 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
20338 qemu_log("IN: %s\n", lookup_symbol(pc_start));
20339 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
20340 qemu_log("\n");
20342 #endif
20345 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
20347 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
20350 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
20352 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
20355 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
20356 int flags)
20358 int i;
20359 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
20361 #define printfpr(fp) \
20362 do { \
20363 if (is_fpu64) \
20364 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20365 " fd:%13g fs:%13g psu: %13g\n", \
20366 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
20367 (double)(fp)->fd, \
20368 (double)(fp)->fs[FP_ENDIAN_IDX], \
20369 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
20370 else { \
20371 fpr_t tmp; \
20372 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
20373 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
20374 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20375 " fd:%13g fs:%13g psu:%13g\n", \
20376 tmp.w[FP_ENDIAN_IDX], tmp.d, \
20377 (double)tmp.fd, \
20378 (double)tmp.fs[FP_ENDIAN_IDX], \
20379 (double)tmp.fs[!FP_ENDIAN_IDX]); \
20381 } while(0)
20384 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
20385 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
20386 get_float_exception_flags(&env->active_fpu.fp_status));
20387 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
20388 fpu_fprintf(f, "%3s: ", fregnames[i]);
20389 printfpr(&env->active_fpu.fpr[i]);
20392 #undef printfpr
20395 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
20396 /* Debug help: The architecture requires 32bit code to maintain proper
20397 sign-extended values on 64bit machines. */
20399 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
20401 static void
20402 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
20403 fprintf_function cpu_fprintf,
20404 int flags)
20406 int i;
20408 if (!SIGN_EXT_P(env->active_tc.PC))
20409 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
20410 if (!SIGN_EXT_P(env->active_tc.HI[0]))
20411 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
20412 if (!SIGN_EXT_P(env->active_tc.LO[0]))
20413 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
20414 if (!SIGN_EXT_P(env->btarget))
20415 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
20417 for (i = 0; i < 32; i++) {
20418 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
20419 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
20422 if (!SIGN_EXT_P(env->CP0_EPC))
20423 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
20424 if (!SIGN_EXT_P(env->lladdr))
20425 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
20427 #endif
20429 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
20430 int flags)
20432 MIPSCPU *cpu = MIPS_CPU(cs);
20433 CPUMIPSState *env = &cpu->env;
20434 int i;
20436 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
20437 " LO=0x" TARGET_FMT_lx " ds %04x "
20438 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
20439 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
20440 env->hflags, env->btarget, env->bcond);
20441 for (i = 0; i < 32; i++) {
20442 if ((i & 3) == 0)
20443 cpu_fprintf(f, "GPR%02d:", i);
20444 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
20445 if ((i & 3) == 3)
20446 cpu_fprintf(f, "\n");
20449 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
20450 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
20451 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
20452 PRIx64 "\n",
20453 env->CP0_Config0, env->CP0_Config1, env->lladdr);
20454 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
20455 env->CP0_Config2, env->CP0_Config3);
20456 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
20457 env->CP0_Config4, env->CP0_Config5);
20458 if (env->hflags & MIPS_HFLAG_FPU)
20459 fpu_dump_state(env, f, cpu_fprintf, flags);
20460 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
20461 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
20462 #endif
20465 void mips_tcg_init(void)
20467 int i;
20468 static int inited;
20470 /* Initialize various static tables. */
20471 if (inited)
20472 return;
20474 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
20475 TCGV_UNUSED(cpu_gpr[0]);
20476 for (i = 1; i < 32; i++)
20477 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
20478 offsetof(CPUMIPSState, active_tc.gpr[i]),
20479 regnames[i]);
20481 for (i = 0; i < 32; i++) {
20482 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
20483 msa_wr_d[i * 2] =
20484 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]);
20485 /* The scalar floating-point unit (FPU) registers are mapped on
20486 * the MSA vector registers. */
20487 fpu_f64[i] = msa_wr_d[i * 2];
20488 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
20489 msa_wr_d[i * 2 + 1] =
20490 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + 1]);
20493 cpu_PC = tcg_global_mem_new(TCG_AREG0,
20494 offsetof(CPUMIPSState, active_tc.PC), "PC");
20495 for (i = 0; i < MIPS_DSP_ACC; i++) {
20496 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
20497 offsetof(CPUMIPSState, active_tc.HI[i]),
20498 regnames_HI[i]);
20499 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
20500 offsetof(CPUMIPSState, active_tc.LO[i]),
20501 regnames_LO[i]);
20503 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
20504 offsetof(CPUMIPSState, active_tc.DSPControl),
20505 "DSPControl");
20506 bcond = tcg_global_mem_new(TCG_AREG0,
20507 offsetof(CPUMIPSState, bcond), "bcond");
20508 btarget = tcg_global_mem_new(TCG_AREG0,
20509 offsetof(CPUMIPSState, btarget), "btarget");
20510 hflags = tcg_global_mem_new_i32(TCG_AREG0,
20511 offsetof(CPUMIPSState, hflags), "hflags");
20513 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
20514 offsetof(CPUMIPSState, active_fpu.fcr0),
20515 "fcr0");
20516 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
20517 offsetof(CPUMIPSState, active_fpu.fcr31),
20518 "fcr31");
20520 inited = 1;
20523 #include "translate_init.c"
20525 MIPSCPU *cpu_mips_init(const char *cpu_model)
20527 MIPSCPU *cpu;
20528 CPUMIPSState *env;
20529 const mips_def_t *def;
20531 def = cpu_mips_find_by_name(cpu_model);
20532 if (!def)
20533 return NULL;
20534 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
20535 env = &cpu->env;
20536 env->cpu_model = def;
20538 #ifndef CONFIG_USER_ONLY
20539 mmu_init(env, def);
20540 #endif
20541 fpu_init(env, def);
20542 mvp_init(env, def);
20544 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
20546 return cpu;
20549 void cpu_state_reset(CPUMIPSState *env)
20551 MIPSCPU *cpu = mips_env_get_cpu(env);
20552 CPUState *cs = CPU(cpu);
20554 /* Reset registers to their default values */
20555 env->CP0_PRid = env->cpu_model->CP0_PRid;
20556 env->CP0_Config0 = env->cpu_model->CP0_Config0;
20557 #ifdef TARGET_WORDS_BIGENDIAN
20558 env->CP0_Config0 |= (1 << CP0C0_BE);
20559 #endif
20560 env->CP0_Config1 = env->cpu_model->CP0_Config1;
20561 env->CP0_Config2 = env->cpu_model->CP0_Config2;
20562 env->CP0_Config3 = env->cpu_model->CP0_Config3;
20563 env->CP0_Config4 = env->cpu_model->CP0_Config4;
20564 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
20565 env->CP0_Config5 = env->cpu_model->CP0_Config5;
20566 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
20567 env->CP0_Config6 = env->cpu_model->CP0_Config6;
20568 env->CP0_Config7 = env->cpu_model->CP0_Config7;
20569 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
20570 << env->cpu_model->CP0_LLAddr_shift;
20571 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
20572 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
20573 env->CCRes = env->cpu_model->CCRes;
20574 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
20575 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
20576 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
20577 env->current_tc = 0;
20578 env->SEGBITS = env->cpu_model->SEGBITS;
20579 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
20580 #if defined(TARGET_MIPS64)
20581 if (env->cpu_model->insn_flags & ISA_MIPS3) {
20582 env->SEGMask |= 3ULL << 62;
20584 #endif
20585 env->PABITS = env->cpu_model->PABITS;
20586 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
20587 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
20588 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
20589 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
20590 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
20591 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
20592 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
20593 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
20594 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
20595 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
20596 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
20597 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
20598 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
20599 env->msair = env->cpu_model->MSAIR;
20600 env->insn_flags = env->cpu_model->insn_flags;
20602 #if defined(CONFIG_USER_ONLY)
20603 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
20604 # ifdef TARGET_MIPS64
20605 /* Enable 64-bit register mode. */
20606 env->CP0_Status |= (1 << CP0St_PX);
20607 # endif
20608 # ifdef TARGET_ABI_MIPSN64
20609 /* Enable 64-bit address mode. */
20610 env->CP0_Status |= (1 << CP0St_UX);
20611 # endif
20612 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
20613 hardware registers. */
20614 env->CP0_HWREna |= 0x0000000F;
20615 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
20616 env->CP0_Status |= (1 << CP0St_CU1);
20618 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
20619 env->CP0_Status |= (1 << CP0St_MX);
20621 # if defined(TARGET_MIPS64)
20622 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
20623 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
20624 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
20625 env->CP0_Status |= (1 << CP0St_FR);
20627 # endif
20628 #else
20629 if (env->hflags & MIPS_HFLAG_BMASK) {
20630 /* If the exception was raised from a delay slot,
20631 come back to the jump. */
20632 env->CP0_ErrorEPC = (env->active_tc.PC
20633 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
20634 } else {
20635 env->CP0_ErrorEPC = env->active_tc.PC;
20637 env->active_tc.PC = (int32_t)0xBFC00000;
20638 env->CP0_Random = env->tlb->nb_tlb - 1;
20639 env->tlb->tlb_in_use = env->tlb->nb_tlb;
20640 env->CP0_Wired = 0;
20641 env->CP0_EBase = (cs->cpu_index & 0x3FF);
20642 if (kvm_enabled()) {
20643 env->CP0_EBase |= 0x40000000;
20644 } else {
20645 env->CP0_EBase |= 0x80000000;
20647 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
20648 /* vectored interrupts not implemented, timer on int 7,
20649 no performance counters. */
20650 env->CP0_IntCtl = 0xe0000000;
20652 int i;
20654 for (i = 0; i < 7; i++) {
20655 env->CP0_WatchLo[i] = 0;
20656 env->CP0_WatchHi[i] = 0x80000000;
20658 env->CP0_WatchLo[7] = 0;
20659 env->CP0_WatchHi[7] = 0;
20661 /* Count register increments in debug mode, EJTAG version 1 */
20662 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
20664 cpu_mips_store_count(env, 1);
20666 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
20667 int i;
20669 /* Only TC0 on VPE 0 starts as active. */
20670 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
20671 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
20672 env->tcs[i].CP0_TCHalt = 1;
20674 env->active_tc.CP0_TCHalt = 1;
20675 cs->halted = 1;
20677 if (cs->cpu_index == 0) {
20678 /* VPE0 starts up enabled. */
20679 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
20680 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
20682 /* TC0 starts up unhalted. */
20683 cs->halted = 0;
20684 env->active_tc.CP0_TCHalt = 0;
20685 env->tcs[0].CP0_TCHalt = 0;
20686 /* With thread 0 active. */
20687 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
20688 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
20691 #endif
20692 if ((env->insn_flags & ISA_MIPS32R6) &&
20693 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
20694 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
20695 env->CP0_Status |= (1 << CP0St_FR);
20698 /* MSA */
20699 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
20700 msa_reset(env);
20703 compute_hflags(env);
20704 restore_rounding_mode(env);
20705 restore_flush_mode(env);
20706 restore_pamask(env);
20707 cs->exception_index = EXCP_NONE;
20709 if (semihosting_get_argc()) {
20710 /* UHI interface can be used to obtain argc and argv */
20711 env->active_tc.gpr[4] = -1;
20715 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
20717 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
20718 env->hflags &= ~MIPS_HFLAG_BMASK;
20719 env->hflags |= gen_opc_hflags[pc_pos];
20720 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
20721 case MIPS_HFLAG_BR:
20722 break;
20723 case MIPS_HFLAG_BC:
20724 case MIPS_HFLAG_BL:
20725 case MIPS_HFLAG_B:
20726 env->btarget = gen_opc_btarget[pc_pos];
20727 break;