cpu-exec: fix cpu_exec_nocache
[qemu.git] / target-mips / translate.c
blobf0b8e6ffe4e3a98e23d7992a2974af2239de84f1
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "cpu.h"
25 #include "disas/disas.h"
26 #include "tcg-op.h"
27 #include "exec/cpu_ldst.h"
29 #include "exec/helper-proto.h"
30 #include "exec/helper-gen.h"
31 #include "sysemu/kvm.h"
33 #include "trace-tcg.h"
36 #define MIPS_DEBUG_DISAS 0
37 //#define MIPS_DEBUG_SIGN_EXTENSIONS
39 /* MIPS major opcodes */
40 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
42 enum {
43 /* indirect opcode tables */
44 OPC_SPECIAL = (0x00 << 26),
45 OPC_REGIMM = (0x01 << 26),
46 OPC_CP0 = (0x10 << 26),
47 OPC_CP1 = (0x11 << 26),
48 OPC_CP2 = (0x12 << 26),
49 OPC_CP3 = (0x13 << 26),
50 OPC_SPECIAL2 = (0x1C << 26),
51 OPC_SPECIAL3 = (0x1F << 26),
52 /* arithmetic with immediate */
53 OPC_ADDI = (0x08 << 26),
54 OPC_ADDIU = (0x09 << 26),
55 OPC_SLTI = (0x0A << 26),
56 OPC_SLTIU = (0x0B << 26),
57 /* logic with immediate */
58 OPC_ANDI = (0x0C << 26),
59 OPC_ORI = (0x0D << 26),
60 OPC_XORI = (0x0E << 26),
61 OPC_LUI = (0x0F << 26),
62 /* arithmetic with immediate */
63 OPC_DADDI = (0x18 << 26),
64 OPC_DADDIU = (0x19 << 26),
65 /* Jump and branches */
66 OPC_J = (0x02 << 26),
67 OPC_JAL = (0x03 << 26),
68 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
69 OPC_BEQL = (0x14 << 26),
70 OPC_BNE = (0x05 << 26),
71 OPC_BNEL = (0x15 << 26),
72 OPC_BLEZ = (0x06 << 26),
73 OPC_BLEZL = (0x16 << 26),
74 OPC_BGTZ = (0x07 << 26),
75 OPC_BGTZL = (0x17 << 26),
76 OPC_JALX = (0x1D << 26),
77 OPC_DAUI = (0x1D << 26),
78 /* Load and stores */
79 OPC_LDL = (0x1A << 26),
80 OPC_LDR = (0x1B << 26),
81 OPC_LB = (0x20 << 26),
82 OPC_LH = (0x21 << 26),
83 OPC_LWL = (0x22 << 26),
84 OPC_LW = (0x23 << 26),
85 OPC_LWPC = OPC_LW | 0x5,
86 OPC_LBU = (0x24 << 26),
87 OPC_LHU = (0x25 << 26),
88 OPC_LWR = (0x26 << 26),
89 OPC_LWU = (0x27 << 26),
90 OPC_SB = (0x28 << 26),
91 OPC_SH = (0x29 << 26),
92 OPC_SWL = (0x2A << 26),
93 OPC_SW = (0x2B << 26),
94 OPC_SDL = (0x2C << 26),
95 OPC_SDR = (0x2D << 26),
96 OPC_SWR = (0x2E << 26),
97 OPC_LL = (0x30 << 26),
98 OPC_LLD = (0x34 << 26),
99 OPC_LD = (0x37 << 26),
100 OPC_LDPC = OPC_LD | 0x5,
101 OPC_SC = (0x38 << 26),
102 OPC_SCD = (0x3C << 26),
103 OPC_SD = (0x3F << 26),
104 /* Floating point load/store */
105 OPC_LWC1 = (0x31 << 26),
106 OPC_LWC2 = (0x32 << 26),
107 OPC_LDC1 = (0x35 << 26),
108 OPC_LDC2 = (0x36 << 26),
109 OPC_SWC1 = (0x39 << 26),
110 OPC_SWC2 = (0x3A << 26),
111 OPC_SDC1 = (0x3D << 26),
112 OPC_SDC2 = (0x3E << 26),
113 /* Compact Branches */
114 OPC_BLEZALC = (0x06 << 26),
115 OPC_BGEZALC = (0x06 << 26),
116 OPC_BGEUC = (0x06 << 26),
117 OPC_BGTZALC = (0x07 << 26),
118 OPC_BLTZALC = (0x07 << 26),
119 OPC_BLTUC = (0x07 << 26),
120 OPC_BOVC = (0x08 << 26),
121 OPC_BEQZALC = (0x08 << 26),
122 OPC_BEQC = (0x08 << 26),
123 OPC_BLEZC = (0x16 << 26),
124 OPC_BGEZC = (0x16 << 26),
125 OPC_BGEC = (0x16 << 26),
126 OPC_BGTZC = (0x17 << 26),
127 OPC_BLTZC = (0x17 << 26),
128 OPC_BLTC = (0x17 << 26),
129 OPC_BNVC = (0x18 << 26),
130 OPC_BNEZALC = (0x18 << 26),
131 OPC_BNEC = (0x18 << 26),
132 OPC_BC = (0x32 << 26),
133 OPC_BEQZC = (0x36 << 26),
134 OPC_JIC = (0x36 << 26),
135 OPC_BALC = (0x3A << 26),
136 OPC_BNEZC = (0x3E << 26),
137 OPC_JIALC = (0x3E << 26),
138 /* MDMX ASE specific */
139 OPC_MDMX = (0x1E << 26),
140 /* MSA ASE, same as MDMX */
141 OPC_MSA = OPC_MDMX,
142 /* Cache and prefetch */
143 OPC_CACHE = (0x2F << 26),
144 OPC_PREF = (0x33 << 26),
145 /* PC-relative address computation / loads */
146 OPC_PCREL = (0x3B << 26),
149 /* PC-relative address computation / loads */
150 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
151 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
152 enum {
153 /* Instructions determined by bits 19 and 20 */
154 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
155 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
156 OPC_LWUPC = OPC_PCREL | (2 << 19),
158 /* Instructions determined by bits 16 ... 20 */
159 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
160 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
162 /* Other */
163 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
166 /* MIPS special opcodes */
167 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
169 enum {
170 /* Shifts */
171 OPC_SLL = 0x00 | OPC_SPECIAL,
172 /* NOP is SLL r0, r0, 0 */
173 /* SSNOP is SLL r0, r0, 1 */
174 /* EHB is SLL r0, r0, 3 */
175 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
176 OPC_ROTR = OPC_SRL | (1 << 21),
177 OPC_SRA = 0x03 | OPC_SPECIAL,
178 OPC_SLLV = 0x04 | OPC_SPECIAL,
179 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
180 OPC_ROTRV = OPC_SRLV | (1 << 6),
181 OPC_SRAV = 0x07 | OPC_SPECIAL,
182 OPC_DSLLV = 0x14 | OPC_SPECIAL,
183 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
184 OPC_DROTRV = OPC_DSRLV | (1 << 6),
185 OPC_DSRAV = 0x17 | OPC_SPECIAL,
186 OPC_DSLL = 0x38 | OPC_SPECIAL,
187 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
188 OPC_DROTR = OPC_DSRL | (1 << 21),
189 OPC_DSRA = 0x3B | OPC_SPECIAL,
190 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
191 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
192 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
193 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
194 /* Multiplication / division */
195 OPC_MULT = 0x18 | OPC_SPECIAL,
196 OPC_MULTU = 0x19 | OPC_SPECIAL,
197 OPC_DIV = 0x1A | OPC_SPECIAL,
198 OPC_DIVU = 0x1B | OPC_SPECIAL,
199 OPC_DMULT = 0x1C | OPC_SPECIAL,
200 OPC_DMULTU = 0x1D | OPC_SPECIAL,
201 OPC_DDIV = 0x1E | OPC_SPECIAL,
202 OPC_DDIVU = 0x1F | OPC_SPECIAL,
204 /* 2 registers arithmetic / logic */
205 OPC_ADD = 0x20 | OPC_SPECIAL,
206 OPC_ADDU = 0x21 | OPC_SPECIAL,
207 OPC_SUB = 0x22 | OPC_SPECIAL,
208 OPC_SUBU = 0x23 | OPC_SPECIAL,
209 OPC_AND = 0x24 | OPC_SPECIAL,
210 OPC_OR = 0x25 | OPC_SPECIAL,
211 OPC_XOR = 0x26 | OPC_SPECIAL,
212 OPC_NOR = 0x27 | OPC_SPECIAL,
213 OPC_SLT = 0x2A | OPC_SPECIAL,
214 OPC_SLTU = 0x2B | OPC_SPECIAL,
215 OPC_DADD = 0x2C | OPC_SPECIAL,
216 OPC_DADDU = 0x2D | OPC_SPECIAL,
217 OPC_DSUB = 0x2E | OPC_SPECIAL,
218 OPC_DSUBU = 0x2F | OPC_SPECIAL,
219 /* Jumps */
220 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
221 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
222 /* Traps */
223 OPC_TGE = 0x30 | OPC_SPECIAL,
224 OPC_TGEU = 0x31 | OPC_SPECIAL,
225 OPC_TLT = 0x32 | OPC_SPECIAL,
226 OPC_TLTU = 0x33 | OPC_SPECIAL,
227 OPC_TEQ = 0x34 | OPC_SPECIAL,
228 OPC_TNE = 0x36 | OPC_SPECIAL,
229 /* HI / LO registers load & stores */
230 OPC_MFHI = 0x10 | OPC_SPECIAL,
231 OPC_MTHI = 0x11 | OPC_SPECIAL,
232 OPC_MFLO = 0x12 | OPC_SPECIAL,
233 OPC_MTLO = 0x13 | OPC_SPECIAL,
234 /* Conditional moves */
235 OPC_MOVZ = 0x0A | OPC_SPECIAL,
236 OPC_MOVN = 0x0B | OPC_SPECIAL,
238 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
239 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
241 OPC_MOVCI = 0x01 | OPC_SPECIAL,
243 /* Special */
244 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
245 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
246 OPC_BREAK = 0x0D | OPC_SPECIAL,
247 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
248 OPC_SYNC = 0x0F | OPC_SPECIAL,
250 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
251 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
252 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
253 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
256 /* R6 Multiply and Divide instructions have the same Opcode
257 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
258 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
260 enum {
261 R6_OPC_MUL = OPC_MULT | (2 << 6),
262 R6_OPC_MUH = OPC_MULT | (3 << 6),
263 R6_OPC_MULU = OPC_MULTU | (2 << 6),
264 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
265 R6_OPC_DIV = OPC_DIV | (2 << 6),
266 R6_OPC_MOD = OPC_DIV | (3 << 6),
267 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
268 R6_OPC_MODU = OPC_DIVU | (3 << 6),
270 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
271 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
272 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
273 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
274 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
275 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
276 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
277 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
279 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
280 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
281 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
282 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
283 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
285 OPC_LSA = 0x05 | OPC_SPECIAL,
286 OPC_DLSA = 0x15 | OPC_SPECIAL,
289 /* Multiplication variants of the vr54xx. */
290 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
292 enum {
293 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
294 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
295 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
296 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
297 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
298 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
299 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
300 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
301 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
302 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
303 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
304 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
305 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
306 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
309 /* REGIMM (rt field) opcodes */
310 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
312 enum {
313 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
314 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
315 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
316 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
317 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
318 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
319 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
320 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
321 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
322 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
323 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
324 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
325 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
326 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
327 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
329 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
330 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
333 /* Special2 opcodes */
334 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
336 enum {
337 /* Multiply & xxx operations */
338 OPC_MADD = 0x00 | OPC_SPECIAL2,
339 OPC_MADDU = 0x01 | OPC_SPECIAL2,
340 OPC_MUL = 0x02 | OPC_SPECIAL2,
341 OPC_MSUB = 0x04 | OPC_SPECIAL2,
342 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
343 /* Loongson 2F */
344 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
345 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
346 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
347 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
348 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
349 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
350 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
351 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
352 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
353 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
354 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
355 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
356 /* Misc */
357 OPC_CLZ = 0x20 | OPC_SPECIAL2,
358 OPC_CLO = 0x21 | OPC_SPECIAL2,
359 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
360 OPC_DCLO = 0x25 | OPC_SPECIAL2,
361 /* Special */
362 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
365 /* Special3 opcodes */
366 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
368 enum {
369 OPC_EXT = 0x00 | OPC_SPECIAL3,
370 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
371 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
372 OPC_DEXT = 0x03 | OPC_SPECIAL3,
373 OPC_INS = 0x04 | OPC_SPECIAL3,
374 OPC_DINSM = 0x05 | OPC_SPECIAL3,
375 OPC_DINSU = 0x06 | OPC_SPECIAL3,
376 OPC_DINS = 0x07 | OPC_SPECIAL3,
377 OPC_FORK = 0x08 | OPC_SPECIAL3,
378 OPC_YIELD = 0x09 | OPC_SPECIAL3,
379 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
380 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
381 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
383 /* Loongson 2E */
384 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
385 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
386 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
387 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
388 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
389 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
390 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
391 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
392 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
393 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
394 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
395 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
397 /* MIPS DSP Load */
398 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
399 /* MIPS DSP Arithmetic */
400 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
401 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
402 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
403 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
404 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
405 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
406 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
407 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
408 /* MIPS DSP GPR-Based Shift Sub-class */
409 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
410 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
411 /* MIPS DSP Multiply Sub-class insns */
412 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
413 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
414 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
415 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
416 /* DSP Bit/Manipulation Sub-class */
417 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
418 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
419 /* MIPS DSP Append Sub-class */
420 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
421 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
422 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
423 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
424 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
426 /* R6 */
427 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
428 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
429 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
430 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
431 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
432 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
435 /* BSHFL opcodes */
436 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
438 enum {
439 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
440 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
441 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
442 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
443 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
444 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
447 /* DBSHFL opcodes */
448 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
450 enum {
451 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
452 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
453 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
454 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
455 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
458 /* MIPS DSP REGIMM opcodes */
459 enum {
460 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
461 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
464 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
465 /* MIPS DSP Load */
466 enum {
467 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
468 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
469 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
470 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
473 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
474 enum {
475 /* MIPS DSP Arithmetic Sub-class */
476 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
477 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
478 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
479 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
480 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
481 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
482 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
483 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
484 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
485 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
486 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
487 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
488 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
489 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
490 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
491 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
492 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
493 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
494 /* MIPS DSP Multiply Sub-class insns */
495 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
496 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
497 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
498 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
499 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
500 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
503 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
504 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
505 enum {
506 /* MIPS DSP Arithmetic Sub-class */
507 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
508 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
509 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
510 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
511 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
512 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
513 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
514 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
515 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
516 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
517 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
518 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
519 /* MIPS DSP Multiply Sub-class insns */
520 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
521 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
522 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
523 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
526 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
527 enum {
528 /* MIPS DSP Arithmetic Sub-class */
529 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
530 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
531 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
532 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
533 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
534 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
535 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
536 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
537 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
538 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
539 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
540 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
541 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
542 /* DSP Bit/Manipulation Sub-class */
543 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
544 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
545 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
546 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
547 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
550 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
551 enum {
552 /* MIPS DSP Arithmetic Sub-class */
553 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
554 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
555 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
556 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
557 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
558 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
559 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
560 /* DSP Compare-Pick Sub-class */
561 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
562 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
563 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
564 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
565 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
566 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
567 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
568 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
569 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
570 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
571 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
572 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
573 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
574 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
575 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
578 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
579 enum {
580 /* MIPS DSP GPR-Based Shift Sub-class */
581 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
582 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
583 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
584 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
585 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
586 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
587 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
588 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
589 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
590 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
591 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
592 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
593 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
594 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
595 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
596 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
597 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
598 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
599 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
600 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
601 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
602 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
605 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
606 enum {
607 /* MIPS DSP Multiply Sub-class insns */
608 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
609 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
610 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
611 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
612 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
613 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
614 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
615 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
616 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
617 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
618 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
619 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
620 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
621 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
622 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
623 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
624 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
625 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
626 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
627 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
628 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
629 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
632 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
633 enum {
634 /* DSP Bit/Manipulation Sub-class */
635 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
638 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
639 enum {
640 /* MIPS DSP Append Sub-class */
641 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
642 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
643 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
646 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
647 enum {
648 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
649 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
650 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
651 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
652 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
653 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
654 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
655 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
656 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
657 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
658 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
659 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
660 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
661 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
662 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
663 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
664 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
665 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
668 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
669 enum {
670 /* MIPS DSP Arithmetic Sub-class */
671 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
672 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
673 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
674 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
675 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
676 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
677 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
678 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
679 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
680 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
681 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
682 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
683 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
684 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
685 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
686 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
687 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
688 /* DSP Bit/Manipulation Sub-class */
689 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
690 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
691 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
692 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
693 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
694 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
697 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
698 enum {
699 /* MIPS DSP Multiply Sub-class insns */
700 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
701 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
702 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
703 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
704 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
705 /* MIPS DSP Arithmetic Sub-class */
706 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
707 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
708 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
709 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
710 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
711 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
712 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
713 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
714 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
715 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
716 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
717 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
718 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
719 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
720 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
721 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
722 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
723 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
724 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
725 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
726 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
729 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
730 enum {
731 /* DSP Compare-Pick Sub-class */
732 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
733 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
734 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
735 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
736 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
737 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
738 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
739 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
740 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
741 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
742 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
743 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
744 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
745 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
746 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
747 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
748 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
749 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
750 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
751 /* MIPS DSP Arithmetic Sub-class */
752 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
753 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
754 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
755 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
756 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
762 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
763 enum {
764 /* DSP Append Sub-class */
765 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
766 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
767 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
768 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
771 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
772 enum {
773 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
774 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
775 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
776 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
777 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
778 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
779 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
780 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
781 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
782 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
783 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
784 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
785 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
786 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
787 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
788 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
789 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
790 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
791 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
792 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
793 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
794 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
797 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
798 enum {
799 /* DSP Bit/Manipulation Sub-class */
800 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
803 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
804 enum {
805 /* MIPS DSP Multiply Sub-class insns */
806 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
807 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
808 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
809 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
810 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
811 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
812 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
813 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
814 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
815 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
816 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
817 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
818 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
819 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
820 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
821 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
822 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
823 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
824 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
825 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
826 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
827 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
828 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
829 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
830 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
834 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
835 enum {
836 /* MIPS DSP GPR-Based Shift Sub-class */
837 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
838 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
839 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
840 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
841 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
842 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
843 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
844 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
845 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
846 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
847 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
848 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
849 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
850 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
851 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
852 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
853 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
854 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
855 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
856 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
857 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
858 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
859 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
860 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
861 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
865 /* Coprocessor 0 (rs field) */
866 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
868 enum {
869 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
870 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
871 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
872 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
873 OPC_MFTR = (0x08 << 21) | OPC_CP0,
874 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
875 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
876 OPC_MTTR = (0x0C << 21) | OPC_CP0,
877 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
878 OPC_C0 = (0x10 << 21) | OPC_CP0,
879 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
880 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
883 /* MFMC0 opcodes */
884 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
886 enum {
887 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
888 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
889 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
890 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
891 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
892 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
895 /* Coprocessor 0 (with rs == C0) */
896 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
898 enum {
899 OPC_TLBR = 0x01 | OPC_C0,
900 OPC_TLBWI = 0x02 | OPC_C0,
901 OPC_TLBINV = 0x03 | OPC_C0,
902 OPC_TLBINVF = 0x04 | OPC_C0,
903 OPC_TLBWR = 0x06 | OPC_C0,
904 OPC_TLBP = 0x08 | OPC_C0,
905 OPC_RFE = 0x10 | OPC_C0,
906 OPC_ERET = 0x18 | OPC_C0,
907 OPC_DERET = 0x1F | OPC_C0,
908 OPC_WAIT = 0x20 | OPC_C0,
911 /* Coprocessor 1 (rs field) */
912 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
914 /* Values for the fmt field in FP instructions */
915 enum {
916 /* 0 - 15 are reserved */
917 FMT_S = 16, /* single fp */
918 FMT_D = 17, /* double fp */
919 FMT_E = 18, /* extended fp */
920 FMT_Q = 19, /* quad fp */
921 FMT_W = 20, /* 32-bit fixed */
922 FMT_L = 21, /* 64-bit fixed */
923 FMT_PS = 22, /* paired single fp */
924 /* 23 - 31 are reserved */
927 enum {
928 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
929 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
930 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
931 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
932 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
933 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
934 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
935 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
936 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
937 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
938 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
939 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
940 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
941 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
942 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
943 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
944 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
945 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
946 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
947 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
948 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
949 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
950 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
951 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
952 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
953 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
954 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
955 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
956 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
957 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
960 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
961 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
963 enum {
964 OPC_BC1F = (0x00 << 16) | OPC_BC1,
965 OPC_BC1T = (0x01 << 16) | OPC_BC1,
966 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
967 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
970 enum {
971 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
972 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
975 enum {
976 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
977 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
980 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
982 enum {
983 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
984 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
985 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
986 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
987 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
988 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
989 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
990 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
991 OPC_BC2 = (0x08 << 21) | OPC_CP2,
992 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
993 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
996 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
998 enum {
999 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1000 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1001 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1002 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1003 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1004 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1005 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1006 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1008 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1009 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1010 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1011 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1012 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1013 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1014 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1015 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1018 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1019 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1020 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1021 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1022 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1023 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1024 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1026 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1027 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1028 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1029 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1030 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1031 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1032 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1033 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1035 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1036 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1037 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1038 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1039 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1040 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1042 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1043 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1044 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1045 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1046 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1047 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1049 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1050 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1051 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1052 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1053 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1054 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1056 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1057 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1058 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1059 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1060 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1061 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1063 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1064 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1065 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1066 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1067 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1068 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1070 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1071 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1072 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1073 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1074 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1075 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1077 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1078 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1079 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1080 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1081 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1082 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1084 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1085 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1086 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1087 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1088 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1089 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1093 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1095 enum {
1096 OPC_LWXC1 = 0x00 | OPC_CP3,
1097 OPC_LDXC1 = 0x01 | OPC_CP3,
1098 OPC_LUXC1 = 0x05 | OPC_CP3,
1099 OPC_SWXC1 = 0x08 | OPC_CP3,
1100 OPC_SDXC1 = 0x09 | OPC_CP3,
1101 OPC_SUXC1 = 0x0D | OPC_CP3,
1102 OPC_PREFX = 0x0F | OPC_CP3,
1103 OPC_ALNV_PS = 0x1E | OPC_CP3,
1104 OPC_MADD_S = 0x20 | OPC_CP3,
1105 OPC_MADD_D = 0x21 | OPC_CP3,
1106 OPC_MADD_PS = 0x26 | OPC_CP3,
1107 OPC_MSUB_S = 0x28 | OPC_CP3,
1108 OPC_MSUB_D = 0x29 | OPC_CP3,
1109 OPC_MSUB_PS = 0x2E | OPC_CP3,
1110 OPC_NMADD_S = 0x30 | OPC_CP3,
1111 OPC_NMADD_D = 0x31 | OPC_CP3,
1112 OPC_NMADD_PS= 0x36 | OPC_CP3,
1113 OPC_NMSUB_S = 0x38 | OPC_CP3,
1114 OPC_NMSUB_D = 0x39 | OPC_CP3,
1115 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1118 /* MSA Opcodes */
1119 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1120 enum {
1121 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1122 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1123 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1124 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1125 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1126 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1127 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1128 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1129 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1130 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1131 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1132 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1133 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1134 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1135 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1136 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1137 OPC_MSA_ELM = 0x19 | OPC_MSA,
1138 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1139 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1140 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1141 OPC_MSA_VEC = 0x1E | OPC_MSA,
1143 /* MI10 instruction */
1144 OPC_LD_B = (0x20) | OPC_MSA,
1145 OPC_LD_H = (0x21) | OPC_MSA,
1146 OPC_LD_W = (0x22) | OPC_MSA,
1147 OPC_LD_D = (0x23) | OPC_MSA,
1148 OPC_ST_B = (0x24) | OPC_MSA,
1149 OPC_ST_H = (0x25) | OPC_MSA,
1150 OPC_ST_W = (0x26) | OPC_MSA,
1151 OPC_ST_D = (0x27) | OPC_MSA,
1154 enum {
1155 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1156 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1157 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1158 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1159 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1160 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1161 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1162 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1163 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1164 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1165 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1166 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1167 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1169 /* I8 instruction */
1170 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1171 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1172 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1173 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1174 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1175 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1176 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1177 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1178 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1179 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1181 /* VEC/2R/2RF instruction */
1182 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1183 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1184 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1185 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1186 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1187 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1188 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1190 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1191 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1193 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1194 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1195 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1196 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1197 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1199 /* 2RF instruction df(bit 16) = _w, _d */
1200 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1201 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1202 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1203 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1204 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1205 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1206 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1207 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1208 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1209 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1210 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1211 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1212 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1213 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1214 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1215 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1217 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1218 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1219 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1220 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1221 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1222 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1223 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1224 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1225 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1226 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1227 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1228 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1229 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1230 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1231 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1232 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1233 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1234 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1235 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1236 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1237 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1238 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1239 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1240 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1241 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1242 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1243 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1244 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1245 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1246 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1247 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1248 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1249 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1250 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1251 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1252 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1253 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1254 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1255 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1256 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1257 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1258 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1259 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1260 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1261 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1262 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1263 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1264 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1265 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1266 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1267 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1268 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1269 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1270 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1271 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1272 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1273 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1274 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1275 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1276 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1277 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1278 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1279 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1280 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1282 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1283 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1284 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1285 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1286 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1287 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1288 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1289 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1290 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1291 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1293 /* 3RF instruction _df(bit 21) = _w, _d */
1294 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1295 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1296 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1297 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1298 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1299 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1300 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1301 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1302 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1303 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1304 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1305 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1306 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1307 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1308 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1309 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1310 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1311 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1312 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1313 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1314 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1315 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1316 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1317 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1318 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1319 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1320 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1321 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1322 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1323 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1324 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1325 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1326 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1327 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1328 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1329 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1330 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1331 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1332 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1333 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1334 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1336 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1337 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1338 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1339 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1340 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1341 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1342 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1343 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1344 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1345 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1346 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1347 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1348 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1351 /* global register indices */
1352 static TCGv_ptr cpu_env;
1353 static TCGv cpu_gpr[32], cpu_PC;
1354 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1355 static TCGv cpu_dspctrl, btarget, bcond;
1356 static TCGv_i32 hflags;
1357 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1358 static TCGv_i64 fpu_f64[32];
1359 static TCGv_i64 msa_wr_d[64];
1361 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
1362 static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
1364 #include "exec/gen-icount.h"
1366 #define gen_helper_0e0i(name, arg) do { \
1367 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1368 gen_helper_##name(cpu_env, helper_tmp); \
1369 tcg_temp_free_i32(helper_tmp); \
1370 } while(0)
1372 #define gen_helper_0e1i(name, arg1, arg2) do { \
1373 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1374 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1375 tcg_temp_free_i32(helper_tmp); \
1376 } while(0)
1378 #define gen_helper_1e0i(name, ret, arg1) do { \
1379 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1380 gen_helper_##name(ret, cpu_env, helper_tmp); \
1381 tcg_temp_free_i32(helper_tmp); \
1382 } while(0)
1384 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1385 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1386 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1387 tcg_temp_free_i32(helper_tmp); \
1388 } while(0)
1390 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1391 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1392 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1393 tcg_temp_free_i32(helper_tmp); \
1394 } while(0)
1396 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1397 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1398 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1399 tcg_temp_free_i32(helper_tmp); \
1400 } while(0)
1402 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1403 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1404 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1405 tcg_temp_free_i32(helper_tmp); \
1406 } while(0)
1408 typedef struct DisasContext {
1409 struct TranslationBlock *tb;
1410 target_ulong pc, saved_pc;
1411 uint32_t opcode;
1412 int singlestep_enabled;
1413 int insn_flags;
1414 int32_t CP0_Config1;
1415 /* Routine used to access memory */
1416 int mem_idx;
1417 uint32_t hflags, saved_hflags;
1418 int bstate;
1419 target_ulong btarget;
1420 bool ulri;
1421 int kscrexist;
1422 bool rxi;
1423 int ie;
1424 bool bi;
1425 bool bp;
1426 } DisasContext;
1428 enum {
1429 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1430 * exception condition */
1431 BS_STOP = 1, /* We want to stop translation for any reason */
1432 BS_BRANCH = 2, /* We reached a branch condition */
1433 BS_EXCP = 3, /* We reached an exception condition */
1436 static const char * const regnames[] = {
1437 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1438 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1439 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1440 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1443 static const char * const regnames_HI[] = {
1444 "HI0", "HI1", "HI2", "HI3",
1447 static const char * const regnames_LO[] = {
1448 "LO0", "LO1", "LO2", "LO3",
1451 static const char * const fregnames[] = {
1452 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1453 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1454 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1455 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1458 static const char * const msaregnames[] = {
1459 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1460 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1461 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1462 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1463 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1464 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1465 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1466 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1467 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1468 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1469 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1470 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1471 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1472 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1473 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1474 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1477 #define MIPS_DEBUG(fmt, ...) \
1478 do { \
1479 if (MIPS_DEBUG_DISAS) { \
1480 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1481 TARGET_FMT_lx ": %08x " fmt "\n", \
1482 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
1484 } while (0)
1486 #define LOG_DISAS(...) \
1487 do { \
1488 if (MIPS_DEBUG_DISAS) { \
1489 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1491 } while (0)
1493 #define MIPS_INVAL(op) \
1494 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
1495 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
1497 /* General purpose registers moves. */
1498 static inline void gen_load_gpr (TCGv t, int reg)
1500 if (reg == 0)
1501 tcg_gen_movi_tl(t, 0);
1502 else
1503 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1506 static inline void gen_store_gpr (TCGv t, int reg)
1508 if (reg != 0)
1509 tcg_gen_mov_tl(cpu_gpr[reg], t);
1512 /* Moves to/from shadow registers. */
1513 static inline void gen_load_srsgpr (int from, int to)
1515 TCGv t0 = tcg_temp_new();
1517 if (from == 0)
1518 tcg_gen_movi_tl(t0, 0);
1519 else {
1520 TCGv_i32 t2 = tcg_temp_new_i32();
1521 TCGv_ptr addr = tcg_temp_new_ptr();
1523 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1524 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1525 tcg_gen_andi_i32(t2, t2, 0xf);
1526 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1527 tcg_gen_ext_i32_ptr(addr, t2);
1528 tcg_gen_add_ptr(addr, cpu_env, addr);
1530 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1531 tcg_temp_free_ptr(addr);
1532 tcg_temp_free_i32(t2);
1534 gen_store_gpr(t0, to);
1535 tcg_temp_free(t0);
1538 static inline void gen_store_srsgpr (int from, int to)
1540 if (to != 0) {
1541 TCGv t0 = tcg_temp_new();
1542 TCGv_i32 t2 = tcg_temp_new_i32();
1543 TCGv_ptr addr = tcg_temp_new_ptr();
1545 gen_load_gpr(t0, from);
1546 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1547 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1548 tcg_gen_andi_i32(t2, t2, 0xf);
1549 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1550 tcg_gen_ext_i32_ptr(addr, t2);
1551 tcg_gen_add_ptr(addr, cpu_env, addr);
1553 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1554 tcg_temp_free_ptr(addr);
1555 tcg_temp_free_i32(t2);
1556 tcg_temp_free(t0);
1560 /* Floating point register moves. */
1561 static void gen_load_fpr32(TCGv_i32 t, int reg)
1563 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
1566 static void gen_store_fpr32(TCGv_i32 t, int reg)
1568 TCGv_i64 t64 = tcg_temp_new_i64();
1569 tcg_gen_extu_i32_i64(t64, t);
1570 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1571 tcg_temp_free_i64(t64);
1574 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1576 if (ctx->hflags & MIPS_HFLAG_F64) {
1577 TCGv_i64 t64 = tcg_temp_new_i64();
1578 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
1579 tcg_gen_trunc_i64_i32(t, t64);
1580 tcg_temp_free_i64(t64);
1581 } else {
1582 gen_load_fpr32(t, reg | 1);
1586 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1588 if (ctx->hflags & MIPS_HFLAG_F64) {
1589 TCGv_i64 t64 = tcg_temp_new_i64();
1590 tcg_gen_extu_i32_i64(t64, t);
1591 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1592 tcg_temp_free_i64(t64);
1593 } else {
1594 gen_store_fpr32(t, reg | 1);
1598 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1600 if (ctx->hflags & MIPS_HFLAG_F64) {
1601 tcg_gen_mov_i64(t, fpu_f64[reg]);
1602 } else {
1603 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1607 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1609 if (ctx->hflags & MIPS_HFLAG_F64) {
1610 tcg_gen_mov_i64(fpu_f64[reg], t);
1611 } else {
1612 TCGv_i64 t0;
1613 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1614 t0 = tcg_temp_new_i64();
1615 tcg_gen_shri_i64(t0, t, 32);
1616 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1617 tcg_temp_free_i64(t0);
1621 static inline int get_fp_bit (int cc)
1623 if (cc)
1624 return 24 + cc;
1625 else
1626 return 23;
1629 /* Tests */
1630 static inline void gen_save_pc(target_ulong pc)
1632 tcg_gen_movi_tl(cpu_PC, pc);
1635 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
1637 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1638 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1639 gen_save_pc(ctx->pc);
1640 ctx->saved_pc = ctx->pc;
1642 if (ctx->hflags != ctx->saved_hflags) {
1643 tcg_gen_movi_i32(hflags, ctx->hflags);
1644 ctx->saved_hflags = ctx->hflags;
1645 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1646 case MIPS_HFLAG_BR:
1647 break;
1648 case MIPS_HFLAG_BC:
1649 case MIPS_HFLAG_BL:
1650 case MIPS_HFLAG_B:
1651 tcg_gen_movi_tl(btarget, ctx->btarget);
1652 break;
1657 static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
1659 ctx->saved_hflags = ctx->hflags;
1660 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1661 case MIPS_HFLAG_BR:
1662 break;
1663 case MIPS_HFLAG_BC:
1664 case MIPS_HFLAG_BL:
1665 case MIPS_HFLAG_B:
1666 ctx->btarget = env->btarget;
1667 break;
1671 static inline void
1672 generate_exception_err (DisasContext *ctx, int excp, int err)
1674 TCGv_i32 texcp = tcg_const_i32(excp);
1675 TCGv_i32 terr = tcg_const_i32(err);
1676 save_cpu_state(ctx, 1);
1677 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1678 tcg_temp_free_i32(terr);
1679 tcg_temp_free_i32(texcp);
1682 static inline void
1683 generate_exception (DisasContext *ctx, int excp)
1685 save_cpu_state(ctx, 1);
1686 gen_helper_0e0i(raise_exception, excp);
1689 /* Addresses computation */
1690 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1692 tcg_gen_add_tl(ret, arg0, arg1);
1694 #if defined(TARGET_MIPS64)
1695 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1696 tcg_gen_ext32s_i64(ret, ret);
1698 #endif
1701 /* Addresses computation (translation time) */
1702 static target_long addr_add(DisasContext *ctx, target_long base,
1703 target_long offset)
1705 target_long sum = base + offset;
1707 #if defined(TARGET_MIPS64)
1708 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1709 sum = (int32_t)sum;
1711 #endif
1712 return sum;
1715 static inline void check_cp0_enabled(DisasContext *ctx)
1717 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1718 generate_exception_err(ctx, EXCP_CpU, 0);
1721 static inline void check_cp1_enabled(DisasContext *ctx)
1723 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1724 generate_exception_err(ctx, EXCP_CpU, 1);
1727 /* Verify that the processor is running with COP1X instructions enabled.
1728 This is associated with the nabla symbol in the MIPS32 and MIPS64
1729 opcode tables. */
1731 static inline void check_cop1x(DisasContext *ctx)
1733 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1734 generate_exception(ctx, EXCP_RI);
1737 /* Verify that the processor is running with 64-bit floating-point
1738 operations enabled. */
1740 static inline void check_cp1_64bitmode(DisasContext *ctx)
1742 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1743 generate_exception(ctx, EXCP_RI);
1747 * Verify if floating point register is valid; an operation is not defined
1748 * if bit 0 of any register specification is set and the FR bit in the
1749 * Status register equals zero, since the register numbers specify an
1750 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1751 * in the Status register equals one, both even and odd register numbers
1752 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1754 * Multiple 64 bit wide registers can be checked by calling
1755 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1757 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1759 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1760 generate_exception(ctx, EXCP_RI);
1763 /* Verify that the processor is running with DSP instructions enabled.
1764 This is enabled by CP0 Status register MX(24) bit.
1767 static inline void check_dsp(DisasContext *ctx)
1769 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1770 if (ctx->insn_flags & ASE_DSP) {
1771 generate_exception(ctx, EXCP_DSPDIS);
1772 } else {
1773 generate_exception(ctx, EXCP_RI);
1778 static inline void check_dspr2(DisasContext *ctx)
1780 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1781 if (ctx->insn_flags & ASE_DSP) {
1782 generate_exception(ctx, EXCP_DSPDIS);
1783 } else {
1784 generate_exception(ctx, EXCP_RI);
1789 /* This code generates a "reserved instruction" exception if the
1790 CPU does not support the instruction set corresponding to flags. */
1791 static inline void check_insn(DisasContext *ctx, int flags)
1793 if (unlikely(!(ctx->insn_flags & flags))) {
1794 generate_exception(ctx, EXCP_RI);
1798 /* This code generates a "reserved instruction" exception if the
1799 CPU has corresponding flag set which indicates that the instruction
1800 has been removed. */
1801 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1803 if (unlikely(ctx->insn_flags & flags)) {
1804 generate_exception(ctx, EXCP_RI);
1808 #ifdef TARGET_MIPS64
1809 /* This code generates a "reserved instruction" exception if 64-bit
1810 instructions are not enabled. */
1811 static inline void check_mips_64(DisasContext *ctx)
1813 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1814 generate_exception(ctx, EXCP_RI);
1816 #endif
1818 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1819 calling interface for 32 and 64-bit FPRs. No sense in changing
1820 all callers for gen_load_fpr32 when we need the CTX parameter for
1821 this one use. */
1822 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
1823 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1824 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1825 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1826 int ft, int fs, int cc) \
1828 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1829 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1830 switch (ifmt) { \
1831 case FMT_PS: \
1832 check_cp1_64bitmode(ctx); \
1833 break; \
1834 case FMT_D: \
1835 if (abs) { \
1836 check_cop1x(ctx); \
1838 check_cp1_registers(ctx, fs | ft); \
1839 break; \
1840 case FMT_S: \
1841 if (abs) { \
1842 check_cop1x(ctx); \
1844 break; \
1846 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1847 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1848 switch (n) { \
1849 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1850 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1851 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1852 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1853 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1854 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1855 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1856 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1857 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1858 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1859 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1860 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1861 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1862 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1863 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1864 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1865 default: abort(); \
1867 tcg_temp_free_i##bits (fp0); \
1868 tcg_temp_free_i##bits (fp1); \
1871 FOP_CONDS(, 0, d, FMT_D, 64)
1872 FOP_CONDS(abs, 1, d, FMT_D, 64)
1873 FOP_CONDS(, 0, s, FMT_S, 32)
1874 FOP_CONDS(abs, 1, s, FMT_S, 32)
1875 FOP_CONDS(, 0, ps, FMT_PS, 64)
1876 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1877 #undef FOP_CONDS
1879 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1880 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1881 int ft, int fs, int fd) \
1883 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1884 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1885 switch (ifmt) { \
1886 case FMT_D: \
1887 check_cp1_registers(ctx, fs | ft | fd); \
1888 break; \
1890 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1891 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1892 switch (n) { \
1893 case 0: \
1894 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1895 break; \
1896 case 1: \
1897 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1898 break; \
1899 case 2: \
1900 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1901 break; \
1902 case 3: \
1903 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1904 break; \
1905 case 4: \
1906 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1907 break; \
1908 case 5: \
1909 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1910 break; \
1911 case 6: \
1912 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1913 break; \
1914 case 7: \
1915 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1916 break; \
1917 case 8: \
1918 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1919 break; \
1920 case 9: \
1921 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1922 break; \
1923 case 10: \
1924 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1925 break; \
1926 case 11: \
1927 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1928 break; \
1929 case 12: \
1930 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1931 break; \
1932 case 13: \
1933 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1934 break; \
1935 case 14: \
1936 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1937 break; \
1938 case 15: \
1939 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1940 break; \
1941 case 17: \
1942 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1943 break; \
1944 case 18: \
1945 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1946 break; \
1947 case 19: \
1948 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1949 break; \
1950 case 25: \
1951 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1952 break; \
1953 case 26: \
1954 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
1955 break; \
1956 case 27: \
1957 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
1958 break; \
1959 default: \
1960 abort(); \
1962 STORE; \
1963 tcg_temp_free_i ## bits (fp0); \
1964 tcg_temp_free_i ## bits (fp1); \
1967 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
1968 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(fp0, fd))
1969 #undef FOP_CONDNS
1970 #undef gen_ldcmp_fpr32
1971 #undef gen_ldcmp_fpr64
1973 /* load/store instructions. */
1974 #ifdef CONFIG_USER_ONLY
1975 #define OP_LD_ATOMIC(insn,fname) \
1976 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1978 TCGv t0 = tcg_temp_new(); \
1979 tcg_gen_mov_tl(t0, arg1); \
1980 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1981 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1982 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
1983 tcg_temp_free(t0); \
1985 #else
1986 #define OP_LD_ATOMIC(insn,fname) \
1987 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1989 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
1991 #endif
1992 OP_LD_ATOMIC(ll,ld32s);
1993 #if defined(TARGET_MIPS64)
1994 OP_LD_ATOMIC(lld,ld64);
1995 #endif
1996 #undef OP_LD_ATOMIC
1998 #ifdef CONFIG_USER_ONLY
1999 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2000 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2002 TCGv t0 = tcg_temp_new(); \
2003 int l1 = gen_new_label(); \
2004 int l2 = gen_new_label(); \
2006 tcg_gen_andi_tl(t0, arg2, almask); \
2007 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2008 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2009 generate_exception(ctx, EXCP_AdES); \
2010 gen_set_label(l1); \
2011 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2012 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2013 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2014 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2015 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2016 gen_helper_0e0i(raise_exception, EXCP_SC); \
2017 gen_set_label(l2); \
2018 tcg_gen_movi_tl(t0, 0); \
2019 gen_store_gpr(t0, rt); \
2020 tcg_temp_free(t0); \
2022 #else
2023 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2024 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2026 TCGv t0 = tcg_temp_new(); \
2027 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
2028 gen_store_gpr(t0, rt); \
2029 tcg_temp_free(t0); \
2031 #endif
2032 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2033 #if defined(TARGET_MIPS64)
2034 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2035 #endif
2036 #undef OP_ST_ATOMIC
2038 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2039 int base, int16_t offset)
2041 if (base == 0) {
2042 tcg_gen_movi_tl(addr, offset);
2043 } else if (offset == 0) {
2044 gen_load_gpr(addr, base);
2045 } else {
2046 tcg_gen_movi_tl(addr, offset);
2047 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2051 static target_ulong pc_relative_pc (DisasContext *ctx)
2053 target_ulong pc = ctx->pc;
2055 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2056 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2058 pc -= branch_bytes;
2061 pc &= ~(target_ulong)3;
2062 return pc;
2065 /* Load */
2066 static void gen_ld(DisasContext *ctx, uint32_t opc,
2067 int rt, int base, int16_t offset)
2069 const char *opn = "ld";
2070 TCGv t0, t1, t2;
2072 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2073 /* Loongson CPU uses a load to zero register for prefetch.
2074 We emulate it as a NOP. On other CPU we must perform the
2075 actual memory access. */
2076 MIPS_DEBUG("NOP");
2077 return;
2080 t0 = tcg_temp_new();
2081 gen_base_offset_addr(ctx, t0, base, offset);
2083 switch (opc) {
2084 #if defined(TARGET_MIPS64)
2085 case OPC_LWU:
2086 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2087 gen_store_gpr(t0, rt);
2088 opn = "lwu";
2089 break;
2090 case OPC_LD:
2091 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2092 gen_store_gpr(t0, rt);
2093 opn = "ld";
2094 break;
2095 case OPC_LLD:
2096 case R6_OPC_LLD:
2097 save_cpu_state(ctx, 1);
2098 op_ld_lld(t0, t0, ctx);
2099 gen_store_gpr(t0, rt);
2100 opn = "lld";
2101 break;
2102 case OPC_LDL:
2103 t1 = tcg_temp_new();
2104 tcg_gen_andi_tl(t1, t0, 7);
2105 #ifndef TARGET_WORDS_BIGENDIAN
2106 tcg_gen_xori_tl(t1, t1, 7);
2107 #endif
2108 tcg_gen_shli_tl(t1, t1, 3);
2109 tcg_gen_andi_tl(t0, t0, ~7);
2110 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2111 tcg_gen_shl_tl(t0, t0, t1);
2112 tcg_gen_xori_tl(t1, t1, 63);
2113 t2 = tcg_const_tl(0x7fffffffffffffffull);
2114 tcg_gen_shr_tl(t2, t2, t1);
2115 gen_load_gpr(t1, rt);
2116 tcg_gen_and_tl(t1, t1, t2);
2117 tcg_temp_free(t2);
2118 tcg_gen_or_tl(t0, t0, t1);
2119 tcg_temp_free(t1);
2120 gen_store_gpr(t0, rt);
2121 opn = "ldl";
2122 break;
2123 case OPC_LDR:
2124 t1 = tcg_temp_new();
2125 tcg_gen_andi_tl(t1, t0, 7);
2126 #ifdef TARGET_WORDS_BIGENDIAN
2127 tcg_gen_xori_tl(t1, t1, 7);
2128 #endif
2129 tcg_gen_shli_tl(t1, t1, 3);
2130 tcg_gen_andi_tl(t0, t0, ~7);
2131 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2132 tcg_gen_shr_tl(t0, t0, t1);
2133 tcg_gen_xori_tl(t1, t1, 63);
2134 t2 = tcg_const_tl(0xfffffffffffffffeull);
2135 tcg_gen_shl_tl(t2, t2, t1);
2136 gen_load_gpr(t1, rt);
2137 tcg_gen_and_tl(t1, t1, t2);
2138 tcg_temp_free(t2);
2139 tcg_gen_or_tl(t0, t0, t1);
2140 tcg_temp_free(t1);
2141 gen_store_gpr(t0, rt);
2142 opn = "ldr";
2143 break;
2144 case OPC_LDPC:
2145 t1 = tcg_const_tl(pc_relative_pc(ctx));
2146 gen_op_addr_add(ctx, t0, t0, t1);
2147 tcg_temp_free(t1);
2148 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2149 gen_store_gpr(t0, rt);
2150 opn = "ldpc";
2151 break;
2152 #endif
2153 case OPC_LWPC:
2154 t1 = tcg_const_tl(pc_relative_pc(ctx));
2155 gen_op_addr_add(ctx, t0, t0, t1);
2156 tcg_temp_free(t1);
2157 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2158 gen_store_gpr(t0, rt);
2159 opn = "lwpc";
2160 break;
2161 case OPC_LW:
2162 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2163 gen_store_gpr(t0, rt);
2164 opn = "lw";
2165 break;
2166 case OPC_LH:
2167 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
2168 gen_store_gpr(t0, rt);
2169 opn = "lh";
2170 break;
2171 case OPC_LHU:
2172 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW);
2173 gen_store_gpr(t0, rt);
2174 opn = "lhu";
2175 break;
2176 case OPC_LB:
2177 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
2178 gen_store_gpr(t0, rt);
2179 opn = "lb";
2180 break;
2181 case OPC_LBU:
2182 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
2183 gen_store_gpr(t0, rt);
2184 opn = "lbu";
2185 break;
2186 case OPC_LWL:
2187 t1 = tcg_temp_new();
2188 tcg_gen_andi_tl(t1, t0, 3);
2189 #ifndef TARGET_WORDS_BIGENDIAN
2190 tcg_gen_xori_tl(t1, t1, 3);
2191 #endif
2192 tcg_gen_shli_tl(t1, t1, 3);
2193 tcg_gen_andi_tl(t0, t0, ~3);
2194 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2195 tcg_gen_shl_tl(t0, t0, t1);
2196 tcg_gen_xori_tl(t1, t1, 31);
2197 t2 = tcg_const_tl(0x7fffffffull);
2198 tcg_gen_shr_tl(t2, t2, t1);
2199 gen_load_gpr(t1, rt);
2200 tcg_gen_and_tl(t1, t1, t2);
2201 tcg_temp_free(t2);
2202 tcg_gen_or_tl(t0, t0, t1);
2203 tcg_temp_free(t1);
2204 tcg_gen_ext32s_tl(t0, t0);
2205 gen_store_gpr(t0, rt);
2206 opn = "lwl";
2207 break;
2208 case OPC_LWR:
2209 t1 = tcg_temp_new();
2210 tcg_gen_andi_tl(t1, t0, 3);
2211 #ifdef TARGET_WORDS_BIGENDIAN
2212 tcg_gen_xori_tl(t1, t1, 3);
2213 #endif
2214 tcg_gen_shli_tl(t1, t1, 3);
2215 tcg_gen_andi_tl(t0, t0, ~3);
2216 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2217 tcg_gen_shr_tl(t0, t0, t1);
2218 tcg_gen_xori_tl(t1, t1, 31);
2219 t2 = tcg_const_tl(0xfffffffeull);
2220 tcg_gen_shl_tl(t2, t2, t1);
2221 gen_load_gpr(t1, rt);
2222 tcg_gen_and_tl(t1, t1, t2);
2223 tcg_temp_free(t2);
2224 tcg_gen_or_tl(t0, t0, t1);
2225 tcg_temp_free(t1);
2226 tcg_gen_ext32s_tl(t0, t0);
2227 gen_store_gpr(t0, rt);
2228 opn = "lwr";
2229 break;
2230 case OPC_LL:
2231 case R6_OPC_LL:
2232 save_cpu_state(ctx, 1);
2233 op_ld_ll(t0, t0, ctx);
2234 gen_store_gpr(t0, rt);
2235 opn = "ll";
2236 break;
2238 (void)opn; /* avoid a compiler warning */
2239 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2240 tcg_temp_free(t0);
2243 /* Store */
2244 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2245 int base, int16_t offset)
2247 const char *opn = "st";
2248 TCGv t0 = tcg_temp_new();
2249 TCGv t1 = tcg_temp_new();
2251 gen_base_offset_addr(ctx, t0, base, offset);
2252 gen_load_gpr(t1, rt);
2253 switch (opc) {
2254 #if defined(TARGET_MIPS64)
2255 case OPC_SD:
2256 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
2257 opn = "sd";
2258 break;
2259 case OPC_SDL:
2260 save_cpu_state(ctx, 1);
2261 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
2262 opn = "sdl";
2263 break;
2264 case OPC_SDR:
2265 save_cpu_state(ctx, 1);
2266 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2267 opn = "sdr";
2268 break;
2269 #endif
2270 case OPC_SW:
2271 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
2272 opn = "sw";
2273 break;
2274 case OPC_SH:
2275 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW);
2276 opn = "sh";
2277 break;
2278 case OPC_SB:
2279 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2280 opn = "sb";
2281 break;
2282 case OPC_SWL:
2283 save_cpu_state(ctx, 1);
2284 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2285 opn = "swl";
2286 break;
2287 case OPC_SWR:
2288 save_cpu_state(ctx, 1);
2289 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2290 opn = "swr";
2291 break;
2293 (void)opn; /* avoid a compiler warning */
2294 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2295 tcg_temp_free(t0);
2296 tcg_temp_free(t1);
2300 /* Store conditional */
2301 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2302 int base, int16_t offset)
2304 const char *opn = "st_cond";
2305 TCGv t0, t1;
2307 #ifdef CONFIG_USER_ONLY
2308 t0 = tcg_temp_local_new();
2309 t1 = tcg_temp_local_new();
2310 #else
2311 t0 = tcg_temp_new();
2312 t1 = tcg_temp_new();
2313 #endif
2314 gen_base_offset_addr(ctx, t0, base, offset);
2315 gen_load_gpr(t1, rt);
2316 switch (opc) {
2317 #if defined(TARGET_MIPS64)
2318 case OPC_SCD:
2319 case R6_OPC_SCD:
2320 save_cpu_state(ctx, 1);
2321 op_st_scd(t1, t0, rt, ctx);
2322 opn = "scd";
2323 break;
2324 #endif
2325 case OPC_SC:
2326 case R6_OPC_SC:
2327 save_cpu_state(ctx, 1);
2328 op_st_sc(t1, t0, rt, ctx);
2329 opn = "sc";
2330 break;
2332 (void)opn; /* avoid a compiler warning */
2333 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2334 tcg_temp_free(t1);
2335 tcg_temp_free(t0);
2338 /* Load and store */
2339 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2340 int base, int16_t offset)
2342 const char *opn = "flt_ldst";
2343 TCGv t0 = tcg_temp_new();
2345 gen_base_offset_addr(ctx, t0, base, offset);
2346 /* Don't do NOP if destination is zero: we must perform the actual
2347 memory access. */
2348 switch (opc) {
2349 case OPC_LWC1:
2351 TCGv_i32 fp0 = tcg_temp_new_i32();
2352 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL);
2353 gen_store_fpr32(fp0, ft);
2354 tcg_temp_free_i32(fp0);
2356 opn = "lwc1";
2357 break;
2358 case OPC_SWC1:
2360 TCGv_i32 fp0 = tcg_temp_new_i32();
2361 gen_load_fpr32(fp0, ft);
2362 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
2363 tcg_temp_free_i32(fp0);
2365 opn = "swc1";
2366 break;
2367 case OPC_LDC1:
2369 TCGv_i64 fp0 = tcg_temp_new_i64();
2370 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
2371 gen_store_fpr64(ctx, fp0, ft);
2372 tcg_temp_free_i64(fp0);
2374 opn = "ldc1";
2375 break;
2376 case OPC_SDC1:
2378 TCGv_i64 fp0 = tcg_temp_new_i64();
2379 gen_load_fpr64(ctx, fp0, ft);
2380 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
2381 tcg_temp_free_i64(fp0);
2383 opn = "sdc1";
2384 break;
2385 default:
2386 MIPS_INVAL(opn);
2387 generate_exception(ctx, EXCP_RI);
2388 goto out;
2390 (void)opn; /* avoid a compiler warning */
2391 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
2392 out:
2393 tcg_temp_free(t0);
2396 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2397 int rs, int16_t imm)
2399 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2400 check_cp1_enabled(ctx);
2401 gen_flt_ldst(ctx, op, rt, rs, imm);
2402 } else {
2403 generate_exception_err(ctx, EXCP_CpU, 1);
2407 /* Arithmetic with immediate operand */
2408 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2409 int rt, int rs, int16_t imm)
2411 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2412 const char *opn = "imm arith";
2414 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2415 /* If no destination, treat it as a NOP.
2416 For addi, we must generate the overflow exception when needed. */
2417 MIPS_DEBUG("NOP");
2418 return;
2420 switch (opc) {
2421 case OPC_ADDI:
2423 TCGv t0 = tcg_temp_local_new();
2424 TCGv t1 = tcg_temp_new();
2425 TCGv t2 = tcg_temp_new();
2426 int l1 = gen_new_label();
2428 gen_load_gpr(t1, rs);
2429 tcg_gen_addi_tl(t0, t1, uimm);
2430 tcg_gen_ext32s_tl(t0, t0);
2432 tcg_gen_xori_tl(t1, t1, ~uimm);
2433 tcg_gen_xori_tl(t2, t0, uimm);
2434 tcg_gen_and_tl(t1, t1, t2);
2435 tcg_temp_free(t2);
2436 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2437 tcg_temp_free(t1);
2438 /* operands of same sign, result different sign */
2439 generate_exception(ctx, EXCP_OVERFLOW);
2440 gen_set_label(l1);
2441 tcg_gen_ext32s_tl(t0, t0);
2442 gen_store_gpr(t0, rt);
2443 tcg_temp_free(t0);
2445 opn = "addi";
2446 break;
2447 case OPC_ADDIU:
2448 if (rs != 0) {
2449 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2450 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2451 } else {
2452 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2454 opn = "addiu";
2455 break;
2456 #if defined(TARGET_MIPS64)
2457 case OPC_DADDI:
2459 TCGv t0 = tcg_temp_local_new();
2460 TCGv t1 = tcg_temp_new();
2461 TCGv t2 = tcg_temp_new();
2462 int l1 = gen_new_label();
2464 gen_load_gpr(t1, rs);
2465 tcg_gen_addi_tl(t0, t1, uimm);
2467 tcg_gen_xori_tl(t1, t1, ~uimm);
2468 tcg_gen_xori_tl(t2, t0, uimm);
2469 tcg_gen_and_tl(t1, t1, t2);
2470 tcg_temp_free(t2);
2471 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2472 tcg_temp_free(t1);
2473 /* operands of same sign, result different sign */
2474 generate_exception(ctx, EXCP_OVERFLOW);
2475 gen_set_label(l1);
2476 gen_store_gpr(t0, rt);
2477 tcg_temp_free(t0);
2479 opn = "daddi";
2480 break;
2481 case OPC_DADDIU:
2482 if (rs != 0) {
2483 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2484 } else {
2485 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2487 opn = "daddiu";
2488 break;
2489 #endif
2491 (void)opn; /* avoid a compiler warning */
2492 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2495 /* Logic with immediate operand */
2496 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2497 int rt, int rs, int16_t imm)
2499 target_ulong uimm;
2501 if (rt == 0) {
2502 /* If no destination, treat it as a NOP. */
2503 MIPS_DEBUG("NOP");
2504 return;
2506 uimm = (uint16_t)imm;
2507 switch (opc) {
2508 case OPC_ANDI:
2509 if (likely(rs != 0))
2510 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2511 else
2512 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2513 MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
2514 regnames[rs], uimm);
2515 break;
2516 case OPC_ORI:
2517 if (rs != 0)
2518 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2519 else
2520 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2521 MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
2522 regnames[rs], uimm);
2523 break;
2524 case OPC_XORI:
2525 if (likely(rs != 0))
2526 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2527 else
2528 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2529 MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
2530 regnames[rs], uimm);
2531 break;
2532 case OPC_LUI:
2533 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2534 /* OPC_AUI */
2535 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2536 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2537 MIPS_DEBUG("aui %s, %s, %04x", regnames[rt], regnames[rs], imm);
2538 } else {
2539 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2540 MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
2542 break;
2544 default:
2545 MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
2546 break;
2550 /* Set on less than with immediate operand */
2551 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2552 int rt, int rs, int16_t imm)
2554 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2555 const char *opn = "imm arith";
2556 TCGv t0;
2558 if (rt == 0) {
2559 /* If no destination, treat it as a NOP. */
2560 MIPS_DEBUG("NOP");
2561 return;
2563 t0 = tcg_temp_new();
2564 gen_load_gpr(t0, rs);
2565 switch (opc) {
2566 case OPC_SLTI:
2567 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2568 opn = "slti";
2569 break;
2570 case OPC_SLTIU:
2571 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2572 opn = "sltiu";
2573 break;
2575 (void)opn; /* avoid a compiler warning */
2576 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2577 tcg_temp_free(t0);
2580 /* Shifts with immediate operand */
2581 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2582 int rt, int rs, int16_t imm)
2584 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2585 const char *opn = "imm shift";
2586 TCGv t0;
2588 if (rt == 0) {
2589 /* If no destination, treat it as a NOP. */
2590 MIPS_DEBUG("NOP");
2591 return;
2594 t0 = tcg_temp_new();
2595 gen_load_gpr(t0, rs);
2596 switch (opc) {
2597 case OPC_SLL:
2598 tcg_gen_shli_tl(t0, t0, uimm);
2599 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2600 opn = "sll";
2601 break;
2602 case OPC_SRA:
2603 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2604 opn = "sra";
2605 break;
2606 case OPC_SRL:
2607 if (uimm != 0) {
2608 tcg_gen_ext32u_tl(t0, t0);
2609 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2610 } else {
2611 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2613 opn = "srl";
2614 break;
2615 case OPC_ROTR:
2616 if (uimm != 0) {
2617 TCGv_i32 t1 = tcg_temp_new_i32();
2619 tcg_gen_trunc_tl_i32(t1, t0);
2620 tcg_gen_rotri_i32(t1, t1, uimm);
2621 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2622 tcg_temp_free_i32(t1);
2623 } else {
2624 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2626 opn = "rotr";
2627 break;
2628 #if defined(TARGET_MIPS64)
2629 case OPC_DSLL:
2630 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2631 opn = "dsll";
2632 break;
2633 case OPC_DSRA:
2634 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2635 opn = "dsra";
2636 break;
2637 case OPC_DSRL:
2638 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2639 opn = "dsrl";
2640 break;
2641 case OPC_DROTR:
2642 if (uimm != 0) {
2643 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2644 } else {
2645 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2647 opn = "drotr";
2648 break;
2649 case OPC_DSLL32:
2650 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2651 opn = "dsll32";
2652 break;
2653 case OPC_DSRA32:
2654 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2655 opn = "dsra32";
2656 break;
2657 case OPC_DSRL32:
2658 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2659 opn = "dsrl32";
2660 break;
2661 case OPC_DROTR32:
2662 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2663 opn = "drotr32";
2664 break;
2665 #endif
2667 (void)opn; /* avoid a compiler warning */
2668 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2669 tcg_temp_free(t0);
2672 /* Arithmetic */
2673 static void gen_arith(DisasContext *ctx, uint32_t opc,
2674 int rd, int rs, int rt)
2676 const char *opn = "arith";
2678 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2679 && opc != OPC_DADD && opc != OPC_DSUB) {
2680 /* If no destination, treat it as a NOP.
2681 For add & sub, we must generate the overflow exception when needed. */
2682 MIPS_DEBUG("NOP");
2683 return;
2686 switch (opc) {
2687 case OPC_ADD:
2689 TCGv t0 = tcg_temp_local_new();
2690 TCGv t1 = tcg_temp_new();
2691 TCGv t2 = tcg_temp_new();
2692 int l1 = gen_new_label();
2694 gen_load_gpr(t1, rs);
2695 gen_load_gpr(t2, rt);
2696 tcg_gen_add_tl(t0, t1, t2);
2697 tcg_gen_ext32s_tl(t0, t0);
2698 tcg_gen_xor_tl(t1, t1, t2);
2699 tcg_gen_xor_tl(t2, t0, t2);
2700 tcg_gen_andc_tl(t1, t2, t1);
2701 tcg_temp_free(t2);
2702 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2703 tcg_temp_free(t1);
2704 /* operands of same sign, result different sign */
2705 generate_exception(ctx, EXCP_OVERFLOW);
2706 gen_set_label(l1);
2707 gen_store_gpr(t0, rd);
2708 tcg_temp_free(t0);
2710 opn = "add";
2711 break;
2712 case OPC_ADDU:
2713 if (rs != 0 && rt != 0) {
2714 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2715 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2716 } else if (rs == 0 && rt != 0) {
2717 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2718 } else if (rs != 0 && rt == 0) {
2719 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2720 } else {
2721 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2723 opn = "addu";
2724 break;
2725 case OPC_SUB:
2727 TCGv t0 = tcg_temp_local_new();
2728 TCGv t1 = tcg_temp_new();
2729 TCGv t2 = tcg_temp_new();
2730 int l1 = gen_new_label();
2732 gen_load_gpr(t1, rs);
2733 gen_load_gpr(t2, rt);
2734 tcg_gen_sub_tl(t0, t1, t2);
2735 tcg_gen_ext32s_tl(t0, t0);
2736 tcg_gen_xor_tl(t2, t1, t2);
2737 tcg_gen_xor_tl(t1, t0, t1);
2738 tcg_gen_and_tl(t1, t1, t2);
2739 tcg_temp_free(t2);
2740 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2741 tcg_temp_free(t1);
2742 /* operands of different sign, first operand and result different sign */
2743 generate_exception(ctx, EXCP_OVERFLOW);
2744 gen_set_label(l1);
2745 gen_store_gpr(t0, rd);
2746 tcg_temp_free(t0);
2748 opn = "sub";
2749 break;
2750 case OPC_SUBU:
2751 if (rs != 0 && rt != 0) {
2752 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2753 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2754 } else if (rs == 0 && rt != 0) {
2755 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2756 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2757 } else if (rs != 0 && rt == 0) {
2758 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2759 } else {
2760 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2762 opn = "subu";
2763 break;
2764 #if defined(TARGET_MIPS64)
2765 case OPC_DADD:
2767 TCGv t0 = tcg_temp_local_new();
2768 TCGv t1 = tcg_temp_new();
2769 TCGv t2 = tcg_temp_new();
2770 int l1 = gen_new_label();
2772 gen_load_gpr(t1, rs);
2773 gen_load_gpr(t2, rt);
2774 tcg_gen_add_tl(t0, t1, t2);
2775 tcg_gen_xor_tl(t1, t1, t2);
2776 tcg_gen_xor_tl(t2, t0, t2);
2777 tcg_gen_andc_tl(t1, t2, t1);
2778 tcg_temp_free(t2);
2779 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2780 tcg_temp_free(t1);
2781 /* operands of same sign, result different sign */
2782 generate_exception(ctx, EXCP_OVERFLOW);
2783 gen_set_label(l1);
2784 gen_store_gpr(t0, rd);
2785 tcg_temp_free(t0);
2787 opn = "dadd";
2788 break;
2789 case OPC_DADDU:
2790 if (rs != 0 && rt != 0) {
2791 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2792 } else if (rs == 0 && rt != 0) {
2793 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2794 } else if (rs != 0 && rt == 0) {
2795 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2796 } else {
2797 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2799 opn = "daddu";
2800 break;
2801 case OPC_DSUB:
2803 TCGv t0 = tcg_temp_local_new();
2804 TCGv t1 = tcg_temp_new();
2805 TCGv t2 = tcg_temp_new();
2806 int l1 = gen_new_label();
2808 gen_load_gpr(t1, rs);
2809 gen_load_gpr(t2, rt);
2810 tcg_gen_sub_tl(t0, t1, t2);
2811 tcg_gen_xor_tl(t2, t1, t2);
2812 tcg_gen_xor_tl(t1, t0, t1);
2813 tcg_gen_and_tl(t1, t1, t2);
2814 tcg_temp_free(t2);
2815 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2816 tcg_temp_free(t1);
2817 /* operands of different sign, first operand and result different sign */
2818 generate_exception(ctx, EXCP_OVERFLOW);
2819 gen_set_label(l1);
2820 gen_store_gpr(t0, rd);
2821 tcg_temp_free(t0);
2823 opn = "dsub";
2824 break;
2825 case OPC_DSUBU:
2826 if (rs != 0 && rt != 0) {
2827 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2828 } else if (rs == 0 && rt != 0) {
2829 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2830 } else if (rs != 0 && rt == 0) {
2831 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2832 } else {
2833 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2835 opn = "dsubu";
2836 break;
2837 #endif
2838 case OPC_MUL:
2839 if (likely(rs != 0 && rt != 0)) {
2840 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2841 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2842 } else {
2843 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2845 opn = "mul";
2846 break;
2848 (void)opn; /* avoid a compiler warning */
2849 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2852 /* Conditional move */
2853 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2854 int rd, int rs, int rt)
2856 const char *opn = "cond move";
2857 TCGv t0, t1, t2;
2859 if (rd == 0) {
2860 /* If no destination, treat it as a NOP. */
2861 MIPS_DEBUG("NOP");
2862 return;
2865 t0 = tcg_temp_new();
2866 gen_load_gpr(t0, rt);
2867 t1 = tcg_const_tl(0);
2868 t2 = tcg_temp_new();
2869 gen_load_gpr(t2, rs);
2870 switch (opc) {
2871 case OPC_MOVN:
2872 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2873 opn = "movn";
2874 break;
2875 case OPC_MOVZ:
2876 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2877 opn = "movz";
2878 break;
2879 case OPC_SELNEZ:
2880 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2881 opn = "selnez";
2882 break;
2883 case OPC_SELEQZ:
2884 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2885 opn = "seleqz";
2886 break;
2888 tcg_temp_free(t2);
2889 tcg_temp_free(t1);
2890 tcg_temp_free(t0);
2892 (void)opn; /* avoid a compiler warning */
2893 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2896 /* Logic */
2897 static void gen_logic(DisasContext *ctx, uint32_t opc,
2898 int rd, int rs, int rt)
2900 const char *opn = "logic";
2902 if (rd == 0) {
2903 /* If no destination, treat it as a NOP. */
2904 MIPS_DEBUG("NOP");
2905 return;
2908 switch (opc) {
2909 case OPC_AND:
2910 if (likely(rs != 0 && rt != 0)) {
2911 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2912 } else {
2913 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2915 opn = "and";
2916 break;
2917 case OPC_NOR:
2918 if (rs != 0 && rt != 0) {
2919 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2920 } else if (rs == 0 && rt != 0) {
2921 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2922 } else if (rs != 0 && rt == 0) {
2923 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2924 } else {
2925 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2927 opn = "nor";
2928 break;
2929 case OPC_OR:
2930 if (likely(rs != 0 && rt != 0)) {
2931 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2932 } else if (rs == 0 && rt != 0) {
2933 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2934 } else if (rs != 0 && rt == 0) {
2935 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2936 } else {
2937 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2939 opn = "or";
2940 break;
2941 case OPC_XOR:
2942 if (likely(rs != 0 && rt != 0)) {
2943 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2944 } else if (rs == 0 && rt != 0) {
2945 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2946 } else if (rs != 0 && rt == 0) {
2947 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2948 } else {
2949 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2951 opn = "xor";
2952 break;
2954 (void)opn; /* avoid a compiler warning */
2955 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2958 /* Set on lower than */
2959 static void gen_slt(DisasContext *ctx, uint32_t opc,
2960 int rd, int rs, int rt)
2962 const char *opn = "slt";
2963 TCGv t0, t1;
2965 if (rd == 0) {
2966 /* If no destination, treat it as a NOP. */
2967 MIPS_DEBUG("NOP");
2968 return;
2971 t0 = tcg_temp_new();
2972 t1 = tcg_temp_new();
2973 gen_load_gpr(t0, rs);
2974 gen_load_gpr(t1, rt);
2975 switch (opc) {
2976 case OPC_SLT:
2977 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2978 opn = "slt";
2979 break;
2980 case OPC_SLTU:
2981 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2982 opn = "sltu";
2983 break;
2985 (void)opn; /* avoid a compiler warning */
2986 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2987 tcg_temp_free(t0);
2988 tcg_temp_free(t1);
2991 /* Shifts */
2992 static void gen_shift(DisasContext *ctx, uint32_t opc,
2993 int rd, int rs, int rt)
2995 const char *opn = "shifts";
2996 TCGv t0, t1;
2998 if (rd == 0) {
2999 /* If no destination, treat it as a NOP.
3000 For add & sub, we must generate the overflow exception when needed. */
3001 MIPS_DEBUG("NOP");
3002 return;
3005 t0 = tcg_temp_new();
3006 t1 = tcg_temp_new();
3007 gen_load_gpr(t0, rs);
3008 gen_load_gpr(t1, rt);
3009 switch (opc) {
3010 case OPC_SLLV:
3011 tcg_gen_andi_tl(t0, t0, 0x1f);
3012 tcg_gen_shl_tl(t0, t1, t0);
3013 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3014 opn = "sllv";
3015 break;
3016 case OPC_SRAV:
3017 tcg_gen_andi_tl(t0, t0, 0x1f);
3018 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3019 opn = "srav";
3020 break;
3021 case OPC_SRLV:
3022 tcg_gen_ext32u_tl(t1, t1);
3023 tcg_gen_andi_tl(t0, t0, 0x1f);
3024 tcg_gen_shr_tl(t0, t1, t0);
3025 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3026 opn = "srlv";
3027 break;
3028 case OPC_ROTRV:
3030 TCGv_i32 t2 = tcg_temp_new_i32();
3031 TCGv_i32 t3 = tcg_temp_new_i32();
3033 tcg_gen_trunc_tl_i32(t2, t0);
3034 tcg_gen_trunc_tl_i32(t3, t1);
3035 tcg_gen_andi_i32(t2, t2, 0x1f);
3036 tcg_gen_rotr_i32(t2, t3, t2);
3037 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3038 tcg_temp_free_i32(t2);
3039 tcg_temp_free_i32(t3);
3040 opn = "rotrv";
3042 break;
3043 #if defined(TARGET_MIPS64)
3044 case OPC_DSLLV:
3045 tcg_gen_andi_tl(t0, t0, 0x3f);
3046 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3047 opn = "dsllv";
3048 break;
3049 case OPC_DSRAV:
3050 tcg_gen_andi_tl(t0, t0, 0x3f);
3051 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3052 opn = "dsrav";
3053 break;
3054 case OPC_DSRLV:
3055 tcg_gen_andi_tl(t0, t0, 0x3f);
3056 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3057 opn = "dsrlv";
3058 break;
3059 case OPC_DROTRV:
3060 tcg_gen_andi_tl(t0, t0, 0x3f);
3061 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3062 opn = "drotrv";
3063 break;
3064 #endif
3066 (void)opn; /* avoid a compiler warning */
3067 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3068 tcg_temp_free(t0);
3069 tcg_temp_free(t1);
3072 /* Arithmetic on HI/LO registers */
3073 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3075 const char *opn = "hilo";
3077 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3078 /* Treat as NOP. */
3079 MIPS_DEBUG("NOP");
3080 return;
3083 if (acc != 0) {
3084 check_dsp(ctx);
3087 switch (opc) {
3088 case OPC_MFHI:
3089 #if defined(TARGET_MIPS64)
3090 if (acc != 0) {
3091 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3092 } else
3093 #endif
3095 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3097 opn = "mfhi";
3098 break;
3099 case OPC_MFLO:
3100 #if defined(TARGET_MIPS64)
3101 if (acc != 0) {
3102 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3103 } else
3104 #endif
3106 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3108 opn = "mflo";
3109 break;
3110 case OPC_MTHI:
3111 if (reg != 0) {
3112 #if defined(TARGET_MIPS64)
3113 if (acc != 0) {
3114 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3115 } else
3116 #endif
3118 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3120 } else {
3121 tcg_gen_movi_tl(cpu_HI[acc], 0);
3123 opn = "mthi";
3124 break;
3125 case OPC_MTLO:
3126 if (reg != 0) {
3127 #if defined(TARGET_MIPS64)
3128 if (acc != 0) {
3129 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3130 } else
3131 #endif
3133 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3135 } else {
3136 tcg_gen_movi_tl(cpu_LO[acc], 0);
3138 opn = "mtlo";
3139 break;
3141 (void)opn; /* avoid a compiler warning */
3142 MIPS_DEBUG("%s %s", opn, regnames[reg]);
3145 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3146 TCGMemOp memop)
3148 TCGv t0 = tcg_const_tl(addr);
3149 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3150 gen_store_gpr(t0, reg);
3151 tcg_temp_free(t0);
3154 static inline void gen_pcrel(DisasContext *ctx, int rs, int16_t imm)
3156 target_long offset;
3157 target_long addr;
3159 switch (MASK_OPC_PCREL_TOP2BITS(ctx->opcode)) {
3160 case OPC_ADDIUPC:
3161 if (rs != 0) {
3162 offset = sextract32(ctx->opcode << 2, 0, 21);
3163 addr = addr_add(ctx, ctx->pc, offset);
3164 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3166 break;
3167 case R6_OPC_LWPC:
3168 offset = sextract32(ctx->opcode << 2, 0, 21);
3169 addr = addr_add(ctx, ctx->pc, offset);
3170 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3171 break;
3172 #if defined(TARGET_MIPS64)
3173 case OPC_LWUPC:
3174 check_mips_64(ctx);
3175 offset = sextract32(ctx->opcode << 2, 0, 21);
3176 addr = addr_add(ctx, ctx->pc, offset);
3177 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3178 break;
3179 #endif
3180 default:
3181 switch (MASK_OPC_PCREL_TOP5BITS(ctx->opcode)) {
3182 case OPC_AUIPC:
3183 if (rs != 0) {
3184 offset = imm << 16;
3185 addr = addr_add(ctx, ctx->pc, offset);
3186 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3188 break;
3189 case OPC_ALUIPC:
3190 if (rs != 0) {
3191 offset = imm << 16;
3192 addr = ~0xFFFF & addr_add(ctx, ctx->pc, offset);
3193 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3195 break;
3196 #if defined(TARGET_MIPS64)
3197 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3198 case R6_OPC_LDPC + (1 << 16):
3199 case R6_OPC_LDPC + (2 << 16):
3200 case R6_OPC_LDPC + (3 << 16):
3201 check_mips_64(ctx);
3202 offset = sextract32(ctx->opcode << 3, 0, 21);
3203 addr = addr_add(ctx, (ctx->pc & ~0x7), offset);
3204 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3205 break;
3206 #endif
3207 default:
3208 MIPS_INVAL("OPC_PCREL");
3209 generate_exception(ctx, EXCP_RI);
3210 break;
3212 break;
3216 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3218 const char *opn = "r6 mul/div";
3219 TCGv t0, t1;
3221 if (rd == 0) {
3222 /* Treat as NOP. */
3223 MIPS_DEBUG("NOP");
3224 return;
3227 t0 = tcg_temp_new();
3228 t1 = tcg_temp_new();
3230 gen_load_gpr(t0, rs);
3231 gen_load_gpr(t1, rt);
3233 switch (opc) {
3234 case R6_OPC_DIV:
3236 TCGv t2 = tcg_temp_new();
3237 TCGv t3 = tcg_temp_new();
3238 tcg_gen_ext32s_tl(t0, t0);
3239 tcg_gen_ext32s_tl(t1, t1);
3240 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3241 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3242 tcg_gen_and_tl(t2, t2, t3);
3243 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3244 tcg_gen_or_tl(t2, t2, t3);
3245 tcg_gen_movi_tl(t3, 0);
3246 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3247 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3248 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3249 tcg_temp_free(t3);
3250 tcg_temp_free(t2);
3252 opn = "div";
3253 break;
3254 case R6_OPC_MOD:
3256 TCGv t2 = tcg_temp_new();
3257 TCGv t3 = tcg_temp_new();
3258 tcg_gen_ext32s_tl(t0, t0);
3259 tcg_gen_ext32s_tl(t1, t1);
3260 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3261 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3262 tcg_gen_and_tl(t2, t2, t3);
3263 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3264 tcg_gen_or_tl(t2, t2, t3);
3265 tcg_gen_movi_tl(t3, 0);
3266 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3267 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3268 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3269 tcg_temp_free(t3);
3270 tcg_temp_free(t2);
3272 opn = "mod";
3273 break;
3274 case R6_OPC_DIVU:
3276 TCGv t2 = tcg_const_tl(0);
3277 TCGv t3 = tcg_const_tl(1);
3278 tcg_gen_ext32u_tl(t0, t0);
3279 tcg_gen_ext32u_tl(t1, t1);
3280 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3281 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3282 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3283 tcg_temp_free(t3);
3284 tcg_temp_free(t2);
3286 opn = "divu";
3287 break;
3288 case R6_OPC_MODU:
3290 TCGv t2 = tcg_const_tl(0);
3291 TCGv t3 = tcg_const_tl(1);
3292 tcg_gen_ext32u_tl(t0, t0);
3293 tcg_gen_ext32u_tl(t1, t1);
3294 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3295 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3296 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3297 tcg_temp_free(t3);
3298 tcg_temp_free(t2);
3300 opn = "modu";
3301 break;
3302 case R6_OPC_MUL:
3304 TCGv_i32 t2 = tcg_temp_new_i32();
3305 TCGv_i32 t3 = tcg_temp_new_i32();
3306 tcg_gen_trunc_tl_i32(t2, t0);
3307 tcg_gen_trunc_tl_i32(t3, t1);
3308 tcg_gen_mul_i32(t2, t2, t3);
3309 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3310 tcg_temp_free_i32(t2);
3311 tcg_temp_free_i32(t3);
3313 opn = "mul";
3314 break;
3315 case R6_OPC_MUH:
3317 TCGv_i32 t2 = tcg_temp_new_i32();
3318 TCGv_i32 t3 = tcg_temp_new_i32();
3319 tcg_gen_trunc_tl_i32(t2, t0);
3320 tcg_gen_trunc_tl_i32(t3, t1);
3321 tcg_gen_muls2_i32(t2, t3, t2, t3);
3322 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3323 tcg_temp_free_i32(t2);
3324 tcg_temp_free_i32(t3);
3326 opn = "muh";
3327 break;
3328 case R6_OPC_MULU:
3330 TCGv_i32 t2 = tcg_temp_new_i32();
3331 TCGv_i32 t3 = tcg_temp_new_i32();
3332 tcg_gen_trunc_tl_i32(t2, t0);
3333 tcg_gen_trunc_tl_i32(t3, t1);
3334 tcg_gen_mul_i32(t2, t2, t3);
3335 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3336 tcg_temp_free_i32(t2);
3337 tcg_temp_free_i32(t3);
3339 opn = "mulu";
3340 break;
3341 case R6_OPC_MUHU:
3343 TCGv_i32 t2 = tcg_temp_new_i32();
3344 TCGv_i32 t3 = tcg_temp_new_i32();
3345 tcg_gen_trunc_tl_i32(t2, t0);
3346 tcg_gen_trunc_tl_i32(t3, t1);
3347 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3348 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3349 tcg_temp_free_i32(t2);
3350 tcg_temp_free_i32(t3);
3352 opn = "muhu";
3353 break;
3354 #if defined(TARGET_MIPS64)
3355 case R6_OPC_DDIV:
3357 TCGv t2 = tcg_temp_new();
3358 TCGv t3 = tcg_temp_new();
3359 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3360 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3361 tcg_gen_and_tl(t2, t2, t3);
3362 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3363 tcg_gen_or_tl(t2, t2, t3);
3364 tcg_gen_movi_tl(t3, 0);
3365 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3366 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3367 tcg_temp_free(t3);
3368 tcg_temp_free(t2);
3370 opn = "ddiv";
3371 break;
3372 case R6_OPC_DMOD:
3374 TCGv t2 = tcg_temp_new();
3375 TCGv t3 = tcg_temp_new();
3376 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3377 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3378 tcg_gen_and_tl(t2, t2, t3);
3379 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3380 tcg_gen_or_tl(t2, t2, t3);
3381 tcg_gen_movi_tl(t3, 0);
3382 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3383 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3384 tcg_temp_free(t3);
3385 tcg_temp_free(t2);
3387 opn = "dmod";
3388 break;
3389 case R6_OPC_DDIVU:
3391 TCGv t2 = tcg_const_tl(0);
3392 TCGv t3 = tcg_const_tl(1);
3393 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3394 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3395 tcg_temp_free(t3);
3396 tcg_temp_free(t2);
3398 opn = "ddivu";
3399 break;
3400 case R6_OPC_DMODU:
3402 TCGv t2 = tcg_const_tl(0);
3403 TCGv t3 = tcg_const_tl(1);
3404 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3405 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3406 tcg_temp_free(t3);
3407 tcg_temp_free(t2);
3409 opn = "dmodu";
3410 break;
3411 case R6_OPC_DMUL:
3412 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3413 opn = "dmul";
3414 break;
3415 case R6_OPC_DMUH:
3417 TCGv t2 = tcg_temp_new();
3418 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3419 tcg_temp_free(t2);
3421 opn = "dmuh";
3422 break;
3423 case R6_OPC_DMULU:
3424 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3425 opn = "dmulu";
3426 break;
3427 case R6_OPC_DMUHU:
3429 TCGv t2 = tcg_temp_new();
3430 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3431 tcg_temp_free(t2);
3433 opn = "dmuhu";
3434 break;
3435 #endif
3436 default:
3437 MIPS_INVAL(opn);
3438 generate_exception(ctx, EXCP_RI);
3439 goto out;
3441 (void)opn; /* avoid a compiler warning */
3442 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3443 out:
3444 tcg_temp_free(t0);
3445 tcg_temp_free(t1);
3448 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3449 int acc, int rs, int rt)
3451 const char *opn = "mul/div";
3452 TCGv t0, t1;
3454 t0 = tcg_temp_new();
3455 t1 = tcg_temp_new();
3457 gen_load_gpr(t0, rs);
3458 gen_load_gpr(t1, rt);
3460 if (acc != 0) {
3461 check_dsp(ctx);
3464 switch (opc) {
3465 case OPC_DIV:
3467 TCGv t2 = tcg_temp_new();
3468 TCGv t3 = tcg_temp_new();
3469 tcg_gen_ext32s_tl(t0, t0);
3470 tcg_gen_ext32s_tl(t1, t1);
3471 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3472 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3473 tcg_gen_and_tl(t2, t2, t3);
3474 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3475 tcg_gen_or_tl(t2, t2, t3);
3476 tcg_gen_movi_tl(t3, 0);
3477 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3478 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3479 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3480 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3481 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3482 tcg_temp_free(t3);
3483 tcg_temp_free(t2);
3485 opn = "div";
3486 break;
3487 case OPC_DIVU:
3489 TCGv t2 = tcg_const_tl(0);
3490 TCGv t3 = tcg_const_tl(1);
3491 tcg_gen_ext32u_tl(t0, t0);
3492 tcg_gen_ext32u_tl(t1, t1);
3493 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3494 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3495 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3496 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3497 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3498 tcg_temp_free(t3);
3499 tcg_temp_free(t2);
3501 opn = "divu";
3502 break;
3503 case OPC_MULT:
3505 TCGv_i32 t2 = tcg_temp_new_i32();
3506 TCGv_i32 t3 = tcg_temp_new_i32();
3507 tcg_gen_trunc_tl_i32(t2, t0);
3508 tcg_gen_trunc_tl_i32(t3, t1);
3509 tcg_gen_muls2_i32(t2, t3, t2, t3);
3510 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3511 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3512 tcg_temp_free_i32(t2);
3513 tcg_temp_free_i32(t3);
3515 opn = "mult";
3516 break;
3517 case OPC_MULTU:
3519 TCGv_i32 t2 = tcg_temp_new_i32();
3520 TCGv_i32 t3 = tcg_temp_new_i32();
3521 tcg_gen_trunc_tl_i32(t2, t0);
3522 tcg_gen_trunc_tl_i32(t3, t1);
3523 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3524 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3525 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3526 tcg_temp_free_i32(t2);
3527 tcg_temp_free_i32(t3);
3529 opn = "multu";
3530 break;
3531 #if defined(TARGET_MIPS64)
3532 case OPC_DDIV:
3534 TCGv t2 = tcg_temp_new();
3535 TCGv t3 = tcg_temp_new();
3536 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3537 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3538 tcg_gen_and_tl(t2, t2, t3);
3539 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3540 tcg_gen_or_tl(t2, t2, t3);
3541 tcg_gen_movi_tl(t3, 0);
3542 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3543 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3544 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3545 tcg_temp_free(t3);
3546 tcg_temp_free(t2);
3548 opn = "ddiv";
3549 break;
3550 case OPC_DDIVU:
3552 TCGv t2 = tcg_const_tl(0);
3553 TCGv t3 = tcg_const_tl(1);
3554 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3555 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3556 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3557 tcg_temp_free(t3);
3558 tcg_temp_free(t2);
3560 opn = "ddivu";
3561 break;
3562 case OPC_DMULT:
3563 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3564 opn = "dmult";
3565 break;
3566 case OPC_DMULTU:
3567 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3568 opn = "dmultu";
3569 break;
3570 #endif
3571 case OPC_MADD:
3573 TCGv_i64 t2 = tcg_temp_new_i64();
3574 TCGv_i64 t3 = tcg_temp_new_i64();
3576 tcg_gen_ext_tl_i64(t2, t0);
3577 tcg_gen_ext_tl_i64(t3, t1);
3578 tcg_gen_mul_i64(t2, t2, t3);
3579 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3580 tcg_gen_add_i64(t2, t2, t3);
3581 tcg_temp_free_i64(t3);
3582 tcg_gen_trunc_i64_tl(t0, t2);
3583 tcg_gen_shri_i64(t2, t2, 32);
3584 tcg_gen_trunc_i64_tl(t1, t2);
3585 tcg_temp_free_i64(t2);
3586 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3587 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3589 opn = "madd";
3590 break;
3591 case OPC_MADDU:
3593 TCGv_i64 t2 = tcg_temp_new_i64();
3594 TCGv_i64 t3 = tcg_temp_new_i64();
3596 tcg_gen_ext32u_tl(t0, t0);
3597 tcg_gen_ext32u_tl(t1, t1);
3598 tcg_gen_extu_tl_i64(t2, t0);
3599 tcg_gen_extu_tl_i64(t3, t1);
3600 tcg_gen_mul_i64(t2, t2, t3);
3601 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3602 tcg_gen_add_i64(t2, t2, t3);
3603 tcg_temp_free_i64(t3);
3604 tcg_gen_trunc_i64_tl(t0, t2);
3605 tcg_gen_shri_i64(t2, t2, 32);
3606 tcg_gen_trunc_i64_tl(t1, t2);
3607 tcg_temp_free_i64(t2);
3608 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3609 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3611 opn = "maddu";
3612 break;
3613 case OPC_MSUB:
3615 TCGv_i64 t2 = tcg_temp_new_i64();
3616 TCGv_i64 t3 = tcg_temp_new_i64();
3618 tcg_gen_ext_tl_i64(t2, t0);
3619 tcg_gen_ext_tl_i64(t3, t1);
3620 tcg_gen_mul_i64(t2, t2, t3);
3621 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3622 tcg_gen_sub_i64(t2, t3, t2);
3623 tcg_temp_free_i64(t3);
3624 tcg_gen_trunc_i64_tl(t0, t2);
3625 tcg_gen_shri_i64(t2, t2, 32);
3626 tcg_gen_trunc_i64_tl(t1, t2);
3627 tcg_temp_free_i64(t2);
3628 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3629 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3631 opn = "msub";
3632 break;
3633 case OPC_MSUBU:
3635 TCGv_i64 t2 = tcg_temp_new_i64();
3636 TCGv_i64 t3 = tcg_temp_new_i64();
3638 tcg_gen_ext32u_tl(t0, t0);
3639 tcg_gen_ext32u_tl(t1, t1);
3640 tcg_gen_extu_tl_i64(t2, t0);
3641 tcg_gen_extu_tl_i64(t3, t1);
3642 tcg_gen_mul_i64(t2, t2, t3);
3643 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3644 tcg_gen_sub_i64(t2, t3, t2);
3645 tcg_temp_free_i64(t3);
3646 tcg_gen_trunc_i64_tl(t0, t2);
3647 tcg_gen_shri_i64(t2, t2, 32);
3648 tcg_gen_trunc_i64_tl(t1, t2);
3649 tcg_temp_free_i64(t2);
3650 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3651 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3653 opn = "msubu";
3654 break;
3655 default:
3656 MIPS_INVAL(opn);
3657 generate_exception(ctx, EXCP_RI);
3658 goto out;
3660 (void)opn; /* avoid a compiler warning */
3661 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3662 out:
3663 tcg_temp_free(t0);
3664 tcg_temp_free(t1);
3667 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3668 int rd, int rs, int rt)
3670 const char *opn = "mul vr54xx";
3671 TCGv t0 = tcg_temp_new();
3672 TCGv t1 = tcg_temp_new();
3674 gen_load_gpr(t0, rs);
3675 gen_load_gpr(t1, rt);
3677 switch (opc) {
3678 case OPC_VR54XX_MULS:
3679 gen_helper_muls(t0, cpu_env, t0, t1);
3680 opn = "muls";
3681 break;
3682 case OPC_VR54XX_MULSU:
3683 gen_helper_mulsu(t0, cpu_env, t0, t1);
3684 opn = "mulsu";
3685 break;
3686 case OPC_VR54XX_MACC:
3687 gen_helper_macc(t0, cpu_env, t0, t1);
3688 opn = "macc";
3689 break;
3690 case OPC_VR54XX_MACCU:
3691 gen_helper_maccu(t0, cpu_env, t0, t1);
3692 opn = "maccu";
3693 break;
3694 case OPC_VR54XX_MSAC:
3695 gen_helper_msac(t0, cpu_env, t0, t1);
3696 opn = "msac";
3697 break;
3698 case OPC_VR54XX_MSACU:
3699 gen_helper_msacu(t0, cpu_env, t0, t1);
3700 opn = "msacu";
3701 break;
3702 case OPC_VR54XX_MULHI:
3703 gen_helper_mulhi(t0, cpu_env, t0, t1);
3704 opn = "mulhi";
3705 break;
3706 case OPC_VR54XX_MULHIU:
3707 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3708 opn = "mulhiu";
3709 break;
3710 case OPC_VR54XX_MULSHI:
3711 gen_helper_mulshi(t0, cpu_env, t0, t1);
3712 opn = "mulshi";
3713 break;
3714 case OPC_VR54XX_MULSHIU:
3715 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3716 opn = "mulshiu";
3717 break;
3718 case OPC_VR54XX_MACCHI:
3719 gen_helper_macchi(t0, cpu_env, t0, t1);
3720 opn = "macchi";
3721 break;
3722 case OPC_VR54XX_MACCHIU:
3723 gen_helper_macchiu(t0, cpu_env, t0, t1);
3724 opn = "macchiu";
3725 break;
3726 case OPC_VR54XX_MSACHI:
3727 gen_helper_msachi(t0, cpu_env, t0, t1);
3728 opn = "msachi";
3729 break;
3730 case OPC_VR54XX_MSACHIU:
3731 gen_helper_msachiu(t0, cpu_env, t0, t1);
3732 opn = "msachiu";
3733 break;
3734 default:
3735 MIPS_INVAL("mul vr54xx");
3736 generate_exception(ctx, EXCP_RI);
3737 goto out;
3739 gen_store_gpr(t0, rd);
3740 (void)opn; /* avoid a compiler warning */
3741 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3743 out:
3744 tcg_temp_free(t0);
3745 tcg_temp_free(t1);
3748 static void gen_cl (DisasContext *ctx, uint32_t opc,
3749 int rd, int rs)
3751 const char *opn = "CLx";
3752 TCGv t0;
3754 if (rd == 0) {
3755 /* Treat as NOP. */
3756 MIPS_DEBUG("NOP");
3757 return;
3759 t0 = tcg_temp_new();
3760 gen_load_gpr(t0, rs);
3761 switch (opc) {
3762 case OPC_CLO:
3763 case R6_OPC_CLO:
3764 gen_helper_clo(cpu_gpr[rd], t0);
3765 opn = "clo";
3766 break;
3767 case OPC_CLZ:
3768 case R6_OPC_CLZ:
3769 gen_helper_clz(cpu_gpr[rd], t0);
3770 opn = "clz";
3771 break;
3772 #if defined(TARGET_MIPS64)
3773 case OPC_DCLO:
3774 case R6_OPC_DCLO:
3775 gen_helper_dclo(cpu_gpr[rd], t0);
3776 opn = "dclo";
3777 break;
3778 case OPC_DCLZ:
3779 case R6_OPC_DCLZ:
3780 gen_helper_dclz(cpu_gpr[rd], t0);
3781 opn = "dclz";
3782 break;
3783 #endif
3785 (void)opn; /* avoid a compiler warning */
3786 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3787 tcg_temp_free(t0);
3790 /* Godson integer instructions */
3791 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3792 int rd, int rs, int rt)
3794 const char *opn = "loongson";
3795 TCGv t0, t1;
3797 if (rd == 0) {
3798 /* Treat as NOP. */
3799 MIPS_DEBUG("NOP");
3800 return;
3803 switch (opc) {
3804 case OPC_MULT_G_2E:
3805 case OPC_MULT_G_2F:
3806 case OPC_MULTU_G_2E:
3807 case OPC_MULTU_G_2F:
3808 #if defined(TARGET_MIPS64)
3809 case OPC_DMULT_G_2E:
3810 case OPC_DMULT_G_2F:
3811 case OPC_DMULTU_G_2E:
3812 case OPC_DMULTU_G_2F:
3813 #endif
3814 t0 = tcg_temp_new();
3815 t1 = tcg_temp_new();
3816 break;
3817 default:
3818 t0 = tcg_temp_local_new();
3819 t1 = tcg_temp_local_new();
3820 break;
3823 gen_load_gpr(t0, rs);
3824 gen_load_gpr(t1, rt);
3826 switch (opc) {
3827 case OPC_MULT_G_2E:
3828 case OPC_MULT_G_2F:
3829 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3830 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3831 opn = "mult.g";
3832 break;
3833 case OPC_MULTU_G_2E:
3834 case OPC_MULTU_G_2F:
3835 tcg_gen_ext32u_tl(t0, t0);
3836 tcg_gen_ext32u_tl(t1, t1);
3837 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3838 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3839 opn = "multu.g";
3840 break;
3841 case OPC_DIV_G_2E:
3842 case OPC_DIV_G_2F:
3844 int l1 = gen_new_label();
3845 int l2 = gen_new_label();
3846 int l3 = gen_new_label();
3847 tcg_gen_ext32s_tl(t0, t0);
3848 tcg_gen_ext32s_tl(t1, t1);
3849 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3850 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3851 tcg_gen_br(l3);
3852 gen_set_label(l1);
3853 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3854 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3855 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3856 tcg_gen_br(l3);
3857 gen_set_label(l2);
3858 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3859 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3860 gen_set_label(l3);
3862 opn = "div.g";
3863 break;
3864 case OPC_DIVU_G_2E:
3865 case OPC_DIVU_G_2F:
3867 int l1 = gen_new_label();
3868 int l2 = gen_new_label();
3869 tcg_gen_ext32u_tl(t0, t0);
3870 tcg_gen_ext32u_tl(t1, t1);
3871 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3872 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3873 tcg_gen_br(l2);
3874 gen_set_label(l1);
3875 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3876 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3877 gen_set_label(l2);
3879 opn = "divu.g";
3880 break;
3881 case OPC_MOD_G_2E:
3882 case OPC_MOD_G_2F:
3884 int l1 = gen_new_label();
3885 int l2 = gen_new_label();
3886 int l3 = gen_new_label();
3887 tcg_gen_ext32u_tl(t0, t0);
3888 tcg_gen_ext32u_tl(t1, t1);
3889 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3890 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3891 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3892 gen_set_label(l1);
3893 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3894 tcg_gen_br(l3);
3895 gen_set_label(l2);
3896 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3897 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3898 gen_set_label(l3);
3900 opn = "mod.g";
3901 break;
3902 case OPC_MODU_G_2E:
3903 case OPC_MODU_G_2F:
3905 int l1 = gen_new_label();
3906 int l2 = gen_new_label();
3907 tcg_gen_ext32u_tl(t0, t0);
3908 tcg_gen_ext32u_tl(t1, t1);
3909 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3910 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3911 tcg_gen_br(l2);
3912 gen_set_label(l1);
3913 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3914 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3915 gen_set_label(l2);
3917 opn = "modu.g";
3918 break;
3919 #if defined(TARGET_MIPS64)
3920 case OPC_DMULT_G_2E:
3921 case OPC_DMULT_G_2F:
3922 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3923 opn = "dmult.g";
3924 break;
3925 case OPC_DMULTU_G_2E:
3926 case OPC_DMULTU_G_2F:
3927 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3928 opn = "dmultu.g";
3929 break;
3930 case OPC_DDIV_G_2E:
3931 case OPC_DDIV_G_2F:
3933 int l1 = gen_new_label();
3934 int l2 = gen_new_label();
3935 int l3 = gen_new_label();
3936 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3937 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3938 tcg_gen_br(l3);
3939 gen_set_label(l1);
3940 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3941 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3942 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3943 tcg_gen_br(l3);
3944 gen_set_label(l2);
3945 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3946 gen_set_label(l3);
3948 opn = "ddiv.g";
3949 break;
3950 case OPC_DDIVU_G_2E:
3951 case OPC_DDIVU_G_2F:
3953 int l1 = gen_new_label();
3954 int l2 = gen_new_label();
3955 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3956 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3957 tcg_gen_br(l2);
3958 gen_set_label(l1);
3959 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3960 gen_set_label(l2);
3962 opn = "ddivu.g";
3963 break;
3964 case OPC_DMOD_G_2E:
3965 case OPC_DMOD_G_2F:
3967 int l1 = gen_new_label();
3968 int l2 = gen_new_label();
3969 int l3 = gen_new_label();
3970 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3971 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3972 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3973 gen_set_label(l1);
3974 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3975 tcg_gen_br(l3);
3976 gen_set_label(l2);
3977 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3978 gen_set_label(l3);
3980 opn = "dmod.g";
3981 break;
3982 case OPC_DMODU_G_2E:
3983 case OPC_DMODU_G_2F:
3985 int l1 = gen_new_label();
3986 int l2 = gen_new_label();
3987 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3988 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3989 tcg_gen_br(l2);
3990 gen_set_label(l1);
3991 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3992 gen_set_label(l2);
3994 opn = "dmodu.g";
3995 break;
3996 #endif
3999 (void)opn; /* avoid a compiler warning */
4000 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
4001 tcg_temp_free(t0);
4002 tcg_temp_free(t1);
4005 /* Loongson multimedia instructions */
4006 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4008 const char *opn = "loongson_cp2";
4009 uint32_t opc, shift_max;
4010 TCGv_i64 t0, t1;
4012 opc = MASK_LMI(ctx->opcode);
4013 switch (opc) {
4014 case OPC_ADD_CP2:
4015 case OPC_SUB_CP2:
4016 case OPC_DADD_CP2:
4017 case OPC_DSUB_CP2:
4018 t0 = tcg_temp_local_new_i64();
4019 t1 = tcg_temp_local_new_i64();
4020 break;
4021 default:
4022 t0 = tcg_temp_new_i64();
4023 t1 = tcg_temp_new_i64();
4024 break;
4027 gen_load_fpr64(ctx, t0, rs);
4028 gen_load_fpr64(ctx, t1, rt);
4030 #define LMI_HELPER(UP, LO) \
4031 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
4032 #define LMI_HELPER_1(UP, LO) \
4033 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
4034 #define LMI_DIRECT(UP, LO, OP) \
4035 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
4037 switch (opc) {
4038 LMI_HELPER(PADDSH, paddsh);
4039 LMI_HELPER(PADDUSH, paddush);
4040 LMI_HELPER(PADDH, paddh);
4041 LMI_HELPER(PADDW, paddw);
4042 LMI_HELPER(PADDSB, paddsb);
4043 LMI_HELPER(PADDUSB, paddusb);
4044 LMI_HELPER(PADDB, paddb);
4046 LMI_HELPER(PSUBSH, psubsh);
4047 LMI_HELPER(PSUBUSH, psubush);
4048 LMI_HELPER(PSUBH, psubh);
4049 LMI_HELPER(PSUBW, psubw);
4050 LMI_HELPER(PSUBSB, psubsb);
4051 LMI_HELPER(PSUBUSB, psubusb);
4052 LMI_HELPER(PSUBB, psubb);
4054 LMI_HELPER(PSHUFH, pshufh);
4055 LMI_HELPER(PACKSSWH, packsswh);
4056 LMI_HELPER(PACKSSHB, packsshb);
4057 LMI_HELPER(PACKUSHB, packushb);
4059 LMI_HELPER(PUNPCKLHW, punpcklhw);
4060 LMI_HELPER(PUNPCKHHW, punpckhhw);
4061 LMI_HELPER(PUNPCKLBH, punpcklbh);
4062 LMI_HELPER(PUNPCKHBH, punpckhbh);
4063 LMI_HELPER(PUNPCKLWD, punpcklwd);
4064 LMI_HELPER(PUNPCKHWD, punpckhwd);
4066 LMI_HELPER(PAVGH, pavgh);
4067 LMI_HELPER(PAVGB, pavgb);
4068 LMI_HELPER(PMAXSH, pmaxsh);
4069 LMI_HELPER(PMINSH, pminsh);
4070 LMI_HELPER(PMAXUB, pmaxub);
4071 LMI_HELPER(PMINUB, pminub);
4073 LMI_HELPER(PCMPEQW, pcmpeqw);
4074 LMI_HELPER(PCMPGTW, pcmpgtw);
4075 LMI_HELPER(PCMPEQH, pcmpeqh);
4076 LMI_HELPER(PCMPGTH, pcmpgth);
4077 LMI_HELPER(PCMPEQB, pcmpeqb);
4078 LMI_HELPER(PCMPGTB, pcmpgtb);
4080 LMI_HELPER(PSLLW, psllw);
4081 LMI_HELPER(PSLLH, psllh);
4082 LMI_HELPER(PSRLW, psrlw);
4083 LMI_HELPER(PSRLH, psrlh);
4084 LMI_HELPER(PSRAW, psraw);
4085 LMI_HELPER(PSRAH, psrah);
4087 LMI_HELPER(PMULLH, pmullh);
4088 LMI_HELPER(PMULHH, pmulhh);
4089 LMI_HELPER(PMULHUH, pmulhuh);
4090 LMI_HELPER(PMADDHW, pmaddhw);
4092 LMI_HELPER(PASUBUB, pasubub);
4093 LMI_HELPER_1(BIADD, biadd);
4094 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4096 LMI_DIRECT(PADDD, paddd, add);
4097 LMI_DIRECT(PSUBD, psubd, sub);
4098 LMI_DIRECT(XOR_CP2, xor, xor);
4099 LMI_DIRECT(NOR_CP2, nor, nor);
4100 LMI_DIRECT(AND_CP2, and, and);
4101 LMI_DIRECT(PANDN, pandn, andc);
4102 LMI_DIRECT(OR, or, or);
4104 case OPC_PINSRH_0:
4105 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4106 opn = "pinsrh_0";
4107 break;
4108 case OPC_PINSRH_1:
4109 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4110 opn = "pinsrh_1";
4111 break;
4112 case OPC_PINSRH_2:
4113 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4114 opn = "pinsrh_2";
4115 break;
4116 case OPC_PINSRH_3:
4117 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4118 opn = "pinsrh_3";
4119 break;
4121 case OPC_PEXTRH:
4122 tcg_gen_andi_i64(t1, t1, 3);
4123 tcg_gen_shli_i64(t1, t1, 4);
4124 tcg_gen_shr_i64(t0, t0, t1);
4125 tcg_gen_ext16u_i64(t0, t0);
4126 opn = "pextrh";
4127 break;
4129 case OPC_ADDU_CP2:
4130 tcg_gen_add_i64(t0, t0, t1);
4131 tcg_gen_ext32s_i64(t0, t0);
4132 opn = "addu";
4133 break;
4134 case OPC_SUBU_CP2:
4135 tcg_gen_sub_i64(t0, t0, t1);
4136 tcg_gen_ext32s_i64(t0, t0);
4137 opn = "addu";
4138 break;
4140 case OPC_SLL_CP2:
4141 opn = "sll";
4142 shift_max = 32;
4143 goto do_shift;
4144 case OPC_SRL_CP2:
4145 opn = "srl";
4146 shift_max = 32;
4147 goto do_shift;
4148 case OPC_SRA_CP2:
4149 opn = "sra";
4150 shift_max = 32;
4151 goto do_shift;
4152 case OPC_DSLL_CP2:
4153 opn = "dsll";
4154 shift_max = 64;
4155 goto do_shift;
4156 case OPC_DSRL_CP2:
4157 opn = "dsrl";
4158 shift_max = 64;
4159 goto do_shift;
4160 case OPC_DSRA_CP2:
4161 opn = "dsra";
4162 shift_max = 64;
4163 goto do_shift;
4164 do_shift:
4165 /* Make sure shift count isn't TCG undefined behaviour. */
4166 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4168 switch (opc) {
4169 case OPC_SLL_CP2:
4170 case OPC_DSLL_CP2:
4171 tcg_gen_shl_i64(t0, t0, t1);
4172 break;
4173 case OPC_SRA_CP2:
4174 case OPC_DSRA_CP2:
4175 /* Since SRA is UndefinedResult without sign-extended inputs,
4176 we can treat SRA and DSRA the same. */
4177 tcg_gen_sar_i64(t0, t0, t1);
4178 break;
4179 case OPC_SRL_CP2:
4180 /* We want to shift in zeros for SRL; zero-extend first. */
4181 tcg_gen_ext32u_i64(t0, t0);
4182 /* FALLTHRU */
4183 case OPC_DSRL_CP2:
4184 tcg_gen_shr_i64(t0, t0, t1);
4185 break;
4188 if (shift_max == 32) {
4189 tcg_gen_ext32s_i64(t0, t0);
4192 /* Shifts larger than MAX produce zero. */
4193 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4194 tcg_gen_neg_i64(t1, t1);
4195 tcg_gen_and_i64(t0, t0, t1);
4196 break;
4198 case OPC_ADD_CP2:
4199 case OPC_DADD_CP2:
4201 TCGv_i64 t2 = tcg_temp_new_i64();
4202 int lab = gen_new_label();
4204 tcg_gen_mov_i64(t2, t0);
4205 tcg_gen_add_i64(t0, t1, t2);
4206 if (opc == OPC_ADD_CP2) {
4207 tcg_gen_ext32s_i64(t0, t0);
4209 tcg_gen_xor_i64(t1, t1, t2);
4210 tcg_gen_xor_i64(t2, t2, t0);
4211 tcg_gen_andc_i64(t1, t2, t1);
4212 tcg_temp_free_i64(t2);
4213 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4214 generate_exception(ctx, EXCP_OVERFLOW);
4215 gen_set_label(lab);
4217 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
4218 break;
4221 case OPC_SUB_CP2:
4222 case OPC_DSUB_CP2:
4224 TCGv_i64 t2 = tcg_temp_new_i64();
4225 int lab = gen_new_label();
4227 tcg_gen_mov_i64(t2, t0);
4228 tcg_gen_sub_i64(t0, t1, t2);
4229 if (opc == OPC_SUB_CP2) {
4230 tcg_gen_ext32s_i64(t0, t0);
4232 tcg_gen_xor_i64(t1, t1, t2);
4233 tcg_gen_xor_i64(t2, t2, t0);
4234 tcg_gen_and_i64(t1, t1, t2);
4235 tcg_temp_free_i64(t2);
4236 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4237 generate_exception(ctx, EXCP_OVERFLOW);
4238 gen_set_label(lab);
4240 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
4241 break;
4244 case OPC_PMULUW:
4245 tcg_gen_ext32u_i64(t0, t0);
4246 tcg_gen_ext32u_i64(t1, t1);
4247 tcg_gen_mul_i64(t0, t0, t1);
4248 opn = "pmuluw";
4249 break;
4251 case OPC_SEQU_CP2:
4252 case OPC_SEQ_CP2:
4253 case OPC_SLTU_CP2:
4254 case OPC_SLT_CP2:
4255 case OPC_SLEU_CP2:
4256 case OPC_SLE_CP2:
4257 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4258 FD field is the CC field? */
4259 default:
4260 MIPS_INVAL(opn);
4261 generate_exception(ctx, EXCP_RI);
4262 return;
4265 #undef LMI_HELPER
4266 #undef LMI_DIRECT
4268 gen_store_fpr64(ctx, t0, rd);
4270 (void)opn; /* avoid a compiler warning */
4271 MIPS_DEBUG("%s %s, %s, %s", opn,
4272 fregnames[rd], fregnames[rs], fregnames[rt]);
4273 tcg_temp_free_i64(t0);
4274 tcg_temp_free_i64(t1);
4277 /* Traps */
4278 static void gen_trap (DisasContext *ctx, uint32_t opc,
4279 int rs, int rt, int16_t imm)
4281 int cond;
4282 TCGv t0 = tcg_temp_new();
4283 TCGv t1 = tcg_temp_new();
4285 cond = 0;
4286 /* Load needed operands */
4287 switch (opc) {
4288 case OPC_TEQ:
4289 case OPC_TGE:
4290 case OPC_TGEU:
4291 case OPC_TLT:
4292 case OPC_TLTU:
4293 case OPC_TNE:
4294 /* Compare two registers */
4295 if (rs != rt) {
4296 gen_load_gpr(t0, rs);
4297 gen_load_gpr(t1, rt);
4298 cond = 1;
4300 break;
4301 case OPC_TEQI:
4302 case OPC_TGEI:
4303 case OPC_TGEIU:
4304 case OPC_TLTI:
4305 case OPC_TLTIU:
4306 case OPC_TNEI:
4307 /* Compare register to immediate */
4308 if (rs != 0 || imm != 0) {
4309 gen_load_gpr(t0, rs);
4310 tcg_gen_movi_tl(t1, (int32_t)imm);
4311 cond = 1;
4313 break;
4315 if (cond == 0) {
4316 switch (opc) {
4317 case OPC_TEQ: /* rs == rs */
4318 case OPC_TEQI: /* r0 == 0 */
4319 case OPC_TGE: /* rs >= rs */
4320 case OPC_TGEI: /* r0 >= 0 */
4321 case OPC_TGEU: /* rs >= rs unsigned */
4322 case OPC_TGEIU: /* r0 >= 0 unsigned */
4323 /* Always trap */
4324 generate_exception(ctx, EXCP_TRAP);
4325 break;
4326 case OPC_TLT: /* rs < rs */
4327 case OPC_TLTI: /* r0 < 0 */
4328 case OPC_TLTU: /* rs < rs unsigned */
4329 case OPC_TLTIU: /* r0 < 0 unsigned */
4330 case OPC_TNE: /* rs != rs */
4331 case OPC_TNEI: /* r0 != 0 */
4332 /* Never trap: treat as NOP. */
4333 break;
4335 } else {
4336 int l1 = gen_new_label();
4338 switch (opc) {
4339 case OPC_TEQ:
4340 case OPC_TEQI:
4341 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4342 break;
4343 case OPC_TGE:
4344 case OPC_TGEI:
4345 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4346 break;
4347 case OPC_TGEU:
4348 case OPC_TGEIU:
4349 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4350 break;
4351 case OPC_TLT:
4352 case OPC_TLTI:
4353 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4354 break;
4355 case OPC_TLTU:
4356 case OPC_TLTIU:
4357 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4358 break;
4359 case OPC_TNE:
4360 case OPC_TNEI:
4361 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4362 break;
4364 generate_exception(ctx, EXCP_TRAP);
4365 gen_set_label(l1);
4367 tcg_temp_free(t0);
4368 tcg_temp_free(t1);
4371 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4373 TranslationBlock *tb;
4374 tb = ctx->tb;
4375 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
4376 likely(!ctx->singlestep_enabled)) {
4377 tcg_gen_goto_tb(n);
4378 gen_save_pc(dest);
4379 tcg_gen_exit_tb((uintptr_t)tb + n);
4380 } else {
4381 gen_save_pc(dest);
4382 if (ctx->singlestep_enabled) {
4383 save_cpu_state(ctx, 0);
4384 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
4386 tcg_gen_exit_tb(0);
4390 /* Branches (before delay slot) */
4391 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4392 int insn_bytes,
4393 int rs, int rt, int32_t offset,
4394 int delayslot_size)
4396 target_ulong btgt = -1;
4397 int blink = 0;
4398 int bcond_compute = 0;
4399 TCGv t0 = tcg_temp_new();
4400 TCGv t1 = tcg_temp_new();
4402 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4403 #ifdef MIPS_DEBUG_DISAS
4404 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4405 TARGET_FMT_lx "\n", ctx->pc);
4406 #endif
4407 generate_exception(ctx, EXCP_RI);
4408 goto out;
4411 /* Load needed operands */
4412 switch (opc) {
4413 case OPC_BEQ:
4414 case OPC_BEQL:
4415 case OPC_BNE:
4416 case OPC_BNEL:
4417 /* Compare two registers */
4418 if (rs != rt) {
4419 gen_load_gpr(t0, rs);
4420 gen_load_gpr(t1, rt);
4421 bcond_compute = 1;
4423 btgt = ctx->pc + insn_bytes + offset;
4424 break;
4425 case OPC_BGEZ:
4426 case OPC_BGEZAL:
4427 case OPC_BGEZALL:
4428 case OPC_BGEZL:
4429 case OPC_BGTZ:
4430 case OPC_BGTZL:
4431 case OPC_BLEZ:
4432 case OPC_BLEZL:
4433 case OPC_BLTZ:
4434 case OPC_BLTZAL:
4435 case OPC_BLTZALL:
4436 case OPC_BLTZL:
4437 /* Compare to zero */
4438 if (rs != 0) {
4439 gen_load_gpr(t0, rs);
4440 bcond_compute = 1;
4442 btgt = ctx->pc + insn_bytes + offset;
4443 break;
4444 case OPC_BPOSGE32:
4445 #if defined(TARGET_MIPS64)
4446 case OPC_BPOSGE64:
4447 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4448 #else
4449 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4450 #endif
4451 bcond_compute = 1;
4452 btgt = ctx->pc + insn_bytes + offset;
4453 break;
4454 case OPC_J:
4455 case OPC_JAL:
4456 case OPC_JALX:
4457 /* Jump to immediate */
4458 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4459 break;
4460 case OPC_JR:
4461 case OPC_JALR:
4462 /* Jump to register */
4463 if (offset != 0 && offset != 16) {
4464 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4465 others are reserved. */
4466 MIPS_INVAL("jump hint");
4467 generate_exception(ctx, EXCP_RI);
4468 goto out;
4470 gen_load_gpr(btarget, rs);
4471 break;
4472 default:
4473 MIPS_INVAL("branch/jump");
4474 generate_exception(ctx, EXCP_RI);
4475 goto out;
4477 if (bcond_compute == 0) {
4478 /* No condition to be computed */
4479 switch (opc) {
4480 case OPC_BEQ: /* rx == rx */
4481 case OPC_BEQL: /* rx == rx likely */
4482 case OPC_BGEZ: /* 0 >= 0 */
4483 case OPC_BGEZL: /* 0 >= 0 likely */
4484 case OPC_BLEZ: /* 0 <= 0 */
4485 case OPC_BLEZL: /* 0 <= 0 likely */
4486 /* Always take */
4487 ctx->hflags |= MIPS_HFLAG_B;
4488 MIPS_DEBUG("balways");
4489 break;
4490 case OPC_BGEZAL: /* 0 >= 0 */
4491 case OPC_BGEZALL: /* 0 >= 0 likely */
4492 /* Always take and link */
4493 blink = 31;
4494 ctx->hflags |= MIPS_HFLAG_B;
4495 MIPS_DEBUG("balways and link");
4496 break;
4497 case OPC_BNE: /* rx != rx */
4498 case OPC_BGTZ: /* 0 > 0 */
4499 case OPC_BLTZ: /* 0 < 0 */
4500 /* Treat as NOP. */
4501 MIPS_DEBUG("bnever (NOP)");
4502 goto out;
4503 case OPC_BLTZAL: /* 0 < 0 */
4504 /* Handle as an unconditional branch to get correct delay
4505 slot checking. */
4506 blink = 31;
4507 btgt = ctx->pc + insn_bytes + delayslot_size;
4508 ctx->hflags |= MIPS_HFLAG_B;
4509 MIPS_DEBUG("bnever and link");
4510 break;
4511 case OPC_BLTZALL: /* 0 < 0 likely */
4512 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4513 /* Skip the instruction in the delay slot */
4514 MIPS_DEBUG("bnever, link and skip");
4515 ctx->pc += 4;
4516 goto out;
4517 case OPC_BNEL: /* rx != rx likely */
4518 case OPC_BGTZL: /* 0 > 0 likely */
4519 case OPC_BLTZL: /* 0 < 0 likely */
4520 /* Skip the instruction in the delay slot */
4521 MIPS_DEBUG("bnever and skip");
4522 ctx->pc += 4;
4523 goto out;
4524 case OPC_J:
4525 ctx->hflags |= MIPS_HFLAG_B;
4526 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
4527 break;
4528 case OPC_JALX:
4529 ctx->hflags |= MIPS_HFLAG_BX;
4530 /* Fallthrough */
4531 case OPC_JAL:
4532 blink = 31;
4533 ctx->hflags |= MIPS_HFLAG_B;
4534 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
4535 break;
4536 case OPC_JR:
4537 ctx->hflags |= MIPS_HFLAG_BR;
4538 MIPS_DEBUG("jr %s", regnames[rs]);
4539 break;
4540 case OPC_JALR:
4541 blink = rt;
4542 ctx->hflags |= MIPS_HFLAG_BR;
4543 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
4544 break;
4545 default:
4546 MIPS_INVAL("branch/jump");
4547 generate_exception(ctx, EXCP_RI);
4548 goto out;
4550 } else {
4551 switch (opc) {
4552 case OPC_BEQ:
4553 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4554 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
4555 regnames[rs], regnames[rt], btgt);
4556 goto not_likely;
4557 case OPC_BEQL:
4558 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4559 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
4560 regnames[rs], regnames[rt], btgt);
4561 goto likely;
4562 case OPC_BNE:
4563 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4564 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
4565 regnames[rs], regnames[rt], btgt);
4566 goto not_likely;
4567 case OPC_BNEL:
4568 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4569 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
4570 regnames[rs], regnames[rt], btgt);
4571 goto likely;
4572 case OPC_BGEZ:
4573 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4574 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4575 goto not_likely;
4576 case OPC_BGEZL:
4577 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4578 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4579 goto likely;
4580 case OPC_BGEZAL:
4581 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4582 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4583 blink = 31;
4584 goto not_likely;
4585 case OPC_BGEZALL:
4586 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4587 blink = 31;
4588 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4589 goto likely;
4590 case OPC_BGTZ:
4591 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4592 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4593 goto not_likely;
4594 case OPC_BGTZL:
4595 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4596 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4597 goto likely;
4598 case OPC_BLEZ:
4599 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4600 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4601 goto not_likely;
4602 case OPC_BLEZL:
4603 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4604 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4605 goto likely;
4606 case OPC_BLTZ:
4607 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4608 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4609 goto not_likely;
4610 case OPC_BLTZL:
4611 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4612 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4613 goto likely;
4614 case OPC_BPOSGE32:
4615 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4616 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
4617 goto not_likely;
4618 #if defined(TARGET_MIPS64)
4619 case OPC_BPOSGE64:
4620 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4621 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
4622 goto not_likely;
4623 #endif
4624 case OPC_BLTZAL:
4625 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4626 blink = 31;
4627 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4628 not_likely:
4629 ctx->hflags |= MIPS_HFLAG_BC;
4630 break;
4631 case OPC_BLTZALL:
4632 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4633 blink = 31;
4634 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4635 likely:
4636 ctx->hflags |= MIPS_HFLAG_BL;
4637 break;
4638 default:
4639 MIPS_INVAL("conditional branch/jump");
4640 generate_exception(ctx, EXCP_RI);
4641 goto out;
4644 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
4645 blink, ctx->hflags, btgt);
4647 ctx->btarget = btgt;
4649 switch (delayslot_size) {
4650 case 2:
4651 ctx->hflags |= MIPS_HFLAG_BDS16;
4652 break;
4653 case 4:
4654 ctx->hflags |= MIPS_HFLAG_BDS32;
4655 break;
4658 if (blink > 0) {
4659 int post_delay = insn_bytes + delayslot_size;
4660 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4662 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4665 out:
4666 if (insn_bytes == 2)
4667 ctx->hflags |= MIPS_HFLAG_B16;
4668 tcg_temp_free(t0);
4669 tcg_temp_free(t1);
4672 /* special3 bitfield operations */
4673 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4674 int rs, int lsb, int msb)
4676 TCGv t0 = tcg_temp_new();
4677 TCGv t1 = tcg_temp_new();
4679 gen_load_gpr(t1, rs);
4680 switch (opc) {
4681 case OPC_EXT:
4682 if (lsb + msb > 31)
4683 goto fail;
4684 tcg_gen_shri_tl(t0, t1, lsb);
4685 if (msb != 31) {
4686 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
4687 } else {
4688 tcg_gen_ext32s_tl(t0, t0);
4690 break;
4691 #if defined(TARGET_MIPS64)
4692 case OPC_DEXTM:
4693 tcg_gen_shri_tl(t0, t1, lsb);
4694 if (msb != 31) {
4695 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
4697 break;
4698 case OPC_DEXTU:
4699 tcg_gen_shri_tl(t0, t1, lsb + 32);
4700 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4701 break;
4702 case OPC_DEXT:
4703 tcg_gen_shri_tl(t0, t1, lsb);
4704 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4705 break;
4706 #endif
4707 case OPC_INS:
4708 if (lsb > msb)
4709 goto fail;
4710 gen_load_gpr(t0, rt);
4711 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4712 tcg_gen_ext32s_tl(t0, t0);
4713 break;
4714 #if defined(TARGET_MIPS64)
4715 case OPC_DINSM:
4716 gen_load_gpr(t0, rt);
4717 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb + 32 - lsb + 1);
4718 break;
4719 case OPC_DINSU:
4720 gen_load_gpr(t0, rt);
4721 tcg_gen_deposit_tl(t0, t0, t1, lsb + 32, msb - lsb + 1);
4722 break;
4723 case OPC_DINS:
4724 gen_load_gpr(t0, rt);
4725 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4726 break;
4727 #endif
4728 default:
4729 fail:
4730 MIPS_INVAL("bitops");
4731 generate_exception(ctx, EXCP_RI);
4732 tcg_temp_free(t0);
4733 tcg_temp_free(t1);
4734 return;
4736 gen_store_gpr(t0, rt);
4737 tcg_temp_free(t0);
4738 tcg_temp_free(t1);
4741 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4743 TCGv t0;
4745 if (rd == 0) {
4746 /* If no destination, treat it as a NOP. */
4747 MIPS_DEBUG("NOP");
4748 return;
4751 t0 = tcg_temp_new();
4752 gen_load_gpr(t0, rt);
4753 switch (op2) {
4754 case OPC_WSBH:
4756 TCGv t1 = tcg_temp_new();
4758 tcg_gen_shri_tl(t1, t0, 8);
4759 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4760 tcg_gen_shli_tl(t0, t0, 8);
4761 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4762 tcg_gen_or_tl(t0, t0, t1);
4763 tcg_temp_free(t1);
4764 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4766 break;
4767 case OPC_SEB:
4768 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4769 break;
4770 case OPC_SEH:
4771 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4772 break;
4773 #if defined(TARGET_MIPS64)
4774 case OPC_DSBH:
4776 TCGv t1 = tcg_temp_new();
4778 tcg_gen_shri_tl(t1, t0, 8);
4779 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4780 tcg_gen_shli_tl(t0, t0, 8);
4781 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4782 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4783 tcg_temp_free(t1);
4785 break;
4786 case OPC_DSHD:
4788 TCGv t1 = tcg_temp_new();
4790 tcg_gen_shri_tl(t1, t0, 16);
4791 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4792 tcg_gen_shli_tl(t0, t0, 16);
4793 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4794 tcg_gen_or_tl(t0, t0, t1);
4795 tcg_gen_shri_tl(t1, t0, 32);
4796 tcg_gen_shli_tl(t0, t0, 32);
4797 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4798 tcg_temp_free(t1);
4800 break;
4801 #endif
4802 default:
4803 MIPS_INVAL("bsfhl");
4804 generate_exception(ctx, EXCP_RI);
4805 tcg_temp_free(t0);
4806 return;
4808 tcg_temp_free(t0);
4811 #ifndef CONFIG_USER_ONLY
4812 /* CP0 (MMU and control) */
4813 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4815 TCGv_i32 t0 = tcg_temp_new_i32();
4817 tcg_gen_ld_i32(t0, cpu_env, off);
4818 tcg_gen_ext_i32_tl(arg, t0);
4819 tcg_temp_free_i32(t0);
4822 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4824 tcg_gen_ld_tl(arg, cpu_env, off);
4825 tcg_gen_ext32s_tl(arg, arg);
4828 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4830 TCGv_i32 t0 = tcg_temp_new_i32();
4832 tcg_gen_trunc_tl_i32(t0, arg);
4833 tcg_gen_st_i32(t0, cpu_env, off);
4834 tcg_temp_free_i32(t0);
4837 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
4839 tcg_gen_ext32s_tl(arg, arg);
4840 tcg_gen_st_tl(arg, cpu_env, off);
4843 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
4845 if (ctx->insn_flags & ISA_MIPS32R6) {
4846 tcg_gen_movi_tl(arg, 0);
4847 } else {
4848 tcg_gen_movi_tl(arg, ~0);
4852 #define CP0_CHECK(c) \
4853 do { \
4854 if (!(c)) { \
4855 goto cp0_unimplemented; \
4857 } while (0)
4859 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4861 const char *rn = "invalid";
4863 if (sel != 0)
4864 check_insn(ctx, ISA_MIPS32);
4866 switch (reg) {
4867 case 0:
4868 switch (sel) {
4869 case 0:
4870 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4871 rn = "Index";
4872 break;
4873 case 1:
4874 CP0_CHECK(ctx->insn_flags & ASE_MT);
4875 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4876 rn = "MVPControl";
4877 break;
4878 case 2:
4879 CP0_CHECK(ctx->insn_flags & ASE_MT);
4880 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4881 rn = "MVPConf0";
4882 break;
4883 case 3:
4884 CP0_CHECK(ctx->insn_flags & ASE_MT);
4885 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4886 rn = "MVPConf1";
4887 break;
4888 default:
4889 goto cp0_unimplemented;
4891 break;
4892 case 1:
4893 switch (sel) {
4894 case 0:
4895 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
4896 gen_helper_mfc0_random(arg, cpu_env);
4897 rn = "Random";
4898 break;
4899 case 1:
4900 CP0_CHECK(ctx->insn_flags & ASE_MT);
4901 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4902 rn = "VPEControl";
4903 break;
4904 case 2:
4905 CP0_CHECK(ctx->insn_flags & ASE_MT);
4906 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
4907 rn = "VPEConf0";
4908 break;
4909 case 3:
4910 CP0_CHECK(ctx->insn_flags & ASE_MT);
4911 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
4912 rn = "VPEConf1";
4913 break;
4914 case 4:
4915 CP0_CHECK(ctx->insn_flags & ASE_MT);
4916 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
4917 rn = "YQMask";
4918 break;
4919 case 5:
4920 CP0_CHECK(ctx->insn_flags & ASE_MT);
4921 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
4922 rn = "VPESchedule";
4923 break;
4924 case 6:
4925 CP0_CHECK(ctx->insn_flags & ASE_MT);
4926 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4927 rn = "VPEScheFBack";
4928 break;
4929 case 7:
4930 CP0_CHECK(ctx->insn_flags & ASE_MT);
4931 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
4932 rn = "VPEOpt";
4933 break;
4934 default:
4935 goto cp0_unimplemented;
4937 break;
4938 case 2:
4939 switch (sel) {
4940 case 0:
4941 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
4942 #if defined(TARGET_MIPS64)
4943 if (ctx->rxi) {
4944 TCGv tmp = tcg_temp_new();
4945 tcg_gen_andi_tl(tmp, arg, (3ull << 62));
4946 tcg_gen_shri_tl(tmp, tmp, 32);
4947 tcg_gen_or_tl(arg, arg, tmp);
4948 tcg_temp_free(tmp);
4950 #endif
4951 tcg_gen_ext32s_tl(arg, arg);
4952 rn = "EntryLo0";
4953 break;
4954 case 1:
4955 CP0_CHECK(ctx->insn_flags & ASE_MT);
4956 gen_helper_mfc0_tcstatus(arg, cpu_env);
4957 rn = "TCStatus";
4958 break;
4959 case 2:
4960 CP0_CHECK(ctx->insn_flags & ASE_MT);
4961 gen_helper_mfc0_tcbind(arg, cpu_env);
4962 rn = "TCBind";
4963 break;
4964 case 3:
4965 CP0_CHECK(ctx->insn_flags & ASE_MT);
4966 gen_helper_mfc0_tcrestart(arg, cpu_env);
4967 rn = "TCRestart";
4968 break;
4969 case 4:
4970 CP0_CHECK(ctx->insn_flags & ASE_MT);
4971 gen_helper_mfc0_tchalt(arg, cpu_env);
4972 rn = "TCHalt";
4973 break;
4974 case 5:
4975 CP0_CHECK(ctx->insn_flags & ASE_MT);
4976 gen_helper_mfc0_tccontext(arg, cpu_env);
4977 rn = "TCContext";
4978 break;
4979 case 6:
4980 CP0_CHECK(ctx->insn_flags & ASE_MT);
4981 gen_helper_mfc0_tcschedule(arg, cpu_env);
4982 rn = "TCSchedule";
4983 break;
4984 case 7:
4985 CP0_CHECK(ctx->insn_flags & ASE_MT);
4986 gen_helper_mfc0_tcschefback(arg, cpu_env);
4987 rn = "TCScheFBack";
4988 break;
4989 default:
4990 goto cp0_unimplemented;
4992 break;
4993 case 3:
4994 switch (sel) {
4995 case 0:
4996 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
4997 #if defined(TARGET_MIPS64)
4998 if (ctx->rxi) {
4999 TCGv tmp = tcg_temp_new();
5000 tcg_gen_andi_tl(tmp, arg, (3ull << 62));
5001 tcg_gen_shri_tl(tmp, tmp, 32);
5002 tcg_gen_or_tl(arg, arg, tmp);
5003 tcg_temp_free(tmp);
5005 #endif
5006 tcg_gen_ext32s_tl(arg, arg);
5007 rn = "EntryLo1";
5008 break;
5009 default:
5010 goto cp0_unimplemented;
5012 break;
5013 case 4:
5014 switch (sel) {
5015 case 0:
5016 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5017 tcg_gen_ext32s_tl(arg, arg);
5018 rn = "Context";
5019 break;
5020 case 1:
5021 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5022 rn = "ContextConfig";
5023 goto cp0_unimplemented;
5024 // break;
5025 case 2:
5026 CP0_CHECK(ctx->ulri);
5027 tcg_gen_ld32s_tl(arg, cpu_env,
5028 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5029 rn = "UserLocal";
5030 break;
5031 default:
5032 goto cp0_unimplemented;
5034 break;
5035 case 5:
5036 switch (sel) {
5037 case 0:
5038 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5039 rn = "PageMask";
5040 break;
5041 case 1:
5042 check_insn(ctx, ISA_MIPS32R2);
5043 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5044 rn = "PageGrain";
5045 break;
5046 default:
5047 goto cp0_unimplemented;
5049 break;
5050 case 6:
5051 switch (sel) {
5052 case 0:
5053 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5054 rn = "Wired";
5055 break;
5056 case 1:
5057 check_insn(ctx, ISA_MIPS32R2);
5058 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5059 rn = "SRSConf0";
5060 break;
5061 case 2:
5062 check_insn(ctx, ISA_MIPS32R2);
5063 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5064 rn = "SRSConf1";
5065 break;
5066 case 3:
5067 check_insn(ctx, ISA_MIPS32R2);
5068 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5069 rn = "SRSConf2";
5070 break;
5071 case 4:
5072 check_insn(ctx, ISA_MIPS32R2);
5073 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5074 rn = "SRSConf3";
5075 break;
5076 case 5:
5077 check_insn(ctx, ISA_MIPS32R2);
5078 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5079 rn = "SRSConf4";
5080 break;
5081 default:
5082 goto cp0_unimplemented;
5084 break;
5085 case 7:
5086 switch (sel) {
5087 case 0:
5088 check_insn(ctx, ISA_MIPS32R2);
5089 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5090 rn = "HWREna";
5091 break;
5092 default:
5093 goto cp0_unimplemented;
5095 break;
5096 case 8:
5097 switch (sel) {
5098 case 0:
5099 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5100 tcg_gen_ext32s_tl(arg, arg);
5101 rn = "BadVAddr";
5102 break;
5103 case 1:
5104 CP0_CHECK(ctx->bi);
5105 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5106 rn = "BadInstr";
5107 break;
5108 case 2:
5109 CP0_CHECK(ctx->bp);
5110 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5111 rn = "BadInstrP";
5112 break;
5113 default:
5114 goto cp0_unimplemented;
5116 break;
5117 case 9:
5118 switch (sel) {
5119 case 0:
5120 /* Mark as an IO operation because we read the time. */
5121 if (use_icount)
5122 gen_io_start();
5123 gen_helper_mfc0_count(arg, cpu_env);
5124 if (use_icount) {
5125 gen_io_end();
5127 /* Break the TB to be able to take timer interrupts immediately
5128 after reading count. */
5129 ctx->bstate = BS_STOP;
5130 rn = "Count";
5131 break;
5132 /* 6,7 are implementation dependent */
5133 default:
5134 goto cp0_unimplemented;
5136 break;
5137 case 10:
5138 switch (sel) {
5139 case 0:
5140 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5141 tcg_gen_ext32s_tl(arg, arg);
5142 rn = "EntryHi";
5143 break;
5144 default:
5145 goto cp0_unimplemented;
5147 break;
5148 case 11:
5149 switch (sel) {
5150 case 0:
5151 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5152 rn = "Compare";
5153 break;
5154 /* 6,7 are implementation dependent */
5155 default:
5156 goto cp0_unimplemented;
5158 break;
5159 case 12:
5160 switch (sel) {
5161 case 0:
5162 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5163 rn = "Status";
5164 break;
5165 case 1:
5166 check_insn(ctx, ISA_MIPS32R2);
5167 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5168 rn = "IntCtl";
5169 break;
5170 case 2:
5171 check_insn(ctx, ISA_MIPS32R2);
5172 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5173 rn = "SRSCtl";
5174 break;
5175 case 3:
5176 check_insn(ctx, ISA_MIPS32R2);
5177 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5178 rn = "SRSMap";
5179 break;
5180 default:
5181 goto cp0_unimplemented;
5183 break;
5184 case 13:
5185 switch (sel) {
5186 case 0:
5187 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5188 rn = "Cause";
5189 break;
5190 default:
5191 goto cp0_unimplemented;
5193 break;
5194 case 14:
5195 switch (sel) {
5196 case 0:
5197 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5198 tcg_gen_ext32s_tl(arg, arg);
5199 rn = "EPC";
5200 break;
5201 default:
5202 goto cp0_unimplemented;
5204 break;
5205 case 15:
5206 switch (sel) {
5207 case 0:
5208 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5209 rn = "PRid";
5210 break;
5211 case 1:
5212 check_insn(ctx, ISA_MIPS32R2);
5213 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5214 rn = "EBase";
5215 break;
5216 default:
5217 goto cp0_unimplemented;
5219 break;
5220 case 16:
5221 switch (sel) {
5222 case 0:
5223 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5224 rn = "Config";
5225 break;
5226 case 1:
5227 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5228 rn = "Config1";
5229 break;
5230 case 2:
5231 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5232 rn = "Config2";
5233 break;
5234 case 3:
5235 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5236 rn = "Config3";
5237 break;
5238 case 4:
5239 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5240 rn = "Config4";
5241 break;
5242 case 5:
5243 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5244 rn = "Config5";
5245 break;
5246 /* 6,7 are implementation dependent */
5247 case 6:
5248 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5249 rn = "Config6";
5250 break;
5251 case 7:
5252 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5253 rn = "Config7";
5254 break;
5255 default:
5256 goto cp0_unimplemented;
5258 break;
5259 case 17:
5260 switch (sel) {
5261 case 0:
5262 gen_helper_mfc0_lladdr(arg, cpu_env);
5263 rn = "LLAddr";
5264 break;
5265 default:
5266 goto cp0_unimplemented;
5268 break;
5269 case 18:
5270 switch (sel) {
5271 case 0 ... 7:
5272 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5273 rn = "WatchLo";
5274 break;
5275 default:
5276 goto cp0_unimplemented;
5278 break;
5279 case 19:
5280 switch (sel) {
5281 case 0 ...7:
5282 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5283 rn = "WatchHi";
5284 break;
5285 default:
5286 goto cp0_unimplemented;
5288 break;
5289 case 20:
5290 switch (sel) {
5291 case 0:
5292 #if defined(TARGET_MIPS64)
5293 check_insn(ctx, ISA_MIPS3);
5294 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5295 tcg_gen_ext32s_tl(arg, arg);
5296 rn = "XContext";
5297 break;
5298 #endif
5299 default:
5300 goto cp0_unimplemented;
5302 break;
5303 case 21:
5304 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5305 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5306 switch (sel) {
5307 case 0:
5308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5309 rn = "Framemask";
5310 break;
5311 default:
5312 goto cp0_unimplemented;
5314 break;
5315 case 22:
5316 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5317 rn = "'Diagnostic"; /* implementation dependent */
5318 break;
5319 case 23:
5320 switch (sel) {
5321 case 0:
5322 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5323 rn = "Debug";
5324 break;
5325 case 1:
5326 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5327 rn = "TraceControl";
5328 // break;
5329 case 2:
5330 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5331 rn = "TraceControl2";
5332 // break;
5333 case 3:
5334 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5335 rn = "UserTraceData";
5336 // break;
5337 case 4:
5338 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5339 rn = "TraceBPC";
5340 // break;
5341 default:
5342 goto cp0_unimplemented;
5344 break;
5345 case 24:
5346 switch (sel) {
5347 case 0:
5348 /* EJTAG support */
5349 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5350 tcg_gen_ext32s_tl(arg, arg);
5351 rn = "DEPC";
5352 break;
5353 default:
5354 goto cp0_unimplemented;
5356 break;
5357 case 25:
5358 switch (sel) {
5359 case 0:
5360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5361 rn = "Performance0";
5362 break;
5363 case 1:
5364 // gen_helper_mfc0_performance1(arg);
5365 rn = "Performance1";
5366 // break;
5367 case 2:
5368 // gen_helper_mfc0_performance2(arg);
5369 rn = "Performance2";
5370 // break;
5371 case 3:
5372 // gen_helper_mfc0_performance3(arg);
5373 rn = "Performance3";
5374 // break;
5375 case 4:
5376 // gen_helper_mfc0_performance4(arg);
5377 rn = "Performance4";
5378 // break;
5379 case 5:
5380 // gen_helper_mfc0_performance5(arg);
5381 rn = "Performance5";
5382 // break;
5383 case 6:
5384 // gen_helper_mfc0_performance6(arg);
5385 rn = "Performance6";
5386 // break;
5387 case 7:
5388 // gen_helper_mfc0_performance7(arg);
5389 rn = "Performance7";
5390 // break;
5391 default:
5392 goto cp0_unimplemented;
5394 break;
5395 case 26:
5396 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5397 rn = "ECC";
5398 break;
5399 case 27:
5400 switch (sel) {
5401 case 0 ... 3:
5402 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5403 rn = "CacheErr";
5404 break;
5405 default:
5406 goto cp0_unimplemented;
5408 break;
5409 case 28:
5410 switch (sel) {
5411 case 0:
5412 case 2:
5413 case 4:
5414 case 6:
5415 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
5416 rn = "TagLo";
5417 break;
5418 case 1:
5419 case 3:
5420 case 5:
5421 case 7:
5422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5423 rn = "DataLo";
5424 break;
5425 default:
5426 goto cp0_unimplemented;
5428 break;
5429 case 29:
5430 switch (sel) {
5431 case 0:
5432 case 2:
5433 case 4:
5434 case 6:
5435 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5436 rn = "TagHi";
5437 break;
5438 case 1:
5439 case 3:
5440 case 5:
5441 case 7:
5442 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5443 rn = "DataHi";
5444 break;
5445 default:
5446 goto cp0_unimplemented;
5448 break;
5449 case 30:
5450 switch (sel) {
5451 case 0:
5452 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5453 tcg_gen_ext32s_tl(arg, arg);
5454 rn = "ErrorEPC";
5455 break;
5456 default:
5457 goto cp0_unimplemented;
5459 break;
5460 case 31:
5461 switch (sel) {
5462 case 0:
5463 /* EJTAG support */
5464 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5465 rn = "DESAVE";
5466 break;
5467 case 2 ... 7:
5468 CP0_CHECK(ctx->kscrexist & (1 << sel));
5469 tcg_gen_ld_tl(arg, cpu_env,
5470 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5471 tcg_gen_ext32s_tl(arg, arg);
5472 rn = "KScratch";
5473 break;
5474 default:
5475 goto cp0_unimplemented;
5477 break;
5478 default:
5479 goto cp0_unimplemented;
5481 (void)rn; /* avoid a compiler warning */
5482 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5483 return;
5485 cp0_unimplemented:
5486 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5487 gen_mfc0_unimplemented(ctx, arg);
5490 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5492 const char *rn = "invalid";
5494 if (sel != 0)
5495 check_insn(ctx, ISA_MIPS32);
5497 if (use_icount)
5498 gen_io_start();
5500 switch (reg) {
5501 case 0:
5502 switch (sel) {
5503 case 0:
5504 gen_helper_mtc0_index(cpu_env, arg);
5505 rn = "Index";
5506 break;
5507 case 1:
5508 CP0_CHECK(ctx->insn_flags & ASE_MT);
5509 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5510 rn = "MVPControl";
5511 break;
5512 case 2:
5513 CP0_CHECK(ctx->insn_flags & ASE_MT);
5514 /* ignored */
5515 rn = "MVPConf0";
5516 break;
5517 case 3:
5518 CP0_CHECK(ctx->insn_flags & ASE_MT);
5519 /* ignored */
5520 rn = "MVPConf1";
5521 break;
5522 default:
5523 goto cp0_unimplemented;
5525 break;
5526 case 1:
5527 switch (sel) {
5528 case 0:
5529 /* ignored */
5530 rn = "Random";
5531 break;
5532 case 1:
5533 CP0_CHECK(ctx->insn_flags & ASE_MT);
5534 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5535 rn = "VPEControl";
5536 break;
5537 case 2:
5538 CP0_CHECK(ctx->insn_flags & ASE_MT);
5539 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5540 rn = "VPEConf0";
5541 break;
5542 case 3:
5543 CP0_CHECK(ctx->insn_flags & ASE_MT);
5544 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5545 rn = "VPEConf1";
5546 break;
5547 case 4:
5548 CP0_CHECK(ctx->insn_flags & ASE_MT);
5549 gen_helper_mtc0_yqmask(cpu_env, arg);
5550 rn = "YQMask";
5551 break;
5552 case 5:
5553 CP0_CHECK(ctx->insn_flags & ASE_MT);
5554 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5555 rn = "VPESchedule";
5556 break;
5557 case 6:
5558 CP0_CHECK(ctx->insn_flags & ASE_MT);
5559 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5560 rn = "VPEScheFBack";
5561 break;
5562 case 7:
5563 CP0_CHECK(ctx->insn_flags & ASE_MT);
5564 gen_helper_mtc0_vpeopt(cpu_env, arg);
5565 rn = "VPEOpt";
5566 break;
5567 default:
5568 goto cp0_unimplemented;
5570 break;
5571 case 2:
5572 switch (sel) {
5573 case 0:
5574 gen_helper_mtc0_entrylo0(cpu_env, arg);
5575 rn = "EntryLo0";
5576 break;
5577 case 1:
5578 CP0_CHECK(ctx->insn_flags & ASE_MT);
5579 gen_helper_mtc0_tcstatus(cpu_env, arg);
5580 rn = "TCStatus";
5581 break;
5582 case 2:
5583 CP0_CHECK(ctx->insn_flags & ASE_MT);
5584 gen_helper_mtc0_tcbind(cpu_env, arg);
5585 rn = "TCBind";
5586 break;
5587 case 3:
5588 CP0_CHECK(ctx->insn_flags & ASE_MT);
5589 gen_helper_mtc0_tcrestart(cpu_env, arg);
5590 rn = "TCRestart";
5591 break;
5592 case 4:
5593 CP0_CHECK(ctx->insn_flags & ASE_MT);
5594 gen_helper_mtc0_tchalt(cpu_env, arg);
5595 rn = "TCHalt";
5596 break;
5597 case 5:
5598 CP0_CHECK(ctx->insn_flags & ASE_MT);
5599 gen_helper_mtc0_tccontext(cpu_env, arg);
5600 rn = "TCContext";
5601 break;
5602 case 6:
5603 CP0_CHECK(ctx->insn_flags & ASE_MT);
5604 gen_helper_mtc0_tcschedule(cpu_env, arg);
5605 rn = "TCSchedule";
5606 break;
5607 case 7:
5608 CP0_CHECK(ctx->insn_flags & ASE_MT);
5609 gen_helper_mtc0_tcschefback(cpu_env, arg);
5610 rn = "TCScheFBack";
5611 break;
5612 default:
5613 goto cp0_unimplemented;
5615 break;
5616 case 3:
5617 switch (sel) {
5618 case 0:
5619 gen_helper_mtc0_entrylo1(cpu_env, arg);
5620 rn = "EntryLo1";
5621 break;
5622 default:
5623 goto cp0_unimplemented;
5625 break;
5626 case 4:
5627 switch (sel) {
5628 case 0:
5629 gen_helper_mtc0_context(cpu_env, arg);
5630 rn = "Context";
5631 break;
5632 case 1:
5633 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5634 rn = "ContextConfig";
5635 goto cp0_unimplemented;
5636 // break;
5637 case 2:
5638 CP0_CHECK(ctx->ulri);
5639 tcg_gen_st_tl(arg, cpu_env,
5640 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5641 rn = "UserLocal";
5642 break;
5643 default:
5644 goto cp0_unimplemented;
5646 break;
5647 case 5:
5648 switch (sel) {
5649 case 0:
5650 gen_helper_mtc0_pagemask(cpu_env, arg);
5651 rn = "PageMask";
5652 break;
5653 case 1:
5654 check_insn(ctx, ISA_MIPS32R2);
5655 gen_helper_mtc0_pagegrain(cpu_env, arg);
5656 rn = "PageGrain";
5657 break;
5658 default:
5659 goto cp0_unimplemented;
5661 break;
5662 case 6:
5663 switch (sel) {
5664 case 0:
5665 gen_helper_mtc0_wired(cpu_env, arg);
5666 rn = "Wired";
5667 break;
5668 case 1:
5669 check_insn(ctx, ISA_MIPS32R2);
5670 gen_helper_mtc0_srsconf0(cpu_env, arg);
5671 rn = "SRSConf0";
5672 break;
5673 case 2:
5674 check_insn(ctx, ISA_MIPS32R2);
5675 gen_helper_mtc0_srsconf1(cpu_env, arg);
5676 rn = "SRSConf1";
5677 break;
5678 case 3:
5679 check_insn(ctx, ISA_MIPS32R2);
5680 gen_helper_mtc0_srsconf2(cpu_env, arg);
5681 rn = "SRSConf2";
5682 break;
5683 case 4:
5684 check_insn(ctx, ISA_MIPS32R2);
5685 gen_helper_mtc0_srsconf3(cpu_env, arg);
5686 rn = "SRSConf3";
5687 break;
5688 case 5:
5689 check_insn(ctx, ISA_MIPS32R2);
5690 gen_helper_mtc0_srsconf4(cpu_env, arg);
5691 rn = "SRSConf4";
5692 break;
5693 default:
5694 goto cp0_unimplemented;
5696 break;
5697 case 7:
5698 switch (sel) {
5699 case 0:
5700 check_insn(ctx, ISA_MIPS32R2);
5701 gen_helper_mtc0_hwrena(cpu_env, arg);
5702 ctx->bstate = BS_STOP;
5703 rn = "HWREna";
5704 break;
5705 default:
5706 goto cp0_unimplemented;
5708 break;
5709 case 8:
5710 switch (sel) {
5711 case 0:
5712 /* ignored */
5713 rn = "BadVAddr";
5714 break;
5715 case 1:
5716 /* ignored */
5717 rn = "BadInstr";
5718 break;
5719 case 2:
5720 /* ignored */
5721 rn = "BadInstrP";
5722 break;
5723 default:
5724 goto cp0_unimplemented;
5726 break;
5727 case 9:
5728 switch (sel) {
5729 case 0:
5730 gen_helper_mtc0_count(cpu_env, arg);
5731 rn = "Count";
5732 break;
5733 /* 6,7 are implementation dependent */
5734 default:
5735 goto cp0_unimplemented;
5737 break;
5738 case 10:
5739 switch (sel) {
5740 case 0:
5741 gen_helper_mtc0_entryhi(cpu_env, arg);
5742 rn = "EntryHi";
5743 break;
5744 default:
5745 goto cp0_unimplemented;
5747 break;
5748 case 11:
5749 switch (sel) {
5750 case 0:
5751 gen_helper_mtc0_compare(cpu_env, arg);
5752 rn = "Compare";
5753 break;
5754 /* 6,7 are implementation dependent */
5755 default:
5756 goto cp0_unimplemented;
5758 break;
5759 case 12:
5760 switch (sel) {
5761 case 0:
5762 save_cpu_state(ctx, 1);
5763 gen_helper_mtc0_status(cpu_env, arg);
5764 /* BS_STOP isn't good enough here, hflags may have changed. */
5765 gen_save_pc(ctx->pc + 4);
5766 ctx->bstate = BS_EXCP;
5767 rn = "Status";
5768 break;
5769 case 1:
5770 check_insn(ctx, ISA_MIPS32R2);
5771 gen_helper_mtc0_intctl(cpu_env, arg);
5772 /* Stop translation as we may have switched the execution mode */
5773 ctx->bstate = BS_STOP;
5774 rn = "IntCtl";
5775 break;
5776 case 2:
5777 check_insn(ctx, ISA_MIPS32R2);
5778 gen_helper_mtc0_srsctl(cpu_env, arg);
5779 /* Stop translation as we may have switched the execution mode */
5780 ctx->bstate = BS_STOP;
5781 rn = "SRSCtl";
5782 break;
5783 case 3:
5784 check_insn(ctx, ISA_MIPS32R2);
5785 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5786 /* Stop translation as we may have switched the execution mode */
5787 ctx->bstate = BS_STOP;
5788 rn = "SRSMap";
5789 break;
5790 default:
5791 goto cp0_unimplemented;
5793 break;
5794 case 13:
5795 switch (sel) {
5796 case 0:
5797 save_cpu_state(ctx, 1);
5798 gen_helper_mtc0_cause(cpu_env, arg);
5799 rn = "Cause";
5800 break;
5801 default:
5802 goto cp0_unimplemented;
5804 break;
5805 case 14:
5806 switch (sel) {
5807 case 0:
5808 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
5809 rn = "EPC";
5810 break;
5811 default:
5812 goto cp0_unimplemented;
5814 break;
5815 case 15:
5816 switch (sel) {
5817 case 0:
5818 /* ignored */
5819 rn = "PRid";
5820 break;
5821 case 1:
5822 check_insn(ctx, ISA_MIPS32R2);
5823 gen_helper_mtc0_ebase(cpu_env, arg);
5824 rn = "EBase";
5825 break;
5826 default:
5827 goto cp0_unimplemented;
5829 break;
5830 case 16:
5831 switch (sel) {
5832 case 0:
5833 gen_helper_mtc0_config0(cpu_env, arg);
5834 rn = "Config";
5835 /* Stop translation as we may have switched the execution mode */
5836 ctx->bstate = BS_STOP;
5837 break;
5838 case 1:
5839 /* ignored, read only */
5840 rn = "Config1";
5841 break;
5842 case 2:
5843 gen_helper_mtc0_config2(cpu_env, arg);
5844 rn = "Config2";
5845 /* Stop translation as we may have switched the execution mode */
5846 ctx->bstate = BS_STOP;
5847 break;
5848 case 3:
5849 /* ignored, read only */
5850 rn = "Config3";
5851 break;
5852 case 4:
5853 gen_helper_mtc0_config4(cpu_env, arg);
5854 rn = "Config4";
5855 ctx->bstate = BS_STOP;
5856 break;
5857 case 5:
5858 gen_helper_mtc0_config5(cpu_env, arg);
5859 rn = "Config5";
5860 /* Stop translation as we may have switched the execution mode */
5861 ctx->bstate = BS_STOP;
5862 break;
5863 /* 6,7 are implementation dependent */
5864 case 6:
5865 /* ignored */
5866 rn = "Config6";
5867 break;
5868 case 7:
5869 /* ignored */
5870 rn = "Config7";
5871 break;
5872 default:
5873 rn = "Invalid config selector";
5874 goto cp0_unimplemented;
5876 break;
5877 case 17:
5878 switch (sel) {
5879 case 0:
5880 gen_helper_mtc0_lladdr(cpu_env, arg);
5881 rn = "LLAddr";
5882 break;
5883 default:
5884 goto cp0_unimplemented;
5886 break;
5887 case 18:
5888 switch (sel) {
5889 case 0 ... 7:
5890 gen_helper_0e1i(mtc0_watchlo, arg, sel);
5891 rn = "WatchLo";
5892 break;
5893 default:
5894 goto cp0_unimplemented;
5896 break;
5897 case 19:
5898 switch (sel) {
5899 case 0 ... 7:
5900 gen_helper_0e1i(mtc0_watchhi, arg, sel);
5901 rn = "WatchHi";
5902 break;
5903 default:
5904 goto cp0_unimplemented;
5906 break;
5907 case 20:
5908 switch (sel) {
5909 case 0:
5910 #if defined(TARGET_MIPS64)
5911 check_insn(ctx, ISA_MIPS3);
5912 gen_helper_mtc0_xcontext(cpu_env, arg);
5913 rn = "XContext";
5914 break;
5915 #endif
5916 default:
5917 goto cp0_unimplemented;
5919 break;
5920 case 21:
5921 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5922 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5923 switch (sel) {
5924 case 0:
5925 gen_helper_mtc0_framemask(cpu_env, arg);
5926 rn = "Framemask";
5927 break;
5928 default:
5929 goto cp0_unimplemented;
5931 break;
5932 case 22:
5933 /* ignored */
5934 rn = "Diagnostic"; /* implementation dependent */
5935 break;
5936 case 23:
5937 switch (sel) {
5938 case 0:
5939 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
5940 /* BS_STOP isn't good enough here, hflags may have changed. */
5941 gen_save_pc(ctx->pc + 4);
5942 ctx->bstate = BS_EXCP;
5943 rn = "Debug";
5944 break;
5945 case 1:
5946 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
5947 rn = "TraceControl";
5948 /* Stop translation as we may have switched the execution mode */
5949 ctx->bstate = BS_STOP;
5950 // break;
5951 case 2:
5952 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
5953 rn = "TraceControl2";
5954 /* Stop translation as we may have switched the execution mode */
5955 ctx->bstate = BS_STOP;
5956 // break;
5957 case 3:
5958 /* Stop translation as we may have switched the execution mode */
5959 ctx->bstate = BS_STOP;
5960 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
5961 rn = "UserTraceData";
5962 /* Stop translation as we may have switched the execution mode */
5963 ctx->bstate = BS_STOP;
5964 // break;
5965 case 4:
5966 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
5967 /* Stop translation as we may have switched the execution mode */
5968 ctx->bstate = BS_STOP;
5969 rn = "TraceBPC";
5970 // break;
5971 default:
5972 goto cp0_unimplemented;
5974 break;
5975 case 24:
5976 switch (sel) {
5977 case 0:
5978 /* EJTAG support */
5979 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
5980 rn = "DEPC";
5981 break;
5982 default:
5983 goto cp0_unimplemented;
5985 break;
5986 case 25:
5987 switch (sel) {
5988 case 0:
5989 gen_helper_mtc0_performance0(cpu_env, arg);
5990 rn = "Performance0";
5991 break;
5992 case 1:
5993 // gen_helper_mtc0_performance1(arg);
5994 rn = "Performance1";
5995 // break;
5996 case 2:
5997 // gen_helper_mtc0_performance2(arg);
5998 rn = "Performance2";
5999 // break;
6000 case 3:
6001 // gen_helper_mtc0_performance3(arg);
6002 rn = "Performance3";
6003 // break;
6004 case 4:
6005 // gen_helper_mtc0_performance4(arg);
6006 rn = "Performance4";
6007 // break;
6008 case 5:
6009 // gen_helper_mtc0_performance5(arg);
6010 rn = "Performance5";
6011 // break;
6012 case 6:
6013 // gen_helper_mtc0_performance6(arg);
6014 rn = "Performance6";
6015 // break;
6016 case 7:
6017 // gen_helper_mtc0_performance7(arg);
6018 rn = "Performance7";
6019 // break;
6020 default:
6021 goto cp0_unimplemented;
6023 break;
6024 case 26:
6025 /* ignored */
6026 rn = "ECC";
6027 break;
6028 case 27:
6029 switch (sel) {
6030 case 0 ... 3:
6031 /* ignored */
6032 rn = "CacheErr";
6033 break;
6034 default:
6035 goto cp0_unimplemented;
6037 break;
6038 case 28:
6039 switch (sel) {
6040 case 0:
6041 case 2:
6042 case 4:
6043 case 6:
6044 gen_helper_mtc0_taglo(cpu_env, arg);
6045 rn = "TagLo";
6046 break;
6047 case 1:
6048 case 3:
6049 case 5:
6050 case 7:
6051 gen_helper_mtc0_datalo(cpu_env, arg);
6052 rn = "DataLo";
6053 break;
6054 default:
6055 goto cp0_unimplemented;
6057 break;
6058 case 29:
6059 switch (sel) {
6060 case 0:
6061 case 2:
6062 case 4:
6063 case 6:
6064 gen_helper_mtc0_taghi(cpu_env, arg);
6065 rn = "TagHi";
6066 break;
6067 case 1:
6068 case 3:
6069 case 5:
6070 case 7:
6071 gen_helper_mtc0_datahi(cpu_env, arg);
6072 rn = "DataHi";
6073 break;
6074 default:
6075 rn = "invalid sel";
6076 goto cp0_unimplemented;
6078 break;
6079 case 30:
6080 switch (sel) {
6081 case 0:
6082 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
6083 rn = "ErrorEPC";
6084 break;
6085 default:
6086 goto cp0_unimplemented;
6088 break;
6089 case 31:
6090 switch (sel) {
6091 case 0:
6092 /* EJTAG support */
6093 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6094 rn = "DESAVE";
6095 break;
6096 case 2 ... 7:
6097 CP0_CHECK(ctx->kscrexist & (1 << sel));
6098 tcg_gen_st_tl(arg, cpu_env,
6099 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6100 rn = "KScratch";
6101 break;
6102 default:
6103 goto cp0_unimplemented;
6105 /* Stop translation as we may have switched the execution mode */
6106 ctx->bstate = BS_STOP;
6107 break;
6108 default:
6109 goto cp0_unimplemented;
6111 (void)rn; /* avoid a compiler warning */
6112 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6113 /* For simplicity assume that all writes can cause interrupts. */
6114 if (use_icount) {
6115 gen_io_end();
6116 ctx->bstate = BS_STOP;
6118 return;
6120 cp0_unimplemented:
6121 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6124 #if defined(TARGET_MIPS64)
6125 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6127 const char *rn = "invalid";
6129 if (sel != 0)
6130 check_insn(ctx, ISA_MIPS64);
6132 switch (reg) {
6133 case 0:
6134 switch (sel) {
6135 case 0:
6136 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6137 rn = "Index";
6138 break;
6139 case 1:
6140 CP0_CHECK(ctx->insn_flags & ASE_MT);
6141 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6142 rn = "MVPControl";
6143 break;
6144 case 2:
6145 CP0_CHECK(ctx->insn_flags & ASE_MT);
6146 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6147 rn = "MVPConf0";
6148 break;
6149 case 3:
6150 CP0_CHECK(ctx->insn_flags & ASE_MT);
6151 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6152 rn = "MVPConf1";
6153 break;
6154 default:
6155 goto cp0_unimplemented;
6157 break;
6158 case 1:
6159 switch (sel) {
6160 case 0:
6161 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6162 gen_helper_mfc0_random(arg, cpu_env);
6163 rn = "Random";
6164 break;
6165 case 1:
6166 CP0_CHECK(ctx->insn_flags & ASE_MT);
6167 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6168 rn = "VPEControl";
6169 break;
6170 case 2:
6171 CP0_CHECK(ctx->insn_flags & ASE_MT);
6172 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6173 rn = "VPEConf0";
6174 break;
6175 case 3:
6176 CP0_CHECK(ctx->insn_flags & ASE_MT);
6177 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6178 rn = "VPEConf1";
6179 break;
6180 case 4:
6181 CP0_CHECK(ctx->insn_flags & ASE_MT);
6182 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6183 rn = "YQMask";
6184 break;
6185 case 5:
6186 CP0_CHECK(ctx->insn_flags & ASE_MT);
6187 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6188 rn = "VPESchedule";
6189 break;
6190 case 6:
6191 CP0_CHECK(ctx->insn_flags & ASE_MT);
6192 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6193 rn = "VPEScheFBack";
6194 break;
6195 case 7:
6196 CP0_CHECK(ctx->insn_flags & ASE_MT);
6197 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6198 rn = "VPEOpt";
6199 break;
6200 default:
6201 goto cp0_unimplemented;
6203 break;
6204 case 2:
6205 switch (sel) {
6206 case 0:
6207 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6208 rn = "EntryLo0";
6209 break;
6210 case 1:
6211 CP0_CHECK(ctx->insn_flags & ASE_MT);
6212 gen_helper_mfc0_tcstatus(arg, cpu_env);
6213 rn = "TCStatus";
6214 break;
6215 case 2:
6216 CP0_CHECK(ctx->insn_flags & ASE_MT);
6217 gen_helper_mfc0_tcbind(arg, cpu_env);
6218 rn = "TCBind";
6219 break;
6220 case 3:
6221 CP0_CHECK(ctx->insn_flags & ASE_MT);
6222 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6223 rn = "TCRestart";
6224 break;
6225 case 4:
6226 CP0_CHECK(ctx->insn_flags & ASE_MT);
6227 gen_helper_dmfc0_tchalt(arg, cpu_env);
6228 rn = "TCHalt";
6229 break;
6230 case 5:
6231 CP0_CHECK(ctx->insn_flags & ASE_MT);
6232 gen_helper_dmfc0_tccontext(arg, cpu_env);
6233 rn = "TCContext";
6234 break;
6235 case 6:
6236 CP0_CHECK(ctx->insn_flags & ASE_MT);
6237 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6238 rn = "TCSchedule";
6239 break;
6240 case 7:
6241 CP0_CHECK(ctx->insn_flags & ASE_MT);
6242 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6243 rn = "TCScheFBack";
6244 break;
6245 default:
6246 goto cp0_unimplemented;
6248 break;
6249 case 3:
6250 switch (sel) {
6251 case 0:
6252 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6253 rn = "EntryLo1";
6254 break;
6255 default:
6256 goto cp0_unimplemented;
6258 break;
6259 case 4:
6260 switch (sel) {
6261 case 0:
6262 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6263 rn = "Context";
6264 break;
6265 case 1:
6266 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6267 rn = "ContextConfig";
6268 goto cp0_unimplemented;
6269 // break;
6270 case 2:
6271 CP0_CHECK(ctx->ulri);
6272 tcg_gen_ld_tl(arg, cpu_env,
6273 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6274 rn = "UserLocal";
6275 break;
6276 default:
6277 goto cp0_unimplemented;
6279 break;
6280 case 5:
6281 switch (sel) {
6282 case 0:
6283 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6284 rn = "PageMask";
6285 break;
6286 case 1:
6287 check_insn(ctx, ISA_MIPS32R2);
6288 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6289 rn = "PageGrain";
6290 break;
6291 default:
6292 goto cp0_unimplemented;
6294 break;
6295 case 6:
6296 switch (sel) {
6297 case 0:
6298 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6299 rn = "Wired";
6300 break;
6301 case 1:
6302 check_insn(ctx, ISA_MIPS32R2);
6303 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6304 rn = "SRSConf0";
6305 break;
6306 case 2:
6307 check_insn(ctx, ISA_MIPS32R2);
6308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6309 rn = "SRSConf1";
6310 break;
6311 case 3:
6312 check_insn(ctx, ISA_MIPS32R2);
6313 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6314 rn = "SRSConf2";
6315 break;
6316 case 4:
6317 check_insn(ctx, ISA_MIPS32R2);
6318 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6319 rn = "SRSConf3";
6320 break;
6321 case 5:
6322 check_insn(ctx, ISA_MIPS32R2);
6323 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6324 rn = "SRSConf4";
6325 break;
6326 default:
6327 goto cp0_unimplemented;
6329 break;
6330 case 7:
6331 switch (sel) {
6332 case 0:
6333 check_insn(ctx, ISA_MIPS32R2);
6334 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6335 rn = "HWREna";
6336 break;
6337 default:
6338 goto cp0_unimplemented;
6340 break;
6341 case 8:
6342 switch (sel) {
6343 case 0:
6344 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6345 rn = "BadVAddr";
6346 break;
6347 case 1:
6348 CP0_CHECK(ctx->bi);
6349 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6350 rn = "BadInstr";
6351 break;
6352 case 2:
6353 CP0_CHECK(ctx->bp);
6354 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6355 rn = "BadInstrP";
6356 break;
6357 default:
6358 goto cp0_unimplemented;
6360 break;
6361 case 9:
6362 switch (sel) {
6363 case 0:
6364 /* Mark as an IO operation because we read the time. */
6365 if (use_icount)
6366 gen_io_start();
6367 gen_helper_mfc0_count(arg, cpu_env);
6368 if (use_icount) {
6369 gen_io_end();
6371 /* Break the TB to be able to take timer interrupts immediately
6372 after reading count. */
6373 ctx->bstate = BS_STOP;
6374 rn = "Count";
6375 break;
6376 /* 6,7 are implementation dependent */
6377 default:
6378 goto cp0_unimplemented;
6380 break;
6381 case 10:
6382 switch (sel) {
6383 case 0:
6384 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6385 rn = "EntryHi";
6386 break;
6387 default:
6388 goto cp0_unimplemented;
6390 break;
6391 case 11:
6392 switch (sel) {
6393 case 0:
6394 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6395 rn = "Compare";
6396 break;
6397 /* 6,7 are implementation dependent */
6398 default:
6399 goto cp0_unimplemented;
6401 break;
6402 case 12:
6403 switch (sel) {
6404 case 0:
6405 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6406 rn = "Status";
6407 break;
6408 case 1:
6409 check_insn(ctx, ISA_MIPS32R2);
6410 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6411 rn = "IntCtl";
6412 break;
6413 case 2:
6414 check_insn(ctx, ISA_MIPS32R2);
6415 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6416 rn = "SRSCtl";
6417 break;
6418 case 3:
6419 check_insn(ctx, ISA_MIPS32R2);
6420 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6421 rn = "SRSMap";
6422 break;
6423 default:
6424 goto cp0_unimplemented;
6426 break;
6427 case 13:
6428 switch (sel) {
6429 case 0:
6430 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6431 rn = "Cause";
6432 break;
6433 default:
6434 goto cp0_unimplemented;
6436 break;
6437 case 14:
6438 switch (sel) {
6439 case 0:
6440 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6441 rn = "EPC";
6442 break;
6443 default:
6444 goto cp0_unimplemented;
6446 break;
6447 case 15:
6448 switch (sel) {
6449 case 0:
6450 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6451 rn = "PRid";
6452 break;
6453 case 1:
6454 check_insn(ctx, ISA_MIPS32R2);
6455 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6456 rn = "EBase";
6457 break;
6458 default:
6459 goto cp0_unimplemented;
6461 break;
6462 case 16:
6463 switch (sel) {
6464 case 0:
6465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6466 rn = "Config";
6467 break;
6468 case 1:
6469 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6470 rn = "Config1";
6471 break;
6472 case 2:
6473 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6474 rn = "Config2";
6475 break;
6476 case 3:
6477 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6478 rn = "Config3";
6479 break;
6480 case 4:
6481 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6482 rn = "Config4";
6483 break;
6484 case 5:
6485 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6486 rn = "Config5";
6487 break;
6488 /* 6,7 are implementation dependent */
6489 case 6:
6490 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6491 rn = "Config6";
6492 break;
6493 case 7:
6494 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6495 rn = "Config7";
6496 break;
6497 default:
6498 goto cp0_unimplemented;
6500 break;
6501 case 17:
6502 switch (sel) {
6503 case 0:
6504 gen_helper_dmfc0_lladdr(arg, cpu_env);
6505 rn = "LLAddr";
6506 break;
6507 default:
6508 goto cp0_unimplemented;
6510 break;
6511 case 18:
6512 switch (sel) {
6513 case 0 ... 7:
6514 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6515 rn = "WatchLo";
6516 break;
6517 default:
6518 goto cp0_unimplemented;
6520 break;
6521 case 19:
6522 switch (sel) {
6523 case 0 ... 7:
6524 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6525 rn = "WatchHi";
6526 break;
6527 default:
6528 goto cp0_unimplemented;
6530 break;
6531 case 20:
6532 switch (sel) {
6533 case 0:
6534 check_insn(ctx, ISA_MIPS3);
6535 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6536 rn = "XContext";
6537 break;
6538 default:
6539 goto cp0_unimplemented;
6541 break;
6542 case 21:
6543 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6544 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6545 switch (sel) {
6546 case 0:
6547 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6548 rn = "Framemask";
6549 break;
6550 default:
6551 goto cp0_unimplemented;
6553 break;
6554 case 22:
6555 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6556 rn = "'Diagnostic"; /* implementation dependent */
6557 break;
6558 case 23:
6559 switch (sel) {
6560 case 0:
6561 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6562 rn = "Debug";
6563 break;
6564 case 1:
6565 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6566 rn = "TraceControl";
6567 // break;
6568 case 2:
6569 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6570 rn = "TraceControl2";
6571 // break;
6572 case 3:
6573 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6574 rn = "UserTraceData";
6575 // break;
6576 case 4:
6577 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6578 rn = "TraceBPC";
6579 // break;
6580 default:
6581 goto cp0_unimplemented;
6583 break;
6584 case 24:
6585 switch (sel) {
6586 case 0:
6587 /* EJTAG support */
6588 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6589 rn = "DEPC";
6590 break;
6591 default:
6592 goto cp0_unimplemented;
6594 break;
6595 case 25:
6596 switch (sel) {
6597 case 0:
6598 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6599 rn = "Performance0";
6600 break;
6601 case 1:
6602 // gen_helper_dmfc0_performance1(arg);
6603 rn = "Performance1";
6604 // break;
6605 case 2:
6606 // gen_helper_dmfc0_performance2(arg);
6607 rn = "Performance2";
6608 // break;
6609 case 3:
6610 // gen_helper_dmfc0_performance3(arg);
6611 rn = "Performance3";
6612 // break;
6613 case 4:
6614 // gen_helper_dmfc0_performance4(arg);
6615 rn = "Performance4";
6616 // break;
6617 case 5:
6618 // gen_helper_dmfc0_performance5(arg);
6619 rn = "Performance5";
6620 // break;
6621 case 6:
6622 // gen_helper_dmfc0_performance6(arg);
6623 rn = "Performance6";
6624 // break;
6625 case 7:
6626 // gen_helper_dmfc0_performance7(arg);
6627 rn = "Performance7";
6628 // break;
6629 default:
6630 goto cp0_unimplemented;
6632 break;
6633 case 26:
6634 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6635 rn = "ECC";
6636 break;
6637 case 27:
6638 switch (sel) {
6639 /* ignored */
6640 case 0 ... 3:
6641 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6642 rn = "CacheErr";
6643 break;
6644 default:
6645 goto cp0_unimplemented;
6647 break;
6648 case 28:
6649 switch (sel) {
6650 case 0:
6651 case 2:
6652 case 4:
6653 case 6:
6654 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
6655 rn = "TagLo";
6656 break;
6657 case 1:
6658 case 3:
6659 case 5:
6660 case 7:
6661 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6662 rn = "DataLo";
6663 break;
6664 default:
6665 goto cp0_unimplemented;
6667 break;
6668 case 29:
6669 switch (sel) {
6670 case 0:
6671 case 2:
6672 case 4:
6673 case 6:
6674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6675 rn = "TagHi";
6676 break;
6677 case 1:
6678 case 3:
6679 case 5:
6680 case 7:
6681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6682 rn = "DataHi";
6683 break;
6684 default:
6685 goto cp0_unimplemented;
6687 break;
6688 case 30:
6689 switch (sel) {
6690 case 0:
6691 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6692 rn = "ErrorEPC";
6693 break;
6694 default:
6695 goto cp0_unimplemented;
6697 break;
6698 case 31:
6699 switch (sel) {
6700 case 0:
6701 /* EJTAG support */
6702 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6703 rn = "DESAVE";
6704 break;
6705 case 2 ... 7:
6706 CP0_CHECK(ctx->kscrexist & (1 << sel));
6707 tcg_gen_ld_tl(arg, cpu_env,
6708 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6709 rn = "KScratch";
6710 break;
6711 default:
6712 goto cp0_unimplemented;
6714 break;
6715 default:
6716 goto cp0_unimplemented;
6718 (void)rn; /* avoid a compiler warning */
6719 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6720 return;
6722 cp0_unimplemented:
6723 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6724 gen_mfc0_unimplemented(ctx, arg);
6727 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6729 const char *rn = "invalid";
6731 if (sel != 0)
6732 check_insn(ctx, ISA_MIPS64);
6734 if (use_icount)
6735 gen_io_start();
6737 switch (reg) {
6738 case 0:
6739 switch (sel) {
6740 case 0:
6741 gen_helper_mtc0_index(cpu_env, arg);
6742 rn = "Index";
6743 break;
6744 case 1:
6745 CP0_CHECK(ctx->insn_flags & ASE_MT);
6746 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6747 rn = "MVPControl";
6748 break;
6749 case 2:
6750 CP0_CHECK(ctx->insn_flags & ASE_MT);
6751 /* ignored */
6752 rn = "MVPConf0";
6753 break;
6754 case 3:
6755 CP0_CHECK(ctx->insn_flags & ASE_MT);
6756 /* ignored */
6757 rn = "MVPConf1";
6758 break;
6759 default:
6760 goto cp0_unimplemented;
6762 break;
6763 case 1:
6764 switch (sel) {
6765 case 0:
6766 /* ignored */
6767 rn = "Random";
6768 break;
6769 case 1:
6770 CP0_CHECK(ctx->insn_flags & ASE_MT);
6771 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6772 rn = "VPEControl";
6773 break;
6774 case 2:
6775 CP0_CHECK(ctx->insn_flags & ASE_MT);
6776 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6777 rn = "VPEConf0";
6778 break;
6779 case 3:
6780 CP0_CHECK(ctx->insn_flags & ASE_MT);
6781 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6782 rn = "VPEConf1";
6783 break;
6784 case 4:
6785 CP0_CHECK(ctx->insn_flags & ASE_MT);
6786 gen_helper_mtc0_yqmask(cpu_env, arg);
6787 rn = "YQMask";
6788 break;
6789 case 5:
6790 CP0_CHECK(ctx->insn_flags & ASE_MT);
6791 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6792 rn = "VPESchedule";
6793 break;
6794 case 6:
6795 CP0_CHECK(ctx->insn_flags & ASE_MT);
6796 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6797 rn = "VPEScheFBack";
6798 break;
6799 case 7:
6800 CP0_CHECK(ctx->insn_flags & ASE_MT);
6801 gen_helper_mtc0_vpeopt(cpu_env, arg);
6802 rn = "VPEOpt";
6803 break;
6804 default:
6805 goto cp0_unimplemented;
6807 break;
6808 case 2:
6809 switch (sel) {
6810 case 0:
6811 gen_helper_dmtc0_entrylo0(cpu_env, arg);
6812 rn = "EntryLo0";
6813 break;
6814 case 1:
6815 CP0_CHECK(ctx->insn_flags & ASE_MT);
6816 gen_helper_mtc0_tcstatus(cpu_env, arg);
6817 rn = "TCStatus";
6818 break;
6819 case 2:
6820 CP0_CHECK(ctx->insn_flags & ASE_MT);
6821 gen_helper_mtc0_tcbind(cpu_env, arg);
6822 rn = "TCBind";
6823 break;
6824 case 3:
6825 CP0_CHECK(ctx->insn_flags & ASE_MT);
6826 gen_helper_mtc0_tcrestart(cpu_env, arg);
6827 rn = "TCRestart";
6828 break;
6829 case 4:
6830 CP0_CHECK(ctx->insn_flags & ASE_MT);
6831 gen_helper_mtc0_tchalt(cpu_env, arg);
6832 rn = "TCHalt";
6833 break;
6834 case 5:
6835 CP0_CHECK(ctx->insn_flags & ASE_MT);
6836 gen_helper_mtc0_tccontext(cpu_env, arg);
6837 rn = "TCContext";
6838 break;
6839 case 6:
6840 CP0_CHECK(ctx->insn_flags & ASE_MT);
6841 gen_helper_mtc0_tcschedule(cpu_env, arg);
6842 rn = "TCSchedule";
6843 break;
6844 case 7:
6845 CP0_CHECK(ctx->insn_flags & ASE_MT);
6846 gen_helper_mtc0_tcschefback(cpu_env, arg);
6847 rn = "TCScheFBack";
6848 break;
6849 default:
6850 goto cp0_unimplemented;
6852 break;
6853 case 3:
6854 switch (sel) {
6855 case 0:
6856 gen_helper_dmtc0_entrylo1(cpu_env, arg);
6857 rn = "EntryLo1";
6858 break;
6859 default:
6860 goto cp0_unimplemented;
6862 break;
6863 case 4:
6864 switch (sel) {
6865 case 0:
6866 gen_helper_mtc0_context(cpu_env, arg);
6867 rn = "Context";
6868 break;
6869 case 1:
6870 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
6871 rn = "ContextConfig";
6872 goto cp0_unimplemented;
6873 // break;
6874 case 2:
6875 CP0_CHECK(ctx->ulri);
6876 tcg_gen_st_tl(arg, cpu_env,
6877 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6878 rn = "UserLocal";
6879 break;
6880 default:
6881 goto cp0_unimplemented;
6883 break;
6884 case 5:
6885 switch (sel) {
6886 case 0:
6887 gen_helper_mtc0_pagemask(cpu_env, arg);
6888 rn = "PageMask";
6889 break;
6890 case 1:
6891 check_insn(ctx, ISA_MIPS32R2);
6892 gen_helper_mtc0_pagegrain(cpu_env, arg);
6893 rn = "PageGrain";
6894 break;
6895 default:
6896 goto cp0_unimplemented;
6898 break;
6899 case 6:
6900 switch (sel) {
6901 case 0:
6902 gen_helper_mtc0_wired(cpu_env, arg);
6903 rn = "Wired";
6904 break;
6905 case 1:
6906 check_insn(ctx, ISA_MIPS32R2);
6907 gen_helper_mtc0_srsconf0(cpu_env, arg);
6908 rn = "SRSConf0";
6909 break;
6910 case 2:
6911 check_insn(ctx, ISA_MIPS32R2);
6912 gen_helper_mtc0_srsconf1(cpu_env, arg);
6913 rn = "SRSConf1";
6914 break;
6915 case 3:
6916 check_insn(ctx, ISA_MIPS32R2);
6917 gen_helper_mtc0_srsconf2(cpu_env, arg);
6918 rn = "SRSConf2";
6919 break;
6920 case 4:
6921 check_insn(ctx, ISA_MIPS32R2);
6922 gen_helper_mtc0_srsconf3(cpu_env, arg);
6923 rn = "SRSConf3";
6924 break;
6925 case 5:
6926 check_insn(ctx, ISA_MIPS32R2);
6927 gen_helper_mtc0_srsconf4(cpu_env, arg);
6928 rn = "SRSConf4";
6929 break;
6930 default:
6931 goto cp0_unimplemented;
6933 break;
6934 case 7:
6935 switch (sel) {
6936 case 0:
6937 check_insn(ctx, ISA_MIPS32R2);
6938 gen_helper_mtc0_hwrena(cpu_env, arg);
6939 ctx->bstate = BS_STOP;
6940 rn = "HWREna";
6941 break;
6942 default:
6943 goto cp0_unimplemented;
6945 break;
6946 case 8:
6947 switch (sel) {
6948 case 0:
6949 /* ignored */
6950 rn = "BadVAddr";
6951 break;
6952 case 1:
6953 /* ignored */
6954 rn = "BadInstr";
6955 break;
6956 case 2:
6957 /* ignored */
6958 rn = "BadInstrP";
6959 break;
6960 default:
6961 goto cp0_unimplemented;
6963 break;
6964 case 9:
6965 switch (sel) {
6966 case 0:
6967 gen_helper_mtc0_count(cpu_env, arg);
6968 rn = "Count";
6969 break;
6970 /* 6,7 are implementation dependent */
6971 default:
6972 goto cp0_unimplemented;
6974 /* Stop translation as we may have switched the execution mode */
6975 ctx->bstate = BS_STOP;
6976 break;
6977 case 10:
6978 switch (sel) {
6979 case 0:
6980 gen_helper_mtc0_entryhi(cpu_env, arg);
6981 rn = "EntryHi";
6982 break;
6983 default:
6984 goto cp0_unimplemented;
6986 break;
6987 case 11:
6988 switch (sel) {
6989 case 0:
6990 gen_helper_mtc0_compare(cpu_env, arg);
6991 rn = "Compare";
6992 break;
6993 /* 6,7 are implementation dependent */
6994 default:
6995 goto cp0_unimplemented;
6997 /* Stop translation as we may have switched the execution mode */
6998 ctx->bstate = BS_STOP;
6999 break;
7000 case 12:
7001 switch (sel) {
7002 case 0:
7003 save_cpu_state(ctx, 1);
7004 gen_helper_mtc0_status(cpu_env, arg);
7005 /* BS_STOP isn't good enough here, hflags may have changed. */
7006 gen_save_pc(ctx->pc + 4);
7007 ctx->bstate = BS_EXCP;
7008 rn = "Status";
7009 break;
7010 case 1:
7011 check_insn(ctx, ISA_MIPS32R2);
7012 gen_helper_mtc0_intctl(cpu_env, arg);
7013 /* Stop translation as we may have switched the execution mode */
7014 ctx->bstate = BS_STOP;
7015 rn = "IntCtl";
7016 break;
7017 case 2:
7018 check_insn(ctx, ISA_MIPS32R2);
7019 gen_helper_mtc0_srsctl(cpu_env, arg);
7020 /* Stop translation as we may have switched the execution mode */
7021 ctx->bstate = BS_STOP;
7022 rn = "SRSCtl";
7023 break;
7024 case 3:
7025 check_insn(ctx, ISA_MIPS32R2);
7026 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7027 /* Stop translation as we may have switched the execution mode */
7028 ctx->bstate = BS_STOP;
7029 rn = "SRSMap";
7030 break;
7031 default:
7032 goto cp0_unimplemented;
7034 break;
7035 case 13:
7036 switch (sel) {
7037 case 0:
7038 save_cpu_state(ctx, 1);
7039 /* Mark as an IO operation because we may trigger a software
7040 interrupt. */
7041 if (use_icount) {
7042 gen_io_start();
7044 gen_helper_mtc0_cause(cpu_env, arg);
7045 if (use_icount) {
7046 gen_io_end();
7048 /* Stop translation as we may have triggered an intetrupt */
7049 ctx->bstate = BS_STOP;
7050 rn = "Cause";
7051 break;
7052 default:
7053 goto cp0_unimplemented;
7055 break;
7056 case 14:
7057 switch (sel) {
7058 case 0:
7059 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7060 rn = "EPC";
7061 break;
7062 default:
7063 goto cp0_unimplemented;
7065 break;
7066 case 15:
7067 switch (sel) {
7068 case 0:
7069 /* ignored */
7070 rn = "PRid";
7071 break;
7072 case 1:
7073 check_insn(ctx, ISA_MIPS32R2);
7074 gen_helper_mtc0_ebase(cpu_env, arg);
7075 rn = "EBase";
7076 break;
7077 default:
7078 goto cp0_unimplemented;
7080 break;
7081 case 16:
7082 switch (sel) {
7083 case 0:
7084 gen_helper_mtc0_config0(cpu_env, arg);
7085 rn = "Config";
7086 /* Stop translation as we may have switched the execution mode */
7087 ctx->bstate = BS_STOP;
7088 break;
7089 case 1:
7090 /* ignored, read only */
7091 rn = "Config1";
7092 break;
7093 case 2:
7094 gen_helper_mtc0_config2(cpu_env, arg);
7095 rn = "Config2";
7096 /* Stop translation as we may have switched the execution mode */
7097 ctx->bstate = BS_STOP;
7098 break;
7099 case 3:
7100 /* ignored */
7101 rn = "Config3";
7102 break;
7103 case 4:
7104 /* currently ignored */
7105 rn = "Config4";
7106 break;
7107 case 5:
7108 gen_helper_mtc0_config5(cpu_env, arg);
7109 rn = "Config5";
7110 /* Stop translation as we may have switched the execution mode */
7111 ctx->bstate = BS_STOP;
7112 break;
7113 /* 6,7 are implementation dependent */
7114 default:
7115 rn = "Invalid config selector";
7116 goto cp0_unimplemented;
7118 break;
7119 case 17:
7120 switch (sel) {
7121 case 0:
7122 gen_helper_mtc0_lladdr(cpu_env, arg);
7123 rn = "LLAddr";
7124 break;
7125 default:
7126 goto cp0_unimplemented;
7128 break;
7129 case 18:
7130 switch (sel) {
7131 case 0 ... 7:
7132 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7133 rn = "WatchLo";
7134 break;
7135 default:
7136 goto cp0_unimplemented;
7138 break;
7139 case 19:
7140 switch (sel) {
7141 case 0 ... 7:
7142 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7143 rn = "WatchHi";
7144 break;
7145 default:
7146 goto cp0_unimplemented;
7148 break;
7149 case 20:
7150 switch (sel) {
7151 case 0:
7152 check_insn(ctx, ISA_MIPS3);
7153 gen_helper_mtc0_xcontext(cpu_env, arg);
7154 rn = "XContext";
7155 break;
7156 default:
7157 goto cp0_unimplemented;
7159 break;
7160 case 21:
7161 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7162 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7163 switch (sel) {
7164 case 0:
7165 gen_helper_mtc0_framemask(cpu_env, arg);
7166 rn = "Framemask";
7167 break;
7168 default:
7169 goto cp0_unimplemented;
7171 break;
7172 case 22:
7173 /* ignored */
7174 rn = "Diagnostic"; /* implementation dependent */
7175 break;
7176 case 23:
7177 switch (sel) {
7178 case 0:
7179 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7180 /* BS_STOP isn't good enough here, hflags may have changed. */
7181 gen_save_pc(ctx->pc + 4);
7182 ctx->bstate = BS_EXCP;
7183 rn = "Debug";
7184 break;
7185 case 1:
7186 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7187 /* Stop translation as we may have switched the execution mode */
7188 ctx->bstate = BS_STOP;
7189 rn = "TraceControl";
7190 // break;
7191 case 2:
7192 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7193 /* Stop translation as we may have switched the execution mode */
7194 ctx->bstate = BS_STOP;
7195 rn = "TraceControl2";
7196 // break;
7197 case 3:
7198 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7199 /* Stop translation as we may have switched the execution mode */
7200 ctx->bstate = BS_STOP;
7201 rn = "UserTraceData";
7202 // break;
7203 case 4:
7204 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7205 /* Stop translation as we may have switched the execution mode */
7206 ctx->bstate = BS_STOP;
7207 rn = "TraceBPC";
7208 // break;
7209 default:
7210 goto cp0_unimplemented;
7212 break;
7213 case 24:
7214 switch (sel) {
7215 case 0:
7216 /* EJTAG support */
7217 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7218 rn = "DEPC";
7219 break;
7220 default:
7221 goto cp0_unimplemented;
7223 break;
7224 case 25:
7225 switch (sel) {
7226 case 0:
7227 gen_helper_mtc0_performance0(cpu_env, arg);
7228 rn = "Performance0";
7229 break;
7230 case 1:
7231 // gen_helper_mtc0_performance1(cpu_env, arg);
7232 rn = "Performance1";
7233 // break;
7234 case 2:
7235 // gen_helper_mtc0_performance2(cpu_env, arg);
7236 rn = "Performance2";
7237 // break;
7238 case 3:
7239 // gen_helper_mtc0_performance3(cpu_env, arg);
7240 rn = "Performance3";
7241 // break;
7242 case 4:
7243 // gen_helper_mtc0_performance4(cpu_env, arg);
7244 rn = "Performance4";
7245 // break;
7246 case 5:
7247 // gen_helper_mtc0_performance5(cpu_env, arg);
7248 rn = "Performance5";
7249 // break;
7250 case 6:
7251 // gen_helper_mtc0_performance6(cpu_env, arg);
7252 rn = "Performance6";
7253 // break;
7254 case 7:
7255 // gen_helper_mtc0_performance7(cpu_env, arg);
7256 rn = "Performance7";
7257 // break;
7258 default:
7259 goto cp0_unimplemented;
7261 break;
7262 case 26:
7263 /* ignored */
7264 rn = "ECC";
7265 break;
7266 case 27:
7267 switch (sel) {
7268 case 0 ... 3:
7269 /* ignored */
7270 rn = "CacheErr";
7271 break;
7272 default:
7273 goto cp0_unimplemented;
7275 break;
7276 case 28:
7277 switch (sel) {
7278 case 0:
7279 case 2:
7280 case 4:
7281 case 6:
7282 gen_helper_mtc0_taglo(cpu_env, arg);
7283 rn = "TagLo";
7284 break;
7285 case 1:
7286 case 3:
7287 case 5:
7288 case 7:
7289 gen_helper_mtc0_datalo(cpu_env, arg);
7290 rn = "DataLo";
7291 break;
7292 default:
7293 goto cp0_unimplemented;
7295 break;
7296 case 29:
7297 switch (sel) {
7298 case 0:
7299 case 2:
7300 case 4:
7301 case 6:
7302 gen_helper_mtc0_taghi(cpu_env, arg);
7303 rn = "TagHi";
7304 break;
7305 case 1:
7306 case 3:
7307 case 5:
7308 case 7:
7309 gen_helper_mtc0_datahi(cpu_env, arg);
7310 rn = "DataHi";
7311 break;
7312 default:
7313 rn = "invalid sel";
7314 goto cp0_unimplemented;
7316 break;
7317 case 30:
7318 switch (sel) {
7319 case 0:
7320 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7321 rn = "ErrorEPC";
7322 break;
7323 default:
7324 goto cp0_unimplemented;
7326 break;
7327 case 31:
7328 switch (sel) {
7329 case 0:
7330 /* EJTAG support */
7331 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7332 rn = "DESAVE";
7333 break;
7334 case 2 ... 7:
7335 CP0_CHECK(ctx->kscrexist & (1 << sel));
7336 tcg_gen_st_tl(arg, cpu_env,
7337 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7338 rn = "KScratch";
7339 break;
7340 default:
7341 goto cp0_unimplemented;
7343 /* Stop translation as we may have switched the execution mode */
7344 ctx->bstate = BS_STOP;
7345 break;
7346 default:
7347 goto cp0_unimplemented;
7349 (void)rn; /* avoid a compiler warning */
7350 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7351 /* For simplicity assume that all writes can cause interrupts. */
7352 if (use_icount) {
7353 gen_io_end();
7354 ctx->bstate = BS_STOP;
7356 return;
7358 cp0_unimplemented:
7359 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7361 #endif /* TARGET_MIPS64 */
7363 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7364 int u, int sel, int h)
7366 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7367 TCGv t0 = tcg_temp_local_new();
7369 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7370 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7371 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7372 tcg_gen_movi_tl(t0, -1);
7373 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7374 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7375 tcg_gen_movi_tl(t0, -1);
7376 else if (u == 0) {
7377 switch (rt) {
7378 case 1:
7379 switch (sel) {
7380 case 1:
7381 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7382 break;
7383 case 2:
7384 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7385 break;
7386 default:
7387 goto die;
7388 break;
7390 break;
7391 case 2:
7392 switch (sel) {
7393 case 1:
7394 gen_helper_mftc0_tcstatus(t0, cpu_env);
7395 break;
7396 case 2:
7397 gen_helper_mftc0_tcbind(t0, cpu_env);
7398 break;
7399 case 3:
7400 gen_helper_mftc0_tcrestart(t0, cpu_env);
7401 break;
7402 case 4:
7403 gen_helper_mftc0_tchalt(t0, cpu_env);
7404 break;
7405 case 5:
7406 gen_helper_mftc0_tccontext(t0, cpu_env);
7407 break;
7408 case 6:
7409 gen_helper_mftc0_tcschedule(t0, cpu_env);
7410 break;
7411 case 7:
7412 gen_helper_mftc0_tcschefback(t0, cpu_env);
7413 break;
7414 default:
7415 gen_mfc0(ctx, t0, rt, sel);
7416 break;
7418 break;
7419 case 10:
7420 switch (sel) {
7421 case 0:
7422 gen_helper_mftc0_entryhi(t0, cpu_env);
7423 break;
7424 default:
7425 gen_mfc0(ctx, t0, rt, sel);
7426 break;
7428 case 12:
7429 switch (sel) {
7430 case 0:
7431 gen_helper_mftc0_status(t0, cpu_env);
7432 break;
7433 default:
7434 gen_mfc0(ctx, t0, rt, sel);
7435 break;
7437 case 13:
7438 switch (sel) {
7439 case 0:
7440 gen_helper_mftc0_cause(t0, cpu_env);
7441 break;
7442 default:
7443 goto die;
7444 break;
7446 break;
7447 case 14:
7448 switch (sel) {
7449 case 0:
7450 gen_helper_mftc0_epc(t0, cpu_env);
7451 break;
7452 default:
7453 goto die;
7454 break;
7456 break;
7457 case 15:
7458 switch (sel) {
7459 case 1:
7460 gen_helper_mftc0_ebase(t0, cpu_env);
7461 break;
7462 default:
7463 goto die;
7464 break;
7466 break;
7467 case 16:
7468 switch (sel) {
7469 case 0 ... 7:
7470 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7471 break;
7472 default:
7473 goto die;
7474 break;
7476 break;
7477 case 23:
7478 switch (sel) {
7479 case 0:
7480 gen_helper_mftc0_debug(t0, cpu_env);
7481 break;
7482 default:
7483 gen_mfc0(ctx, t0, rt, sel);
7484 break;
7486 break;
7487 default:
7488 gen_mfc0(ctx, t0, rt, sel);
7490 } else switch (sel) {
7491 /* GPR registers. */
7492 case 0:
7493 gen_helper_1e0i(mftgpr, t0, rt);
7494 break;
7495 /* Auxiliary CPU registers */
7496 case 1:
7497 switch (rt) {
7498 case 0:
7499 gen_helper_1e0i(mftlo, t0, 0);
7500 break;
7501 case 1:
7502 gen_helper_1e0i(mfthi, t0, 0);
7503 break;
7504 case 2:
7505 gen_helper_1e0i(mftacx, t0, 0);
7506 break;
7507 case 4:
7508 gen_helper_1e0i(mftlo, t0, 1);
7509 break;
7510 case 5:
7511 gen_helper_1e0i(mfthi, t0, 1);
7512 break;
7513 case 6:
7514 gen_helper_1e0i(mftacx, t0, 1);
7515 break;
7516 case 8:
7517 gen_helper_1e0i(mftlo, t0, 2);
7518 break;
7519 case 9:
7520 gen_helper_1e0i(mfthi, t0, 2);
7521 break;
7522 case 10:
7523 gen_helper_1e0i(mftacx, t0, 2);
7524 break;
7525 case 12:
7526 gen_helper_1e0i(mftlo, t0, 3);
7527 break;
7528 case 13:
7529 gen_helper_1e0i(mfthi, t0, 3);
7530 break;
7531 case 14:
7532 gen_helper_1e0i(mftacx, t0, 3);
7533 break;
7534 case 16:
7535 gen_helper_mftdsp(t0, cpu_env);
7536 break;
7537 default:
7538 goto die;
7540 break;
7541 /* Floating point (COP1). */
7542 case 2:
7543 /* XXX: For now we support only a single FPU context. */
7544 if (h == 0) {
7545 TCGv_i32 fp0 = tcg_temp_new_i32();
7547 gen_load_fpr32(fp0, rt);
7548 tcg_gen_ext_i32_tl(t0, fp0);
7549 tcg_temp_free_i32(fp0);
7550 } else {
7551 TCGv_i32 fp0 = tcg_temp_new_i32();
7553 gen_load_fpr32h(ctx, fp0, rt);
7554 tcg_gen_ext_i32_tl(t0, fp0);
7555 tcg_temp_free_i32(fp0);
7557 break;
7558 case 3:
7559 /* XXX: For now we support only a single FPU context. */
7560 gen_helper_1e0i(cfc1, t0, rt);
7561 break;
7562 /* COP2: Not implemented. */
7563 case 4:
7564 case 5:
7565 /* fall through */
7566 default:
7567 goto die;
7569 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7570 gen_store_gpr(t0, rd);
7571 tcg_temp_free(t0);
7572 return;
7574 die:
7575 tcg_temp_free(t0);
7576 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7577 generate_exception(ctx, EXCP_RI);
7580 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7581 int u, int sel, int h)
7583 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7584 TCGv t0 = tcg_temp_local_new();
7586 gen_load_gpr(t0, rt);
7587 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7588 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7589 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7590 /* NOP */ ;
7591 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7592 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7593 /* NOP */ ;
7594 else if (u == 0) {
7595 switch (rd) {
7596 case 1:
7597 switch (sel) {
7598 case 1:
7599 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7600 break;
7601 case 2:
7602 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7603 break;
7604 default:
7605 goto die;
7606 break;
7608 break;
7609 case 2:
7610 switch (sel) {
7611 case 1:
7612 gen_helper_mttc0_tcstatus(cpu_env, t0);
7613 break;
7614 case 2:
7615 gen_helper_mttc0_tcbind(cpu_env, t0);
7616 break;
7617 case 3:
7618 gen_helper_mttc0_tcrestart(cpu_env, t0);
7619 break;
7620 case 4:
7621 gen_helper_mttc0_tchalt(cpu_env, t0);
7622 break;
7623 case 5:
7624 gen_helper_mttc0_tccontext(cpu_env, t0);
7625 break;
7626 case 6:
7627 gen_helper_mttc0_tcschedule(cpu_env, t0);
7628 break;
7629 case 7:
7630 gen_helper_mttc0_tcschefback(cpu_env, t0);
7631 break;
7632 default:
7633 gen_mtc0(ctx, t0, rd, sel);
7634 break;
7636 break;
7637 case 10:
7638 switch (sel) {
7639 case 0:
7640 gen_helper_mttc0_entryhi(cpu_env, t0);
7641 break;
7642 default:
7643 gen_mtc0(ctx, t0, rd, sel);
7644 break;
7646 case 12:
7647 switch (sel) {
7648 case 0:
7649 gen_helper_mttc0_status(cpu_env, t0);
7650 break;
7651 default:
7652 gen_mtc0(ctx, t0, rd, sel);
7653 break;
7655 case 13:
7656 switch (sel) {
7657 case 0:
7658 gen_helper_mttc0_cause(cpu_env, t0);
7659 break;
7660 default:
7661 goto die;
7662 break;
7664 break;
7665 case 15:
7666 switch (sel) {
7667 case 1:
7668 gen_helper_mttc0_ebase(cpu_env, t0);
7669 break;
7670 default:
7671 goto die;
7672 break;
7674 break;
7675 case 23:
7676 switch (sel) {
7677 case 0:
7678 gen_helper_mttc0_debug(cpu_env, t0);
7679 break;
7680 default:
7681 gen_mtc0(ctx, t0, rd, sel);
7682 break;
7684 break;
7685 default:
7686 gen_mtc0(ctx, t0, rd, sel);
7688 } else switch (sel) {
7689 /* GPR registers. */
7690 case 0:
7691 gen_helper_0e1i(mttgpr, t0, rd);
7692 break;
7693 /* Auxiliary CPU registers */
7694 case 1:
7695 switch (rd) {
7696 case 0:
7697 gen_helper_0e1i(mttlo, t0, 0);
7698 break;
7699 case 1:
7700 gen_helper_0e1i(mtthi, t0, 0);
7701 break;
7702 case 2:
7703 gen_helper_0e1i(mttacx, t0, 0);
7704 break;
7705 case 4:
7706 gen_helper_0e1i(mttlo, t0, 1);
7707 break;
7708 case 5:
7709 gen_helper_0e1i(mtthi, t0, 1);
7710 break;
7711 case 6:
7712 gen_helper_0e1i(mttacx, t0, 1);
7713 break;
7714 case 8:
7715 gen_helper_0e1i(mttlo, t0, 2);
7716 break;
7717 case 9:
7718 gen_helper_0e1i(mtthi, t0, 2);
7719 break;
7720 case 10:
7721 gen_helper_0e1i(mttacx, t0, 2);
7722 break;
7723 case 12:
7724 gen_helper_0e1i(mttlo, t0, 3);
7725 break;
7726 case 13:
7727 gen_helper_0e1i(mtthi, t0, 3);
7728 break;
7729 case 14:
7730 gen_helper_0e1i(mttacx, t0, 3);
7731 break;
7732 case 16:
7733 gen_helper_mttdsp(cpu_env, t0);
7734 break;
7735 default:
7736 goto die;
7738 break;
7739 /* Floating point (COP1). */
7740 case 2:
7741 /* XXX: For now we support only a single FPU context. */
7742 if (h == 0) {
7743 TCGv_i32 fp0 = tcg_temp_new_i32();
7745 tcg_gen_trunc_tl_i32(fp0, t0);
7746 gen_store_fpr32(fp0, rd);
7747 tcg_temp_free_i32(fp0);
7748 } else {
7749 TCGv_i32 fp0 = tcg_temp_new_i32();
7751 tcg_gen_trunc_tl_i32(fp0, t0);
7752 gen_store_fpr32h(ctx, fp0, rd);
7753 tcg_temp_free_i32(fp0);
7755 break;
7756 case 3:
7757 /* XXX: For now we support only a single FPU context. */
7758 save_cpu_state(ctx, 1);
7760 TCGv_i32 fs_tmp = tcg_const_i32(rd);
7762 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7763 tcg_temp_free_i32(fs_tmp);
7765 /* Stop translation as we may have changed hflags */
7766 ctx->bstate = BS_STOP;
7767 break;
7768 /* COP2: Not implemented. */
7769 case 4:
7770 case 5:
7771 /* fall through */
7772 default:
7773 goto die;
7775 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7776 tcg_temp_free(t0);
7777 return;
7779 die:
7780 tcg_temp_free(t0);
7781 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7782 generate_exception(ctx, EXCP_RI);
7785 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
7787 const char *opn = "ldst";
7789 check_cp0_enabled(ctx);
7790 switch (opc) {
7791 case OPC_MFC0:
7792 if (rt == 0) {
7793 /* Treat as NOP. */
7794 return;
7796 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7797 opn = "mfc0";
7798 break;
7799 case OPC_MTC0:
7801 TCGv t0 = tcg_temp_new();
7803 gen_load_gpr(t0, rt);
7804 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
7805 tcg_temp_free(t0);
7807 opn = "mtc0";
7808 break;
7809 #if defined(TARGET_MIPS64)
7810 case OPC_DMFC0:
7811 check_insn(ctx, ISA_MIPS3);
7812 if (rt == 0) {
7813 /* Treat as NOP. */
7814 return;
7816 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7817 opn = "dmfc0";
7818 break;
7819 case OPC_DMTC0:
7820 check_insn(ctx, ISA_MIPS3);
7822 TCGv t0 = tcg_temp_new();
7824 gen_load_gpr(t0, rt);
7825 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
7826 tcg_temp_free(t0);
7828 opn = "dmtc0";
7829 break;
7830 #endif
7831 case OPC_MFTR:
7832 check_insn(ctx, ASE_MT);
7833 if (rd == 0) {
7834 /* Treat as NOP. */
7835 return;
7837 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
7838 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
7839 opn = "mftr";
7840 break;
7841 case OPC_MTTR:
7842 check_insn(ctx, ASE_MT);
7843 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
7844 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
7845 opn = "mttr";
7846 break;
7847 case OPC_TLBWI:
7848 opn = "tlbwi";
7849 if (!env->tlb->helper_tlbwi)
7850 goto die;
7851 gen_helper_tlbwi(cpu_env);
7852 break;
7853 case OPC_TLBINV:
7854 opn = "tlbinv";
7855 if (ctx->ie >= 2) {
7856 if (!env->tlb->helper_tlbinv) {
7857 goto die;
7859 gen_helper_tlbinv(cpu_env);
7860 } /* treat as nop if TLBINV not supported */
7861 break;
7862 case OPC_TLBINVF:
7863 opn = "tlbinvf";
7864 if (ctx->ie >= 2) {
7865 if (!env->tlb->helper_tlbinvf) {
7866 goto die;
7868 gen_helper_tlbinvf(cpu_env);
7869 } /* treat as nop if TLBINV not supported */
7870 break;
7871 case OPC_TLBWR:
7872 opn = "tlbwr";
7873 if (!env->tlb->helper_tlbwr)
7874 goto die;
7875 gen_helper_tlbwr(cpu_env);
7876 break;
7877 case OPC_TLBP:
7878 opn = "tlbp";
7879 if (!env->tlb->helper_tlbp)
7880 goto die;
7881 gen_helper_tlbp(cpu_env);
7882 break;
7883 case OPC_TLBR:
7884 opn = "tlbr";
7885 if (!env->tlb->helper_tlbr)
7886 goto die;
7887 gen_helper_tlbr(cpu_env);
7888 break;
7889 case OPC_ERET:
7890 opn = "eret";
7891 check_insn(ctx, ISA_MIPS2);
7892 if ((ctx->insn_flags & ISA_MIPS32R6) &&
7893 (ctx->hflags & MIPS_HFLAG_BMASK)) {
7894 MIPS_DEBUG("CTI in delay / forbidden slot");
7895 goto die;
7897 gen_helper_eret(cpu_env);
7898 ctx->bstate = BS_EXCP;
7899 break;
7900 case OPC_DERET:
7901 opn = "deret";
7902 check_insn(ctx, ISA_MIPS32);
7903 if ((ctx->insn_flags & ISA_MIPS32R6) &&
7904 (ctx->hflags & MIPS_HFLAG_BMASK)) {
7905 MIPS_DEBUG("CTI in delay / forbidden slot");
7906 goto die;
7908 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7909 MIPS_INVAL(opn);
7910 generate_exception(ctx, EXCP_RI);
7911 } else {
7912 gen_helper_deret(cpu_env);
7913 ctx->bstate = BS_EXCP;
7915 break;
7916 case OPC_WAIT:
7917 opn = "wait";
7918 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
7919 if ((ctx->insn_flags & ISA_MIPS32R6) &&
7920 (ctx->hflags & MIPS_HFLAG_BMASK)) {
7921 MIPS_DEBUG("CTI in delay / forbidden slot");
7922 goto die;
7924 /* If we get an exception, we want to restart at next instruction */
7925 ctx->pc += 4;
7926 save_cpu_state(ctx, 1);
7927 ctx->pc -= 4;
7928 gen_helper_wait(cpu_env);
7929 ctx->bstate = BS_EXCP;
7930 break;
7931 default:
7932 die:
7933 MIPS_INVAL(opn);
7934 generate_exception(ctx, EXCP_RI);
7935 return;
7937 (void)opn; /* avoid a compiler warning */
7938 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
7940 #endif /* !CONFIG_USER_ONLY */
7942 /* CP1 Branches (before delay slot) */
7943 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
7944 int32_t cc, int32_t offset)
7946 target_ulong btarget;
7947 const char *opn = "cp1 cond branch";
7948 TCGv_i32 t0 = tcg_temp_new_i32();
7950 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
7951 MIPS_DEBUG("CTI in delay / forbidden slot");
7952 generate_exception(ctx, EXCP_RI);
7953 goto out;
7956 if (cc != 0)
7957 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
7959 btarget = ctx->pc + 4 + offset;
7961 switch (op) {
7962 case OPC_BC1F:
7963 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7964 tcg_gen_not_i32(t0, t0);
7965 tcg_gen_andi_i32(t0, t0, 1);
7966 tcg_gen_extu_i32_tl(bcond, t0);
7967 opn = "bc1f";
7968 goto not_likely;
7969 case OPC_BC1FL:
7970 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7971 tcg_gen_not_i32(t0, t0);
7972 tcg_gen_andi_i32(t0, t0, 1);
7973 tcg_gen_extu_i32_tl(bcond, t0);
7974 opn = "bc1fl";
7975 goto likely;
7976 case OPC_BC1T:
7977 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7978 tcg_gen_andi_i32(t0, t0, 1);
7979 tcg_gen_extu_i32_tl(bcond, t0);
7980 opn = "bc1t";
7981 goto not_likely;
7982 case OPC_BC1TL:
7983 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7984 tcg_gen_andi_i32(t0, t0, 1);
7985 tcg_gen_extu_i32_tl(bcond, t0);
7986 opn = "bc1tl";
7987 likely:
7988 ctx->hflags |= MIPS_HFLAG_BL;
7989 break;
7990 case OPC_BC1FANY2:
7992 TCGv_i32 t1 = tcg_temp_new_i32();
7993 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7994 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7995 tcg_gen_nand_i32(t0, t0, t1);
7996 tcg_temp_free_i32(t1);
7997 tcg_gen_andi_i32(t0, t0, 1);
7998 tcg_gen_extu_i32_tl(bcond, t0);
8000 opn = "bc1any2f";
8001 goto not_likely;
8002 case OPC_BC1TANY2:
8004 TCGv_i32 t1 = tcg_temp_new_i32();
8005 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8006 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8007 tcg_gen_or_i32(t0, t0, t1);
8008 tcg_temp_free_i32(t1);
8009 tcg_gen_andi_i32(t0, t0, 1);
8010 tcg_gen_extu_i32_tl(bcond, t0);
8012 opn = "bc1any2t";
8013 goto not_likely;
8014 case OPC_BC1FANY4:
8016 TCGv_i32 t1 = tcg_temp_new_i32();
8017 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8018 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8019 tcg_gen_and_i32(t0, t0, t1);
8020 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8021 tcg_gen_and_i32(t0, t0, t1);
8022 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8023 tcg_gen_nand_i32(t0, t0, t1);
8024 tcg_temp_free_i32(t1);
8025 tcg_gen_andi_i32(t0, t0, 1);
8026 tcg_gen_extu_i32_tl(bcond, t0);
8028 opn = "bc1any4f";
8029 goto not_likely;
8030 case OPC_BC1TANY4:
8032 TCGv_i32 t1 = tcg_temp_new_i32();
8033 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8034 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8035 tcg_gen_or_i32(t0, t0, t1);
8036 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8037 tcg_gen_or_i32(t0, t0, t1);
8038 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8039 tcg_gen_or_i32(t0, t0, t1);
8040 tcg_temp_free_i32(t1);
8041 tcg_gen_andi_i32(t0, t0, 1);
8042 tcg_gen_extu_i32_tl(bcond, t0);
8044 opn = "bc1any4t";
8045 not_likely:
8046 ctx->hflags |= MIPS_HFLAG_BC;
8047 break;
8048 default:
8049 MIPS_INVAL(opn);
8050 generate_exception (ctx, EXCP_RI);
8051 goto out;
8053 (void)opn; /* avoid a compiler warning */
8054 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8055 ctx->hflags, btarget);
8056 ctx->btarget = btarget;
8057 ctx->hflags |= MIPS_HFLAG_BDS32;
8058 out:
8059 tcg_temp_free_i32(t0);
8062 /* R6 CP1 Branches */
8063 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8064 int32_t ft, int32_t offset)
8066 target_ulong btarget;
8067 const char *opn = "cp1 cond branch";
8068 TCGv_i64 t0 = tcg_temp_new_i64();
8070 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8071 #ifdef MIPS_DEBUG_DISAS
8072 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8073 "\n", ctx->pc);
8074 #endif
8075 generate_exception(ctx, EXCP_RI);
8076 goto out;
8079 gen_load_fpr64(ctx, t0, ft);
8080 tcg_gen_andi_i64(t0, t0, 1);
8082 btarget = addr_add(ctx, ctx->pc + 4, offset);
8084 switch (op) {
8085 case OPC_BC1EQZ:
8086 tcg_gen_xori_i64(t0, t0, 1);
8087 opn = "bc1eqz";
8088 ctx->hflags |= MIPS_HFLAG_BC;
8089 break;
8090 case OPC_BC1NEZ:
8091 /* t0 already set */
8092 opn = "bc1nez";
8093 ctx->hflags |= MIPS_HFLAG_BC;
8094 break;
8095 default:
8096 MIPS_INVAL(opn);
8097 generate_exception(ctx, EXCP_RI);
8098 goto out;
8101 tcg_gen_trunc_i64_tl(bcond, t0);
8103 (void)opn; /* avoid a compiler warning */
8104 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8105 ctx->hflags, btarget);
8106 ctx->btarget = btarget;
8107 ctx->hflags |= MIPS_HFLAG_BDS32;
8109 out:
8110 tcg_temp_free_i64(t0);
8113 /* Coprocessor 1 (FPU) */
8115 #define FOP(func, fmt) (((fmt) << 21) | (func))
8117 enum fopcode {
8118 OPC_ADD_S = FOP(0, FMT_S),
8119 OPC_SUB_S = FOP(1, FMT_S),
8120 OPC_MUL_S = FOP(2, FMT_S),
8121 OPC_DIV_S = FOP(3, FMT_S),
8122 OPC_SQRT_S = FOP(4, FMT_S),
8123 OPC_ABS_S = FOP(5, FMT_S),
8124 OPC_MOV_S = FOP(6, FMT_S),
8125 OPC_NEG_S = FOP(7, FMT_S),
8126 OPC_ROUND_L_S = FOP(8, FMT_S),
8127 OPC_TRUNC_L_S = FOP(9, FMT_S),
8128 OPC_CEIL_L_S = FOP(10, FMT_S),
8129 OPC_FLOOR_L_S = FOP(11, FMT_S),
8130 OPC_ROUND_W_S = FOP(12, FMT_S),
8131 OPC_TRUNC_W_S = FOP(13, FMT_S),
8132 OPC_CEIL_W_S = FOP(14, FMT_S),
8133 OPC_FLOOR_W_S = FOP(15, FMT_S),
8134 OPC_SEL_S = FOP(16, FMT_S),
8135 OPC_MOVCF_S = FOP(17, FMT_S),
8136 OPC_MOVZ_S = FOP(18, FMT_S),
8137 OPC_MOVN_S = FOP(19, FMT_S),
8138 OPC_SELEQZ_S = FOP(20, FMT_S),
8139 OPC_RECIP_S = FOP(21, FMT_S),
8140 OPC_RSQRT_S = FOP(22, FMT_S),
8141 OPC_SELNEZ_S = FOP(23, FMT_S),
8142 OPC_MADDF_S = FOP(24, FMT_S),
8143 OPC_MSUBF_S = FOP(25, FMT_S),
8144 OPC_RINT_S = FOP(26, FMT_S),
8145 OPC_CLASS_S = FOP(27, FMT_S),
8146 OPC_MIN_S = FOP(28, FMT_S),
8147 OPC_RECIP2_S = FOP(28, FMT_S),
8148 OPC_MINA_S = FOP(29, FMT_S),
8149 OPC_RECIP1_S = FOP(29, FMT_S),
8150 OPC_MAX_S = FOP(30, FMT_S),
8151 OPC_RSQRT1_S = FOP(30, FMT_S),
8152 OPC_MAXA_S = FOP(31, FMT_S),
8153 OPC_RSQRT2_S = FOP(31, FMT_S),
8154 OPC_CVT_D_S = FOP(33, FMT_S),
8155 OPC_CVT_W_S = FOP(36, FMT_S),
8156 OPC_CVT_L_S = FOP(37, FMT_S),
8157 OPC_CVT_PS_S = FOP(38, FMT_S),
8158 OPC_CMP_F_S = FOP (48, FMT_S),
8159 OPC_CMP_UN_S = FOP (49, FMT_S),
8160 OPC_CMP_EQ_S = FOP (50, FMT_S),
8161 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8162 OPC_CMP_OLT_S = FOP (52, FMT_S),
8163 OPC_CMP_ULT_S = FOP (53, FMT_S),
8164 OPC_CMP_OLE_S = FOP (54, FMT_S),
8165 OPC_CMP_ULE_S = FOP (55, FMT_S),
8166 OPC_CMP_SF_S = FOP (56, FMT_S),
8167 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8168 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8169 OPC_CMP_NGL_S = FOP (59, FMT_S),
8170 OPC_CMP_LT_S = FOP (60, FMT_S),
8171 OPC_CMP_NGE_S = FOP (61, FMT_S),
8172 OPC_CMP_LE_S = FOP (62, FMT_S),
8173 OPC_CMP_NGT_S = FOP (63, FMT_S),
8175 OPC_ADD_D = FOP(0, FMT_D),
8176 OPC_SUB_D = FOP(1, FMT_D),
8177 OPC_MUL_D = FOP(2, FMT_D),
8178 OPC_DIV_D = FOP(3, FMT_D),
8179 OPC_SQRT_D = FOP(4, FMT_D),
8180 OPC_ABS_D = FOP(5, FMT_D),
8181 OPC_MOV_D = FOP(6, FMT_D),
8182 OPC_NEG_D = FOP(7, FMT_D),
8183 OPC_ROUND_L_D = FOP(8, FMT_D),
8184 OPC_TRUNC_L_D = FOP(9, FMT_D),
8185 OPC_CEIL_L_D = FOP(10, FMT_D),
8186 OPC_FLOOR_L_D = FOP(11, FMT_D),
8187 OPC_ROUND_W_D = FOP(12, FMT_D),
8188 OPC_TRUNC_W_D = FOP(13, FMT_D),
8189 OPC_CEIL_W_D = FOP(14, FMT_D),
8190 OPC_FLOOR_W_D = FOP(15, FMT_D),
8191 OPC_SEL_D = FOP(16, FMT_D),
8192 OPC_MOVCF_D = FOP(17, FMT_D),
8193 OPC_MOVZ_D = FOP(18, FMT_D),
8194 OPC_MOVN_D = FOP(19, FMT_D),
8195 OPC_SELEQZ_D = FOP(20, FMT_D),
8196 OPC_RECIP_D = FOP(21, FMT_D),
8197 OPC_RSQRT_D = FOP(22, FMT_D),
8198 OPC_SELNEZ_D = FOP(23, FMT_D),
8199 OPC_MADDF_D = FOP(24, FMT_D),
8200 OPC_MSUBF_D = FOP(25, FMT_D),
8201 OPC_RINT_D = FOP(26, FMT_D),
8202 OPC_CLASS_D = FOP(27, FMT_D),
8203 OPC_MIN_D = FOP(28, FMT_D),
8204 OPC_RECIP2_D = FOP(28, FMT_D),
8205 OPC_MINA_D = FOP(29, FMT_D),
8206 OPC_RECIP1_D = FOP(29, FMT_D),
8207 OPC_MAX_D = FOP(30, FMT_D),
8208 OPC_RSQRT1_D = FOP(30, FMT_D),
8209 OPC_MAXA_D = FOP(31, FMT_D),
8210 OPC_RSQRT2_D = FOP(31, FMT_D),
8211 OPC_CVT_S_D = FOP(32, FMT_D),
8212 OPC_CVT_W_D = FOP(36, FMT_D),
8213 OPC_CVT_L_D = FOP(37, FMT_D),
8214 OPC_CMP_F_D = FOP (48, FMT_D),
8215 OPC_CMP_UN_D = FOP (49, FMT_D),
8216 OPC_CMP_EQ_D = FOP (50, FMT_D),
8217 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8218 OPC_CMP_OLT_D = FOP (52, FMT_D),
8219 OPC_CMP_ULT_D = FOP (53, FMT_D),
8220 OPC_CMP_OLE_D = FOP (54, FMT_D),
8221 OPC_CMP_ULE_D = FOP (55, FMT_D),
8222 OPC_CMP_SF_D = FOP (56, FMT_D),
8223 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8224 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8225 OPC_CMP_NGL_D = FOP (59, FMT_D),
8226 OPC_CMP_LT_D = FOP (60, FMT_D),
8227 OPC_CMP_NGE_D = FOP (61, FMT_D),
8228 OPC_CMP_LE_D = FOP (62, FMT_D),
8229 OPC_CMP_NGT_D = FOP (63, FMT_D),
8231 OPC_CVT_S_W = FOP(32, FMT_W),
8232 OPC_CVT_D_W = FOP(33, FMT_W),
8233 OPC_CVT_S_L = FOP(32, FMT_L),
8234 OPC_CVT_D_L = FOP(33, FMT_L),
8235 OPC_CVT_PS_PW = FOP(38, FMT_W),
8237 OPC_ADD_PS = FOP(0, FMT_PS),
8238 OPC_SUB_PS = FOP(1, FMT_PS),
8239 OPC_MUL_PS = FOP(2, FMT_PS),
8240 OPC_DIV_PS = FOP(3, FMT_PS),
8241 OPC_ABS_PS = FOP(5, FMT_PS),
8242 OPC_MOV_PS = FOP(6, FMT_PS),
8243 OPC_NEG_PS = FOP(7, FMT_PS),
8244 OPC_MOVCF_PS = FOP(17, FMT_PS),
8245 OPC_MOVZ_PS = FOP(18, FMT_PS),
8246 OPC_MOVN_PS = FOP(19, FMT_PS),
8247 OPC_ADDR_PS = FOP(24, FMT_PS),
8248 OPC_MULR_PS = FOP(26, FMT_PS),
8249 OPC_RECIP2_PS = FOP(28, FMT_PS),
8250 OPC_RECIP1_PS = FOP(29, FMT_PS),
8251 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8252 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8254 OPC_CVT_S_PU = FOP(32, FMT_PS),
8255 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8256 OPC_CVT_S_PL = FOP(40, FMT_PS),
8257 OPC_PLL_PS = FOP(44, FMT_PS),
8258 OPC_PLU_PS = FOP(45, FMT_PS),
8259 OPC_PUL_PS = FOP(46, FMT_PS),
8260 OPC_PUU_PS = FOP(47, FMT_PS),
8261 OPC_CMP_F_PS = FOP (48, FMT_PS),
8262 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8263 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8264 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8265 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8266 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8267 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8268 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8269 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8270 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8271 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8272 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8273 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8274 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8275 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8276 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8279 enum r6_f_cmp_op {
8280 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8281 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8282 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8283 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8284 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8285 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8286 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8287 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8288 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8289 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8290 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8291 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8292 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8293 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8294 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8295 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8296 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8297 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8298 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8299 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8300 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8301 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8303 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8304 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8305 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8306 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8307 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8308 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8309 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8310 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8311 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8312 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8313 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8314 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8315 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8316 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8317 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8318 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8319 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8320 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8321 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8322 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8323 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8324 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8326 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8328 const char *opn = "cp1 move";
8329 TCGv t0 = tcg_temp_new();
8331 switch (opc) {
8332 case OPC_MFC1:
8334 TCGv_i32 fp0 = tcg_temp_new_i32();
8336 gen_load_fpr32(fp0, fs);
8337 tcg_gen_ext_i32_tl(t0, fp0);
8338 tcg_temp_free_i32(fp0);
8340 gen_store_gpr(t0, rt);
8341 opn = "mfc1";
8342 break;
8343 case OPC_MTC1:
8344 gen_load_gpr(t0, rt);
8346 TCGv_i32 fp0 = tcg_temp_new_i32();
8348 tcg_gen_trunc_tl_i32(fp0, t0);
8349 gen_store_fpr32(fp0, fs);
8350 tcg_temp_free_i32(fp0);
8352 opn = "mtc1";
8353 break;
8354 case OPC_CFC1:
8355 gen_helper_1e0i(cfc1, t0, fs);
8356 gen_store_gpr(t0, rt);
8357 opn = "cfc1";
8358 break;
8359 case OPC_CTC1:
8360 gen_load_gpr(t0, rt);
8361 save_cpu_state(ctx, 1);
8363 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8365 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8366 tcg_temp_free_i32(fs_tmp);
8368 /* Stop translation as we may have changed hflags */
8369 ctx->bstate = BS_STOP;
8370 opn = "ctc1";
8371 break;
8372 #if defined(TARGET_MIPS64)
8373 case OPC_DMFC1:
8374 gen_load_fpr64(ctx, t0, fs);
8375 gen_store_gpr(t0, rt);
8376 opn = "dmfc1";
8377 break;
8378 case OPC_DMTC1:
8379 gen_load_gpr(t0, rt);
8380 gen_store_fpr64(ctx, t0, fs);
8381 opn = "dmtc1";
8382 break;
8383 #endif
8384 case OPC_MFHC1:
8386 TCGv_i32 fp0 = tcg_temp_new_i32();
8388 gen_load_fpr32h(ctx, fp0, fs);
8389 tcg_gen_ext_i32_tl(t0, fp0);
8390 tcg_temp_free_i32(fp0);
8392 gen_store_gpr(t0, rt);
8393 opn = "mfhc1";
8394 break;
8395 case OPC_MTHC1:
8396 gen_load_gpr(t0, rt);
8398 TCGv_i32 fp0 = tcg_temp_new_i32();
8400 tcg_gen_trunc_tl_i32(fp0, t0);
8401 gen_store_fpr32h(ctx, fp0, fs);
8402 tcg_temp_free_i32(fp0);
8404 opn = "mthc1";
8405 break;
8406 default:
8407 MIPS_INVAL(opn);
8408 generate_exception (ctx, EXCP_RI);
8409 goto out;
8411 (void)opn; /* avoid a compiler warning */
8412 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
8414 out:
8415 tcg_temp_free(t0);
8418 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8420 int l1;
8421 TCGCond cond;
8422 TCGv_i32 t0;
8424 if (rd == 0) {
8425 /* Treat as NOP. */
8426 return;
8429 if (tf)
8430 cond = TCG_COND_EQ;
8431 else
8432 cond = TCG_COND_NE;
8434 l1 = gen_new_label();
8435 t0 = tcg_temp_new_i32();
8436 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8437 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8438 tcg_temp_free_i32(t0);
8439 if (rs == 0) {
8440 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8441 } else {
8442 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8444 gen_set_label(l1);
8447 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
8449 int cond;
8450 TCGv_i32 t0 = tcg_temp_new_i32();
8451 int l1 = gen_new_label();
8453 if (tf)
8454 cond = TCG_COND_EQ;
8455 else
8456 cond = TCG_COND_NE;
8458 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8459 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8460 gen_load_fpr32(t0, fs);
8461 gen_store_fpr32(t0, fd);
8462 gen_set_label(l1);
8463 tcg_temp_free_i32(t0);
8466 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8468 int cond;
8469 TCGv_i32 t0 = tcg_temp_new_i32();
8470 TCGv_i64 fp0;
8471 int l1 = gen_new_label();
8473 if (tf)
8474 cond = TCG_COND_EQ;
8475 else
8476 cond = TCG_COND_NE;
8478 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8479 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8480 tcg_temp_free_i32(t0);
8481 fp0 = tcg_temp_new_i64();
8482 gen_load_fpr64(ctx, fp0, fs);
8483 gen_store_fpr64(ctx, fp0, fd);
8484 tcg_temp_free_i64(fp0);
8485 gen_set_label(l1);
8488 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8489 int cc, int tf)
8491 int cond;
8492 TCGv_i32 t0 = tcg_temp_new_i32();
8493 int l1 = gen_new_label();
8494 int l2 = gen_new_label();
8496 if (tf)
8497 cond = TCG_COND_EQ;
8498 else
8499 cond = TCG_COND_NE;
8501 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8502 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8503 gen_load_fpr32(t0, fs);
8504 gen_store_fpr32(t0, fd);
8505 gen_set_label(l1);
8507 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8508 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8509 gen_load_fpr32h(ctx, t0, fs);
8510 gen_store_fpr32h(ctx, t0, fd);
8511 tcg_temp_free_i32(t0);
8512 gen_set_label(l2);
8515 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8516 int fs)
8518 TCGv_i32 t1 = tcg_const_i32(0);
8519 TCGv_i32 fp0 = tcg_temp_new_i32();
8520 TCGv_i32 fp1 = tcg_temp_new_i32();
8521 TCGv_i32 fp2 = tcg_temp_new_i32();
8522 gen_load_fpr32(fp0, fd);
8523 gen_load_fpr32(fp1, ft);
8524 gen_load_fpr32(fp2, fs);
8526 switch (op1) {
8527 case OPC_SEL_S:
8528 tcg_gen_andi_i32(fp0, fp0, 1);
8529 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8530 break;
8531 case OPC_SELEQZ_S:
8532 tcg_gen_andi_i32(fp1, fp1, 1);
8533 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8534 break;
8535 case OPC_SELNEZ_S:
8536 tcg_gen_andi_i32(fp1, fp1, 1);
8537 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8538 break;
8539 default:
8540 MIPS_INVAL("gen_sel_s");
8541 generate_exception (ctx, EXCP_RI);
8542 break;
8545 gen_store_fpr32(fp0, fd);
8546 tcg_temp_free_i32(fp2);
8547 tcg_temp_free_i32(fp1);
8548 tcg_temp_free_i32(fp0);
8549 tcg_temp_free_i32(t1);
8552 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8553 int fs)
8555 TCGv_i64 t1 = tcg_const_i64(0);
8556 TCGv_i64 fp0 = tcg_temp_new_i64();
8557 TCGv_i64 fp1 = tcg_temp_new_i64();
8558 TCGv_i64 fp2 = tcg_temp_new_i64();
8559 gen_load_fpr64(ctx, fp0, fd);
8560 gen_load_fpr64(ctx, fp1, ft);
8561 gen_load_fpr64(ctx, fp2, fs);
8563 switch (op1) {
8564 case OPC_SEL_D:
8565 tcg_gen_andi_i64(fp0, fp0, 1);
8566 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8567 break;
8568 case OPC_SELEQZ_D:
8569 tcg_gen_andi_i64(fp1, fp1, 1);
8570 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8571 break;
8572 case OPC_SELNEZ_D:
8573 tcg_gen_andi_i64(fp1, fp1, 1);
8574 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8575 break;
8576 default:
8577 MIPS_INVAL("gen_sel_d");
8578 generate_exception (ctx, EXCP_RI);
8579 break;
8582 gen_store_fpr64(ctx, fp0, fd);
8583 tcg_temp_free_i64(fp2);
8584 tcg_temp_free_i64(fp1);
8585 tcg_temp_free_i64(fp0);
8586 tcg_temp_free_i64(t1);
8589 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8590 int ft, int fs, int fd, int cc)
8592 const char *opn = "farith";
8593 const char *condnames[] = {
8594 "c.f",
8595 "c.un",
8596 "c.eq",
8597 "c.ueq",
8598 "c.olt",
8599 "c.ult",
8600 "c.ole",
8601 "c.ule",
8602 "c.sf",
8603 "c.ngle",
8604 "c.seq",
8605 "c.ngl",
8606 "c.lt",
8607 "c.nge",
8608 "c.le",
8609 "c.ngt",
8611 const char *condnames_abs[] = {
8612 "cabs.f",
8613 "cabs.un",
8614 "cabs.eq",
8615 "cabs.ueq",
8616 "cabs.olt",
8617 "cabs.ult",
8618 "cabs.ole",
8619 "cabs.ule",
8620 "cabs.sf",
8621 "cabs.ngle",
8622 "cabs.seq",
8623 "cabs.ngl",
8624 "cabs.lt",
8625 "cabs.nge",
8626 "cabs.le",
8627 "cabs.ngt",
8629 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
8630 uint32_t func = ctx->opcode & 0x3f;
8632 switch (op1) {
8633 case OPC_ADD_S:
8635 TCGv_i32 fp0 = tcg_temp_new_i32();
8636 TCGv_i32 fp1 = tcg_temp_new_i32();
8638 gen_load_fpr32(fp0, fs);
8639 gen_load_fpr32(fp1, ft);
8640 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
8641 tcg_temp_free_i32(fp1);
8642 gen_store_fpr32(fp0, fd);
8643 tcg_temp_free_i32(fp0);
8645 opn = "add.s";
8646 optype = BINOP;
8647 break;
8648 case OPC_SUB_S:
8650 TCGv_i32 fp0 = tcg_temp_new_i32();
8651 TCGv_i32 fp1 = tcg_temp_new_i32();
8653 gen_load_fpr32(fp0, fs);
8654 gen_load_fpr32(fp1, ft);
8655 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
8656 tcg_temp_free_i32(fp1);
8657 gen_store_fpr32(fp0, fd);
8658 tcg_temp_free_i32(fp0);
8660 opn = "sub.s";
8661 optype = BINOP;
8662 break;
8663 case OPC_MUL_S:
8665 TCGv_i32 fp0 = tcg_temp_new_i32();
8666 TCGv_i32 fp1 = tcg_temp_new_i32();
8668 gen_load_fpr32(fp0, fs);
8669 gen_load_fpr32(fp1, ft);
8670 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
8671 tcg_temp_free_i32(fp1);
8672 gen_store_fpr32(fp0, fd);
8673 tcg_temp_free_i32(fp0);
8675 opn = "mul.s";
8676 optype = BINOP;
8677 break;
8678 case OPC_DIV_S:
8680 TCGv_i32 fp0 = tcg_temp_new_i32();
8681 TCGv_i32 fp1 = tcg_temp_new_i32();
8683 gen_load_fpr32(fp0, fs);
8684 gen_load_fpr32(fp1, ft);
8685 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
8686 tcg_temp_free_i32(fp1);
8687 gen_store_fpr32(fp0, fd);
8688 tcg_temp_free_i32(fp0);
8690 opn = "div.s";
8691 optype = BINOP;
8692 break;
8693 case OPC_SQRT_S:
8695 TCGv_i32 fp0 = tcg_temp_new_i32();
8697 gen_load_fpr32(fp0, fs);
8698 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
8699 gen_store_fpr32(fp0, fd);
8700 tcg_temp_free_i32(fp0);
8702 opn = "sqrt.s";
8703 break;
8704 case OPC_ABS_S:
8706 TCGv_i32 fp0 = tcg_temp_new_i32();
8708 gen_load_fpr32(fp0, fs);
8709 gen_helper_float_abs_s(fp0, fp0);
8710 gen_store_fpr32(fp0, fd);
8711 tcg_temp_free_i32(fp0);
8713 opn = "abs.s";
8714 break;
8715 case OPC_MOV_S:
8717 TCGv_i32 fp0 = tcg_temp_new_i32();
8719 gen_load_fpr32(fp0, fs);
8720 gen_store_fpr32(fp0, fd);
8721 tcg_temp_free_i32(fp0);
8723 opn = "mov.s";
8724 break;
8725 case OPC_NEG_S:
8727 TCGv_i32 fp0 = tcg_temp_new_i32();
8729 gen_load_fpr32(fp0, fs);
8730 gen_helper_float_chs_s(fp0, fp0);
8731 gen_store_fpr32(fp0, fd);
8732 tcg_temp_free_i32(fp0);
8734 opn = "neg.s";
8735 break;
8736 case OPC_ROUND_L_S:
8737 check_cp1_64bitmode(ctx);
8739 TCGv_i32 fp32 = tcg_temp_new_i32();
8740 TCGv_i64 fp64 = tcg_temp_new_i64();
8742 gen_load_fpr32(fp32, fs);
8743 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
8744 tcg_temp_free_i32(fp32);
8745 gen_store_fpr64(ctx, fp64, fd);
8746 tcg_temp_free_i64(fp64);
8748 opn = "round.l.s";
8749 break;
8750 case OPC_TRUNC_L_S:
8751 check_cp1_64bitmode(ctx);
8753 TCGv_i32 fp32 = tcg_temp_new_i32();
8754 TCGv_i64 fp64 = tcg_temp_new_i64();
8756 gen_load_fpr32(fp32, fs);
8757 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
8758 tcg_temp_free_i32(fp32);
8759 gen_store_fpr64(ctx, fp64, fd);
8760 tcg_temp_free_i64(fp64);
8762 opn = "trunc.l.s";
8763 break;
8764 case OPC_CEIL_L_S:
8765 check_cp1_64bitmode(ctx);
8767 TCGv_i32 fp32 = tcg_temp_new_i32();
8768 TCGv_i64 fp64 = tcg_temp_new_i64();
8770 gen_load_fpr32(fp32, fs);
8771 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
8772 tcg_temp_free_i32(fp32);
8773 gen_store_fpr64(ctx, fp64, fd);
8774 tcg_temp_free_i64(fp64);
8776 opn = "ceil.l.s";
8777 break;
8778 case OPC_FLOOR_L_S:
8779 check_cp1_64bitmode(ctx);
8781 TCGv_i32 fp32 = tcg_temp_new_i32();
8782 TCGv_i64 fp64 = tcg_temp_new_i64();
8784 gen_load_fpr32(fp32, fs);
8785 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
8786 tcg_temp_free_i32(fp32);
8787 gen_store_fpr64(ctx, fp64, fd);
8788 tcg_temp_free_i64(fp64);
8790 opn = "floor.l.s";
8791 break;
8792 case OPC_ROUND_W_S:
8794 TCGv_i32 fp0 = tcg_temp_new_i32();
8796 gen_load_fpr32(fp0, fs);
8797 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
8798 gen_store_fpr32(fp0, fd);
8799 tcg_temp_free_i32(fp0);
8801 opn = "round.w.s";
8802 break;
8803 case OPC_TRUNC_W_S:
8805 TCGv_i32 fp0 = tcg_temp_new_i32();
8807 gen_load_fpr32(fp0, fs);
8808 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
8809 gen_store_fpr32(fp0, fd);
8810 tcg_temp_free_i32(fp0);
8812 opn = "trunc.w.s";
8813 break;
8814 case OPC_CEIL_W_S:
8816 TCGv_i32 fp0 = tcg_temp_new_i32();
8818 gen_load_fpr32(fp0, fs);
8819 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
8820 gen_store_fpr32(fp0, fd);
8821 tcg_temp_free_i32(fp0);
8823 opn = "ceil.w.s";
8824 break;
8825 case OPC_FLOOR_W_S:
8827 TCGv_i32 fp0 = tcg_temp_new_i32();
8829 gen_load_fpr32(fp0, fs);
8830 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
8831 gen_store_fpr32(fp0, fd);
8832 tcg_temp_free_i32(fp0);
8834 opn = "floor.w.s";
8835 break;
8836 case OPC_SEL_S:
8837 check_insn(ctx, ISA_MIPS32R6);
8838 gen_sel_s(ctx, op1, fd, ft, fs);
8839 opn = "sel.s";
8840 break;
8841 case OPC_SELEQZ_S:
8842 check_insn(ctx, ISA_MIPS32R6);
8843 gen_sel_s(ctx, op1, fd, ft, fs);
8844 opn = "seleqz.s";
8845 break;
8846 case OPC_SELNEZ_S:
8847 check_insn(ctx, ISA_MIPS32R6);
8848 gen_sel_s(ctx, op1, fd, ft, fs);
8849 opn = "selnez.s";
8850 break;
8851 case OPC_MOVCF_S:
8852 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8853 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
8854 opn = "movcf.s";
8855 break;
8856 case OPC_MOVZ_S:
8857 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8859 int l1 = gen_new_label();
8860 TCGv_i32 fp0;
8862 if (ft != 0) {
8863 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8865 fp0 = tcg_temp_new_i32();
8866 gen_load_fpr32(fp0, fs);
8867 gen_store_fpr32(fp0, fd);
8868 tcg_temp_free_i32(fp0);
8869 gen_set_label(l1);
8871 opn = "movz.s";
8872 break;
8873 case OPC_MOVN_S:
8874 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8876 int l1 = gen_new_label();
8877 TCGv_i32 fp0;
8879 if (ft != 0) {
8880 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8881 fp0 = tcg_temp_new_i32();
8882 gen_load_fpr32(fp0, fs);
8883 gen_store_fpr32(fp0, fd);
8884 tcg_temp_free_i32(fp0);
8885 gen_set_label(l1);
8888 opn = "movn.s";
8889 break;
8890 case OPC_RECIP_S:
8891 check_cop1x(ctx);
8893 TCGv_i32 fp0 = tcg_temp_new_i32();
8895 gen_load_fpr32(fp0, fs);
8896 gen_helper_float_recip_s(fp0, cpu_env, fp0);
8897 gen_store_fpr32(fp0, fd);
8898 tcg_temp_free_i32(fp0);
8900 opn = "recip.s";
8901 break;
8902 case OPC_RSQRT_S:
8903 check_cop1x(ctx);
8905 TCGv_i32 fp0 = tcg_temp_new_i32();
8907 gen_load_fpr32(fp0, fs);
8908 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
8909 gen_store_fpr32(fp0, fd);
8910 tcg_temp_free_i32(fp0);
8912 opn = "rsqrt.s";
8913 break;
8914 case OPC_MADDF_S:
8915 check_insn(ctx, ISA_MIPS32R6);
8917 TCGv_i32 fp0 = tcg_temp_new_i32();
8918 TCGv_i32 fp1 = tcg_temp_new_i32();
8919 TCGv_i32 fp2 = tcg_temp_new_i32();
8920 gen_load_fpr32(fp0, fs);
8921 gen_load_fpr32(fp1, ft);
8922 gen_load_fpr32(fp2, fd);
8923 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
8924 gen_store_fpr32(fp2, fd);
8925 tcg_temp_free_i32(fp2);
8926 tcg_temp_free_i32(fp1);
8927 tcg_temp_free_i32(fp0);
8928 opn = "maddf.s";
8930 break;
8931 case OPC_MSUBF_S:
8932 check_insn(ctx, ISA_MIPS32R6);
8934 TCGv_i32 fp0 = tcg_temp_new_i32();
8935 TCGv_i32 fp1 = tcg_temp_new_i32();
8936 TCGv_i32 fp2 = tcg_temp_new_i32();
8937 gen_load_fpr32(fp0, fs);
8938 gen_load_fpr32(fp1, ft);
8939 gen_load_fpr32(fp2, fd);
8940 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
8941 gen_store_fpr32(fp2, fd);
8942 tcg_temp_free_i32(fp2);
8943 tcg_temp_free_i32(fp1);
8944 tcg_temp_free_i32(fp0);
8945 opn = "msubf.s";
8947 break;
8948 case OPC_RINT_S:
8949 check_insn(ctx, ISA_MIPS32R6);
8951 TCGv_i32 fp0 = tcg_temp_new_i32();
8952 gen_load_fpr32(fp0, fs);
8953 gen_helper_float_rint_s(fp0, cpu_env, fp0);
8954 gen_store_fpr32(fp0, fd);
8955 tcg_temp_free_i32(fp0);
8956 opn = "rint.s";
8958 break;
8959 case OPC_CLASS_S:
8960 check_insn(ctx, ISA_MIPS32R6);
8962 TCGv_i32 fp0 = tcg_temp_new_i32();
8963 gen_load_fpr32(fp0, fs);
8964 gen_helper_float_class_s(fp0, fp0);
8965 gen_store_fpr32(fp0, fd);
8966 tcg_temp_free_i32(fp0);
8967 opn = "class.s";
8969 break;
8970 case OPC_MIN_S: /* OPC_RECIP2_S */
8971 if (ctx->insn_flags & ISA_MIPS32R6) {
8972 /* OPC_MIN_S */
8973 TCGv_i32 fp0 = tcg_temp_new_i32();
8974 TCGv_i32 fp1 = tcg_temp_new_i32();
8975 TCGv_i32 fp2 = tcg_temp_new_i32();
8976 gen_load_fpr32(fp0, fs);
8977 gen_load_fpr32(fp1, ft);
8978 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
8979 gen_store_fpr32(fp2, fd);
8980 tcg_temp_free_i32(fp2);
8981 tcg_temp_free_i32(fp1);
8982 tcg_temp_free_i32(fp0);
8983 opn = "min.s";
8984 } else {
8985 /* OPC_RECIP2_S */
8986 check_cp1_64bitmode(ctx);
8988 TCGv_i32 fp0 = tcg_temp_new_i32();
8989 TCGv_i32 fp1 = tcg_temp_new_i32();
8991 gen_load_fpr32(fp0, fs);
8992 gen_load_fpr32(fp1, ft);
8993 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
8994 tcg_temp_free_i32(fp1);
8995 gen_store_fpr32(fp0, fd);
8996 tcg_temp_free_i32(fp0);
8998 opn = "recip2.s";
9000 break;
9001 case OPC_MINA_S: /* OPC_RECIP1_S */
9002 if (ctx->insn_flags & ISA_MIPS32R6) {
9003 /* OPC_MINA_S */
9004 TCGv_i32 fp0 = tcg_temp_new_i32();
9005 TCGv_i32 fp1 = tcg_temp_new_i32();
9006 TCGv_i32 fp2 = tcg_temp_new_i32();
9007 gen_load_fpr32(fp0, fs);
9008 gen_load_fpr32(fp1, ft);
9009 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9010 gen_store_fpr32(fp2, fd);
9011 tcg_temp_free_i32(fp2);
9012 tcg_temp_free_i32(fp1);
9013 tcg_temp_free_i32(fp0);
9014 opn = "mina.s";
9015 } else {
9016 /* OPC_RECIP1_S */
9017 check_cp1_64bitmode(ctx);
9019 TCGv_i32 fp0 = tcg_temp_new_i32();
9021 gen_load_fpr32(fp0, fs);
9022 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9023 gen_store_fpr32(fp0, fd);
9024 tcg_temp_free_i32(fp0);
9026 opn = "recip1.s";
9028 break;
9029 case OPC_MAX_S: /* OPC_RSQRT1_S */
9030 if (ctx->insn_flags & ISA_MIPS32R6) {
9031 /* OPC_MAX_S */
9032 TCGv_i32 fp0 = tcg_temp_new_i32();
9033 TCGv_i32 fp1 = tcg_temp_new_i32();
9034 gen_load_fpr32(fp0, fs);
9035 gen_load_fpr32(fp1, ft);
9036 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9037 gen_store_fpr32(fp1, fd);
9038 tcg_temp_free_i32(fp1);
9039 tcg_temp_free_i32(fp0);
9040 opn = "max.s";
9041 } else {
9042 /* OPC_RSQRT1_S */
9043 check_cp1_64bitmode(ctx);
9045 TCGv_i32 fp0 = tcg_temp_new_i32();
9047 gen_load_fpr32(fp0, fs);
9048 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9049 gen_store_fpr32(fp0, fd);
9050 tcg_temp_free_i32(fp0);
9052 opn = "rsqrt1.s";
9054 break;
9055 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9056 if (ctx->insn_flags & ISA_MIPS32R6) {
9057 /* OPC_MAXA_S */
9058 TCGv_i32 fp0 = tcg_temp_new_i32();
9059 TCGv_i32 fp1 = tcg_temp_new_i32();
9060 gen_load_fpr32(fp0, fs);
9061 gen_load_fpr32(fp1, ft);
9062 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9063 gen_store_fpr32(fp1, fd);
9064 tcg_temp_free_i32(fp1);
9065 tcg_temp_free_i32(fp0);
9066 opn = "maxa.s";
9067 } else {
9068 /* OPC_RSQRT2_S */
9069 check_cp1_64bitmode(ctx);
9071 TCGv_i32 fp0 = tcg_temp_new_i32();
9072 TCGv_i32 fp1 = tcg_temp_new_i32();
9074 gen_load_fpr32(fp0, fs);
9075 gen_load_fpr32(fp1, ft);
9076 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9077 tcg_temp_free_i32(fp1);
9078 gen_store_fpr32(fp0, fd);
9079 tcg_temp_free_i32(fp0);
9081 opn = "rsqrt2.s";
9083 break;
9084 case OPC_CVT_D_S:
9085 check_cp1_registers(ctx, fd);
9087 TCGv_i32 fp32 = tcg_temp_new_i32();
9088 TCGv_i64 fp64 = tcg_temp_new_i64();
9090 gen_load_fpr32(fp32, fs);
9091 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9092 tcg_temp_free_i32(fp32);
9093 gen_store_fpr64(ctx, fp64, fd);
9094 tcg_temp_free_i64(fp64);
9096 opn = "cvt.d.s";
9097 break;
9098 case OPC_CVT_W_S:
9100 TCGv_i32 fp0 = tcg_temp_new_i32();
9102 gen_load_fpr32(fp0, fs);
9103 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
9104 gen_store_fpr32(fp0, fd);
9105 tcg_temp_free_i32(fp0);
9107 opn = "cvt.w.s";
9108 break;
9109 case OPC_CVT_L_S:
9110 check_cp1_64bitmode(ctx);
9112 TCGv_i32 fp32 = tcg_temp_new_i32();
9113 TCGv_i64 fp64 = tcg_temp_new_i64();
9115 gen_load_fpr32(fp32, fs);
9116 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
9117 tcg_temp_free_i32(fp32);
9118 gen_store_fpr64(ctx, fp64, fd);
9119 tcg_temp_free_i64(fp64);
9121 opn = "cvt.l.s";
9122 break;
9123 case OPC_CVT_PS_S:
9124 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9125 check_cp1_64bitmode(ctx);
9127 TCGv_i64 fp64 = tcg_temp_new_i64();
9128 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9129 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9131 gen_load_fpr32(fp32_0, fs);
9132 gen_load_fpr32(fp32_1, ft);
9133 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9134 tcg_temp_free_i32(fp32_1);
9135 tcg_temp_free_i32(fp32_0);
9136 gen_store_fpr64(ctx, fp64, fd);
9137 tcg_temp_free_i64(fp64);
9139 opn = "cvt.ps.s";
9140 break;
9141 case OPC_CMP_F_S:
9142 case OPC_CMP_UN_S:
9143 case OPC_CMP_EQ_S:
9144 case OPC_CMP_UEQ_S:
9145 case OPC_CMP_OLT_S:
9146 case OPC_CMP_ULT_S:
9147 case OPC_CMP_OLE_S:
9148 case OPC_CMP_ULE_S:
9149 case OPC_CMP_SF_S:
9150 case OPC_CMP_NGLE_S:
9151 case OPC_CMP_SEQ_S:
9152 case OPC_CMP_NGL_S:
9153 case OPC_CMP_LT_S:
9154 case OPC_CMP_NGE_S:
9155 case OPC_CMP_LE_S:
9156 case OPC_CMP_NGT_S:
9157 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9158 if (ctx->opcode & (1 << 6)) {
9159 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9160 opn = condnames_abs[func-48];
9161 } else {
9162 gen_cmp_s(ctx, func-48, ft, fs, cc);
9163 opn = condnames[func-48];
9165 break;
9166 case OPC_ADD_D:
9167 check_cp1_registers(ctx, fs | ft | fd);
9169 TCGv_i64 fp0 = tcg_temp_new_i64();
9170 TCGv_i64 fp1 = tcg_temp_new_i64();
9172 gen_load_fpr64(ctx, fp0, fs);
9173 gen_load_fpr64(ctx, fp1, ft);
9174 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9175 tcg_temp_free_i64(fp1);
9176 gen_store_fpr64(ctx, fp0, fd);
9177 tcg_temp_free_i64(fp0);
9179 opn = "add.d";
9180 optype = BINOP;
9181 break;
9182 case OPC_SUB_D:
9183 check_cp1_registers(ctx, fs | ft | fd);
9185 TCGv_i64 fp0 = tcg_temp_new_i64();
9186 TCGv_i64 fp1 = tcg_temp_new_i64();
9188 gen_load_fpr64(ctx, fp0, fs);
9189 gen_load_fpr64(ctx, fp1, ft);
9190 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9191 tcg_temp_free_i64(fp1);
9192 gen_store_fpr64(ctx, fp0, fd);
9193 tcg_temp_free_i64(fp0);
9195 opn = "sub.d";
9196 optype = BINOP;
9197 break;
9198 case OPC_MUL_D:
9199 check_cp1_registers(ctx, fs | ft | fd);
9201 TCGv_i64 fp0 = tcg_temp_new_i64();
9202 TCGv_i64 fp1 = tcg_temp_new_i64();
9204 gen_load_fpr64(ctx, fp0, fs);
9205 gen_load_fpr64(ctx, fp1, ft);
9206 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9207 tcg_temp_free_i64(fp1);
9208 gen_store_fpr64(ctx, fp0, fd);
9209 tcg_temp_free_i64(fp0);
9211 opn = "mul.d";
9212 optype = BINOP;
9213 break;
9214 case OPC_DIV_D:
9215 check_cp1_registers(ctx, fs | ft | fd);
9217 TCGv_i64 fp0 = tcg_temp_new_i64();
9218 TCGv_i64 fp1 = tcg_temp_new_i64();
9220 gen_load_fpr64(ctx, fp0, fs);
9221 gen_load_fpr64(ctx, fp1, ft);
9222 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9223 tcg_temp_free_i64(fp1);
9224 gen_store_fpr64(ctx, fp0, fd);
9225 tcg_temp_free_i64(fp0);
9227 opn = "div.d";
9228 optype = BINOP;
9229 break;
9230 case OPC_SQRT_D:
9231 check_cp1_registers(ctx, fs | fd);
9233 TCGv_i64 fp0 = tcg_temp_new_i64();
9235 gen_load_fpr64(ctx, fp0, fs);
9236 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9237 gen_store_fpr64(ctx, fp0, fd);
9238 tcg_temp_free_i64(fp0);
9240 opn = "sqrt.d";
9241 break;
9242 case OPC_ABS_D:
9243 check_cp1_registers(ctx, fs | fd);
9245 TCGv_i64 fp0 = tcg_temp_new_i64();
9247 gen_load_fpr64(ctx, fp0, fs);
9248 gen_helper_float_abs_d(fp0, fp0);
9249 gen_store_fpr64(ctx, fp0, fd);
9250 tcg_temp_free_i64(fp0);
9252 opn = "abs.d";
9253 break;
9254 case OPC_MOV_D:
9255 check_cp1_registers(ctx, fs | fd);
9257 TCGv_i64 fp0 = tcg_temp_new_i64();
9259 gen_load_fpr64(ctx, fp0, fs);
9260 gen_store_fpr64(ctx, fp0, fd);
9261 tcg_temp_free_i64(fp0);
9263 opn = "mov.d";
9264 break;
9265 case OPC_NEG_D:
9266 check_cp1_registers(ctx, fs | fd);
9268 TCGv_i64 fp0 = tcg_temp_new_i64();
9270 gen_load_fpr64(ctx, fp0, fs);
9271 gen_helper_float_chs_d(fp0, fp0);
9272 gen_store_fpr64(ctx, fp0, fd);
9273 tcg_temp_free_i64(fp0);
9275 opn = "neg.d";
9276 break;
9277 case OPC_ROUND_L_D:
9278 check_cp1_64bitmode(ctx);
9280 TCGv_i64 fp0 = tcg_temp_new_i64();
9282 gen_load_fpr64(ctx, fp0, fs);
9283 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
9284 gen_store_fpr64(ctx, fp0, fd);
9285 tcg_temp_free_i64(fp0);
9287 opn = "round.l.d";
9288 break;
9289 case OPC_TRUNC_L_D:
9290 check_cp1_64bitmode(ctx);
9292 TCGv_i64 fp0 = tcg_temp_new_i64();
9294 gen_load_fpr64(ctx, fp0, fs);
9295 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
9296 gen_store_fpr64(ctx, fp0, fd);
9297 tcg_temp_free_i64(fp0);
9299 opn = "trunc.l.d";
9300 break;
9301 case OPC_CEIL_L_D:
9302 check_cp1_64bitmode(ctx);
9304 TCGv_i64 fp0 = tcg_temp_new_i64();
9306 gen_load_fpr64(ctx, fp0, fs);
9307 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
9308 gen_store_fpr64(ctx, fp0, fd);
9309 tcg_temp_free_i64(fp0);
9311 opn = "ceil.l.d";
9312 break;
9313 case OPC_FLOOR_L_D:
9314 check_cp1_64bitmode(ctx);
9316 TCGv_i64 fp0 = tcg_temp_new_i64();
9318 gen_load_fpr64(ctx, fp0, fs);
9319 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
9320 gen_store_fpr64(ctx, fp0, fd);
9321 tcg_temp_free_i64(fp0);
9323 opn = "floor.l.d";
9324 break;
9325 case OPC_ROUND_W_D:
9326 check_cp1_registers(ctx, fs);
9328 TCGv_i32 fp32 = tcg_temp_new_i32();
9329 TCGv_i64 fp64 = tcg_temp_new_i64();
9331 gen_load_fpr64(ctx, fp64, fs);
9332 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
9333 tcg_temp_free_i64(fp64);
9334 gen_store_fpr32(fp32, fd);
9335 tcg_temp_free_i32(fp32);
9337 opn = "round.w.d";
9338 break;
9339 case OPC_TRUNC_W_D:
9340 check_cp1_registers(ctx, fs);
9342 TCGv_i32 fp32 = tcg_temp_new_i32();
9343 TCGv_i64 fp64 = tcg_temp_new_i64();
9345 gen_load_fpr64(ctx, fp64, fs);
9346 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
9347 tcg_temp_free_i64(fp64);
9348 gen_store_fpr32(fp32, fd);
9349 tcg_temp_free_i32(fp32);
9351 opn = "trunc.w.d";
9352 break;
9353 case OPC_CEIL_W_D:
9354 check_cp1_registers(ctx, fs);
9356 TCGv_i32 fp32 = tcg_temp_new_i32();
9357 TCGv_i64 fp64 = tcg_temp_new_i64();
9359 gen_load_fpr64(ctx, fp64, fs);
9360 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
9361 tcg_temp_free_i64(fp64);
9362 gen_store_fpr32(fp32, fd);
9363 tcg_temp_free_i32(fp32);
9365 opn = "ceil.w.d";
9366 break;
9367 case OPC_FLOOR_W_D:
9368 check_cp1_registers(ctx, fs);
9370 TCGv_i32 fp32 = tcg_temp_new_i32();
9371 TCGv_i64 fp64 = tcg_temp_new_i64();
9373 gen_load_fpr64(ctx, fp64, fs);
9374 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
9375 tcg_temp_free_i64(fp64);
9376 gen_store_fpr32(fp32, fd);
9377 tcg_temp_free_i32(fp32);
9379 opn = "floor.w.d";
9380 break;
9381 case OPC_SEL_D:
9382 check_insn(ctx, ISA_MIPS32R6);
9383 gen_sel_d(ctx, op1, fd, ft, fs);
9384 opn = "sel.d";
9385 break;
9386 case OPC_SELEQZ_D:
9387 check_insn(ctx, ISA_MIPS32R6);
9388 gen_sel_d(ctx, op1, fd, ft, fs);
9389 opn = "seleqz.d";
9390 break;
9391 case OPC_SELNEZ_D:
9392 check_insn(ctx, ISA_MIPS32R6);
9393 gen_sel_d(ctx, op1, fd, ft, fs);
9394 opn = "selnez.d";
9395 break;
9396 case OPC_MOVCF_D:
9397 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9398 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9399 opn = "movcf.d";
9400 break;
9401 case OPC_MOVZ_D:
9402 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9404 int l1 = gen_new_label();
9405 TCGv_i64 fp0;
9407 if (ft != 0) {
9408 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9410 fp0 = tcg_temp_new_i64();
9411 gen_load_fpr64(ctx, fp0, fs);
9412 gen_store_fpr64(ctx, fp0, fd);
9413 tcg_temp_free_i64(fp0);
9414 gen_set_label(l1);
9416 opn = "movz.d";
9417 break;
9418 case OPC_MOVN_D:
9419 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9421 int l1 = gen_new_label();
9422 TCGv_i64 fp0;
9424 if (ft != 0) {
9425 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9426 fp0 = tcg_temp_new_i64();
9427 gen_load_fpr64(ctx, fp0, fs);
9428 gen_store_fpr64(ctx, fp0, fd);
9429 tcg_temp_free_i64(fp0);
9430 gen_set_label(l1);
9433 opn = "movn.d";
9434 break;
9435 case OPC_RECIP_D:
9436 check_cp1_64bitmode(ctx);
9438 TCGv_i64 fp0 = tcg_temp_new_i64();
9440 gen_load_fpr64(ctx, fp0, fs);
9441 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9442 gen_store_fpr64(ctx, fp0, fd);
9443 tcg_temp_free_i64(fp0);
9445 opn = "recip.d";
9446 break;
9447 case OPC_RSQRT_D:
9448 check_cp1_64bitmode(ctx);
9450 TCGv_i64 fp0 = tcg_temp_new_i64();
9452 gen_load_fpr64(ctx, fp0, fs);
9453 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9454 gen_store_fpr64(ctx, fp0, fd);
9455 tcg_temp_free_i64(fp0);
9457 opn = "rsqrt.d";
9458 break;
9459 case OPC_MADDF_D:
9460 check_insn(ctx, ISA_MIPS32R6);
9462 TCGv_i64 fp0 = tcg_temp_new_i64();
9463 TCGv_i64 fp1 = tcg_temp_new_i64();
9464 TCGv_i64 fp2 = tcg_temp_new_i64();
9465 gen_load_fpr64(ctx, fp0, fs);
9466 gen_load_fpr64(ctx, fp1, ft);
9467 gen_load_fpr64(ctx, fp2, fd);
9468 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9469 gen_store_fpr64(ctx, fp2, fd);
9470 tcg_temp_free_i64(fp2);
9471 tcg_temp_free_i64(fp1);
9472 tcg_temp_free_i64(fp0);
9473 opn = "maddf.d";
9475 break;
9476 case OPC_MSUBF_D:
9477 check_insn(ctx, ISA_MIPS32R6);
9479 TCGv_i64 fp0 = tcg_temp_new_i64();
9480 TCGv_i64 fp1 = tcg_temp_new_i64();
9481 TCGv_i64 fp2 = tcg_temp_new_i64();
9482 gen_load_fpr64(ctx, fp0, fs);
9483 gen_load_fpr64(ctx, fp1, ft);
9484 gen_load_fpr64(ctx, fp2, fd);
9485 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9486 gen_store_fpr64(ctx, fp2, fd);
9487 tcg_temp_free_i64(fp2);
9488 tcg_temp_free_i64(fp1);
9489 tcg_temp_free_i64(fp0);
9490 opn = "msubf.d";
9492 break;
9493 case OPC_RINT_D:
9494 check_insn(ctx, ISA_MIPS32R6);
9496 TCGv_i64 fp0 = tcg_temp_new_i64();
9497 gen_load_fpr64(ctx, fp0, fs);
9498 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9499 gen_store_fpr64(ctx, fp0, fd);
9500 tcg_temp_free_i64(fp0);
9501 opn = "rint.d";
9503 break;
9504 case OPC_CLASS_D:
9505 check_insn(ctx, ISA_MIPS32R6);
9507 TCGv_i64 fp0 = tcg_temp_new_i64();
9508 gen_load_fpr64(ctx, fp0, fs);
9509 gen_helper_float_class_d(fp0, fp0);
9510 gen_store_fpr64(ctx, fp0, fd);
9511 tcg_temp_free_i64(fp0);
9512 opn = "class.d";
9514 break;
9515 case OPC_MIN_D: /* OPC_RECIP2_D */
9516 if (ctx->insn_flags & ISA_MIPS32R6) {
9517 /* OPC_MIN_D */
9518 TCGv_i64 fp0 = tcg_temp_new_i64();
9519 TCGv_i64 fp1 = tcg_temp_new_i64();
9520 gen_load_fpr64(ctx, fp0, fs);
9521 gen_load_fpr64(ctx, fp1, ft);
9522 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9523 gen_store_fpr64(ctx, fp1, fd);
9524 tcg_temp_free_i64(fp1);
9525 tcg_temp_free_i64(fp0);
9526 opn = "min.d";
9527 } else {
9528 /* OPC_RECIP2_D */
9529 check_cp1_64bitmode(ctx);
9531 TCGv_i64 fp0 = tcg_temp_new_i64();
9532 TCGv_i64 fp1 = tcg_temp_new_i64();
9534 gen_load_fpr64(ctx, fp0, fs);
9535 gen_load_fpr64(ctx, fp1, ft);
9536 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9537 tcg_temp_free_i64(fp1);
9538 gen_store_fpr64(ctx, fp0, fd);
9539 tcg_temp_free_i64(fp0);
9541 opn = "recip2.d";
9543 break;
9544 case OPC_MINA_D: /* OPC_RECIP1_D */
9545 if (ctx->insn_flags & ISA_MIPS32R6) {
9546 /* OPC_MINA_D */
9547 TCGv_i64 fp0 = tcg_temp_new_i64();
9548 TCGv_i64 fp1 = tcg_temp_new_i64();
9549 gen_load_fpr64(ctx, fp0, fs);
9550 gen_load_fpr64(ctx, fp1, ft);
9551 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9552 gen_store_fpr64(ctx, fp1, fd);
9553 tcg_temp_free_i64(fp1);
9554 tcg_temp_free_i64(fp0);
9555 opn = "mina.d";
9556 } else {
9557 /* OPC_RECIP1_D */
9558 check_cp1_64bitmode(ctx);
9560 TCGv_i64 fp0 = tcg_temp_new_i64();
9562 gen_load_fpr64(ctx, fp0, fs);
9563 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9564 gen_store_fpr64(ctx, fp0, fd);
9565 tcg_temp_free_i64(fp0);
9567 opn = "recip1.d";
9569 break;
9570 case OPC_MAX_D: /* OPC_RSQRT1_D */
9571 if (ctx->insn_flags & ISA_MIPS32R6) {
9572 /* OPC_MAX_D */
9573 TCGv_i64 fp0 = tcg_temp_new_i64();
9574 TCGv_i64 fp1 = tcg_temp_new_i64();
9575 gen_load_fpr64(ctx, fp0, fs);
9576 gen_load_fpr64(ctx, fp1, ft);
9577 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9578 gen_store_fpr64(ctx, fp1, fd);
9579 tcg_temp_free_i64(fp1);
9580 tcg_temp_free_i64(fp0);
9581 opn = "max.d";
9582 } else {
9583 /* OPC_RSQRT1_D */
9584 check_cp1_64bitmode(ctx);
9586 TCGv_i64 fp0 = tcg_temp_new_i64();
9588 gen_load_fpr64(ctx, fp0, fs);
9589 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9590 gen_store_fpr64(ctx, fp0, fd);
9591 tcg_temp_free_i64(fp0);
9593 opn = "rsqrt1.d";
9595 break;
9596 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9597 if (ctx->insn_flags & ISA_MIPS32R6) {
9598 /* OPC_MAXA_D */
9599 TCGv_i64 fp0 = tcg_temp_new_i64();
9600 TCGv_i64 fp1 = tcg_temp_new_i64();
9601 gen_load_fpr64(ctx, fp0, fs);
9602 gen_load_fpr64(ctx, fp1, ft);
9603 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9604 gen_store_fpr64(ctx, fp1, fd);
9605 tcg_temp_free_i64(fp1);
9606 tcg_temp_free_i64(fp0);
9607 opn = "maxa.d";
9608 } else {
9609 /* OPC_RSQRT2_D */
9610 check_cp1_64bitmode(ctx);
9612 TCGv_i64 fp0 = tcg_temp_new_i64();
9613 TCGv_i64 fp1 = tcg_temp_new_i64();
9615 gen_load_fpr64(ctx, fp0, fs);
9616 gen_load_fpr64(ctx, fp1, ft);
9617 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9618 tcg_temp_free_i64(fp1);
9619 gen_store_fpr64(ctx, fp0, fd);
9620 tcg_temp_free_i64(fp0);
9622 opn = "rsqrt2.d";
9624 break;
9625 case OPC_CMP_F_D:
9626 case OPC_CMP_UN_D:
9627 case OPC_CMP_EQ_D:
9628 case OPC_CMP_UEQ_D:
9629 case OPC_CMP_OLT_D:
9630 case OPC_CMP_ULT_D:
9631 case OPC_CMP_OLE_D:
9632 case OPC_CMP_ULE_D:
9633 case OPC_CMP_SF_D:
9634 case OPC_CMP_NGLE_D:
9635 case OPC_CMP_SEQ_D:
9636 case OPC_CMP_NGL_D:
9637 case OPC_CMP_LT_D:
9638 case OPC_CMP_NGE_D:
9639 case OPC_CMP_LE_D:
9640 case OPC_CMP_NGT_D:
9641 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9642 if (ctx->opcode & (1 << 6)) {
9643 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9644 opn = condnames_abs[func-48];
9645 } else {
9646 gen_cmp_d(ctx, func-48, ft, fs, cc);
9647 opn = condnames[func-48];
9649 break;
9650 case OPC_CVT_S_D:
9651 check_cp1_registers(ctx, fs);
9653 TCGv_i32 fp32 = tcg_temp_new_i32();
9654 TCGv_i64 fp64 = tcg_temp_new_i64();
9656 gen_load_fpr64(ctx, fp64, fs);
9657 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
9658 tcg_temp_free_i64(fp64);
9659 gen_store_fpr32(fp32, fd);
9660 tcg_temp_free_i32(fp32);
9662 opn = "cvt.s.d";
9663 break;
9664 case OPC_CVT_W_D:
9665 check_cp1_registers(ctx, fs);
9667 TCGv_i32 fp32 = tcg_temp_new_i32();
9668 TCGv_i64 fp64 = tcg_temp_new_i64();
9670 gen_load_fpr64(ctx, fp64, fs);
9671 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
9672 tcg_temp_free_i64(fp64);
9673 gen_store_fpr32(fp32, fd);
9674 tcg_temp_free_i32(fp32);
9676 opn = "cvt.w.d";
9677 break;
9678 case OPC_CVT_L_D:
9679 check_cp1_64bitmode(ctx);
9681 TCGv_i64 fp0 = tcg_temp_new_i64();
9683 gen_load_fpr64(ctx, fp0, fs);
9684 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
9685 gen_store_fpr64(ctx, fp0, fd);
9686 tcg_temp_free_i64(fp0);
9688 opn = "cvt.l.d";
9689 break;
9690 case OPC_CVT_S_W:
9692 TCGv_i32 fp0 = tcg_temp_new_i32();
9694 gen_load_fpr32(fp0, fs);
9695 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
9696 gen_store_fpr32(fp0, fd);
9697 tcg_temp_free_i32(fp0);
9699 opn = "cvt.s.w";
9700 break;
9701 case OPC_CVT_D_W:
9702 check_cp1_registers(ctx, fd);
9704 TCGv_i32 fp32 = tcg_temp_new_i32();
9705 TCGv_i64 fp64 = tcg_temp_new_i64();
9707 gen_load_fpr32(fp32, fs);
9708 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
9709 tcg_temp_free_i32(fp32);
9710 gen_store_fpr64(ctx, fp64, fd);
9711 tcg_temp_free_i64(fp64);
9713 opn = "cvt.d.w";
9714 break;
9715 case OPC_CVT_S_L:
9716 check_cp1_64bitmode(ctx);
9718 TCGv_i32 fp32 = tcg_temp_new_i32();
9719 TCGv_i64 fp64 = tcg_temp_new_i64();
9721 gen_load_fpr64(ctx, fp64, fs);
9722 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
9723 tcg_temp_free_i64(fp64);
9724 gen_store_fpr32(fp32, fd);
9725 tcg_temp_free_i32(fp32);
9727 opn = "cvt.s.l";
9728 break;
9729 case OPC_CVT_D_L:
9730 check_cp1_64bitmode(ctx);
9732 TCGv_i64 fp0 = tcg_temp_new_i64();
9734 gen_load_fpr64(ctx, fp0, fs);
9735 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
9736 gen_store_fpr64(ctx, fp0, fd);
9737 tcg_temp_free_i64(fp0);
9739 opn = "cvt.d.l";
9740 break;
9741 case OPC_CVT_PS_PW:
9742 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9743 check_cp1_64bitmode(ctx);
9745 TCGv_i64 fp0 = tcg_temp_new_i64();
9747 gen_load_fpr64(ctx, fp0, fs);
9748 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
9749 gen_store_fpr64(ctx, fp0, fd);
9750 tcg_temp_free_i64(fp0);
9752 opn = "cvt.ps.pw";
9753 break;
9754 case OPC_ADD_PS:
9755 check_cp1_64bitmode(ctx);
9757 TCGv_i64 fp0 = tcg_temp_new_i64();
9758 TCGv_i64 fp1 = tcg_temp_new_i64();
9760 gen_load_fpr64(ctx, fp0, fs);
9761 gen_load_fpr64(ctx, fp1, ft);
9762 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
9763 tcg_temp_free_i64(fp1);
9764 gen_store_fpr64(ctx, fp0, fd);
9765 tcg_temp_free_i64(fp0);
9767 opn = "add.ps";
9768 break;
9769 case OPC_SUB_PS:
9770 check_cp1_64bitmode(ctx);
9772 TCGv_i64 fp0 = tcg_temp_new_i64();
9773 TCGv_i64 fp1 = tcg_temp_new_i64();
9775 gen_load_fpr64(ctx, fp0, fs);
9776 gen_load_fpr64(ctx, fp1, ft);
9777 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
9778 tcg_temp_free_i64(fp1);
9779 gen_store_fpr64(ctx, fp0, fd);
9780 tcg_temp_free_i64(fp0);
9782 opn = "sub.ps";
9783 break;
9784 case OPC_MUL_PS:
9785 check_cp1_64bitmode(ctx);
9787 TCGv_i64 fp0 = tcg_temp_new_i64();
9788 TCGv_i64 fp1 = tcg_temp_new_i64();
9790 gen_load_fpr64(ctx, fp0, fs);
9791 gen_load_fpr64(ctx, fp1, ft);
9792 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
9793 tcg_temp_free_i64(fp1);
9794 gen_store_fpr64(ctx, fp0, fd);
9795 tcg_temp_free_i64(fp0);
9797 opn = "mul.ps";
9798 break;
9799 case OPC_ABS_PS:
9800 check_cp1_64bitmode(ctx);
9802 TCGv_i64 fp0 = tcg_temp_new_i64();
9804 gen_load_fpr64(ctx, fp0, fs);
9805 gen_helper_float_abs_ps(fp0, fp0);
9806 gen_store_fpr64(ctx, fp0, fd);
9807 tcg_temp_free_i64(fp0);
9809 opn = "abs.ps";
9810 break;
9811 case OPC_MOV_PS:
9812 check_cp1_64bitmode(ctx);
9814 TCGv_i64 fp0 = tcg_temp_new_i64();
9816 gen_load_fpr64(ctx, fp0, fs);
9817 gen_store_fpr64(ctx, fp0, fd);
9818 tcg_temp_free_i64(fp0);
9820 opn = "mov.ps";
9821 break;
9822 case OPC_NEG_PS:
9823 check_cp1_64bitmode(ctx);
9825 TCGv_i64 fp0 = tcg_temp_new_i64();
9827 gen_load_fpr64(ctx, fp0, fs);
9828 gen_helper_float_chs_ps(fp0, fp0);
9829 gen_store_fpr64(ctx, fp0, fd);
9830 tcg_temp_free_i64(fp0);
9832 opn = "neg.ps";
9833 break;
9834 case OPC_MOVCF_PS:
9835 check_cp1_64bitmode(ctx);
9836 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9837 opn = "movcf.ps";
9838 break;
9839 case OPC_MOVZ_PS:
9840 check_cp1_64bitmode(ctx);
9842 int l1 = gen_new_label();
9843 TCGv_i64 fp0;
9845 if (ft != 0)
9846 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9847 fp0 = tcg_temp_new_i64();
9848 gen_load_fpr64(ctx, fp0, fs);
9849 gen_store_fpr64(ctx, fp0, fd);
9850 tcg_temp_free_i64(fp0);
9851 gen_set_label(l1);
9853 opn = "movz.ps";
9854 break;
9855 case OPC_MOVN_PS:
9856 check_cp1_64bitmode(ctx);
9858 int l1 = gen_new_label();
9859 TCGv_i64 fp0;
9861 if (ft != 0) {
9862 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9863 fp0 = tcg_temp_new_i64();
9864 gen_load_fpr64(ctx, fp0, fs);
9865 gen_store_fpr64(ctx, fp0, fd);
9866 tcg_temp_free_i64(fp0);
9867 gen_set_label(l1);
9870 opn = "movn.ps";
9871 break;
9872 case OPC_ADDR_PS:
9873 check_cp1_64bitmode(ctx);
9875 TCGv_i64 fp0 = tcg_temp_new_i64();
9876 TCGv_i64 fp1 = tcg_temp_new_i64();
9878 gen_load_fpr64(ctx, fp0, ft);
9879 gen_load_fpr64(ctx, fp1, fs);
9880 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
9881 tcg_temp_free_i64(fp1);
9882 gen_store_fpr64(ctx, fp0, fd);
9883 tcg_temp_free_i64(fp0);
9885 opn = "addr.ps";
9886 break;
9887 case OPC_MULR_PS:
9888 check_cp1_64bitmode(ctx);
9890 TCGv_i64 fp0 = tcg_temp_new_i64();
9891 TCGv_i64 fp1 = tcg_temp_new_i64();
9893 gen_load_fpr64(ctx, fp0, ft);
9894 gen_load_fpr64(ctx, fp1, fs);
9895 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
9896 tcg_temp_free_i64(fp1);
9897 gen_store_fpr64(ctx, fp0, fd);
9898 tcg_temp_free_i64(fp0);
9900 opn = "mulr.ps";
9901 break;
9902 case OPC_RECIP2_PS:
9903 check_cp1_64bitmode(ctx);
9905 TCGv_i64 fp0 = tcg_temp_new_i64();
9906 TCGv_i64 fp1 = tcg_temp_new_i64();
9908 gen_load_fpr64(ctx, fp0, fs);
9909 gen_load_fpr64(ctx, fp1, ft);
9910 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
9911 tcg_temp_free_i64(fp1);
9912 gen_store_fpr64(ctx, fp0, fd);
9913 tcg_temp_free_i64(fp0);
9915 opn = "recip2.ps";
9916 break;
9917 case OPC_RECIP1_PS:
9918 check_cp1_64bitmode(ctx);
9920 TCGv_i64 fp0 = tcg_temp_new_i64();
9922 gen_load_fpr64(ctx, fp0, fs);
9923 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
9924 gen_store_fpr64(ctx, fp0, fd);
9925 tcg_temp_free_i64(fp0);
9927 opn = "recip1.ps";
9928 break;
9929 case OPC_RSQRT1_PS:
9930 check_cp1_64bitmode(ctx);
9932 TCGv_i64 fp0 = tcg_temp_new_i64();
9934 gen_load_fpr64(ctx, fp0, fs);
9935 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
9936 gen_store_fpr64(ctx, fp0, fd);
9937 tcg_temp_free_i64(fp0);
9939 opn = "rsqrt1.ps";
9940 break;
9941 case OPC_RSQRT2_PS:
9942 check_cp1_64bitmode(ctx);
9944 TCGv_i64 fp0 = tcg_temp_new_i64();
9945 TCGv_i64 fp1 = tcg_temp_new_i64();
9947 gen_load_fpr64(ctx, fp0, fs);
9948 gen_load_fpr64(ctx, fp1, ft);
9949 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
9950 tcg_temp_free_i64(fp1);
9951 gen_store_fpr64(ctx, fp0, fd);
9952 tcg_temp_free_i64(fp0);
9954 opn = "rsqrt2.ps";
9955 break;
9956 case OPC_CVT_S_PU:
9957 check_cp1_64bitmode(ctx);
9959 TCGv_i32 fp0 = tcg_temp_new_i32();
9961 gen_load_fpr32h(ctx, fp0, fs);
9962 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
9963 gen_store_fpr32(fp0, fd);
9964 tcg_temp_free_i32(fp0);
9966 opn = "cvt.s.pu";
9967 break;
9968 case OPC_CVT_PW_PS:
9969 check_cp1_64bitmode(ctx);
9971 TCGv_i64 fp0 = tcg_temp_new_i64();
9973 gen_load_fpr64(ctx, fp0, fs);
9974 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
9975 gen_store_fpr64(ctx, fp0, fd);
9976 tcg_temp_free_i64(fp0);
9978 opn = "cvt.pw.ps";
9979 break;
9980 case OPC_CVT_S_PL:
9981 check_cp1_64bitmode(ctx);
9983 TCGv_i32 fp0 = tcg_temp_new_i32();
9985 gen_load_fpr32(fp0, fs);
9986 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
9987 gen_store_fpr32(fp0, fd);
9988 tcg_temp_free_i32(fp0);
9990 opn = "cvt.s.pl";
9991 break;
9992 case OPC_PLL_PS:
9993 check_cp1_64bitmode(ctx);
9995 TCGv_i32 fp0 = tcg_temp_new_i32();
9996 TCGv_i32 fp1 = tcg_temp_new_i32();
9998 gen_load_fpr32(fp0, fs);
9999 gen_load_fpr32(fp1, ft);
10000 gen_store_fpr32h(ctx, fp0, fd);
10001 gen_store_fpr32(fp1, fd);
10002 tcg_temp_free_i32(fp0);
10003 tcg_temp_free_i32(fp1);
10005 opn = "pll.ps";
10006 break;
10007 case OPC_PLU_PS:
10008 check_cp1_64bitmode(ctx);
10010 TCGv_i32 fp0 = tcg_temp_new_i32();
10011 TCGv_i32 fp1 = tcg_temp_new_i32();
10013 gen_load_fpr32(fp0, fs);
10014 gen_load_fpr32h(ctx, fp1, ft);
10015 gen_store_fpr32(fp1, fd);
10016 gen_store_fpr32h(ctx, fp0, fd);
10017 tcg_temp_free_i32(fp0);
10018 tcg_temp_free_i32(fp1);
10020 opn = "plu.ps";
10021 break;
10022 case OPC_PUL_PS:
10023 check_cp1_64bitmode(ctx);
10025 TCGv_i32 fp0 = tcg_temp_new_i32();
10026 TCGv_i32 fp1 = tcg_temp_new_i32();
10028 gen_load_fpr32h(ctx, fp0, fs);
10029 gen_load_fpr32(fp1, ft);
10030 gen_store_fpr32(fp1, fd);
10031 gen_store_fpr32h(ctx, fp0, fd);
10032 tcg_temp_free_i32(fp0);
10033 tcg_temp_free_i32(fp1);
10035 opn = "pul.ps";
10036 break;
10037 case OPC_PUU_PS:
10038 check_cp1_64bitmode(ctx);
10040 TCGv_i32 fp0 = tcg_temp_new_i32();
10041 TCGv_i32 fp1 = tcg_temp_new_i32();
10043 gen_load_fpr32h(ctx, fp0, fs);
10044 gen_load_fpr32h(ctx, fp1, ft);
10045 gen_store_fpr32(fp1, fd);
10046 gen_store_fpr32h(ctx, fp0, fd);
10047 tcg_temp_free_i32(fp0);
10048 tcg_temp_free_i32(fp1);
10050 opn = "puu.ps";
10051 break;
10052 case OPC_CMP_F_PS:
10053 case OPC_CMP_UN_PS:
10054 case OPC_CMP_EQ_PS:
10055 case OPC_CMP_UEQ_PS:
10056 case OPC_CMP_OLT_PS:
10057 case OPC_CMP_ULT_PS:
10058 case OPC_CMP_OLE_PS:
10059 case OPC_CMP_ULE_PS:
10060 case OPC_CMP_SF_PS:
10061 case OPC_CMP_NGLE_PS:
10062 case OPC_CMP_SEQ_PS:
10063 case OPC_CMP_NGL_PS:
10064 case OPC_CMP_LT_PS:
10065 case OPC_CMP_NGE_PS:
10066 case OPC_CMP_LE_PS:
10067 case OPC_CMP_NGT_PS:
10068 if (ctx->opcode & (1 << 6)) {
10069 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10070 opn = condnames_abs[func-48];
10071 } else {
10072 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10073 opn = condnames[func-48];
10075 break;
10076 default:
10077 MIPS_INVAL(opn);
10078 generate_exception (ctx, EXCP_RI);
10079 return;
10081 (void)opn; /* avoid a compiler warning */
10082 switch (optype) {
10083 case BINOP:
10084 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
10085 break;
10086 case CMPOP:
10087 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
10088 break;
10089 default:
10090 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
10091 break;
10095 /* Coprocessor 3 (FPU) */
10096 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10097 int fd, int fs, int base, int index)
10099 const char *opn = "extended float load/store";
10100 int store = 0;
10101 TCGv t0 = tcg_temp_new();
10103 if (base == 0) {
10104 gen_load_gpr(t0, index);
10105 } else if (index == 0) {
10106 gen_load_gpr(t0, base);
10107 } else {
10108 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10110 /* Don't do NOP if destination is zero: we must perform the actual
10111 memory access. */
10112 switch (opc) {
10113 case OPC_LWXC1:
10114 check_cop1x(ctx);
10116 TCGv_i32 fp0 = tcg_temp_new_i32();
10118 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10119 tcg_gen_trunc_tl_i32(fp0, t0);
10120 gen_store_fpr32(fp0, fd);
10121 tcg_temp_free_i32(fp0);
10123 opn = "lwxc1";
10124 break;
10125 case OPC_LDXC1:
10126 check_cop1x(ctx);
10127 check_cp1_registers(ctx, fd);
10129 TCGv_i64 fp0 = tcg_temp_new_i64();
10130 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10131 gen_store_fpr64(ctx, fp0, fd);
10132 tcg_temp_free_i64(fp0);
10134 opn = "ldxc1";
10135 break;
10136 case OPC_LUXC1:
10137 check_cp1_64bitmode(ctx);
10138 tcg_gen_andi_tl(t0, t0, ~0x7);
10140 TCGv_i64 fp0 = tcg_temp_new_i64();
10142 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10143 gen_store_fpr64(ctx, fp0, fd);
10144 tcg_temp_free_i64(fp0);
10146 opn = "luxc1";
10147 break;
10148 case OPC_SWXC1:
10149 check_cop1x(ctx);
10151 TCGv_i32 fp0 = tcg_temp_new_i32();
10152 gen_load_fpr32(fp0, fs);
10153 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10154 tcg_temp_free_i32(fp0);
10156 opn = "swxc1";
10157 store = 1;
10158 break;
10159 case OPC_SDXC1:
10160 check_cop1x(ctx);
10161 check_cp1_registers(ctx, fs);
10163 TCGv_i64 fp0 = tcg_temp_new_i64();
10164 gen_load_fpr64(ctx, fp0, fs);
10165 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10166 tcg_temp_free_i64(fp0);
10168 opn = "sdxc1";
10169 store = 1;
10170 break;
10171 case OPC_SUXC1:
10172 check_cp1_64bitmode(ctx);
10173 tcg_gen_andi_tl(t0, t0, ~0x7);
10175 TCGv_i64 fp0 = tcg_temp_new_i64();
10176 gen_load_fpr64(ctx, fp0, fs);
10177 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10178 tcg_temp_free_i64(fp0);
10180 opn = "suxc1";
10181 store = 1;
10182 break;
10184 tcg_temp_free(t0);
10185 (void)opn; (void)store; /* avoid compiler warnings */
10186 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
10187 regnames[index], regnames[base]);
10190 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10191 int fd, int fr, int fs, int ft)
10193 const char *opn = "flt3_arith";
10195 switch (opc) {
10196 case OPC_ALNV_PS:
10197 check_cp1_64bitmode(ctx);
10199 TCGv t0 = tcg_temp_local_new();
10200 TCGv_i32 fp = tcg_temp_new_i32();
10201 TCGv_i32 fph = tcg_temp_new_i32();
10202 int l1 = gen_new_label();
10203 int l2 = gen_new_label();
10205 gen_load_gpr(t0, fr);
10206 tcg_gen_andi_tl(t0, t0, 0x7);
10208 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10209 gen_load_fpr32(fp, fs);
10210 gen_load_fpr32h(ctx, fph, fs);
10211 gen_store_fpr32(fp, fd);
10212 gen_store_fpr32h(ctx, fph, fd);
10213 tcg_gen_br(l2);
10214 gen_set_label(l1);
10215 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10216 tcg_temp_free(t0);
10217 #ifdef TARGET_WORDS_BIGENDIAN
10218 gen_load_fpr32(fp, fs);
10219 gen_load_fpr32h(ctx, fph, ft);
10220 gen_store_fpr32h(ctx, fp, fd);
10221 gen_store_fpr32(fph, fd);
10222 #else
10223 gen_load_fpr32h(ctx, fph, fs);
10224 gen_load_fpr32(fp, ft);
10225 gen_store_fpr32(fph, fd);
10226 gen_store_fpr32h(ctx, fp, fd);
10227 #endif
10228 gen_set_label(l2);
10229 tcg_temp_free_i32(fp);
10230 tcg_temp_free_i32(fph);
10232 opn = "alnv.ps";
10233 break;
10234 case OPC_MADD_S:
10235 check_cop1x(ctx);
10237 TCGv_i32 fp0 = tcg_temp_new_i32();
10238 TCGv_i32 fp1 = tcg_temp_new_i32();
10239 TCGv_i32 fp2 = tcg_temp_new_i32();
10241 gen_load_fpr32(fp0, fs);
10242 gen_load_fpr32(fp1, ft);
10243 gen_load_fpr32(fp2, fr);
10244 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10245 tcg_temp_free_i32(fp0);
10246 tcg_temp_free_i32(fp1);
10247 gen_store_fpr32(fp2, fd);
10248 tcg_temp_free_i32(fp2);
10250 opn = "madd.s";
10251 break;
10252 case OPC_MADD_D:
10253 check_cop1x(ctx);
10254 check_cp1_registers(ctx, fd | fs | ft | fr);
10256 TCGv_i64 fp0 = tcg_temp_new_i64();
10257 TCGv_i64 fp1 = tcg_temp_new_i64();
10258 TCGv_i64 fp2 = tcg_temp_new_i64();
10260 gen_load_fpr64(ctx, fp0, fs);
10261 gen_load_fpr64(ctx, fp1, ft);
10262 gen_load_fpr64(ctx, fp2, fr);
10263 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10264 tcg_temp_free_i64(fp0);
10265 tcg_temp_free_i64(fp1);
10266 gen_store_fpr64(ctx, fp2, fd);
10267 tcg_temp_free_i64(fp2);
10269 opn = "madd.d";
10270 break;
10271 case OPC_MADD_PS:
10272 check_cp1_64bitmode(ctx);
10274 TCGv_i64 fp0 = tcg_temp_new_i64();
10275 TCGv_i64 fp1 = tcg_temp_new_i64();
10276 TCGv_i64 fp2 = tcg_temp_new_i64();
10278 gen_load_fpr64(ctx, fp0, fs);
10279 gen_load_fpr64(ctx, fp1, ft);
10280 gen_load_fpr64(ctx, fp2, fr);
10281 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10282 tcg_temp_free_i64(fp0);
10283 tcg_temp_free_i64(fp1);
10284 gen_store_fpr64(ctx, fp2, fd);
10285 tcg_temp_free_i64(fp2);
10287 opn = "madd.ps";
10288 break;
10289 case OPC_MSUB_S:
10290 check_cop1x(ctx);
10292 TCGv_i32 fp0 = tcg_temp_new_i32();
10293 TCGv_i32 fp1 = tcg_temp_new_i32();
10294 TCGv_i32 fp2 = tcg_temp_new_i32();
10296 gen_load_fpr32(fp0, fs);
10297 gen_load_fpr32(fp1, ft);
10298 gen_load_fpr32(fp2, fr);
10299 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10300 tcg_temp_free_i32(fp0);
10301 tcg_temp_free_i32(fp1);
10302 gen_store_fpr32(fp2, fd);
10303 tcg_temp_free_i32(fp2);
10305 opn = "msub.s";
10306 break;
10307 case OPC_MSUB_D:
10308 check_cop1x(ctx);
10309 check_cp1_registers(ctx, fd | fs | ft | fr);
10311 TCGv_i64 fp0 = tcg_temp_new_i64();
10312 TCGv_i64 fp1 = tcg_temp_new_i64();
10313 TCGv_i64 fp2 = tcg_temp_new_i64();
10315 gen_load_fpr64(ctx, fp0, fs);
10316 gen_load_fpr64(ctx, fp1, ft);
10317 gen_load_fpr64(ctx, fp2, fr);
10318 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10319 tcg_temp_free_i64(fp0);
10320 tcg_temp_free_i64(fp1);
10321 gen_store_fpr64(ctx, fp2, fd);
10322 tcg_temp_free_i64(fp2);
10324 opn = "msub.d";
10325 break;
10326 case OPC_MSUB_PS:
10327 check_cp1_64bitmode(ctx);
10329 TCGv_i64 fp0 = tcg_temp_new_i64();
10330 TCGv_i64 fp1 = tcg_temp_new_i64();
10331 TCGv_i64 fp2 = tcg_temp_new_i64();
10333 gen_load_fpr64(ctx, fp0, fs);
10334 gen_load_fpr64(ctx, fp1, ft);
10335 gen_load_fpr64(ctx, fp2, fr);
10336 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10337 tcg_temp_free_i64(fp0);
10338 tcg_temp_free_i64(fp1);
10339 gen_store_fpr64(ctx, fp2, fd);
10340 tcg_temp_free_i64(fp2);
10342 opn = "msub.ps";
10343 break;
10344 case OPC_NMADD_S:
10345 check_cop1x(ctx);
10347 TCGv_i32 fp0 = tcg_temp_new_i32();
10348 TCGv_i32 fp1 = tcg_temp_new_i32();
10349 TCGv_i32 fp2 = tcg_temp_new_i32();
10351 gen_load_fpr32(fp0, fs);
10352 gen_load_fpr32(fp1, ft);
10353 gen_load_fpr32(fp2, fr);
10354 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10355 tcg_temp_free_i32(fp0);
10356 tcg_temp_free_i32(fp1);
10357 gen_store_fpr32(fp2, fd);
10358 tcg_temp_free_i32(fp2);
10360 opn = "nmadd.s";
10361 break;
10362 case OPC_NMADD_D:
10363 check_cop1x(ctx);
10364 check_cp1_registers(ctx, fd | fs | ft | fr);
10366 TCGv_i64 fp0 = tcg_temp_new_i64();
10367 TCGv_i64 fp1 = tcg_temp_new_i64();
10368 TCGv_i64 fp2 = tcg_temp_new_i64();
10370 gen_load_fpr64(ctx, fp0, fs);
10371 gen_load_fpr64(ctx, fp1, ft);
10372 gen_load_fpr64(ctx, fp2, fr);
10373 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10374 tcg_temp_free_i64(fp0);
10375 tcg_temp_free_i64(fp1);
10376 gen_store_fpr64(ctx, fp2, fd);
10377 tcg_temp_free_i64(fp2);
10379 opn = "nmadd.d";
10380 break;
10381 case OPC_NMADD_PS:
10382 check_cp1_64bitmode(ctx);
10384 TCGv_i64 fp0 = tcg_temp_new_i64();
10385 TCGv_i64 fp1 = tcg_temp_new_i64();
10386 TCGv_i64 fp2 = tcg_temp_new_i64();
10388 gen_load_fpr64(ctx, fp0, fs);
10389 gen_load_fpr64(ctx, fp1, ft);
10390 gen_load_fpr64(ctx, fp2, fr);
10391 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10392 tcg_temp_free_i64(fp0);
10393 tcg_temp_free_i64(fp1);
10394 gen_store_fpr64(ctx, fp2, fd);
10395 tcg_temp_free_i64(fp2);
10397 opn = "nmadd.ps";
10398 break;
10399 case OPC_NMSUB_S:
10400 check_cop1x(ctx);
10402 TCGv_i32 fp0 = tcg_temp_new_i32();
10403 TCGv_i32 fp1 = tcg_temp_new_i32();
10404 TCGv_i32 fp2 = tcg_temp_new_i32();
10406 gen_load_fpr32(fp0, fs);
10407 gen_load_fpr32(fp1, ft);
10408 gen_load_fpr32(fp2, fr);
10409 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10410 tcg_temp_free_i32(fp0);
10411 tcg_temp_free_i32(fp1);
10412 gen_store_fpr32(fp2, fd);
10413 tcg_temp_free_i32(fp2);
10415 opn = "nmsub.s";
10416 break;
10417 case OPC_NMSUB_D:
10418 check_cop1x(ctx);
10419 check_cp1_registers(ctx, fd | fs | ft | fr);
10421 TCGv_i64 fp0 = tcg_temp_new_i64();
10422 TCGv_i64 fp1 = tcg_temp_new_i64();
10423 TCGv_i64 fp2 = tcg_temp_new_i64();
10425 gen_load_fpr64(ctx, fp0, fs);
10426 gen_load_fpr64(ctx, fp1, ft);
10427 gen_load_fpr64(ctx, fp2, fr);
10428 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10429 tcg_temp_free_i64(fp0);
10430 tcg_temp_free_i64(fp1);
10431 gen_store_fpr64(ctx, fp2, fd);
10432 tcg_temp_free_i64(fp2);
10434 opn = "nmsub.d";
10435 break;
10436 case OPC_NMSUB_PS:
10437 check_cp1_64bitmode(ctx);
10439 TCGv_i64 fp0 = tcg_temp_new_i64();
10440 TCGv_i64 fp1 = tcg_temp_new_i64();
10441 TCGv_i64 fp2 = tcg_temp_new_i64();
10443 gen_load_fpr64(ctx, fp0, fs);
10444 gen_load_fpr64(ctx, fp1, ft);
10445 gen_load_fpr64(ctx, fp2, fr);
10446 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10447 tcg_temp_free_i64(fp0);
10448 tcg_temp_free_i64(fp1);
10449 gen_store_fpr64(ctx, fp2, fd);
10450 tcg_temp_free_i64(fp2);
10452 opn = "nmsub.ps";
10453 break;
10454 default:
10455 MIPS_INVAL(opn);
10456 generate_exception (ctx, EXCP_RI);
10457 return;
10459 (void)opn; /* avoid a compiler warning */
10460 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
10461 fregnames[fs], fregnames[ft]);
10464 static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
10466 TCGv t0;
10468 #if !defined(CONFIG_USER_ONLY)
10469 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10470 Therefore only check the ISA in system mode. */
10471 check_insn(ctx, ISA_MIPS32R2);
10472 #endif
10473 t0 = tcg_temp_new();
10475 switch (rd) {
10476 case 0:
10477 save_cpu_state(ctx, 1);
10478 gen_helper_rdhwr_cpunum(t0, cpu_env);
10479 gen_store_gpr(t0, rt);
10480 break;
10481 case 1:
10482 save_cpu_state(ctx, 1);
10483 gen_helper_rdhwr_synci_step(t0, cpu_env);
10484 gen_store_gpr(t0, rt);
10485 break;
10486 case 2:
10487 save_cpu_state(ctx, 1);
10488 gen_helper_rdhwr_cc(t0, cpu_env);
10489 gen_store_gpr(t0, rt);
10490 break;
10491 case 3:
10492 save_cpu_state(ctx, 1);
10493 gen_helper_rdhwr_ccres(t0, cpu_env);
10494 gen_store_gpr(t0, rt);
10495 break;
10496 case 29:
10497 #if defined(CONFIG_USER_ONLY)
10498 tcg_gen_ld_tl(t0, cpu_env,
10499 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10500 gen_store_gpr(t0, rt);
10501 break;
10502 #else
10503 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10504 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10505 tcg_gen_ld_tl(t0, cpu_env,
10506 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10507 gen_store_gpr(t0, rt);
10508 } else {
10509 generate_exception(ctx, EXCP_RI);
10511 break;
10512 #endif
10513 default: /* Invalid */
10514 MIPS_INVAL("rdhwr");
10515 generate_exception(ctx, EXCP_RI);
10516 break;
10518 tcg_temp_free(t0);
10521 static void gen_branch(DisasContext *ctx, int insn_bytes)
10523 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10524 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10525 /* Branches completion */
10526 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10527 ctx->bstate = BS_BRANCH;
10528 save_cpu_state(ctx, 0);
10529 /* FIXME: Need to clear can_do_io. */
10530 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10531 case MIPS_HFLAG_FBNSLOT:
10532 MIPS_DEBUG("forbidden slot");
10533 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10534 break;
10535 case MIPS_HFLAG_B:
10536 /* unconditional branch */
10537 MIPS_DEBUG("unconditional branch");
10538 if (proc_hflags & MIPS_HFLAG_BX) {
10539 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10541 gen_goto_tb(ctx, 0, ctx->btarget);
10542 break;
10543 case MIPS_HFLAG_BL:
10544 /* blikely taken case */
10545 MIPS_DEBUG("blikely branch taken");
10546 gen_goto_tb(ctx, 0, ctx->btarget);
10547 break;
10548 case MIPS_HFLAG_BC:
10549 /* Conditional branch */
10550 MIPS_DEBUG("conditional branch");
10552 int l1 = gen_new_label();
10554 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10555 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10556 gen_set_label(l1);
10557 gen_goto_tb(ctx, 0, ctx->btarget);
10559 break;
10560 case MIPS_HFLAG_BR:
10561 /* unconditional branch to register */
10562 MIPS_DEBUG("branch to register");
10563 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10564 TCGv t0 = tcg_temp_new();
10565 TCGv_i32 t1 = tcg_temp_new_i32();
10567 tcg_gen_andi_tl(t0, btarget, 0x1);
10568 tcg_gen_trunc_tl_i32(t1, t0);
10569 tcg_temp_free(t0);
10570 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10571 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10572 tcg_gen_or_i32(hflags, hflags, t1);
10573 tcg_temp_free_i32(t1);
10575 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10576 } else {
10577 tcg_gen_mov_tl(cpu_PC, btarget);
10579 if (ctx->singlestep_enabled) {
10580 save_cpu_state(ctx, 0);
10581 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
10583 tcg_gen_exit_tb(0);
10584 break;
10585 default:
10586 MIPS_DEBUG("unknown branch");
10587 break;
10592 /* ISA extensions (ASEs) */
10593 /* MIPS16 extension to MIPS32 */
10595 /* MIPS16 major opcodes */
10596 enum {
10597 M16_OPC_ADDIUSP = 0x00,
10598 M16_OPC_ADDIUPC = 0x01,
10599 M16_OPC_B = 0x02,
10600 M16_OPC_JAL = 0x03,
10601 M16_OPC_BEQZ = 0x04,
10602 M16_OPC_BNEQZ = 0x05,
10603 M16_OPC_SHIFT = 0x06,
10604 M16_OPC_LD = 0x07,
10605 M16_OPC_RRIA = 0x08,
10606 M16_OPC_ADDIU8 = 0x09,
10607 M16_OPC_SLTI = 0x0a,
10608 M16_OPC_SLTIU = 0x0b,
10609 M16_OPC_I8 = 0x0c,
10610 M16_OPC_LI = 0x0d,
10611 M16_OPC_CMPI = 0x0e,
10612 M16_OPC_SD = 0x0f,
10613 M16_OPC_LB = 0x10,
10614 M16_OPC_LH = 0x11,
10615 M16_OPC_LWSP = 0x12,
10616 M16_OPC_LW = 0x13,
10617 M16_OPC_LBU = 0x14,
10618 M16_OPC_LHU = 0x15,
10619 M16_OPC_LWPC = 0x16,
10620 M16_OPC_LWU = 0x17,
10621 M16_OPC_SB = 0x18,
10622 M16_OPC_SH = 0x19,
10623 M16_OPC_SWSP = 0x1a,
10624 M16_OPC_SW = 0x1b,
10625 M16_OPC_RRR = 0x1c,
10626 M16_OPC_RR = 0x1d,
10627 M16_OPC_EXTEND = 0x1e,
10628 M16_OPC_I64 = 0x1f
10631 /* I8 funct field */
10632 enum {
10633 I8_BTEQZ = 0x0,
10634 I8_BTNEZ = 0x1,
10635 I8_SWRASP = 0x2,
10636 I8_ADJSP = 0x3,
10637 I8_SVRS = 0x4,
10638 I8_MOV32R = 0x5,
10639 I8_MOVR32 = 0x7
10642 /* RRR f field */
10643 enum {
10644 RRR_DADDU = 0x0,
10645 RRR_ADDU = 0x1,
10646 RRR_DSUBU = 0x2,
10647 RRR_SUBU = 0x3
10650 /* RR funct field */
10651 enum {
10652 RR_JR = 0x00,
10653 RR_SDBBP = 0x01,
10654 RR_SLT = 0x02,
10655 RR_SLTU = 0x03,
10656 RR_SLLV = 0x04,
10657 RR_BREAK = 0x05,
10658 RR_SRLV = 0x06,
10659 RR_SRAV = 0x07,
10660 RR_DSRL = 0x08,
10661 RR_CMP = 0x0a,
10662 RR_NEG = 0x0b,
10663 RR_AND = 0x0c,
10664 RR_OR = 0x0d,
10665 RR_XOR = 0x0e,
10666 RR_NOT = 0x0f,
10667 RR_MFHI = 0x10,
10668 RR_CNVT = 0x11,
10669 RR_MFLO = 0x12,
10670 RR_DSRA = 0x13,
10671 RR_DSLLV = 0x14,
10672 RR_DSRLV = 0x16,
10673 RR_DSRAV = 0x17,
10674 RR_MULT = 0x18,
10675 RR_MULTU = 0x19,
10676 RR_DIV = 0x1a,
10677 RR_DIVU = 0x1b,
10678 RR_DMULT = 0x1c,
10679 RR_DMULTU = 0x1d,
10680 RR_DDIV = 0x1e,
10681 RR_DDIVU = 0x1f
10684 /* I64 funct field */
10685 enum {
10686 I64_LDSP = 0x0,
10687 I64_SDSP = 0x1,
10688 I64_SDRASP = 0x2,
10689 I64_DADJSP = 0x3,
10690 I64_LDPC = 0x4,
10691 I64_DADDIU5 = 0x5,
10692 I64_DADDIUPC = 0x6,
10693 I64_DADDIUSP = 0x7
10696 /* RR ry field for CNVT */
10697 enum {
10698 RR_RY_CNVT_ZEB = 0x0,
10699 RR_RY_CNVT_ZEH = 0x1,
10700 RR_RY_CNVT_ZEW = 0x2,
10701 RR_RY_CNVT_SEB = 0x4,
10702 RR_RY_CNVT_SEH = 0x5,
10703 RR_RY_CNVT_SEW = 0x6,
10706 static int xlat (int r)
10708 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10710 return map[r];
10713 static void gen_mips16_save (DisasContext *ctx,
10714 int xsregs, int aregs,
10715 int do_ra, int do_s0, int do_s1,
10716 int framesize)
10718 TCGv t0 = tcg_temp_new();
10719 TCGv t1 = tcg_temp_new();
10720 int args, astatic;
10722 switch (aregs) {
10723 case 0:
10724 case 1:
10725 case 2:
10726 case 3:
10727 case 11:
10728 args = 0;
10729 break;
10730 case 4:
10731 case 5:
10732 case 6:
10733 case 7:
10734 args = 1;
10735 break;
10736 case 8:
10737 case 9:
10738 case 10:
10739 args = 2;
10740 break;
10741 case 12:
10742 case 13:
10743 args = 3;
10744 break;
10745 case 14:
10746 args = 4;
10747 break;
10748 default:
10749 generate_exception(ctx, EXCP_RI);
10750 return;
10753 switch (args) {
10754 case 4:
10755 gen_base_offset_addr(ctx, t0, 29, 12);
10756 gen_load_gpr(t1, 7);
10757 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10758 /* Fall through */
10759 case 3:
10760 gen_base_offset_addr(ctx, t0, 29, 8);
10761 gen_load_gpr(t1, 6);
10762 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10763 /* Fall through */
10764 case 2:
10765 gen_base_offset_addr(ctx, t0, 29, 4);
10766 gen_load_gpr(t1, 5);
10767 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10768 /* Fall through */
10769 case 1:
10770 gen_base_offset_addr(ctx, t0, 29, 0);
10771 gen_load_gpr(t1, 4);
10772 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10775 gen_load_gpr(t0, 29);
10777 #define DECR_AND_STORE(reg) do { \
10778 tcg_gen_subi_tl(t0, t0, 4); \
10779 gen_load_gpr(t1, reg); \
10780 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
10781 } while (0)
10783 if (do_ra) {
10784 DECR_AND_STORE(31);
10787 switch (xsregs) {
10788 case 7:
10789 DECR_AND_STORE(30);
10790 /* Fall through */
10791 case 6:
10792 DECR_AND_STORE(23);
10793 /* Fall through */
10794 case 5:
10795 DECR_AND_STORE(22);
10796 /* Fall through */
10797 case 4:
10798 DECR_AND_STORE(21);
10799 /* Fall through */
10800 case 3:
10801 DECR_AND_STORE(20);
10802 /* Fall through */
10803 case 2:
10804 DECR_AND_STORE(19);
10805 /* Fall through */
10806 case 1:
10807 DECR_AND_STORE(18);
10810 if (do_s1) {
10811 DECR_AND_STORE(17);
10813 if (do_s0) {
10814 DECR_AND_STORE(16);
10817 switch (aregs) {
10818 case 0:
10819 case 4:
10820 case 8:
10821 case 12:
10822 case 14:
10823 astatic = 0;
10824 break;
10825 case 1:
10826 case 5:
10827 case 9:
10828 case 13:
10829 astatic = 1;
10830 break;
10831 case 2:
10832 case 6:
10833 case 10:
10834 astatic = 2;
10835 break;
10836 case 3:
10837 case 7:
10838 astatic = 3;
10839 break;
10840 case 11:
10841 astatic = 4;
10842 break;
10843 default:
10844 generate_exception(ctx, EXCP_RI);
10845 return;
10848 if (astatic > 0) {
10849 DECR_AND_STORE(7);
10850 if (astatic > 1) {
10851 DECR_AND_STORE(6);
10852 if (astatic > 2) {
10853 DECR_AND_STORE(5);
10854 if (astatic > 3) {
10855 DECR_AND_STORE(4);
10860 #undef DECR_AND_STORE
10862 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
10863 tcg_temp_free(t0);
10864 tcg_temp_free(t1);
10867 static void gen_mips16_restore (DisasContext *ctx,
10868 int xsregs, int aregs,
10869 int do_ra, int do_s0, int do_s1,
10870 int framesize)
10872 int astatic;
10873 TCGv t0 = tcg_temp_new();
10874 TCGv t1 = tcg_temp_new();
10876 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
10878 #define DECR_AND_LOAD(reg) do { \
10879 tcg_gen_subi_tl(t0, t0, 4); \
10880 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
10881 gen_store_gpr(t1, reg); \
10882 } while (0)
10884 if (do_ra) {
10885 DECR_AND_LOAD(31);
10888 switch (xsregs) {
10889 case 7:
10890 DECR_AND_LOAD(30);
10891 /* Fall through */
10892 case 6:
10893 DECR_AND_LOAD(23);
10894 /* Fall through */
10895 case 5:
10896 DECR_AND_LOAD(22);
10897 /* Fall through */
10898 case 4:
10899 DECR_AND_LOAD(21);
10900 /* Fall through */
10901 case 3:
10902 DECR_AND_LOAD(20);
10903 /* Fall through */
10904 case 2:
10905 DECR_AND_LOAD(19);
10906 /* Fall through */
10907 case 1:
10908 DECR_AND_LOAD(18);
10911 if (do_s1) {
10912 DECR_AND_LOAD(17);
10914 if (do_s0) {
10915 DECR_AND_LOAD(16);
10918 switch (aregs) {
10919 case 0:
10920 case 4:
10921 case 8:
10922 case 12:
10923 case 14:
10924 astatic = 0;
10925 break;
10926 case 1:
10927 case 5:
10928 case 9:
10929 case 13:
10930 astatic = 1;
10931 break;
10932 case 2:
10933 case 6:
10934 case 10:
10935 astatic = 2;
10936 break;
10937 case 3:
10938 case 7:
10939 astatic = 3;
10940 break;
10941 case 11:
10942 astatic = 4;
10943 break;
10944 default:
10945 generate_exception(ctx, EXCP_RI);
10946 return;
10949 if (astatic > 0) {
10950 DECR_AND_LOAD(7);
10951 if (astatic > 1) {
10952 DECR_AND_LOAD(6);
10953 if (astatic > 2) {
10954 DECR_AND_LOAD(5);
10955 if (astatic > 3) {
10956 DECR_AND_LOAD(4);
10961 #undef DECR_AND_LOAD
10963 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
10964 tcg_temp_free(t0);
10965 tcg_temp_free(t1);
10968 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
10969 int is_64_bit, int extended)
10971 TCGv t0;
10973 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10974 generate_exception(ctx, EXCP_RI);
10975 return;
10978 t0 = tcg_temp_new();
10980 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
10981 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
10982 if (!is_64_bit) {
10983 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10986 tcg_temp_free(t0);
10989 #if defined(TARGET_MIPS64)
10990 static void decode_i64_mips16 (DisasContext *ctx,
10991 int ry, int funct, int16_t offset,
10992 int extended)
10994 switch (funct) {
10995 case I64_LDSP:
10996 check_mips_64(ctx);
10997 offset = extended ? offset : offset << 3;
10998 gen_ld(ctx, OPC_LD, ry, 29, offset);
10999 break;
11000 case I64_SDSP:
11001 check_mips_64(ctx);
11002 offset = extended ? offset : offset << 3;
11003 gen_st(ctx, OPC_SD, ry, 29, offset);
11004 break;
11005 case I64_SDRASP:
11006 check_mips_64(ctx);
11007 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11008 gen_st(ctx, OPC_SD, 31, 29, offset);
11009 break;
11010 case I64_DADJSP:
11011 check_mips_64(ctx);
11012 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11013 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11014 break;
11015 case I64_LDPC:
11016 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11017 generate_exception(ctx, EXCP_RI);
11018 } else {
11019 offset = extended ? offset : offset << 3;
11020 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11022 break;
11023 case I64_DADDIU5:
11024 check_mips_64(ctx);
11025 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11026 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11027 break;
11028 case I64_DADDIUPC:
11029 check_mips_64(ctx);
11030 offset = extended ? offset : offset << 2;
11031 gen_addiupc(ctx, ry, offset, 1, extended);
11032 break;
11033 case I64_DADDIUSP:
11034 check_mips_64(ctx);
11035 offset = extended ? offset : offset << 2;
11036 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11037 break;
11040 #endif
11042 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11044 int extend = cpu_lduw_code(env, ctx->pc + 2);
11045 int op, rx, ry, funct, sa;
11046 int16_t imm, offset;
11048 ctx->opcode = (ctx->opcode << 16) | extend;
11049 op = (ctx->opcode >> 11) & 0x1f;
11050 sa = (ctx->opcode >> 22) & 0x1f;
11051 funct = (ctx->opcode >> 8) & 0x7;
11052 rx = xlat((ctx->opcode >> 8) & 0x7);
11053 ry = xlat((ctx->opcode >> 5) & 0x7);
11054 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11055 | ((ctx->opcode >> 21) & 0x3f) << 5
11056 | (ctx->opcode & 0x1f));
11058 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11059 counterparts. */
11060 switch (op) {
11061 case M16_OPC_ADDIUSP:
11062 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11063 break;
11064 case M16_OPC_ADDIUPC:
11065 gen_addiupc(ctx, rx, imm, 0, 1);
11066 break;
11067 case M16_OPC_B:
11068 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11069 /* No delay slot, so just process as a normal instruction */
11070 break;
11071 case M16_OPC_BEQZ:
11072 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11073 /* No delay slot, so just process as a normal instruction */
11074 break;
11075 case M16_OPC_BNEQZ:
11076 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11077 /* No delay slot, so just process as a normal instruction */
11078 break;
11079 case M16_OPC_SHIFT:
11080 switch (ctx->opcode & 0x3) {
11081 case 0x0:
11082 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11083 break;
11084 case 0x1:
11085 #if defined(TARGET_MIPS64)
11086 check_mips_64(ctx);
11087 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11088 #else
11089 generate_exception(ctx, EXCP_RI);
11090 #endif
11091 break;
11092 case 0x2:
11093 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11094 break;
11095 case 0x3:
11096 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11097 break;
11099 break;
11100 #if defined(TARGET_MIPS64)
11101 case M16_OPC_LD:
11102 check_mips_64(ctx);
11103 gen_ld(ctx, OPC_LD, ry, rx, offset);
11104 break;
11105 #endif
11106 case M16_OPC_RRIA:
11107 imm = ctx->opcode & 0xf;
11108 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11109 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11110 imm = (int16_t) (imm << 1) >> 1;
11111 if ((ctx->opcode >> 4) & 0x1) {
11112 #if defined(TARGET_MIPS64)
11113 check_mips_64(ctx);
11114 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11115 #else
11116 generate_exception(ctx, EXCP_RI);
11117 #endif
11118 } else {
11119 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11121 break;
11122 case M16_OPC_ADDIU8:
11123 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11124 break;
11125 case M16_OPC_SLTI:
11126 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11127 break;
11128 case M16_OPC_SLTIU:
11129 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11130 break;
11131 case M16_OPC_I8:
11132 switch (funct) {
11133 case I8_BTEQZ:
11134 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11135 break;
11136 case I8_BTNEZ:
11137 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11138 break;
11139 case I8_SWRASP:
11140 gen_st(ctx, OPC_SW, 31, 29, imm);
11141 break;
11142 case I8_ADJSP:
11143 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11144 break;
11145 case I8_SVRS:
11147 int xsregs = (ctx->opcode >> 24) & 0x7;
11148 int aregs = (ctx->opcode >> 16) & 0xf;
11149 int do_ra = (ctx->opcode >> 6) & 0x1;
11150 int do_s0 = (ctx->opcode >> 5) & 0x1;
11151 int do_s1 = (ctx->opcode >> 4) & 0x1;
11152 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11153 | (ctx->opcode & 0xf)) << 3;
11155 if (ctx->opcode & (1 << 7)) {
11156 gen_mips16_save(ctx, xsregs, aregs,
11157 do_ra, do_s0, do_s1,
11158 framesize);
11159 } else {
11160 gen_mips16_restore(ctx, xsregs, aregs,
11161 do_ra, do_s0, do_s1,
11162 framesize);
11165 break;
11166 default:
11167 generate_exception(ctx, EXCP_RI);
11168 break;
11170 break;
11171 case M16_OPC_LI:
11172 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11173 break;
11174 case M16_OPC_CMPI:
11175 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11176 break;
11177 #if defined(TARGET_MIPS64)
11178 case M16_OPC_SD:
11179 gen_st(ctx, OPC_SD, ry, rx, offset);
11180 break;
11181 #endif
11182 case M16_OPC_LB:
11183 gen_ld(ctx, OPC_LB, ry, rx, offset);
11184 break;
11185 case M16_OPC_LH:
11186 gen_ld(ctx, OPC_LH, ry, rx, offset);
11187 break;
11188 case M16_OPC_LWSP:
11189 gen_ld(ctx, OPC_LW, rx, 29, offset);
11190 break;
11191 case M16_OPC_LW:
11192 gen_ld(ctx, OPC_LW, ry, rx, offset);
11193 break;
11194 case M16_OPC_LBU:
11195 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11196 break;
11197 case M16_OPC_LHU:
11198 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11199 break;
11200 case M16_OPC_LWPC:
11201 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11202 break;
11203 #if defined(TARGET_MIPS64)
11204 case M16_OPC_LWU:
11205 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11206 break;
11207 #endif
11208 case M16_OPC_SB:
11209 gen_st(ctx, OPC_SB, ry, rx, offset);
11210 break;
11211 case M16_OPC_SH:
11212 gen_st(ctx, OPC_SH, ry, rx, offset);
11213 break;
11214 case M16_OPC_SWSP:
11215 gen_st(ctx, OPC_SW, rx, 29, offset);
11216 break;
11217 case M16_OPC_SW:
11218 gen_st(ctx, OPC_SW, ry, rx, offset);
11219 break;
11220 #if defined(TARGET_MIPS64)
11221 case M16_OPC_I64:
11222 decode_i64_mips16(ctx, ry, funct, offset, 1);
11223 break;
11224 #endif
11225 default:
11226 generate_exception(ctx, EXCP_RI);
11227 break;
11230 return 4;
11233 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11235 int rx, ry;
11236 int sa;
11237 int op, cnvt_op, op1, offset;
11238 int funct;
11239 int n_bytes;
11241 op = (ctx->opcode >> 11) & 0x1f;
11242 sa = (ctx->opcode >> 2) & 0x7;
11243 sa = sa == 0 ? 8 : sa;
11244 rx = xlat((ctx->opcode >> 8) & 0x7);
11245 cnvt_op = (ctx->opcode >> 5) & 0x7;
11246 ry = xlat((ctx->opcode >> 5) & 0x7);
11247 op1 = offset = ctx->opcode & 0x1f;
11249 n_bytes = 2;
11251 switch (op) {
11252 case M16_OPC_ADDIUSP:
11254 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11256 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11258 break;
11259 case M16_OPC_ADDIUPC:
11260 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11261 break;
11262 case M16_OPC_B:
11263 offset = (ctx->opcode & 0x7ff) << 1;
11264 offset = (int16_t)(offset << 4) >> 4;
11265 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11266 /* No delay slot, so just process as a normal instruction */
11267 break;
11268 case M16_OPC_JAL:
11269 offset = cpu_lduw_code(env, ctx->pc + 2);
11270 offset = (((ctx->opcode & 0x1f) << 21)
11271 | ((ctx->opcode >> 5) & 0x1f) << 16
11272 | offset) << 2;
11273 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11274 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11275 n_bytes = 4;
11276 break;
11277 case M16_OPC_BEQZ:
11278 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11279 ((int8_t)ctx->opcode) << 1, 0);
11280 /* No delay slot, so just process as a normal instruction */
11281 break;
11282 case M16_OPC_BNEQZ:
11283 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11284 ((int8_t)ctx->opcode) << 1, 0);
11285 /* No delay slot, so just process as a normal instruction */
11286 break;
11287 case M16_OPC_SHIFT:
11288 switch (ctx->opcode & 0x3) {
11289 case 0x0:
11290 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11291 break;
11292 case 0x1:
11293 #if defined(TARGET_MIPS64)
11294 check_mips_64(ctx);
11295 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11296 #else
11297 generate_exception(ctx, EXCP_RI);
11298 #endif
11299 break;
11300 case 0x2:
11301 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11302 break;
11303 case 0x3:
11304 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11305 break;
11307 break;
11308 #if defined(TARGET_MIPS64)
11309 case M16_OPC_LD:
11310 check_mips_64(ctx);
11311 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
11312 break;
11313 #endif
11314 case M16_OPC_RRIA:
11316 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
11318 if ((ctx->opcode >> 4) & 1) {
11319 #if defined(TARGET_MIPS64)
11320 check_mips_64(ctx);
11321 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11322 #else
11323 generate_exception(ctx, EXCP_RI);
11324 #endif
11325 } else {
11326 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11329 break;
11330 case M16_OPC_ADDIU8:
11332 int16_t imm = (int8_t) ctx->opcode;
11334 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11336 break;
11337 case M16_OPC_SLTI:
11339 int16_t imm = (uint8_t) ctx->opcode;
11340 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11342 break;
11343 case M16_OPC_SLTIU:
11345 int16_t imm = (uint8_t) ctx->opcode;
11346 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11348 break;
11349 case M16_OPC_I8:
11351 int reg32;
11353 funct = (ctx->opcode >> 8) & 0x7;
11354 switch (funct) {
11355 case I8_BTEQZ:
11356 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
11357 ((int8_t)ctx->opcode) << 1, 0);
11358 break;
11359 case I8_BTNEZ:
11360 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
11361 ((int8_t)ctx->opcode) << 1, 0);
11362 break;
11363 case I8_SWRASP:
11364 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
11365 break;
11366 case I8_ADJSP:
11367 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
11368 ((int8_t)ctx->opcode) << 3);
11369 break;
11370 case I8_SVRS:
11372 int do_ra = ctx->opcode & (1 << 6);
11373 int do_s0 = ctx->opcode & (1 << 5);
11374 int do_s1 = ctx->opcode & (1 << 4);
11375 int framesize = ctx->opcode & 0xf;
11377 if (framesize == 0) {
11378 framesize = 128;
11379 } else {
11380 framesize = framesize << 3;
11383 if (ctx->opcode & (1 << 7)) {
11384 gen_mips16_save(ctx, 0, 0,
11385 do_ra, do_s0, do_s1, framesize);
11386 } else {
11387 gen_mips16_restore(ctx, 0, 0,
11388 do_ra, do_s0, do_s1, framesize);
11391 break;
11392 case I8_MOV32R:
11394 int rz = xlat(ctx->opcode & 0x7);
11396 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
11397 ((ctx->opcode >> 5) & 0x7);
11398 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
11400 break;
11401 case I8_MOVR32:
11402 reg32 = ctx->opcode & 0x1f;
11403 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
11404 break;
11405 default:
11406 generate_exception(ctx, EXCP_RI);
11407 break;
11410 break;
11411 case M16_OPC_LI:
11413 int16_t imm = (uint8_t) ctx->opcode;
11415 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
11417 break;
11418 case M16_OPC_CMPI:
11420 int16_t imm = (uint8_t) ctx->opcode;
11421 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
11423 break;
11424 #if defined(TARGET_MIPS64)
11425 case M16_OPC_SD:
11426 check_mips_64(ctx);
11427 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
11428 break;
11429 #endif
11430 case M16_OPC_LB:
11431 gen_ld(ctx, OPC_LB, ry, rx, offset);
11432 break;
11433 case M16_OPC_LH:
11434 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
11435 break;
11436 case M16_OPC_LWSP:
11437 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11438 break;
11439 case M16_OPC_LW:
11440 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
11441 break;
11442 case M16_OPC_LBU:
11443 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11444 break;
11445 case M16_OPC_LHU:
11446 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
11447 break;
11448 case M16_OPC_LWPC:
11449 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
11450 break;
11451 #if defined (TARGET_MIPS64)
11452 case M16_OPC_LWU:
11453 check_mips_64(ctx);
11454 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
11455 break;
11456 #endif
11457 case M16_OPC_SB:
11458 gen_st(ctx, OPC_SB, ry, rx, offset);
11459 break;
11460 case M16_OPC_SH:
11461 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
11462 break;
11463 case M16_OPC_SWSP:
11464 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11465 break;
11466 case M16_OPC_SW:
11467 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
11468 break;
11469 case M16_OPC_RRR:
11471 int rz = xlat((ctx->opcode >> 2) & 0x7);
11472 int mips32_op;
11474 switch (ctx->opcode & 0x3) {
11475 case RRR_ADDU:
11476 mips32_op = OPC_ADDU;
11477 break;
11478 case RRR_SUBU:
11479 mips32_op = OPC_SUBU;
11480 break;
11481 #if defined(TARGET_MIPS64)
11482 case RRR_DADDU:
11483 mips32_op = OPC_DADDU;
11484 check_mips_64(ctx);
11485 break;
11486 case RRR_DSUBU:
11487 mips32_op = OPC_DSUBU;
11488 check_mips_64(ctx);
11489 break;
11490 #endif
11491 default:
11492 generate_exception(ctx, EXCP_RI);
11493 goto done;
11496 gen_arith(ctx, mips32_op, rz, rx, ry);
11497 done:
11500 break;
11501 case M16_OPC_RR:
11502 switch (op1) {
11503 case RR_JR:
11505 int nd = (ctx->opcode >> 7) & 0x1;
11506 int link = (ctx->opcode >> 6) & 0x1;
11507 int ra = (ctx->opcode >> 5) & 0x1;
11509 if (link) {
11510 op = OPC_JALR;
11511 } else {
11512 op = OPC_JR;
11515 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
11516 (nd ? 0 : 2));
11518 break;
11519 case RR_SDBBP:
11520 /* XXX: not clear which exception should be raised
11521 * when in debug mode...
11523 check_insn(ctx, ISA_MIPS32);
11524 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11525 generate_exception(ctx, EXCP_DBp);
11526 } else {
11527 generate_exception(ctx, EXCP_DBp);
11529 break;
11530 case RR_SLT:
11531 gen_slt(ctx, OPC_SLT, 24, rx, ry);
11532 break;
11533 case RR_SLTU:
11534 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
11535 break;
11536 case RR_BREAK:
11537 generate_exception(ctx, EXCP_BREAK);
11538 break;
11539 case RR_SLLV:
11540 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
11541 break;
11542 case RR_SRLV:
11543 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
11544 break;
11545 case RR_SRAV:
11546 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
11547 break;
11548 #if defined (TARGET_MIPS64)
11549 case RR_DSRL:
11550 check_mips_64(ctx);
11551 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
11552 break;
11553 #endif
11554 case RR_CMP:
11555 gen_logic(ctx, OPC_XOR, 24, rx, ry);
11556 break;
11557 case RR_NEG:
11558 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
11559 break;
11560 case RR_AND:
11561 gen_logic(ctx, OPC_AND, rx, rx, ry);
11562 break;
11563 case RR_OR:
11564 gen_logic(ctx, OPC_OR, rx, rx, ry);
11565 break;
11566 case RR_XOR:
11567 gen_logic(ctx, OPC_XOR, rx, rx, ry);
11568 break;
11569 case RR_NOT:
11570 gen_logic(ctx, OPC_NOR, rx, ry, 0);
11571 break;
11572 case RR_MFHI:
11573 gen_HILO(ctx, OPC_MFHI, 0, rx);
11574 break;
11575 case RR_CNVT:
11576 switch (cnvt_op) {
11577 case RR_RY_CNVT_ZEB:
11578 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11579 break;
11580 case RR_RY_CNVT_ZEH:
11581 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11582 break;
11583 case RR_RY_CNVT_SEB:
11584 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11585 break;
11586 case RR_RY_CNVT_SEH:
11587 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11588 break;
11589 #if defined (TARGET_MIPS64)
11590 case RR_RY_CNVT_ZEW:
11591 check_mips_64(ctx);
11592 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11593 break;
11594 case RR_RY_CNVT_SEW:
11595 check_mips_64(ctx);
11596 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11597 break;
11598 #endif
11599 default:
11600 generate_exception(ctx, EXCP_RI);
11601 break;
11603 break;
11604 case RR_MFLO:
11605 gen_HILO(ctx, OPC_MFLO, 0, rx);
11606 break;
11607 #if defined (TARGET_MIPS64)
11608 case RR_DSRA:
11609 check_mips_64(ctx);
11610 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
11611 break;
11612 case RR_DSLLV:
11613 check_mips_64(ctx);
11614 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
11615 break;
11616 case RR_DSRLV:
11617 check_mips_64(ctx);
11618 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
11619 break;
11620 case RR_DSRAV:
11621 check_mips_64(ctx);
11622 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
11623 break;
11624 #endif
11625 case RR_MULT:
11626 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
11627 break;
11628 case RR_MULTU:
11629 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
11630 break;
11631 case RR_DIV:
11632 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
11633 break;
11634 case RR_DIVU:
11635 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
11636 break;
11637 #if defined (TARGET_MIPS64)
11638 case RR_DMULT:
11639 check_mips_64(ctx);
11640 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
11641 break;
11642 case RR_DMULTU:
11643 check_mips_64(ctx);
11644 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
11645 break;
11646 case RR_DDIV:
11647 check_mips_64(ctx);
11648 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
11649 break;
11650 case RR_DDIVU:
11651 check_mips_64(ctx);
11652 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
11653 break;
11654 #endif
11655 default:
11656 generate_exception(ctx, EXCP_RI);
11657 break;
11659 break;
11660 case M16_OPC_EXTEND:
11661 decode_extended_mips16_opc(env, ctx);
11662 n_bytes = 4;
11663 break;
11664 #if defined(TARGET_MIPS64)
11665 case M16_OPC_I64:
11666 funct = (ctx->opcode >> 8) & 0x7;
11667 decode_i64_mips16(ctx, ry, funct, offset, 0);
11668 break;
11669 #endif
11670 default:
11671 generate_exception(ctx, EXCP_RI);
11672 break;
11675 return n_bytes;
11678 /* microMIPS extension to MIPS32/MIPS64 */
11681 * microMIPS32/microMIPS64 major opcodes
11683 * 1. MIPS Architecture for Programmers Volume II-B:
11684 * The microMIPS32 Instruction Set (Revision 3.05)
11686 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
11688 * 2. MIPS Architecture For Programmers Volume II-A:
11689 * The MIPS64 Instruction Set (Revision 3.51)
11692 enum {
11693 POOL32A = 0x00,
11694 POOL16A = 0x01,
11695 LBU16 = 0x02,
11696 MOVE16 = 0x03,
11697 ADDI32 = 0x04,
11698 LBU32 = 0x05,
11699 SB32 = 0x06,
11700 LB32 = 0x07,
11702 POOL32B = 0x08,
11703 POOL16B = 0x09,
11704 LHU16 = 0x0a,
11705 ANDI16 = 0x0b,
11706 ADDIU32 = 0x0c,
11707 LHU32 = 0x0d,
11708 SH32 = 0x0e,
11709 LH32 = 0x0f,
11711 POOL32I = 0x10,
11712 POOL16C = 0x11,
11713 LWSP16 = 0x12,
11714 POOL16D = 0x13,
11715 ORI32 = 0x14,
11716 POOL32F = 0x15,
11717 POOL32S = 0x16, /* MIPS64 */
11718 DADDIU32 = 0x17, /* MIPS64 */
11720 /* 0x1f is reserved */
11721 POOL32C = 0x18,
11722 LWGP16 = 0x19,
11723 LW16 = 0x1a,
11724 POOL16E = 0x1b,
11725 XORI32 = 0x1c,
11726 JALS32 = 0x1d,
11727 ADDIUPC = 0x1e,
11729 /* 0x20 is reserved */
11730 RES_20 = 0x20,
11731 POOL16F = 0x21,
11732 SB16 = 0x22,
11733 BEQZ16 = 0x23,
11734 SLTI32 = 0x24,
11735 BEQ32 = 0x25,
11736 SWC132 = 0x26,
11737 LWC132 = 0x27,
11739 /* 0x28 and 0x29 are reserved */
11740 RES_28 = 0x28,
11741 RES_29 = 0x29,
11742 SH16 = 0x2a,
11743 BNEZ16 = 0x2b,
11744 SLTIU32 = 0x2c,
11745 BNE32 = 0x2d,
11746 SDC132 = 0x2e,
11747 LDC132 = 0x2f,
11749 /* 0x30 and 0x31 are reserved */
11750 RES_30 = 0x30,
11751 RES_31 = 0x31,
11752 SWSP16 = 0x32,
11753 B16 = 0x33,
11754 ANDI32 = 0x34,
11755 J32 = 0x35,
11756 SD32 = 0x36, /* MIPS64 */
11757 LD32 = 0x37, /* MIPS64 */
11759 /* 0x38 and 0x39 are reserved */
11760 RES_38 = 0x38,
11761 RES_39 = 0x39,
11762 SW16 = 0x3a,
11763 LI16 = 0x3b,
11764 JALX32 = 0x3c,
11765 JAL32 = 0x3d,
11766 SW32 = 0x3e,
11767 LW32 = 0x3f
11770 /* POOL32A encoding of minor opcode field */
11772 enum {
11773 /* These opcodes are distinguished only by bits 9..6; those bits are
11774 * what are recorded below. */
11775 SLL32 = 0x0,
11776 SRL32 = 0x1,
11777 SRA = 0x2,
11778 ROTR = 0x3,
11780 SLLV = 0x0,
11781 SRLV = 0x1,
11782 SRAV = 0x2,
11783 ROTRV = 0x3,
11784 ADD = 0x4,
11785 ADDU32 = 0x5,
11786 SUB = 0x6,
11787 SUBU32 = 0x7,
11788 MUL = 0x8,
11789 AND = 0x9,
11790 OR32 = 0xa,
11791 NOR = 0xb,
11792 XOR32 = 0xc,
11793 SLT = 0xd,
11794 SLTU = 0xe,
11796 MOVN = 0x0,
11797 MOVZ = 0x1,
11798 LWXS = 0x4,
11800 /* The following can be distinguished by their lower 6 bits. */
11801 INS = 0x0c,
11802 EXT = 0x2c,
11803 POOL32AXF = 0x3c
11806 /* POOL32AXF encoding of minor opcode field extension */
11809 * 1. MIPS Architecture for Programmers Volume II-B:
11810 * The microMIPS32 Instruction Set (Revision 3.05)
11812 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
11814 * 2. MIPS Architecture for Programmers VolumeIV-e:
11815 * The MIPS DSP Application-Specific Extension
11816 * to the microMIPS32 Architecture (Revision 2.34)
11818 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
11821 enum {
11822 /* bits 11..6 */
11823 TEQ = 0x00,
11824 TGE = 0x08,
11825 TGEU = 0x10,
11826 TLT = 0x20,
11827 TLTU = 0x28,
11828 TNE = 0x30,
11830 MFC0 = 0x03,
11831 MTC0 = 0x0b,
11833 /* begin of microMIPS32 DSP */
11835 /* bits 13..12 for 0x01 */
11836 MFHI_ACC = 0x0,
11837 MFLO_ACC = 0x1,
11838 MTHI_ACC = 0x2,
11839 MTLO_ACC = 0x3,
11841 /* bits 13..12 for 0x2a */
11842 MADD_ACC = 0x0,
11843 MADDU_ACC = 0x1,
11844 MSUB_ACC = 0x2,
11845 MSUBU_ACC = 0x3,
11847 /* bits 13..12 for 0x32 */
11848 MULT_ACC = 0x0,
11849 MULTU_ACC = 0x1,
11851 /* end of microMIPS32 DSP */
11853 /* bits 15..12 for 0x2c */
11854 SEB = 0x2,
11855 SEH = 0x3,
11856 CLO = 0x4,
11857 CLZ = 0x5,
11858 RDHWR = 0x6,
11859 WSBH = 0x7,
11860 MULT = 0x8,
11861 MULTU = 0x9,
11862 DIV = 0xa,
11863 DIVU = 0xb,
11864 MADD = 0xc,
11865 MADDU = 0xd,
11866 MSUB = 0xe,
11867 MSUBU = 0xf,
11869 /* bits 15..12 for 0x34 */
11870 MFC2 = 0x4,
11871 MTC2 = 0x5,
11872 MFHC2 = 0x8,
11873 MTHC2 = 0x9,
11874 CFC2 = 0xc,
11875 CTC2 = 0xd,
11877 /* bits 15..12 for 0x3c */
11878 JALR = 0x0,
11879 JR = 0x0, /* alias */
11880 JALR_HB = 0x1,
11881 JALRS = 0x4,
11882 JALRS_HB = 0x5,
11884 /* bits 15..12 for 0x05 */
11885 RDPGPR = 0xe,
11886 WRPGPR = 0xf,
11888 /* bits 15..12 for 0x0d */
11889 TLBP = 0x0,
11890 TLBR = 0x1,
11891 TLBWI = 0x2,
11892 TLBWR = 0x3,
11893 WAIT = 0x9,
11894 IRET = 0xd,
11895 DERET = 0xe,
11896 ERET = 0xf,
11898 /* bits 15..12 for 0x15 */
11899 DMT = 0x0,
11900 DVPE = 0x1,
11901 EMT = 0x2,
11902 EVPE = 0x3,
11904 /* bits 15..12 for 0x1d */
11905 DI = 0x4,
11906 EI = 0x5,
11908 /* bits 15..12 for 0x2d */
11909 SYNC = 0x6,
11910 SYSCALL = 0x8,
11911 SDBBP = 0xd,
11913 /* bits 15..12 for 0x35 */
11914 MFHI32 = 0x0,
11915 MFLO32 = 0x1,
11916 MTHI32 = 0x2,
11917 MTLO32 = 0x3,
11920 /* POOL32B encoding of minor opcode field (bits 15..12) */
11922 enum {
11923 LWC2 = 0x0,
11924 LWP = 0x1,
11925 LDP = 0x4,
11926 LWM32 = 0x5,
11927 CACHE = 0x6,
11928 LDM = 0x7,
11929 SWC2 = 0x8,
11930 SWP = 0x9,
11931 SDP = 0xc,
11932 SWM32 = 0xd,
11933 SDM = 0xf
11936 /* POOL32C encoding of minor opcode field (bits 15..12) */
11938 enum {
11939 LWL = 0x0,
11940 SWL = 0x8,
11941 LWR = 0x1,
11942 SWR = 0x9,
11943 PREF = 0x2,
11944 /* 0xa is reserved */
11945 LL = 0x3,
11946 SC = 0xb,
11947 LDL = 0x4,
11948 SDL = 0xc,
11949 LDR = 0x5,
11950 SDR = 0xd,
11951 /* 0x6 is reserved */
11952 LWU = 0xe,
11953 LLD = 0x7,
11954 SCD = 0xf
11957 /* POOL32F encoding of minor opcode field (bits 5..0) */
11959 enum {
11960 /* These are the bit 7..6 values */
11961 ADD_FMT = 0x0,
11962 MOVN_FMT = 0x0,
11964 SUB_FMT = 0x1,
11965 MOVZ_FMT = 0x1,
11967 MUL_FMT = 0x2,
11969 DIV_FMT = 0x3,
11971 /* These are the bit 8..6 values */
11972 RSQRT2_FMT = 0x0,
11973 MOVF_FMT = 0x0,
11975 LWXC1 = 0x1,
11976 MOVT_FMT = 0x1,
11978 PLL_PS = 0x2,
11979 SWXC1 = 0x2,
11981 PLU_PS = 0x3,
11982 LDXC1 = 0x3,
11984 PUL_PS = 0x4,
11985 SDXC1 = 0x4,
11986 RECIP2_FMT = 0x4,
11988 PUU_PS = 0x5,
11989 LUXC1 = 0x5,
11991 CVT_PS_S = 0x6,
11992 SUXC1 = 0x6,
11993 ADDR_PS = 0x6,
11994 PREFX = 0x6,
11996 MULR_PS = 0x7,
11998 MADD_S = 0x01,
11999 MADD_D = 0x09,
12000 MADD_PS = 0x11,
12001 ALNV_PS = 0x19,
12002 MSUB_S = 0x21,
12003 MSUB_D = 0x29,
12004 MSUB_PS = 0x31,
12006 NMADD_S = 0x02,
12007 NMADD_D = 0x0a,
12008 NMADD_PS = 0x12,
12009 NMSUB_S = 0x22,
12010 NMSUB_D = 0x2a,
12011 NMSUB_PS = 0x32,
12013 POOL32FXF = 0x3b,
12015 CABS_COND_FMT = 0x1c, /* MIPS3D */
12016 C_COND_FMT = 0x3c
12019 /* POOL32Fxf encoding of minor opcode extension field */
12021 enum {
12022 CVT_L = 0x04,
12023 RSQRT_FMT = 0x08,
12024 FLOOR_L = 0x0c,
12025 CVT_PW_PS = 0x1c,
12026 CVT_W = 0x24,
12027 SQRT_FMT = 0x28,
12028 FLOOR_W = 0x2c,
12029 CVT_PS_PW = 0x3c,
12030 CFC1 = 0x40,
12031 RECIP_FMT = 0x48,
12032 CEIL_L = 0x4c,
12033 CTC1 = 0x60,
12034 CEIL_W = 0x6c,
12035 MFC1 = 0x80,
12036 CVT_S_PL = 0x84,
12037 TRUNC_L = 0x8c,
12038 MTC1 = 0xa0,
12039 CVT_S_PU = 0xa4,
12040 TRUNC_W = 0xac,
12041 MFHC1 = 0xc0,
12042 ROUND_L = 0xcc,
12043 MTHC1 = 0xe0,
12044 ROUND_W = 0xec,
12046 MOV_FMT = 0x01,
12047 MOVF = 0x05,
12048 ABS_FMT = 0x0d,
12049 RSQRT1_FMT = 0x1d,
12050 MOVT = 0x25,
12051 NEG_FMT = 0x2d,
12052 CVT_D = 0x4d,
12053 RECIP1_FMT = 0x5d,
12054 CVT_S = 0x6d
12057 /* POOL32I encoding of minor opcode field (bits 25..21) */
12059 enum {
12060 BLTZ = 0x00,
12061 BLTZAL = 0x01,
12062 BGEZ = 0x02,
12063 BGEZAL = 0x03,
12064 BLEZ = 0x04,
12065 BNEZC = 0x05,
12066 BGTZ = 0x06,
12067 BEQZC = 0x07,
12068 TLTI = 0x08,
12069 TGEI = 0x09,
12070 TLTIU = 0x0a,
12071 TGEIU = 0x0b,
12072 TNEI = 0x0c,
12073 LUI = 0x0d,
12074 TEQI = 0x0e,
12075 SYNCI = 0x10,
12076 BLTZALS = 0x11,
12077 BGEZALS = 0x13,
12078 BC2F = 0x14,
12079 BC2T = 0x15,
12080 BPOSGE64 = 0x1a,
12081 BPOSGE32 = 0x1b,
12082 /* These overlap and are distinguished by bit16 of the instruction */
12083 BC1F = 0x1c,
12084 BC1T = 0x1d,
12085 BC1ANY2F = 0x1c,
12086 BC1ANY2T = 0x1d,
12087 BC1ANY4F = 0x1e,
12088 BC1ANY4T = 0x1f
12091 /* POOL16A encoding of minor opcode field */
12093 enum {
12094 ADDU16 = 0x0,
12095 SUBU16 = 0x1
12098 /* POOL16B encoding of minor opcode field */
12100 enum {
12101 SLL16 = 0x0,
12102 SRL16 = 0x1
12105 /* POOL16C encoding of minor opcode field */
12107 enum {
12108 NOT16 = 0x00,
12109 XOR16 = 0x04,
12110 AND16 = 0x08,
12111 OR16 = 0x0c,
12112 LWM16 = 0x10,
12113 SWM16 = 0x14,
12114 JR16 = 0x18,
12115 JRC16 = 0x1a,
12116 JALR16 = 0x1c,
12117 JALR16S = 0x1e,
12118 MFHI16 = 0x20,
12119 MFLO16 = 0x24,
12120 BREAK16 = 0x28,
12121 SDBBP16 = 0x2c,
12122 JRADDIUSP = 0x30
12125 /* POOL16D encoding of minor opcode field */
12127 enum {
12128 ADDIUS5 = 0x0,
12129 ADDIUSP = 0x1
12132 /* POOL16E encoding of minor opcode field */
12134 enum {
12135 ADDIUR2 = 0x0,
12136 ADDIUR1SP = 0x1
12139 static int mmreg (int r)
12141 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12143 return map[r];
12146 /* Used for 16-bit store instructions. */
12147 static int mmreg2 (int r)
12149 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12151 return map[r];
12154 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12155 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12156 #define uMIPS_RS2(op) uMIPS_RS(op)
12157 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12158 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12159 #define uMIPS_RS5(op) (op & 0x1f)
12161 /* Signed immediate */
12162 #define SIMM(op, start, width) \
12163 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12164 << (32-width)) \
12165 >> (32-width))
12166 /* Zero-extended immediate */
12167 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12169 static void gen_addiur1sp(DisasContext *ctx)
12171 int rd = mmreg(uMIPS_RD(ctx->opcode));
12173 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12176 static void gen_addiur2(DisasContext *ctx)
12178 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12179 int rd = mmreg(uMIPS_RD(ctx->opcode));
12180 int rs = mmreg(uMIPS_RS(ctx->opcode));
12182 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12185 static void gen_addiusp(DisasContext *ctx)
12187 int encoded = ZIMM(ctx->opcode, 1, 9);
12188 int decoded;
12190 if (encoded <= 1) {
12191 decoded = 256 + encoded;
12192 } else if (encoded <= 255) {
12193 decoded = encoded;
12194 } else if (encoded <= 509) {
12195 decoded = encoded - 512;
12196 } else {
12197 decoded = encoded - 768;
12200 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
12203 static void gen_addius5(DisasContext *ctx)
12205 int imm = SIMM(ctx->opcode, 1, 4);
12206 int rd = (ctx->opcode >> 5) & 0x1f;
12208 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
12211 static void gen_andi16(DisasContext *ctx)
12213 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
12214 31, 32, 63, 64, 255, 32768, 65535 };
12215 int rd = mmreg(uMIPS_RD(ctx->opcode));
12216 int rs = mmreg(uMIPS_RS(ctx->opcode));
12217 int encoded = ZIMM(ctx->opcode, 0, 4);
12219 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
12222 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
12223 int base, int16_t offset)
12225 const char *opn = "ldst_multiple";
12226 TCGv t0, t1;
12227 TCGv_i32 t2;
12229 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12230 generate_exception(ctx, EXCP_RI);
12231 return;
12234 t0 = tcg_temp_new();
12236 gen_base_offset_addr(ctx, t0, base, offset);
12238 t1 = tcg_const_tl(reglist);
12239 t2 = tcg_const_i32(ctx->mem_idx);
12241 save_cpu_state(ctx, 1);
12242 switch (opc) {
12243 case LWM32:
12244 gen_helper_lwm(cpu_env, t0, t1, t2);
12245 opn = "lwm";
12246 break;
12247 case SWM32:
12248 gen_helper_swm(cpu_env, t0, t1, t2);
12249 opn = "swm";
12250 break;
12251 #ifdef TARGET_MIPS64
12252 case LDM:
12253 gen_helper_ldm(cpu_env, t0, t1, t2);
12254 opn = "ldm";
12255 break;
12256 case SDM:
12257 gen_helper_sdm(cpu_env, t0, t1, t2);
12258 opn = "sdm";
12259 break;
12260 #endif
12262 (void)opn;
12263 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
12264 tcg_temp_free(t0);
12265 tcg_temp_free(t1);
12266 tcg_temp_free_i32(t2);
12270 static void gen_pool16c_insn(DisasContext *ctx)
12272 int rd = mmreg((ctx->opcode >> 3) & 0x7);
12273 int rs = mmreg(ctx->opcode & 0x7);
12275 switch (((ctx->opcode) >> 4) & 0x3f) {
12276 case NOT16 + 0:
12277 case NOT16 + 1:
12278 case NOT16 + 2:
12279 case NOT16 + 3:
12280 gen_logic(ctx, OPC_NOR, rd, rs, 0);
12281 break;
12282 case XOR16 + 0:
12283 case XOR16 + 1:
12284 case XOR16 + 2:
12285 case XOR16 + 3:
12286 gen_logic(ctx, OPC_XOR, rd, rd, rs);
12287 break;
12288 case AND16 + 0:
12289 case AND16 + 1:
12290 case AND16 + 2:
12291 case AND16 + 3:
12292 gen_logic(ctx, OPC_AND, rd, rd, rs);
12293 break;
12294 case OR16 + 0:
12295 case OR16 + 1:
12296 case OR16 + 2:
12297 case OR16 + 3:
12298 gen_logic(ctx, OPC_OR, rd, rd, rs);
12299 break;
12300 case LWM16 + 0:
12301 case LWM16 + 1:
12302 case LWM16 + 2:
12303 case LWM16 + 3:
12305 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12306 int offset = ZIMM(ctx->opcode, 0, 4);
12308 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
12309 29, offset << 2);
12311 break;
12312 case SWM16 + 0:
12313 case SWM16 + 1:
12314 case SWM16 + 2:
12315 case SWM16 + 3:
12317 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12318 int offset = ZIMM(ctx->opcode, 0, 4);
12320 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
12321 29, offset << 2);
12323 break;
12324 case JR16 + 0:
12325 case JR16 + 1:
12327 int reg = ctx->opcode & 0x1f;
12329 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
12331 break;
12332 case JRC16 + 0:
12333 case JRC16 + 1:
12335 int reg = ctx->opcode & 0x1f;
12336 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
12337 /* Let normal delay slot handling in our caller take us
12338 to the branch target. */
12340 break;
12341 case JALR16 + 0:
12342 case JALR16 + 1:
12343 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
12344 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12345 break;
12346 case JALR16S + 0:
12347 case JALR16S + 1:
12348 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
12349 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12350 break;
12351 case MFHI16 + 0:
12352 case MFHI16 + 1:
12353 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
12354 break;
12355 case MFLO16 + 0:
12356 case MFLO16 + 1:
12357 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
12358 break;
12359 case BREAK16:
12360 generate_exception(ctx, EXCP_BREAK);
12361 break;
12362 case SDBBP16:
12363 /* XXX: not clear which exception should be raised
12364 * when in debug mode...
12366 check_insn(ctx, ISA_MIPS32);
12367 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
12368 generate_exception(ctx, EXCP_DBp);
12369 } else {
12370 generate_exception(ctx, EXCP_DBp);
12372 break;
12373 case JRADDIUSP + 0:
12374 case JRADDIUSP + 1:
12376 int imm = ZIMM(ctx->opcode, 0, 5);
12377 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12378 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12379 /* Let normal delay slot handling in our caller take us
12380 to the branch target. */
12382 break;
12383 default:
12384 generate_exception(ctx, EXCP_RI);
12385 break;
12389 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
12391 TCGv t0 = tcg_temp_new();
12392 TCGv t1 = tcg_temp_new();
12394 gen_load_gpr(t0, base);
12396 if (index != 0) {
12397 gen_load_gpr(t1, index);
12398 tcg_gen_shli_tl(t1, t1, 2);
12399 gen_op_addr_add(ctx, t0, t1, t0);
12402 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12403 gen_store_gpr(t1, rd);
12405 tcg_temp_free(t0);
12406 tcg_temp_free(t1);
12409 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
12410 int base, int16_t offset)
12412 const char *opn = "ldst_pair";
12413 TCGv t0, t1;
12415 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
12416 generate_exception(ctx, EXCP_RI);
12417 return;
12420 t0 = tcg_temp_new();
12421 t1 = tcg_temp_new();
12423 gen_base_offset_addr(ctx, t0, base, offset);
12425 switch (opc) {
12426 case LWP:
12427 if (rd == base) {
12428 generate_exception(ctx, EXCP_RI);
12429 return;
12431 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12432 gen_store_gpr(t1, rd);
12433 tcg_gen_movi_tl(t1, 4);
12434 gen_op_addr_add(ctx, t0, t0, t1);
12435 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12436 gen_store_gpr(t1, rd+1);
12437 opn = "lwp";
12438 break;
12439 case SWP:
12440 gen_load_gpr(t1, rd);
12441 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12442 tcg_gen_movi_tl(t1, 4);
12443 gen_op_addr_add(ctx, t0, t0, t1);
12444 gen_load_gpr(t1, rd+1);
12445 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12446 opn = "swp";
12447 break;
12448 #ifdef TARGET_MIPS64
12449 case LDP:
12450 if (rd == base) {
12451 generate_exception(ctx, EXCP_RI);
12452 return;
12454 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12455 gen_store_gpr(t1, rd);
12456 tcg_gen_movi_tl(t1, 8);
12457 gen_op_addr_add(ctx, t0, t0, t1);
12458 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12459 gen_store_gpr(t1, rd+1);
12460 opn = "ldp";
12461 break;
12462 case SDP:
12463 gen_load_gpr(t1, rd);
12464 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12465 tcg_gen_movi_tl(t1, 8);
12466 gen_op_addr_add(ctx, t0, t0, t1);
12467 gen_load_gpr(t1, rd+1);
12468 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12469 opn = "sdp";
12470 break;
12471 #endif
12473 (void)opn; /* avoid a compiler warning */
12474 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
12475 tcg_temp_free(t0);
12476 tcg_temp_free(t1);
12479 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
12481 int extension = (ctx->opcode >> 6) & 0x3f;
12482 int minor = (ctx->opcode >> 12) & 0xf;
12483 uint32_t mips32_op;
12485 switch (extension) {
12486 case TEQ:
12487 mips32_op = OPC_TEQ;
12488 goto do_trap;
12489 case TGE:
12490 mips32_op = OPC_TGE;
12491 goto do_trap;
12492 case TGEU:
12493 mips32_op = OPC_TGEU;
12494 goto do_trap;
12495 case TLT:
12496 mips32_op = OPC_TLT;
12497 goto do_trap;
12498 case TLTU:
12499 mips32_op = OPC_TLTU;
12500 goto do_trap;
12501 case TNE:
12502 mips32_op = OPC_TNE;
12503 do_trap:
12504 gen_trap(ctx, mips32_op, rs, rt, -1);
12505 break;
12506 #ifndef CONFIG_USER_ONLY
12507 case MFC0:
12508 case MFC0 + 32:
12509 check_cp0_enabled(ctx);
12510 if (rt == 0) {
12511 /* Treat as NOP. */
12512 break;
12514 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
12515 break;
12516 case MTC0:
12517 case MTC0 + 32:
12518 check_cp0_enabled(ctx);
12520 TCGv t0 = tcg_temp_new();
12522 gen_load_gpr(t0, rt);
12523 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
12524 tcg_temp_free(t0);
12526 break;
12527 #endif
12528 case 0x2a:
12529 switch (minor & 3) {
12530 case MADD_ACC:
12531 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
12532 break;
12533 case MADDU_ACC:
12534 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
12535 break;
12536 case MSUB_ACC:
12537 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
12538 break;
12539 case MSUBU_ACC:
12540 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
12541 break;
12542 default:
12543 goto pool32axf_invalid;
12545 break;
12546 case 0x32:
12547 switch (minor & 3) {
12548 case MULT_ACC:
12549 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
12550 break;
12551 case MULTU_ACC:
12552 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
12553 break;
12554 default:
12555 goto pool32axf_invalid;
12557 break;
12558 case 0x2c:
12559 switch (minor) {
12560 case SEB:
12561 gen_bshfl(ctx, OPC_SEB, rs, rt);
12562 break;
12563 case SEH:
12564 gen_bshfl(ctx, OPC_SEH, rs, rt);
12565 break;
12566 case CLO:
12567 mips32_op = OPC_CLO;
12568 goto do_cl;
12569 case CLZ:
12570 mips32_op = OPC_CLZ;
12571 do_cl:
12572 check_insn(ctx, ISA_MIPS32);
12573 gen_cl(ctx, mips32_op, rt, rs);
12574 break;
12575 case RDHWR:
12576 gen_rdhwr(ctx, rt, rs);
12577 break;
12578 case WSBH:
12579 gen_bshfl(ctx, OPC_WSBH, rs, rt);
12580 break;
12581 case MULT:
12582 mips32_op = OPC_MULT;
12583 goto do_mul;
12584 case MULTU:
12585 mips32_op = OPC_MULTU;
12586 goto do_mul;
12587 case DIV:
12588 mips32_op = OPC_DIV;
12589 goto do_div;
12590 case DIVU:
12591 mips32_op = OPC_DIVU;
12592 goto do_div;
12593 do_div:
12594 check_insn(ctx, ISA_MIPS32);
12595 gen_muldiv(ctx, mips32_op, 0, rs, rt);
12596 break;
12597 case MADD:
12598 mips32_op = OPC_MADD;
12599 goto do_mul;
12600 case MADDU:
12601 mips32_op = OPC_MADDU;
12602 goto do_mul;
12603 case MSUB:
12604 mips32_op = OPC_MSUB;
12605 goto do_mul;
12606 case MSUBU:
12607 mips32_op = OPC_MSUBU;
12608 do_mul:
12609 check_insn(ctx, ISA_MIPS32);
12610 gen_muldiv(ctx, mips32_op, 0, rs, rt);
12611 break;
12612 default:
12613 goto pool32axf_invalid;
12615 break;
12616 case 0x34:
12617 switch (minor) {
12618 case MFC2:
12619 case MTC2:
12620 case MFHC2:
12621 case MTHC2:
12622 case CFC2:
12623 case CTC2:
12624 generate_exception_err(ctx, EXCP_CpU, 2);
12625 break;
12626 default:
12627 goto pool32axf_invalid;
12629 break;
12630 case 0x3c:
12631 switch (minor) {
12632 case JALR:
12633 case JALR_HB:
12634 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
12635 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12636 break;
12637 case JALRS:
12638 case JALRS_HB:
12639 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
12640 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12641 break;
12642 default:
12643 goto pool32axf_invalid;
12645 break;
12646 case 0x05:
12647 switch (minor) {
12648 case RDPGPR:
12649 check_cp0_enabled(ctx);
12650 check_insn(ctx, ISA_MIPS32R2);
12651 gen_load_srsgpr(rt, rs);
12652 break;
12653 case WRPGPR:
12654 check_cp0_enabled(ctx);
12655 check_insn(ctx, ISA_MIPS32R2);
12656 gen_store_srsgpr(rt, rs);
12657 break;
12658 default:
12659 goto pool32axf_invalid;
12661 break;
12662 #ifndef CONFIG_USER_ONLY
12663 case 0x0d:
12664 switch (minor) {
12665 case TLBP:
12666 mips32_op = OPC_TLBP;
12667 goto do_cp0;
12668 case TLBR:
12669 mips32_op = OPC_TLBR;
12670 goto do_cp0;
12671 case TLBWI:
12672 mips32_op = OPC_TLBWI;
12673 goto do_cp0;
12674 case TLBWR:
12675 mips32_op = OPC_TLBWR;
12676 goto do_cp0;
12677 case WAIT:
12678 mips32_op = OPC_WAIT;
12679 goto do_cp0;
12680 case DERET:
12681 mips32_op = OPC_DERET;
12682 goto do_cp0;
12683 case ERET:
12684 mips32_op = OPC_ERET;
12685 do_cp0:
12686 gen_cp0(env, ctx, mips32_op, rt, rs);
12687 break;
12688 default:
12689 goto pool32axf_invalid;
12691 break;
12692 case 0x1d:
12693 switch (minor) {
12694 case DI:
12695 check_cp0_enabled(ctx);
12697 TCGv t0 = tcg_temp_new();
12699 save_cpu_state(ctx, 1);
12700 gen_helper_di(t0, cpu_env);
12701 gen_store_gpr(t0, rs);
12702 /* Stop translation as we may have switched the execution mode */
12703 ctx->bstate = BS_STOP;
12704 tcg_temp_free(t0);
12706 break;
12707 case EI:
12708 check_cp0_enabled(ctx);
12710 TCGv t0 = tcg_temp_new();
12712 save_cpu_state(ctx, 1);
12713 gen_helper_ei(t0, cpu_env);
12714 gen_store_gpr(t0, rs);
12715 /* Stop translation as we may have switched the execution mode */
12716 ctx->bstate = BS_STOP;
12717 tcg_temp_free(t0);
12719 break;
12720 default:
12721 goto pool32axf_invalid;
12723 break;
12724 #endif
12725 case 0x2d:
12726 switch (minor) {
12727 case SYNC:
12728 /* NOP */
12729 break;
12730 case SYSCALL:
12731 generate_exception(ctx, EXCP_SYSCALL);
12732 ctx->bstate = BS_STOP;
12733 break;
12734 case SDBBP:
12735 check_insn(ctx, ISA_MIPS32);
12736 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
12737 generate_exception(ctx, EXCP_DBp);
12738 } else {
12739 generate_exception(ctx, EXCP_DBp);
12741 break;
12742 default:
12743 goto pool32axf_invalid;
12745 break;
12746 case 0x01:
12747 switch (minor & 3) {
12748 case MFHI_ACC:
12749 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
12750 break;
12751 case MFLO_ACC:
12752 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
12753 break;
12754 case MTHI_ACC:
12755 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
12756 break;
12757 case MTLO_ACC:
12758 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
12759 break;
12760 default:
12761 goto pool32axf_invalid;
12763 break;
12764 case 0x35:
12765 switch (minor) {
12766 case MFHI32:
12767 gen_HILO(ctx, OPC_MFHI, 0, rs);
12768 break;
12769 case MFLO32:
12770 gen_HILO(ctx, OPC_MFLO, 0, rs);
12771 break;
12772 case MTHI32:
12773 gen_HILO(ctx, OPC_MTHI, 0, rs);
12774 break;
12775 case MTLO32:
12776 gen_HILO(ctx, OPC_MTLO, 0, rs);
12777 break;
12778 default:
12779 goto pool32axf_invalid;
12781 break;
12782 default:
12783 pool32axf_invalid:
12784 MIPS_INVAL("pool32axf");
12785 generate_exception(ctx, EXCP_RI);
12786 break;
12790 /* Values for microMIPS fmt field. Variable-width, depending on which
12791 formats the instruction supports. */
12793 enum {
12794 FMT_SD_S = 0,
12795 FMT_SD_D = 1,
12797 FMT_SDPS_S = 0,
12798 FMT_SDPS_D = 1,
12799 FMT_SDPS_PS = 2,
12801 FMT_SWL_S = 0,
12802 FMT_SWL_W = 1,
12803 FMT_SWL_L = 2,
12805 FMT_DWL_D = 0,
12806 FMT_DWL_W = 1,
12807 FMT_DWL_L = 2
12810 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
12812 int extension = (ctx->opcode >> 6) & 0x3ff;
12813 uint32_t mips32_op;
12815 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
12816 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
12817 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
12819 switch (extension) {
12820 case FLOAT_1BIT_FMT(CFC1, 0):
12821 mips32_op = OPC_CFC1;
12822 goto do_cp1;
12823 case FLOAT_1BIT_FMT(CTC1, 0):
12824 mips32_op = OPC_CTC1;
12825 goto do_cp1;
12826 case FLOAT_1BIT_FMT(MFC1, 0):
12827 mips32_op = OPC_MFC1;
12828 goto do_cp1;
12829 case FLOAT_1BIT_FMT(MTC1, 0):
12830 mips32_op = OPC_MTC1;
12831 goto do_cp1;
12832 case FLOAT_1BIT_FMT(MFHC1, 0):
12833 mips32_op = OPC_MFHC1;
12834 goto do_cp1;
12835 case FLOAT_1BIT_FMT(MTHC1, 0):
12836 mips32_op = OPC_MTHC1;
12837 do_cp1:
12838 gen_cp1(ctx, mips32_op, rt, rs);
12839 break;
12841 /* Reciprocal square root */
12842 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
12843 mips32_op = OPC_RSQRT_S;
12844 goto do_unaryfp;
12845 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
12846 mips32_op = OPC_RSQRT_D;
12847 goto do_unaryfp;
12849 /* Square root */
12850 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
12851 mips32_op = OPC_SQRT_S;
12852 goto do_unaryfp;
12853 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
12854 mips32_op = OPC_SQRT_D;
12855 goto do_unaryfp;
12857 /* Reciprocal */
12858 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
12859 mips32_op = OPC_RECIP_S;
12860 goto do_unaryfp;
12861 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
12862 mips32_op = OPC_RECIP_D;
12863 goto do_unaryfp;
12865 /* Floor */
12866 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
12867 mips32_op = OPC_FLOOR_L_S;
12868 goto do_unaryfp;
12869 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
12870 mips32_op = OPC_FLOOR_L_D;
12871 goto do_unaryfp;
12872 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
12873 mips32_op = OPC_FLOOR_W_S;
12874 goto do_unaryfp;
12875 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
12876 mips32_op = OPC_FLOOR_W_D;
12877 goto do_unaryfp;
12879 /* Ceiling */
12880 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
12881 mips32_op = OPC_CEIL_L_S;
12882 goto do_unaryfp;
12883 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
12884 mips32_op = OPC_CEIL_L_D;
12885 goto do_unaryfp;
12886 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
12887 mips32_op = OPC_CEIL_W_S;
12888 goto do_unaryfp;
12889 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
12890 mips32_op = OPC_CEIL_W_D;
12891 goto do_unaryfp;
12893 /* Truncation */
12894 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
12895 mips32_op = OPC_TRUNC_L_S;
12896 goto do_unaryfp;
12897 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
12898 mips32_op = OPC_TRUNC_L_D;
12899 goto do_unaryfp;
12900 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
12901 mips32_op = OPC_TRUNC_W_S;
12902 goto do_unaryfp;
12903 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
12904 mips32_op = OPC_TRUNC_W_D;
12905 goto do_unaryfp;
12907 /* Round */
12908 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
12909 mips32_op = OPC_ROUND_L_S;
12910 goto do_unaryfp;
12911 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
12912 mips32_op = OPC_ROUND_L_D;
12913 goto do_unaryfp;
12914 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
12915 mips32_op = OPC_ROUND_W_S;
12916 goto do_unaryfp;
12917 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
12918 mips32_op = OPC_ROUND_W_D;
12919 goto do_unaryfp;
12921 /* Integer to floating-point conversion */
12922 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
12923 mips32_op = OPC_CVT_L_S;
12924 goto do_unaryfp;
12925 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
12926 mips32_op = OPC_CVT_L_D;
12927 goto do_unaryfp;
12928 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
12929 mips32_op = OPC_CVT_W_S;
12930 goto do_unaryfp;
12931 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
12932 mips32_op = OPC_CVT_W_D;
12933 goto do_unaryfp;
12935 /* Paired-foo conversions */
12936 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
12937 mips32_op = OPC_CVT_S_PL;
12938 goto do_unaryfp;
12939 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
12940 mips32_op = OPC_CVT_S_PU;
12941 goto do_unaryfp;
12942 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
12943 mips32_op = OPC_CVT_PW_PS;
12944 goto do_unaryfp;
12945 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
12946 mips32_op = OPC_CVT_PS_PW;
12947 goto do_unaryfp;
12949 /* Floating-point moves */
12950 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
12951 mips32_op = OPC_MOV_S;
12952 goto do_unaryfp;
12953 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
12954 mips32_op = OPC_MOV_D;
12955 goto do_unaryfp;
12956 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
12957 mips32_op = OPC_MOV_PS;
12958 goto do_unaryfp;
12960 /* Absolute value */
12961 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
12962 mips32_op = OPC_ABS_S;
12963 goto do_unaryfp;
12964 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
12965 mips32_op = OPC_ABS_D;
12966 goto do_unaryfp;
12967 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
12968 mips32_op = OPC_ABS_PS;
12969 goto do_unaryfp;
12971 /* Negation */
12972 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
12973 mips32_op = OPC_NEG_S;
12974 goto do_unaryfp;
12975 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
12976 mips32_op = OPC_NEG_D;
12977 goto do_unaryfp;
12978 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
12979 mips32_op = OPC_NEG_PS;
12980 goto do_unaryfp;
12982 /* Reciprocal square root step */
12983 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
12984 mips32_op = OPC_RSQRT1_S;
12985 goto do_unaryfp;
12986 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
12987 mips32_op = OPC_RSQRT1_D;
12988 goto do_unaryfp;
12989 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
12990 mips32_op = OPC_RSQRT1_PS;
12991 goto do_unaryfp;
12993 /* Reciprocal step */
12994 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
12995 mips32_op = OPC_RECIP1_S;
12996 goto do_unaryfp;
12997 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
12998 mips32_op = OPC_RECIP1_S;
12999 goto do_unaryfp;
13000 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13001 mips32_op = OPC_RECIP1_PS;
13002 goto do_unaryfp;
13004 /* Conversions from double */
13005 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13006 mips32_op = OPC_CVT_D_S;
13007 goto do_unaryfp;
13008 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13009 mips32_op = OPC_CVT_D_W;
13010 goto do_unaryfp;
13011 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13012 mips32_op = OPC_CVT_D_L;
13013 goto do_unaryfp;
13015 /* Conversions from single */
13016 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13017 mips32_op = OPC_CVT_S_D;
13018 goto do_unaryfp;
13019 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13020 mips32_op = OPC_CVT_S_W;
13021 goto do_unaryfp;
13022 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13023 mips32_op = OPC_CVT_S_L;
13024 do_unaryfp:
13025 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13026 break;
13028 /* Conditional moves on floating-point codes */
13029 case COND_FLOAT_MOV(MOVT, 0):
13030 case COND_FLOAT_MOV(MOVT, 1):
13031 case COND_FLOAT_MOV(MOVT, 2):
13032 case COND_FLOAT_MOV(MOVT, 3):
13033 case COND_FLOAT_MOV(MOVT, 4):
13034 case COND_FLOAT_MOV(MOVT, 5):
13035 case COND_FLOAT_MOV(MOVT, 6):
13036 case COND_FLOAT_MOV(MOVT, 7):
13037 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13038 break;
13039 case COND_FLOAT_MOV(MOVF, 0):
13040 case COND_FLOAT_MOV(MOVF, 1):
13041 case COND_FLOAT_MOV(MOVF, 2):
13042 case COND_FLOAT_MOV(MOVF, 3):
13043 case COND_FLOAT_MOV(MOVF, 4):
13044 case COND_FLOAT_MOV(MOVF, 5):
13045 case COND_FLOAT_MOV(MOVF, 6):
13046 case COND_FLOAT_MOV(MOVF, 7):
13047 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13048 break;
13049 default:
13050 MIPS_INVAL("pool32fxf");
13051 generate_exception(ctx, EXCP_RI);
13052 break;
13056 static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
13057 uint16_t insn_hw1)
13059 int32_t offset;
13060 uint16_t insn;
13061 int rt, rs, rd, rr;
13062 int16_t imm;
13063 uint32_t op, minor, mips32_op;
13064 uint32_t cond, fmt, cc;
13066 insn = cpu_lduw_code(env, ctx->pc + 2);
13067 ctx->opcode = (ctx->opcode << 16) | insn;
13069 rt = (ctx->opcode >> 21) & 0x1f;
13070 rs = (ctx->opcode >> 16) & 0x1f;
13071 rd = (ctx->opcode >> 11) & 0x1f;
13072 rr = (ctx->opcode >> 6) & 0x1f;
13073 imm = (int16_t) ctx->opcode;
13075 op = (ctx->opcode >> 26) & 0x3f;
13076 switch (op) {
13077 case POOL32A:
13078 minor = ctx->opcode & 0x3f;
13079 switch (minor) {
13080 case 0x00:
13081 minor = (ctx->opcode >> 6) & 0xf;
13082 switch (minor) {
13083 case SLL32:
13084 mips32_op = OPC_SLL;
13085 goto do_shifti;
13086 case SRA:
13087 mips32_op = OPC_SRA;
13088 goto do_shifti;
13089 case SRL32:
13090 mips32_op = OPC_SRL;
13091 goto do_shifti;
13092 case ROTR:
13093 mips32_op = OPC_ROTR;
13094 do_shifti:
13095 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
13096 break;
13097 default:
13098 goto pool32a_invalid;
13100 break;
13101 case 0x10:
13102 minor = (ctx->opcode >> 6) & 0xf;
13103 switch (minor) {
13104 /* Arithmetic */
13105 case ADD:
13106 mips32_op = OPC_ADD;
13107 goto do_arith;
13108 case ADDU32:
13109 mips32_op = OPC_ADDU;
13110 goto do_arith;
13111 case SUB:
13112 mips32_op = OPC_SUB;
13113 goto do_arith;
13114 case SUBU32:
13115 mips32_op = OPC_SUBU;
13116 goto do_arith;
13117 case MUL:
13118 mips32_op = OPC_MUL;
13119 do_arith:
13120 gen_arith(ctx, mips32_op, rd, rs, rt);
13121 break;
13122 /* Shifts */
13123 case SLLV:
13124 mips32_op = OPC_SLLV;
13125 goto do_shift;
13126 case SRLV:
13127 mips32_op = OPC_SRLV;
13128 goto do_shift;
13129 case SRAV:
13130 mips32_op = OPC_SRAV;
13131 goto do_shift;
13132 case ROTRV:
13133 mips32_op = OPC_ROTRV;
13134 do_shift:
13135 gen_shift(ctx, mips32_op, rd, rs, rt);
13136 break;
13137 /* Logical operations */
13138 case AND:
13139 mips32_op = OPC_AND;
13140 goto do_logic;
13141 case OR32:
13142 mips32_op = OPC_OR;
13143 goto do_logic;
13144 case NOR:
13145 mips32_op = OPC_NOR;
13146 goto do_logic;
13147 case XOR32:
13148 mips32_op = OPC_XOR;
13149 do_logic:
13150 gen_logic(ctx, mips32_op, rd, rs, rt);
13151 break;
13152 /* Set less than */
13153 case SLT:
13154 mips32_op = OPC_SLT;
13155 goto do_slt;
13156 case SLTU:
13157 mips32_op = OPC_SLTU;
13158 do_slt:
13159 gen_slt(ctx, mips32_op, rd, rs, rt);
13160 break;
13161 default:
13162 goto pool32a_invalid;
13164 break;
13165 case 0x18:
13166 minor = (ctx->opcode >> 6) & 0xf;
13167 switch (minor) {
13168 /* Conditional moves */
13169 case MOVN:
13170 mips32_op = OPC_MOVN;
13171 goto do_cmov;
13172 case MOVZ:
13173 mips32_op = OPC_MOVZ;
13174 do_cmov:
13175 gen_cond_move(ctx, mips32_op, rd, rs, rt);
13176 break;
13177 case LWXS:
13178 gen_ldxs(ctx, rs, rt, rd);
13179 break;
13180 default:
13181 goto pool32a_invalid;
13183 break;
13184 case INS:
13185 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
13186 return;
13187 case EXT:
13188 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
13189 return;
13190 case POOL32AXF:
13191 gen_pool32axf(env, ctx, rt, rs);
13192 break;
13193 case 0x07:
13194 generate_exception(ctx, EXCP_BREAK);
13195 break;
13196 default:
13197 pool32a_invalid:
13198 MIPS_INVAL("pool32a");
13199 generate_exception(ctx, EXCP_RI);
13200 break;
13202 break;
13203 case POOL32B:
13204 minor = (ctx->opcode >> 12) & 0xf;
13205 switch (minor) {
13206 case CACHE:
13207 check_cp0_enabled(ctx);
13208 /* Treat as no-op. */
13209 break;
13210 case LWC2:
13211 case SWC2:
13212 /* COP2: Not implemented. */
13213 generate_exception_err(ctx, EXCP_CpU, 2);
13214 break;
13215 case LWP:
13216 case SWP:
13217 #ifdef TARGET_MIPS64
13218 case LDP:
13219 case SDP:
13220 #endif
13221 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13222 break;
13223 case LWM32:
13224 case SWM32:
13225 #ifdef TARGET_MIPS64
13226 case LDM:
13227 case SDM:
13228 #endif
13229 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13230 break;
13231 default:
13232 MIPS_INVAL("pool32b");
13233 generate_exception(ctx, EXCP_RI);
13234 break;
13236 break;
13237 case POOL32F:
13238 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
13239 minor = ctx->opcode & 0x3f;
13240 check_cp1_enabled(ctx);
13241 switch (minor) {
13242 case ALNV_PS:
13243 mips32_op = OPC_ALNV_PS;
13244 goto do_madd;
13245 case MADD_S:
13246 mips32_op = OPC_MADD_S;
13247 goto do_madd;
13248 case MADD_D:
13249 mips32_op = OPC_MADD_D;
13250 goto do_madd;
13251 case MADD_PS:
13252 mips32_op = OPC_MADD_PS;
13253 goto do_madd;
13254 case MSUB_S:
13255 mips32_op = OPC_MSUB_S;
13256 goto do_madd;
13257 case MSUB_D:
13258 mips32_op = OPC_MSUB_D;
13259 goto do_madd;
13260 case MSUB_PS:
13261 mips32_op = OPC_MSUB_PS;
13262 goto do_madd;
13263 case NMADD_S:
13264 mips32_op = OPC_NMADD_S;
13265 goto do_madd;
13266 case NMADD_D:
13267 mips32_op = OPC_NMADD_D;
13268 goto do_madd;
13269 case NMADD_PS:
13270 mips32_op = OPC_NMADD_PS;
13271 goto do_madd;
13272 case NMSUB_S:
13273 mips32_op = OPC_NMSUB_S;
13274 goto do_madd;
13275 case NMSUB_D:
13276 mips32_op = OPC_NMSUB_D;
13277 goto do_madd;
13278 case NMSUB_PS:
13279 mips32_op = OPC_NMSUB_PS;
13280 do_madd:
13281 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
13282 break;
13283 case CABS_COND_FMT:
13284 cond = (ctx->opcode >> 6) & 0xf;
13285 cc = (ctx->opcode >> 13) & 0x7;
13286 fmt = (ctx->opcode >> 10) & 0x3;
13287 switch (fmt) {
13288 case 0x0:
13289 gen_cmpabs_s(ctx, cond, rt, rs, cc);
13290 break;
13291 case 0x1:
13292 gen_cmpabs_d(ctx, cond, rt, rs, cc);
13293 break;
13294 case 0x2:
13295 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
13296 break;
13297 default:
13298 goto pool32f_invalid;
13300 break;
13301 case C_COND_FMT:
13302 cond = (ctx->opcode >> 6) & 0xf;
13303 cc = (ctx->opcode >> 13) & 0x7;
13304 fmt = (ctx->opcode >> 10) & 0x3;
13305 switch (fmt) {
13306 case 0x0:
13307 gen_cmp_s(ctx, cond, rt, rs, cc);
13308 break;
13309 case 0x1:
13310 gen_cmp_d(ctx, cond, rt, rs, cc);
13311 break;
13312 case 0x2:
13313 gen_cmp_ps(ctx, cond, rt, rs, cc);
13314 break;
13315 default:
13316 goto pool32f_invalid;
13318 break;
13319 case POOL32FXF:
13320 gen_pool32fxf(ctx, rt, rs);
13321 break;
13322 case 0x00:
13323 /* PLL foo */
13324 switch ((ctx->opcode >> 6) & 0x7) {
13325 case PLL_PS:
13326 mips32_op = OPC_PLL_PS;
13327 goto do_ps;
13328 case PLU_PS:
13329 mips32_op = OPC_PLU_PS;
13330 goto do_ps;
13331 case PUL_PS:
13332 mips32_op = OPC_PUL_PS;
13333 goto do_ps;
13334 case PUU_PS:
13335 mips32_op = OPC_PUU_PS;
13336 goto do_ps;
13337 case CVT_PS_S:
13338 mips32_op = OPC_CVT_PS_S;
13339 do_ps:
13340 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13341 break;
13342 default:
13343 goto pool32f_invalid;
13345 break;
13346 case 0x08:
13347 /* [LS][WDU]XC1 */
13348 switch ((ctx->opcode >> 6) & 0x7) {
13349 case LWXC1:
13350 mips32_op = OPC_LWXC1;
13351 goto do_ldst_cp1;
13352 case SWXC1:
13353 mips32_op = OPC_SWXC1;
13354 goto do_ldst_cp1;
13355 case LDXC1:
13356 mips32_op = OPC_LDXC1;
13357 goto do_ldst_cp1;
13358 case SDXC1:
13359 mips32_op = OPC_SDXC1;
13360 goto do_ldst_cp1;
13361 case LUXC1:
13362 mips32_op = OPC_LUXC1;
13363 goto do_ldst_cp1;
13364 case SUXC1:
13365 mips32_op = OPC_SUXC1;
13366 do_ldst_cp1:
13367 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
13368 break;
13369 default:
13370 goto pool32f_invalid;
13372 break;
13373 case 0x18:
13374 /* 3D insns */
13375 fmt = (ctx->opcode >> 9) & 0x3;
13376 switch ((ctx->opcode >> 6) & 0x7) {
13377 case RSQRT2_FMT:
13378 switch (fmt) {
13379 case FMT_SDPS_S:
13380 mips32_op = OPC_RSQRT2_S;
13381 goto do_3d;
13382 case FMT_SDPS_D:
13383 mips32_op = OPC_RSQRT2_D;
13384 goto do_3d;
13385 case FMT_SDPS_PS:
13386 mips32_op = OPC_RSQRT2_PS;
13387 goto do_3d;
13388 default:
13389 goto pool32f_invalid;
13391 break;
13392 case RECIP2_FMT:
13393 switch (fmt) {
13394 case FMT_SDPS_S:
13395 mips32_op = OPC_RECIP2_S;
13396 goto do_3d;
13397 case FMT_SDPS_D:
13398 mips32_op = OPC_RECIP2_D;
13399 goto do_3d;
13400 case FMT_SDPS_PS:
13401 mips32_op = OPC_RECIP2_PS;
13402 goto do_3d;
13403 default:
13404 goto pool32f_invalid;
13406 break;
13407 case ADDR_PS:
13408 mips32_op = OPC_ADDR_PS;
13409 goto do_3d;
13410 case MULR_PS:
13411 mips32_op = OPC_MULR_PS;
13412 do_3d:
13413 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13414 break;
13415 default:
13416 goto pool32f_invalid;
13418 break;
13419 case 0x20:
13420 /* MOV[FT].fmt and PREFX */
13421 cc = (ctx->opcode >> 13) & 0x7;
13422 fmt = (ctx->opcode >> 9) & 0x3;
13423 switch ((ctx->opcode >> 6) & 0x7) {
13424 case MOVF_FMT:
13425 switch (fmt) {
13426 case FMT_SDPS_S:
13427 gen_movcf_s(rs, rt, cc, 0);
13428 break;
13429 case FMT_SDPS_D:
13430 gen_movcf_d(ctx, rs, rt, cc, 0);
13431 break;
13432 case FMT_SDPS_PS:
13433 gen_movcf_ps(ctx, rs, rt, cc, 0);
13434 break;
13435 default:
13436 goto pool32f_invalid;
13438 break;
13439 case MOVT_FMT:
13440 switch (fmt) {
13441 case FMT_SDPS_S:
13442 gen_movcf_s(rs, rt, cc, 1);
13443 break;
13444 case FMT_SDPS_D:
13445 gen_movcf_d(ctx, rs, rt, cc, 1);
13446 break;
13447 case FMT_SDPS_PS:
13448 gen_movcf_ps(ctx, rs, rt, cc, 1);
13449 break;
13450 default:
13451 goto pool32f_invalid;
13453 break;
13454 case PREFX:
13455 break;
13456 default:
13457 goto pool32f_invalid;
13459 break;
13460 #define FINSN_3ARG_SDPS(prfx) \
13461 switch ((ctx->opcode >> 8) & 0x3) { \
13462 case FMT_SDPS_S: \
13463 mips32_op = OPC_##prfx##_S; \
13464 goto do_fpop; \
13465 case FMT_SDPS_D: \
13466 mips32_op = OPC_##prfx##_D; \
13467 goto do_fpop; \
13468 case FMT_SDPS_PS: \
13469 mips32_op = OPC_##prfx##_PS; \
13470 goto do_fpop; \
13471 default: \
13472 goto pool32f_invalid; \
13474 case 0x30:
13475 /* regular FP ops */
13476 switch ((ctx->opcode >> 6) & 0x3) {
13477 case ADD_FMT:
13478 FINSN_3ARG_SDPS(ADD);
13479 break;
13480 case SUB_FMT:
13481 FINSN_3ARG_SDPS(SUB);
13482 break;
13483 case MUL_FMT:
13484 FINSN_3ARG_SDPS(MUL);
13485 break;
13486 case DIV_FMT:
13487 fmt = (ctx->opcode >> 8) & 0x3;
13488 if (fmt == 1) {
13489 mips32_op = OPC_DIV_D;
13490 } else if (fmt == 0) {
13491 mips32_op = OPC_DIV_S;
13492 } else {
13493 goto pool32f_invalid;
13495 goto do_fpop;
13496 default:
13497 goto pool32f_invalid;
13499 break;
13500 case 0x38:
13501 /* cmovs */
13502 switch ((ctx->opcode >> 6) & 0x3) {
13503 case MOVN_FMT:
13504 FINSN_3ARG_SDPS(MOVN);
13505 break;
13506 case MOVZ_FMT:
13507 FINSN_3ARG_SDPS(MOVZ);
13508 break;
13509 default:
13510 goto pool32f_invalid;
13512 break;
13513 do_fpop:
13514 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13515 break;
13516 default:
13517 pool32f_invalid:
13518 MIPS_INVAL("pool32f");
13519 generate_exception(ctx, EXCP_RI);
13520 break;
13522 } else {
13523 generate_exception_err(ctx, EXCP_CpU, 1);
13525 break;
13526 case POOL32I:
13527 minor = (ctx->opcode >> 21) & 0x1f;
13528 switch (minor) {
13529 case BLTZ:
13530 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
13531 break;
13532 case BLTZAL:
13533 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
13534 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13535 break;
13536 case BLTZALS:
13537 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
13538 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13539 break;
13540 case BGEZ:
13541 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
13542 break;
13543 case BGEZAL:
13544 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
13545 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13546 break;
13547 case BGEZALS:
13548 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
13549 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13550 break;
13551 case BLEZ:
13552 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
13553 break;
13554 case BGTZ:
13555 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
13556 break;
13558 /* Traps */
13559 case TLTI:
13560 mips32_op = OPC_TLTI;
13561 goto do_trapi;
13562 case TGEI:
13563 mips32_op = OPC_TGEI;
13564 goto do_trapi;
13565 case TLTIU:
13566 mips32_op = OPC_TLTIU;
13567 goto do_trapi;
13568 case TGEIU:
13569 mips32_op = OPC_TGEIU;
13570 goto do_trapi;
13571 case TNEI:
13572 mips32_op = OPC_TNEI;
13573 goto do_trapi;
13574 case TEQI:
13575 mips32_op = OPC_TEQI;
13576 do_trapi:
13577 gen_trap(ctx, mips32_op, rs, -1, imm);
13578 break;
13580 case BNEZC:
13581 case BEQZC:
13582 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
13583 4, rs, 0, imm << 1, 0);
13584 /* Compact branches don't have a delay slot, so just let
13585 the normal delay slot handling take us to the branch
13586 target. */
13587 break;
13588 case LUI:
13589 gen_logic_imm(ctx, OPC_LUI, rs, -1, imm);
13590 break;
13591 case SYNCI:
13592 /* Break the TB to be able to sync copied instructions
13593 immediately */
13594 ctx->bstate = BS_STOP;
13595 break;
13596 case BC2F:
13597 case BC2T:
13598 /* COP2: Not implemented. */
13599 generate_exception_err(ctx, EXCP_CpU, 2);
13600 break;
13601 case BC1F:
13602 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
13603 goto do_cp1branch;
13604 case BC1T:
13605 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
13606 goto do_cp1branch;
13607 case BC1ANY4F:
13608 mips32_op = OPC_BC1FANY4;
13609 goto do_cp1mips3d;
13610 case BC1ANY4T:
13611 mips32_op = OPC_BC1TANY4;
13612 do_cp1mips3d:
13613 check_cop1x(ctx);
13614 check_insn(ctx, ASE_MIPS3D);
13615 /* Fall through */
13616 do_cp1branch:
13617 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
13618 check_cp1_enabled(ctx);
13619 gen_compute_branch1(ctx, mips32_op,
13620 (ctx->opcode >> 18) & 0x7, imm << 1);
13621 } else {
13622 generate_exception_err(ctx, EXCP_CpU, 1);
13624 break;
13625 case BPOSGE64:
13626 case BPOSGE32:
13627 /* MIPS DSP: not implemented */
13628 /* Fall through */
13629 default:
13630 MIPS_INVAL("pool32i");
13631 generate_exception(ctx, EXCP_RI);
13632 break;
13634 break;
13635 case POOL32C:
13636 minor = (ctx->opcode >> 12) & 0xf;
13637 switch (minor) {
13638 case LWL:
13639 mips32_op = OPC_LWL;
13640 goto do_ld_lr;
13641 case SWL:
13642 mips32_op = OPC_SWL;
13643 goto do_st_lr;
13644 case LWR:
13645 mips32_op = OPC_LWR;
13646 goto do_ld_lr;
13647 case SWR:
13648 mips32_op = OPC_SWR;
13649 goto do_st_lr;
13650 #if defined(TARGET_MIPS64)
13651 case LDL:
13652 mips32_op = OPC_LDL;
13653 goto do_ld_lr;
13654 case SDL:
13655 mips32_op = OPC_SDL;
13656 goto do_st_lr;
13657 case LDR:
13658 mips32_op = OPC_LDR;
13659 goto do_ld_lr;
13660 case SDR:
13661 mips32_op = OPC_SDR;
13662 goto do_st_lr;
13663 case LWU:
13664 mips32_op = OPC_LWU;
13665 goto do_ld_lr;
13666 case LLD:
13667 mips32_op = OPC_LLD;
13668 goto do_ld_lr;
13669 #endif
13670 case LL:
13671 mips32_op = OPC_LL;
13672 goto do_ld_lr;
13673 do_ld_lr:
13674 gen_ld(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
13675 break;
13676 do_st_lr:
13677 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
13678 break;
13679 case SC:
13680 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
13681 break;
13682 #if defined(TARGET_MIPS64)
13683 case SCD:
13684 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
13685 break;
13686 #endif
13687 case PREF:
13688 /* Treat as no-op */
13689 break;
13690 default:
13691 MIPS_INVAL("pool32c");
13692 generate_exception(ctx, EXCP_RI);
13693 break;
13695 break;
13696 case ADDI32:
13697 mips32_op = OPC_ADDI;
13698 goto do_addi;
13699 case ADDIU32:
13700 mips32_op = OPC_ADDIU;
13701 do_addi:
13702 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
13703 break;
13705 /* Logical operations */
13706 case ORI32:
13707 mips32_op = OPC_ORI;
13708 goto do_logici;
13709 case XORI32:
13710 mips32_op = OPC_XORI;
13711 goto do_logici;
13712 case ANDI32:
13713 mips32_op = OPC_ANDI;
13714 do_logici:
13715 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
13716 break;
13718 /* Set less than immediate */
13719 case SLTI32:
13720 mips32_op = OPC_SLTI;
13721 goto do_slti;
13722 case SLTIU32:
13723 mips32_op = OPC_SLTIU;
13724 do_slti:
13725 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
13726 break;
13727 case JALX32:
13728 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
13729 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
13730 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13731 break;
13732 case JALS32:
13733 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
13734 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
13735 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13736 break;
13737 case BEQ32:
13738 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
13739 break;
13740 case BNE32:
13741 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
13742 break;
13743 case J32:
13744 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
13745 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
13746 break;
13747 case JAL32:
13748 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
13749 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
13750 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13751 break;
13752 /* Floating point (COP1) */
13753 case LWC132:
13754 mips32_op = OPC_LWC1;
13755 goto do_cop1;
13756 case LDC132:
13757 mips32_op = OPC_LDC1;
13758 goto do_cop1;
13759 case SWC132:
13760 mips32_op = OPC_SWC1;
13761 goto do_cop1;
13762 case SDC132:
13763 mips32_op = OPC_SDC1;
13764 do_cop1:
13765 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
13766 break;
13767 case ADDIUPC:
13769 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
13770 int offset = SIMM(ctx->opcode, 0, 23) << 2;
13772 gen_addiupc(ctx, reg, offset, 0, 0);
13774 break;
13775 /* Loads and stores */
13776 case LB32:
13777 mips32_op = OPC_LB;
13778 goto do_ld;
13779 case LBU32:
13780 mips32_op = OPC_LBU;
13781 goto do_ld;
13782 case LH32:
13783 mips32_op = OPC_LH;
13784 goto do_ld;
13785 case LHU32:
13786 mips32_op = OPC_LHU;
13787 goto do_ld;
13788 case LW32:
13789 mips32_op = OPC_LW;
13790 goto do_ld;
13791 #ifdef TARGET_MIPS64
13792 case LD32:
13793 mips32_op = OPC_LD;
13794 goto do_ld;
13795 case SD32:
13796 mips32_op = OPC_SD;
13797 goto do_st;
13798 #endif
13799 case SB32:
13800 mips32_op = OPC_SB;
13801 goto do_st;
13802 case SH32:
13803 mips32_op = OPC_SH;
13804 goto do_st;
13805 case SW32:
13806 mips32_op = OPC_SW;
13807 goto do_st;
13808 do_ld:
13809 gen_ld(ctx, mips32_op, rt, rs, imm);
13810 break;
13811 do_st:
13812 gen_st(ctx, mips32_op, rt, rs, imm);
13813 break;
13814 default:
13815 generate_exception(ctx, EXCP_RI);
13816 break;
13820 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
13822 uint32_t op;
13824 /* make sure instructions are on a halfword boundary */
13825 if (ctx->pc & 0x1) {
13826 env->CP0_BadVAddr = ctx->pc;
13827 generate_exception(ctx, EXCP_AdEL);
13828 ctx->bstate = BS_STOP;
13829 return 2;
13832 op = (ctx->opcode >> 10) & 0x3f;
13833 /* Enforce properly-sized instructions in a delay slot */
13834 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
13835 switch (op & 0x7) { /* MSB-3..MSB-5 */
13836 case 0:
13837 /* POOL32A, POOL32B, POOL32I, POOL32C */
13838 case 4:
13839 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
13840 case 5:
13841 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
13842 case 6:
13843 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
13844 case 7:
13845 /* LB32, LH32, LWC132, LDC132, LW32 */
13846 if (ctx->hflags & MIPS_HFLAG_BDS16) {
13847 generate_exception(ctx, EXCP_RI);
13848 /* Just stop translation; the user is confused. */
13849 ctx->bstate = BS_STOP;
13850 return 2;
13852 break;
13853 case 1:
13854 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
13855 case 2:
13856 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
13857 case 3:
13858 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
13859 if (ctx->hflags & MIPS_HFLAG_BDS32) {
13860 generate_exception(ctx, EXCP_RI);
13861 /* Just stop translation; the user is confused. */
13862 ctx->bstate = BS_STOP;
13863 return 2;
13865 break;
13869 switch (op) {
13870 case POOL16A:
13872 int rd = mmreg(uMIPS_RD(ctx->opcode));
13873 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
13874 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
13875 uint32_t opc = 0;
13877 switch (ctx->opcode & 0x1) {
13878 case ADDU16:
13879 opc = OPC_ADDU;
13880 break;
13881 case SUBU16:
13882 opc = OPC_SUBU;
13883 break;
13886 gen_arith(ctx, opc, rd, rs1, rs2);
13888 break;
13889 case POOL16B:
13891 int rd = mmreg(uMIPS_RD(ctx->opcode));
13892 int rs = mmreg(uMIPS_RS(ctx->opcode));
13893 int amount = (ctx->opcode >> 1) & 0x7;
13894 uint32_t opc = 0;
13895 amount = amount == 0 ? 8 : amount;
13897 switch (ctx->opcode & 0x1) {
13898 case SLL16:
13899 opc = OPC_SLL;
13900 break;
13901 case SRL16:
13902 opc = OPC_SRL;
13903 break;
13906 gen_shift_imm(ctx, opc, rd, rs, amount);
13908 break;
13909 case POOL16C:
13910 gen_pool16c_insn(ctx);
13911 break;
13912 case LWGP16:
13914 int rd = mmreg(uMIPS_RD(ctx->opcode));
13915 int rb = 28; /* GP */
13916 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
13918 gen_ld(ctx, OPC_LW, rd, rb, offset);
13920 break;
13921 case POOL16F:
13922 if (ctx->opcode & 1) {
13923 generate_exception(ctx, EXCP_RI);
13924 } else {
13925 /* MOVEP */
13926 int enc_dest = uMIPS_RD(ctx->opcode);
13927 int enc_rt = uMIPS_RS2(ctx->opcode);
13928 int enc_rs = uMIPS_RS1(ctx->opcode);
13929 int rd, rs, re, rt;
13930 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
13931 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
13932 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
13934 rd = rd_enc[enc_dest];
13935 re = re_enc[enc_dest];
13936 rs = rs_rt_enc[enc_rs];
13937 rt = rs_rt_enc[enc_rt];
13939 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
13940 gen_arith_imm(ctx, OPC_ADDIU, re, rt, 0);
13942 break;
13943 case LBU16:
13945 int rd = mmreg(uMIPS_RD(ctx->opcode));
13946 int rb = mmreg(uMIPS_RS(ctx->opcode));
13947 int16_t offset = ZIMM(ctx->opcode, 0, 4);
13948 offset = (offset == 0xf ? -1 : offset);
13950 gen_ld(ctx, OPC_LBU, rd, rb, offset);
13952 break;
13953 case LHU16:
13955 int rd = mmreg(uMIPS_RD(ctx->opcode));
13956 int rb = mmreg(uMIPS_RS(ctx->opcode));
13957 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
13959 gen_ld(ctx, OPC_LHU, rd, rb, offset);
13961 break;
13962 case LWSP16:
13964 int rd = (ctx->opcode >> 5) & 0x1f;
13965 int rb = 29; /* SP */
13966 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
13968 gen_ld(ctx, OPC_LW, rd, rb, offset);
13970 break;
13971 case LW16:
13973 int rd = mmreg(uMIPS_RD(ctx->opcode));
13974 int rb = mmreg(uMIPS_RS(ctx->opcode));
13975 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
13977 gen_ld(ctx, OPC_LW, rd, rb, offset);
13979 break;
13980 case SB16:
13982 int rd = mmreg2(uMIPS_RD(ctx->opcode));
13983 int rb = mmreg(uMIPS_RS(ctx->opcode));
13984 int16_t offset = ZIMM(ctx->opcode, 0, 4);
13986 gen_st(ctx, OPC_SB, rd, rb, offset);
13988 break;
13989 case SH16:
13991 int rd = mmreg2(uMIPS_RD(ctx->opcode));
13992 int rb = mmreg(uMIPS_RS(ctx->opcode));
13993 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
13995 gen_st(ctx, OPC_SH, rd, rb, offset);
13997 break;
13998 case SWSP16:
14000 int rd = (ctx->opcode >> 5) & 0x1f;
14001 int rb = 29; /* SP */
14002 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
14004 gen_st(ctx, OPC_SW, rd, rb, offset);
14006 break;
14007 case SW16:
14009 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14010 int rb = mmreg(uMIPS_RS(ctx->opcode));
14011 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
14013 gen_st(ctx, OPC_SW, rd, rb, offset);
14015 break;
14016 case MOVE16:
14018 int rd = uMIPS_RD5(ctx->opcode);
14019 int rs = uMIPS_RS5(ctx->opcode);
14021 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
14023 break;
14024 case ANDI16:
14025 gen_andi16(ctx);
14026 break;
14027 case POOL16D:
14028 switch (ctx->opcode & 0x1) {
14029 case ADDIUS5:
14030 gen_addius5(ctx);
14031 break;
14032 case ADDIUSP:
14033 gen_addiusp(ctx);
14034 break;
14036 break;
14037 case POOL16E:
14038 switch (ctx->opcode & 0x1) {
14039 case ADDIUR2:
14040 gen_addiur2(ctx);
14041 break;
14042 case ADDIUR1SP:
14043 gen_addiur1sp(ctx);
14044 break;
14046 break;
14047 case B16:
14048 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
14049 SIMM(ctx->opcode, 0, 10) << 1, 4);
14050 break;
14051 case BNEZ16:
14052 case BEQZ16:
14053 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
14054 mmreg(uMIPS_RD(ctx->opcode)),
14055 0, SIMM(ctx->opcode, 0, 7) << 1, 4);
14056 break;
14057 case LI16:
14059 int reg = mmreg(uMIPS_RD(ctx->opcode));
14060 int imm = ZIMM(ctx->opcode, 0, 7);
14062 imm = (imm == 0x7f ? -1 : imm);
14063 tcg_gen_movi_tl(cpu_gpr[reg], imm);
14065 break;
14066 case RES_20:
14067 case RES_28:
14068 case RES_29:
14069 case RES_30:
14070 case RES_31:
14071 case RES_38:
14072 case RES_39:
14073 generate_exception(ctx, EXCP_RI);
14074 break;
14075 default:
14076 decode_micromips32_opc (env, ctx, op);
14077 return 4;
14080 return 2;
14083 /* SmartMIPS extension to MIPS32 */
14085 #if defined(TARGET_MIPS64)
14087 /* MDMX extension to MIPS64 */
14089 #endif
14091 /* MIPSDSP functions. */
14092 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
14093 int rd, int base, int offset)
14095 const char *opn = "ldx";
14096 TCGv t0;
14098 check_dsp(ctx);
14099 t0 = tcg_temp_new();
14101 if (base == 0) {
14102 gen_load_gpr(t0, offset);
14103 } else if (offset == 0) {
14104 gen_load_gpr(t0, base);
14105 } else {
14106 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
14109 switch (opc) {
14110 case OPC_LBUX:
14111 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
14112 gen_store_gpr(t0, rd);
14113 opn = "lbux";
14114 break;
14115 case OPC_LHX:
14116 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
14117 gen_store_gpr(t0, rd);
14118 opn = "lhx";
14119 break;
14120 case OPC_LWX:
14121 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
14122 gen_store_gpr(t0, rd);
14123 opn = "lwx";
14124 break;
14125 #if defined(TARGET_MIPS64)
14126 case OPC_LDX:
14127 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
14128 gen_store_gpr(t0, rd);
14129 opn = "ldx";
14130 break;
14131 #endif
14133 (void)opn; /* avoid a compiler warning */
14134 MIPS_DEBUG("%s %s, %s(%s)", opn,
14135 regnames[rd], regnames[offset], regnames[base]);
14136 tcg_temp_free(t0);
14139 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
14140 int ret, int v1, int v2)
14142 const char *opn = "mipsdsp arith";
14143 TCGv v1_t;
14144 TCGv v2_t;
14146 if (ret == 0) {
14147 /* Treat as NOP. */
14148 MIPS_DEBUG("NOP");
14149 return;
14152 v1_t = tcg_temp_new();
14153 v2_t = tcg_temp_new();
14155 gen_load_gpr(v1_t, v1);
14156 gen_load_gpr(v2_t, v2);
14158 switch (op1) {
14159 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
14160 case OPC_MULT_G_2E:
14161 check_dspr2(ctx);
14162 switch (op2) {
14163 case OPC_ADDUH_QB:
14164 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
14165 break;
14166 case OPC_ADDUH_R_QB:
14167 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
14168 break;
14169 case OPC_ADDQH_PH:
14170 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
14171 break;
14172 case OPC_ADDQH_R_PH:
14173 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
14174 break;
14175 case OPC_ADDQH_W:
14176 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
14177 break;
14178 case OPC_ADDQH_R_W:
14179 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
14180 break;
14181 case OPC_SUBUH_QB:
14182 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
14183 break;
14184 case OPC_SUBUH_R_QB:
14185 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
14186 break;
14187 case OPC_SUBQH_PH:
14188 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
14189 break;
14190 case OPC_SUBQH_R_PH:
14191 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
14192 break;
14193 case OPC_SUBQH_W:
14194 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
14195 break;
14196 case OPC_SUBQH_R_W:
14197 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
14198 break;
14200 break;
14201 case OPC_ABSQ_S_PH_DSP:
14202 switch (op2) {
14203 case OPC_ABSQ_S_QB:
14204 check_dspr2(ctx);
14205 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
14206 break;
14207 case OPC_ABSQ_S_PH:
14208 check_dsp(ctx);
14209 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
14210 break;
14211 case OPC_ABSQ_S_W:
14212 check_dsp(ctx);
14213 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
14214 break;
14215 case OPC_PRECEQ_W_PHL:
14216 check_dsp(ctx);
14217 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
14218 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
14219 break;
14220 case OPC_PRECEQ_W_PHR:
14221 check_dsp(ctx);
14222 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
14223 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
14224 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
14225 break;
14226 case OPC_PRECEQU_PH_QBL:
14227 check_dsp(ctx);
14228 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
14229 break;
14230 case OPC_PRECEQU_PH_QBR:
14231 check_dsp(ctx);
14232 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
14233 break;
14234 case OPC_PRECEQU_PH_QBLA:
14235 check_dsp(ctx);
14236 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
14237 break;
14238 case OPC_PRECEQU_PH_QBRA:
14239 check_dsp(ctx);
14240 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
14241 break;
14242 case OPC_PRECEU_PH_QBL:
14243 check_dsp(ctx);
14244 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
14245 break;
14246 case OPC_PRECEU_PH_QBR:
14247 check_dsp(ctx);
14248 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
14249 break;
14250 case OPC_PRECEU_PH_QBLA:
14251 check_dsp(ctx);
14252 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
14253 break;
14254 case OPC_PRECEU_PH_QBRA:
14255 check_dsp(ctx);
14256 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
14257 break;
14259 break;
14260 case OPC_ADDU_QB_DSP:
14261 switch (op2) {
14262 case OPC_ADDQ_PH:
14263 check_dsp(ctx);
14264 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14265 break;
14266 case OPC_ADDQ_S_PH:
14267 check_dsp(ctx);
14268 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14269 break;
14270 case OPC_ADDQ_S_W:
14271 check_dsp(ctx);
14272 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14273 break;
14274 case OPC_ADDU_QB:
14275 check_dsp(ctx);
14276 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14277 break;
14278 case OPC_ADDU_S_QB:
14279 check_dsp(ctx);
14280 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14281 break;
14282 case OPC_ADDU_PH:
14283 check_dspr2(ctx);
14284 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14285 break;
14286 case OPC_ADDU_S_PH:
14287 check_dspr2(ctx);
14288 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14289 break;
14290 case OPC_SUBQ_PH:
14291 check_dsp(ctx);
14292 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14293 break;
14294 case OPC_SUBQ_S_PH:
14295 check_dsp(ctx);
14296 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14297 break;
14298 case OPC_SUBQ_S_W:
14299 check_dsp(ctx);
14300 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14301 break;
14302 case OPC_SUBU_QB:
14303 check_dsp(ctx);
14304 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14305 break;
14306 case OPC_SUBU_S_QB:
14307 check_dsp(ctx);
14308 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14309 break;
14310 case OPC_SUBU_PH:
14311 check_dspr2(ctx);
14312 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14313 break;
14314 case OPC_SUBU_S_PH:
14315 check_dspr2(ctx);
14316 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14317 break;
14318 case OPC_ADDSC:
14319 check_dsp(ctx);
14320 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14321 break;
14322 case OPC_ADDWC:
14323 check_dsp(ctx);
14324 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14325 break;
14326 case OPC_MODSUB:
14327 check_dsp(ctx);
14328 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
14329 break;
14330 case OPC_RADDU_W_QB:
14331 check_dsp(ctx);
14332 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
14333 break;
14335 break;
14336 case OPC_CMPU_EQ_QB_DSP:
14337 switch (op2) {
14338 case OPC_PRECR_QB_PH:
14339 check_dspr2(ctx);
14340 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
14341 break;
14342 case OPC_PRECRQ_QB_PH:
14343 check_dsp(ctx);
14344 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
14345 break;
14346 case OPC_PRECR_SRA_PH_W:
14347 check_dspr2(ctx);
14349 TCGv_i32 sa_t = tcg_const_i32(v2);
14350 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
14351 cpu_gpr[ret]);
14352 tcg_temp_free_i32(sa_t);
14353 break;
14355 case OPC_PRECR_SRA_R_PH_W:
14356 check_dspr2(ctx);
14358 TCGv_i32 sa_t = tcg_const_i32(v2);
14359 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
14360 cpu_gpr[ret]);
14361 tcg_temp_free_i32(sa_t);
14362 break;
14364 case OPC_PRECRQ_PH_W:
14365 check_dsp(ctx);
14366 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
14367 break;
14368 case OPC_PRECRQ_RS_PH_W:
14369 check_dsp(ctx);
14370 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14371 break;
14372 case OPC_PRECRQU_S_QB_PH:
14373 check_dsp(ctx);
14374 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14375 break;
14377 break;
14378 #ifdef TARGET_MIPS64
14379 case OPC_ABSQ_S_QH_DSP:
14380 switch (op2) {
14381 case OPC_PRECEQ_L_PWL:
14382 check_dsp(ctx);
14383 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
14384 break;
14385 case OPC_PRECEQ_L_PWR:
14386 check_dsp(ctx);
14387 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
14388 break;
14389 case OPC_PRECEQ_PW_QHL:
14390 check_dsp(ctx);
14391 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
14392 break;
14393 case OPC_PRECEQ_PW_QHR:
14394 check_dsp(ctx);
14395 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
14396 break;
14397 case OPC_PRECEQ_PW_QHLA:
14398 check_dsp(ctx);
14399 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
14400 break;
14401 case OPC_PRECEQ_PW_QHRA:
14402 check_dsp(ctx);
14403 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
14404 break;
14405 case OPC_PRECEQU_QH_OBL:
14406 check_dsp(ctx);
14407 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
14408 break;
14409 case OPC_PRECEQU_QH_OBR:
14410 check_dsp(ctx);
14411 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
14412 break;
14413 case OPC_PRECEQU_QH_OBLA:
14414 check_dsp(ctx);
14415 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
14416 break;
14417 case OPC_PRECEQU_QH_OBRA:
14418 check_dsp(ctx);
14419 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
14420 break;
14421 case OPC_PRECEU_QH_OBL:
14422 check_dsp(ctx);
14423 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
14424 break;
14425 case OPC_PRECEU_QH_OBR:
14426 check_dsp(ctx);
14427 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
14428 break;
14429 case OPC_PRECEU_QH_OBLA:
14430 check_dsp(ctx);
14431 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
14432 break;
14433 case OPC_PRECEU_QH_OBRA:
14434 check_dsp(ctx);
14435 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
14436 break;
14437 case OPC_ABSQ_S_OB:
14438 check_dspr2(ctx);
14439 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
14440 break;
14441 case OPC_ABSQ_S_PW:
14442 check_dsp(ctx);
14443 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
14444 break;
14445 case OPC_ABSQ_S_QH:
14446 check_dsp(ctx);
14447 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
14448 break;
14450 break;
14451 case OPC_ADDU_OB_DSP:
14452 switch (op2) {
14453 case OPC_RADDU_L_OB:
14454 check_dsp(ctx);
14455 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
14456 break;
14457 case OPC_SUBQ_PW:
14458 check_dsp(ctx);
14459 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14460 break;
14461 case OPC_SUBQ_S_PW:
14462 check_dsp(ctx);
14463 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14464 break;
14465 case OPC_SUBQ_QH:
14466 check_dsp(ctx);
14467 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14468 break;
14469 case OPC_SUBQ_S_QH:
14470 check_dsp(ctx);
14471 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14472 break;
14473 case OPC_SUBU_OB:
14474 check_dsp(ctx);
14475 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14476 break;
14477 case OPC_SUBU_S_OB:
14478 check_dsp(ctx);
14479 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14480 break;
14481 case OPC_SUBU_QH:
14482 check_dspr2(ctx);
14483 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14484 break;
14485 case OPC_SUBU_S_QH:
14486 check_dspr2(ctx);
14487 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14488 break;
14489 case OPC_SUBUH_OB:
14490 check_dspr2(ctx);
14491 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
14492 break;
14493 case OPC_SUBUH_R_OB:
14494 check_dspr2(ctx);
14495 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
14496 break;
14497 case OPC_ADDQ_PW:
14498 check_dsp(ctx);
14499 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14500 break;
14501 case OPC_ADDQ_S_PW:
14502 check_dsp(ctx);
14503 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14504 break;
14505 case OPC_ADDQ_QH:
14506 check_dsp(ctx);
14507 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14508 break;
14509 case OPC_ADDQ_S_QH:
14510 check_dsp(ctx);
14511 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14512 break;
14513 case OPC_ADDU_OB:
14514 check_dsp(ctx);
14515 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14516 break;
14517 case OPC_ADDU_S_OB:
14518 check_dsp(ctx);
14519 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14520 break;
14521 case OPC_ADDU_QH:
14522 check_dspr2(ctx);
14523 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14524 break;
14525 case OPC_ADDU_S_QH:
14526 check_dspr2(ctx);
14527 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14528 break;
14529 case OPC_ADDUH_OB:
14530 check_dspr2(ctx);
14531 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
14532 break;
14533 case OPC_ADDUH_R_OB:
14534 check_dspr2(ctx);
14535 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
14536 break;
14538 break;
14539 case OPC_CMPU_EQ_OB_DSP:
14540 switch (op2) {
14541 case OPC_PRECR_OB_QH:
14542 check_dspr2(ctx);
14543 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
14544 break;
14545 case OPC_PRECR_SRA_QH_PW:
14546 check_dspr2(ctx);
14548 TCGv_i32 ret_t = tcg_const_i32(ret);
14549 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
14550 tcg_temp_free_i32(ret_t);
14551 break;
14553 case OPC_PRECR_SRA_R_QH_PW:
14554 check_dspr2(ctx);
14556 TCGv_i32 sa_v = tcg_const_i32(ret);
14557 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
14558 tcg_temp_free_i32(sa_v);
14559 break;
14561 case OPC_PRECRQ_OB_QH:
14562 check_dsp(ctx);
14563 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
14564 break;
14565 case OPC_PRECRQ_PW_L:
14566 check_dsp(ctx);
14567 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
14568 break;
14569 case OPC_PRECRQ_QH_PW:
14570 check_dsp(ctx);
14571 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
14572 break;
14573 case OPC_PRECRQ_RS_QH_PW:
14574 check_dsp(ctx);
14575 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14576 break;
14577 case OPC_PRECRQU_S_OB_QH:
14578 check_dsp(ctx);
14579 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14580 break;
14582 break;
14583 #endif
14586 tcg_temp_free(v1_t);
14587 tcg_temp_free(v2_t);
14589 (void)opn; /* avoid a compiler warning */
14590 MIPS_DEBUG("%s", opn);
14593 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
14594 int ret, int v1, int v2)
14596 uint32_t op2;
14597 const char *opn = "mipsdsp shift";
14598 TCGv t0;
14599 TCGv v1_t;
14600 TCGv v2_t;
14602 if (ret == 0) {
14603 /* Treat as NOP. */
14604 MIPS_DEBUG("NOP");
14605 return;
14608 t0 = tcg_temp_new();
14609 v1_t = tcg_temp_new();
14610 v2_t = tcg_temp_new();
14612 tcg_gen_movi_tl(t0, v1);
14613 gen_load_gpr(v1_t, v1);
14614 gen_load_gpr(v2_t, v2);
14616 switch (opc) {
14617 case OPC_SHLL_QB_DSP:
14619 op2 = MASK_SHLL_QB(ctx->opcode);
14620 switch (op2) {
14621 case OPC_SHLL_QB:
14622 check_dsp(ctx);
14623 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
14624 break;
14625 case OPC_SHLLV_QB:
14626 check_dsp(ctx);
14627 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14628 break;
14629 case OPC_SHLL_PH:
14630 check_dsp(ctx);
14631 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
14632 break;
14633 case OPC_SHLLV_PH:
14634 check_dsp(ctx);
14635 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14636 break;
14637 case OPC_SHLL_S_PH:
14638 check_dsp(ctx);
14639 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
14640 break;
14641 case OPC_SHLLV_S_PH:
14642 check_dsp(ctx);
14643 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14644 break;
14645 case OPC_SHLL_S_W:
14646 check_dsp(ctx);
14647 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
14648 break;
14649 case OPC_SHLLV_S_W:
14650 check_dsp(ctx);
14651 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14652 break;
14653 case OPC_SHRL_QB:
14654 check_dsp(ctx);
14655 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
14656 break;
14657 case OPC_SHRLV_QB:
14658 check_dsp(ctx);
14659 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
14660 break;
14661 case OPC_SHRL_PH:
14662 check_dspr2(ctx);
14663 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
14664 break;
14665 case OPC_SHRLV_PH:
14666 check_dspr2(ctx);
14667 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
14668 break;
14669 case OPC_SHRA_QB:
14670 check_dspr2(ctx);
14671 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
14672 break;
14673 case OPC_SHRA_R_QB:
14674 check_dspr2(ctx);
14675 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
14676 break;
14677 case OPC_SHRAV_QB:
14678 check_dspr2(ctx);
14679 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
14680 break;
14681 case OPC_SHRAV_R_QB:
14682 check_dspr2(ctx);
14683 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
14684 break;
14685 case OPC_SHRA_PH:
14686 check_dsp(ctx);
14687 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
14688 break;
14689 case OPC_SHRA_R_PH:
14690 check_dsp(ctx);
14691 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
14692 break;
14693 case OPC_SHRAV_PH:
14694 check_dsp(ctx);
14695 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
14696 break;
14697 case OPC_SHRAV_R_PH:
14698 check_dsp(ctx);
14699 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
14700 break;
14701 case OPC_SHRA_R_W:
14702 check_dsp(ctx);
14703 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
14704 break;
14705 case OPC_SHRAV_R_W:
14706 check_dsp(ctx);
14707 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
14708 break;
14709 default: /* Invalid */
14710 MIPS_INVAL("MASK SHLL.QB");
14711 generate_exception(ctx, EXCP_RI);
14712 break;
14714 break;
14716 #ifdef TARGET_MIPS64
14717 case OPC_SHLL_OB_DSP:
14718 op2 = MASK_SHLL_OB(ctx->opcode);
14719 switch (op2) {
14720 case OPC_SHLL_PW:
14721 check_dsp(ctx);
14722 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
14723 break;
14724 case OPC_SHLLV_PW:
14725 check_dsp(ctx);
14726 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14727 break;
14728 case OPC_SHLL_S_PW:
14729 check_dsp(ctx);
14730 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
14731 break;
14732 case OPC_SHLLV_S_PW:
14733 check_dsp(ctx);
14734 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14735 break;
14736 case OPC_SHLL_OB:
14737 check_dsp(ctx);
14738 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
14739 break;
14740 case OPC_SHLLV_OB:
14741 check_dsp(ctx);
14742 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14743 break;
14744 case OPC_SHLL_QH:
14745 check_dsp(ctx);
14746 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
14747 break;
14748 case OPC_SHLLV_QH:
14749 check_dsp(ctx);
14750 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14751 break;
14752 case OPC_SHLL_S_QH:
14753 check_dsp(ctx);
14754 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
14755 break;
14756 case OPC_SHLLV_S_QH:
14757 check_dsp(ctx);
14758 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14759 break;
14760 case OPC_SHRA_OB:
14761 check_dspr2(ctx);
14762 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
14763 break;
14764 case OPC_SHRAV_OB:
14765 check_dspr2(ctx);
14766 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
14767 break;
14768 case OPC_SHRA_R_OB:
14769 check_dspr2(ctx);
14770 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
14771 break;
14772 case OPC_SHRAV_R_OB:
14773 check_dspr2(ctx);
14774 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
14775 break;
14776 case OPC_SHRA_PW:
14777 check_dsp(ctx);
14778 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
14779 break;
14780 case OPC_SHRAV_PW:
14781 check_dsp(ctx);
14782 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
14783 break;
14784 case OPC_SHRA_R_PW:
14785 check_dsp(ctx);
14786 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
14787 break;
14788 case OPC_SHRAV_R_PW:
14789 check_dsp(ctx);
14790 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
14791 break;
14792 case OPC_SHRA_QH:
14793 check_dsp(ctx);
14794 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
14795 break;
14796 case OPC_SHRAV_QH:
14797 check_dsp(ctx);
14798 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
14799 break;
14800 case OPC_SHRA_R_QH:
14801 check_dsp(ctx);
14802 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
14803 break;
14804 case OPC_SHRAV_R_QH:
14805 check_dsp(ctx);
14806 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
14807 break;
14808 case OPC_SHRL_OB:
14809 check_dsp(ctx);
14810 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
14811 break;
14812 case OPC_SHRLV_OB:
14813 check_dsp(ctx);
14814 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
14815 break;
14816 case OPC_SHRL_QH:
14817 check_dspr2(ctx);
14818 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
14819 break;
14820 case OPC_SHRLV_QH:
14821 check_dspr2(ctx);
14822 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
14823 break;
14824 default: /* Invalid */
14825 MIPS_INVAL("MASK SHLL.OB");
14826 generate_exception(ctx, EXCP_RI);
14827 break;
14829 break;
14830 #endif
14833 tcg_temp_free(t0);
14834 tcg_temp_free(v1_t);
14835 tcg_temp_free(v2_t);
14836 (void)opn; /* avoid a compiler warning */
14837 MIPS_DEBUG("%s", opn);
14840 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
14841 int ret, int v1, int v2, int check_ret)
14843 const char *opn = "mipsdsp multiply";
14844 TCGv_i32 t0;
14845 TCGv v1_t;
14846 TCGv v2_t;
14848 if ((ret == 0) && (check_ret == 1)) {
14849 /* Treat as NOP. */
14850 MIPS_DEBUG("NOP");
14851 return;
14854 t0 = tcg_temp_new_i32();
14855 v1_t = tcg_temp_new();
14856 v2_t = tcg_temp_new();
14858 tcg_gen_movi_i32(t0, ret);
14859 gen_load_gpr(v1_t, v1);
14860 gen_load_gpr(v2_t, v2);
14862 switch (op1) {
14863 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
14864 * the same mask and op1. */
14865 case OPC_MULT_G_2E:
14866 check_dspr2(ctx);
14867 switch (op2) {
14868 case OPC_MUL_PH:
14869 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14870 break;
14871 case OPC_MUL_S_PH:
14872 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14873 break;
14874 case OPC_MULQ_S_W:
14875 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14876 break;
14877 case OPC_MULQ_RS_W:
14878 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14879 break;
14881 break;
14882 case OPC_DPA_W_PH_DSP:
14883 switch (op2) {
14884 case OPC_DPAU_H_QBL:
14885 check_dsp(ctx);
14886 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
14887 break;
14888 case OPC_DPAU_H_QBR:
14889 check_dsp(ctx);
14890 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
14891 break;
14892 case OPC_DPSU_H_QBL:
14893 check_dsp(ctx);
14894 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
14895 break;
14896 case OPC_DPSU_H_QBR:
14897 check_dsp(ctx);
14898 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
14899 break;
14900 case OPC_DPA_W_PH:
14901 check_dspr2(ctx);
14902 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
14903 break;
14904 case OPC_DPAX_W_PH:
14905 check_dspr2(ctx);
14906 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
14907 break;
14908 case OPC_DPAQ_S_W_PH:
14909 check_dsp(ctx);
14910 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
14911 break;
14912 case OPC_DPAQX_S_W_PH:
14913 check_dspr2(ctx);
14914 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
14915 break;
14916 case OPC_DPAQX_SA_W_PH:
14917 check_dspr2(ctx);
14918 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
14919 break;
14920 case OPC_DPS_W_PH:
14921 check_dspr2(ctx);
14922 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
14923 break;
14924 case OPC_DPSX_W_PH:
14925 check_dspr2(ctx);
14926 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
14927 break;
14928 case OPC_DPSQ_S_W_PH:
14929 check_dsp(ctx);
14930 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
14931 break;
14932 case OPC_DPSQX_S_W_PH:
14933 check_dspr2(ctx);
14934 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
14935 break;
14936 case OPC_DPSQX_SA_W_PH:
14937 check_dspr2(ctx);
14938 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
14939 break;
14940 case OPC_MULSAQ_S_W_PH:
14941 check_dsp(ctx);
14942 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
14943 break;
14944 case OPC_DPAQ_SA_L_W:
14945 check_dsp(ctx);
14946 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
14947 break;
14948 case OPC_DPSQ_SA_L_W:
14949 check_dsp(ctx);
14950 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
14951 break;
14952 case OPC_MAQ_S_W_PHL:
14953 check_dsp(ctx);
14954 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
14955 break;
14956 case OPC_MAQ_S_W_PHR:
14957 check_dsp(ctx);
14958 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
14959 break;
14960 case OPC_MAQ_SA_W_PHL:
14961 check_dsp(ctx);
14962 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
14963 break;
14964 case OPC_MAQ_SA_W_PHR:
14965 check_dsp(ctx);
14966 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
14967 break;
14968 case OPC_MULSA_W_PH:
14969 check_dspr2(ctx);
14970 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
14971 break;
14973 break;
14974 #ifdef TARGET_MIPS64
14975 case OPC_DPAQ_W_QH_DSP:
14977 int ac = ret & 0x03;
14978 tcg_gen_movi_i32(t0, ac);
14980 switch (op2) {
14981 case OPC_DMADD:
14982 check_dsp(ctx);
14983 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
14984 break;
14985 case OPC_DMADDU:
14986 check_dsp(ctx);
14987 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
14988 break;
14989 case OPC_DMSUB:
14990 check_dsp(ctx);
14991 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
14992 break;
14993 case OPC_DMSUBU:
14994 check_dsp(ctx);
14995 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
14996 break;
14997 case OPC_DPA_W_QH:
14998 check_dspr2(ctx);
14999 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
15000 break;
15001 case OPC_DPAQ_S_W_QH:
15002 check_dsp(ctx);
15003 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15004 break;
15005 case OPC_DPAQ_SA_L_PW:
15006 check_dsp(ctx);
15007 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
15008 break;
15009 case OPC_DPAU_H_OBL:
15010 check_dsp(ctx);
15011 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
15012 break;
15013 case OPC_DPAU_H_OBR:
15014 check_dsp(ctx);
15015 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
15016 break;
15017 case OPC_DPS_W_QH:
15018 check_dspr2(ctx);
15019 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
15020 break;
15021 case OPC_DPSQ_S_W_QH:
15022 check_dsp(ctx);
15023 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15024 break;
15025 case OPC_DPSQ_SA_L_PW:
15026 check_dsp(ctx);
15027 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
15028 break;
15029 case OPC_DPSU_H_OBL:
15030 check_dsp(ctx);
15031 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
15032 break;
15033 case OPC_DPSU_H_OBR:
15034 check_dsp(ctx);
15035 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
15036 break;
15037 case OPC_MAQ_S_L_PWL:
15038 check_dsp(ctx);
15039 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
15040 break;
15041 case OPC_MAQ_S_L_PWR:
15042 check_dsp(ctx);
15043 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
15044 break;
15045 case OPC_MAQ_S_W_QHLL:
15046 check_dsp(ctx);
15047 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
15048 break;
15049 case OPC_MAQ_SA_W_QHLL:
15050 check_dsp(ctx);
15051 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
15052 break;
15053 case OPC_MAQ_S_W_QHLR:
15054 check_dsp(ctx);
15055 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
15056 break;
15057 case OPC_MAQ_SA_W_QHLR:
15058 check_dsp(ctx);
15059 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
15060 break;
15061 case OPC_MAQ_S_W_QHRL:
15062 check_dsp(ctx);
15063 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
15064 break;
15065 case OPC_MAQ_SA_W_QHRL:
15066 check_dsp(ctx);
15067 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
15068 break;
15069 case OPC_MAQ_S_W_QHRR:
15070 check_dsp(ctx);
15071 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
15072 break;
15073 case OPC_MAQ_SA_W_QHRR:
15074 check_dsp(ctx);
15075 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
15076 break;
15077 case OPC_MULSAQ_S_L_PW:
15078 check_dsp(ctx);
15079 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
15080 break;
15081 case OPC_MULSAQ_S_W_QH:
15082 check_dsp(ctx);
15083 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15084 break;
15087 break;
15088 #endif
15089 case OPC_ADDU_QB_DSP:
15090 switch (op2) {
15091 case OPC_MULEU_S_PH_QBL:
15092 check_dsp(ctx);
15093 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15094 break;
15095 case OPC_MULEU_S_PH_QBR:
15096 check_dsp(ctx);
15097 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15098 break;
15099 case OPC_MULQ_RS_PH:
15100 check_dsp(ctx);
15101 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15102 break;
15103 case OPC_MULEQ_S_W_PHL:
15104 check_dsp(ctx);
15105 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15106 break;
15107 case OPC_MULEQ_S_W_PHR:
15108 check_dsp(ctx);
15109 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15110 break;
15111 case OPC_MULQ_S_PH:
15112 check_dspr2(ctx);
15113 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15114 break;
15116 break;
15117 #ifdef TARGET_MIPS64
15118 case OPC_ADDU_OB_DSP:
15119 switch (op2) {
15120 case OPC_MULEQ_S_PW_QHL:
15121 check_dsp(ctx);
15122 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15123 break;
15124 case OPC_MULEQ_S_PW_QHR:
15125 check_dsp(ctx);
15126 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15127 break;
15128 case OPC_MULEU_S_QH_OBL:
15129 check_dsp(ctx);
15130 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15131 break;
15132 case OPC_MULEU_S_QH_OBR:
15133 check_dsp(ctx);
15134 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15135 break;
15136 case OPC_MULQ_RS_QH:
15137 check_dsp(ctx);
15138 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15139 break;
15141 break;
15142 #endif
15145 tcg_temp_free_i32(t0);
15146 tcg_temp_free(v1_t);
15147 tcg_temp_free(v2_t);
15149 (void)opn; /* avoid a compiler warning */
15150 MIPS_DEBUG("%s", opn);
15154 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
15155 int ret, int val)
15157 const char *opn = "mipsdsp Bit/ Manipulation";
15158 int16_t imm;
15159 TCGv t0;
15160 TCGv val_t;
15162 if (ret == 0) {
15163 /* Treat as NOP. */
15164 MIPS_DEBUG("NOP");
15165 return;
15168 t0 = tcg_temp_new();
15169 val_t = tcg_temp_new();
15170 gen_load_gpr(val_t, val);
15172 switch (op1) {
15173 case OPC_ABSQ_S_PH_DSP:
15174 switch (op2) {
15175 case OPC_BITREV:
15176 check_dsp(ctx);
15177 gen_helper_bitrev(cpu_gpr[ret], val_t);
15178 break;
15179 case OPC_REPL_QB:
15180 check_dsp(ctx);
15182 target_long result;
15183 imm = (ctx->opcode >> 16) & 0xFF;
15184 result = (uint32_t)imm << 24 |
15185 (uint32_t)imm << 16 |
15186 (uint32_t)imm << 8 |
15187 (uint32_t)imm;
15188 result = (int32_t)result;
15189 tcg_gen_movi_tl(cpu_gpr[ret], result);
15191 break;
15192 case OPC_REPLV_QB:
15193 check_dsp(ctx);
15194 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
15195 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
15196 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15197 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
15198 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15199 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15200 break;
15201 case OPC_REPL_PH:
15202 check_dsp(ctx);
15204 imm = (ctx->opcode >> 16) & 0x03FF;
15205 imm = (int16_t)(imm << 6) >> 6;
15206 tcg_gen_movi_tl(cpu_gpr[ret], \
15207 (target_long)((int32_t)imm << 16 | \
15208 (uint16_t)imm));
15210 break;
15211 case OPC_REPLV_PH:
15212 check_dsp(ctx);
15213 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
15214 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
15215 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15216 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15217 break;
15219 break;
15220 #ifdef TARGET_MIPS64
15221 case OPC_ABSQ_S_QH_DSP:
15222 switch (op2) {
15223 case OPC_REPL_OB:
15224 check_dsp(ctx);
15226 target_long temp;
15228 imm = (ctx->opcode >> 16) & 0xFF;
15229 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
15230 temp = (temp << 16) | temp;
15231 temp = (temp << 32) | temp;
15232 tcg_gen_movi_tl(cpu_gpr[ret], temp);
15233 break;
15235 case OPC_REPL_PW:
15236 check_dsp(ctx);
15238 target_long temp;
15240 imm = (ctx->opcode >> 16) & 0x03FF;
15241 imm = (int16_t)(imm << 6) >> 6;
15242 temp = ((target_long)imm << 32) \
15243 | ((target_long)imm & 0xFFFFFFFF);
15244 tcg_gen_movi_tl(cpu_gpr[ret], temp);
15245 break;
15247 case OPC_REPL_QH:
15248 check_dsp(ctx);
15250 target_long temp;
15252 imm = (ctx->opcode >> 16) & 0x03FF;
15253 imm = (int16_t)(imm << 6) >> 6;
15255 temp = ((uint64_t)(uint16_t)imm << 48) |
15256 ((uint64_t)(uint16_t)imm << 32) |
15257 ((uint64_t)(uint16_t)imm << 16) |
15258 (uint64_t)(uint16_t)imm;
15259 tcg_gen_movi_tl(cpu_gpr[ret], temp);
15260 break;
15262 case OPC_REPLV_OB:
15263 check_dsp(ctx);
15264 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
15265 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
15266 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15267 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
15268 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15269 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
15270 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15271 break;
15272 case OPC_REPLV_PW:
15273 check_dsp(ctx);
15274 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
15275 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
15276 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15277 break;
15278 case OPC_REPLV_QH:
15279 check_dsp(ctx);
15280 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
15281 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
15282 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15283 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
15284 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
15285 break;
15287 break;
15288 #endif
15290 tcg_temp_free(t0);
15291 tcg_temp_free(val_t);
15293 (void)opn; /* avoid a compiler warning */
15294 MIPS_DEBUG("%s", opn);
15297 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
15298 uint32_t op1, uint32_t op2,
15299 int ret, int v1, int v2, int check_ret)
15301 const char *opn = "mipsdsp add compare pick";
15302 TCGv t1;
15303 TCGv v1_t;
15304 TCGv v2_t;
15306 if ((ret == 0) && (check_ret == 1)) {
15307 /* Treat as NOP. */
15308 MIPS_DEBUG("NOP");
15309 return;
15312 t1 = tcg_temp_new();
15313 v1_t = tcg_temp_new();
15314 v2_t = tcg_temp_new();
15316 gen_load_gpr(v1_t, v1);
15317 gen_load_gpr(v2_t, v2);
15319 switch (op1) {
15320 case OPC_CMPU_EQ_QB_DSP:
15321 switch (op2) {
15322 case OPC_CMPU_EQ_QB:
15323 check_dsp(ctx);
15324 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
15325 break;
15326 case OPC_CMPU_LT_QB:
15327 check_dsp(ctx);
15328 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
15329 break;
15330 case OPC_CMPU_LE_QB:
15331 check_dsp(ctx);
15332 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
15333 break;
15334 case OPC_CMPGU_EQ_QB:
15335 check_dsp(ctx);
15336 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
15337 break;
15338 case OPC_CMPGU_LT_QB:
15339 check_dsp(ctx);
15340 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
15341 break;
15342 case OPC_CMPGU_LE_QB:
15343 check_dsp(ctx);
15344 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
15345 break;
15346 case OPC_CMPGDU_EQ_QB:
15347 check_dspr2(ctx);
15348 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
15349 tcg_gen_mov_tl(cpu_gpr[ret], t1);
15350 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
15351 tcg_gen_shli_tl(t1, t1, 24);
15352 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
15353 break;
15354 case OPC_CMPGDU_LT_QB:
15355 check_dspr2(ctx);
15356 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
15357 tcg_gen_mov_tl(cpu_gpr[ret], t1);
15358 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
15359 tcg_gen_shli_tl(t1, t1, 24);
15360 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
15361 break;
15362 case OPC_CMPGDU_LE_QB:
15363 check_dspr2(ctx);
15364 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
15365 tcg_gen_mov_tl(cpu_gpr[ret], t1);
15366 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
15367 tcg_gen_shli_tl(t1, t1, 24);
15368 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
15369 break;
15370 case OPC_CMP_EQ_PH:
15371 check_dsp(ctx);
15372 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
15373 break;
15374 case OPC_CMP_LT_PH:
15375 check_dsp(ctx);
15376 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
15377 break;
15378 case OPC_CMP_LE_PH:
15379 check_dsp(ctx);
15380 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
15381 break;
15382 case OPC_PICK_QB:
15383 check_dsp(ctx);
15384 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15385 break;
15386 case OPC_PICK_PH:
15387 check_dsp(ctx);
15388 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15389 break;
15390 case OPC_PACKRL_PH:
15391 check_dsp(ctx);
15392 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
15393 break;
15395 break;
15396 #ifdef TARGET_MIPS64
15397 case OPC_CMPU_EQ_OB_DSP:
15398 switch (op2) {
15399 case OPC_CMP_EQ_PW:
15400 check_dsp(ctx);
15401 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
15402 break;
15403 case OPC_CMP_LT_PW:
15404 check_dsp(ctx);
15405 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
15406 break;
15407 case OPC_CMP_LE_PW:
15408 check_dsp(ctx);
15409 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
15410 break;
15411 case OPC_CMP_EQ_QH:
15412 check_dsp(ctx);
15413 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
15414 break;
15415 case OPC_CMP_LT_QH:
15416 check_dsp(ctx);
15417 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
15418 break;
15419 case OPC_CMP_LE_QH:
15420 check_dsp(ctx);
15421 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
15422 break;
15423 case OPC_CMPGDU_EQ_OB:
15424 check_dspr2(ctx);
15425 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15426 break;
15427 case OPC_CMPGDU_LT_OB:
15428 check_dspr2(ctx);
15429 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15430 break;
15431 case OPC_CMPGDU_LE_OB:
15432 check_dspr2(ctx);
15433 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15434 break;
15435 case OPC_CMPGU_EQ_OB:
15436 check_dsp(ctx);
15437 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
15438 break;
15439 case OPC_CMPGU_LT_OB:
15440 check_dsp(ctx);
15441 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
15442 break;
15443 case OPC_CMPGU_LE_OB:
15444 check_dsp(ctx);
15445 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
15446 break;
15447 case OPC_CMPU_EQ_OB:
15448 check_dsp(ctx);
15449 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
15450 break;
15451 case OPC_CMPU_LT_OB:
15452 check_dsp(ctx);
15453 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
15454 break;
15455 case OPC_CMPU_LE_OB:
15456 check_dsp(ctx);
15457 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
15458 break;
15459 case OPC_PACKRL_PW:
15460 check_dsp(ctx);
15461 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
15462 break;
15463 case OPC_PICK_OB:
15464 check_dsp(ctx);
15465 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15466 break;
15467 case OPC_PICK_PW:
15468 check_dsp(ctx);
15469 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15470 break;
15471 case OPC_PICK_QH:
15472 check_dsp(ctx);
15473 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15474 break;
15476 break;
15477 #endif
15480 tcg_temp_free(t1);
15481 tcg_temp_free(v1_t);
15482 tcg_temp_free(v2_t);
15484 (void)opn; /* avoid a compiler warning */
15485 MIPS_DEBUG("%s", opn);
15488 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
15489 uint32_t op1, int rt, int rs, int sa)
15491 const char *opn = "mipsdsp append/dappend";
15492 TCGv t0;
15494 check_dspr2(ctx);
15496 if (rt == 0) {
15497 /* Treat as NOP. */
15498 MIPS_DEBUG("NOP");
15499 return;
15502 t0 = tcg_temp_new();
15503 gen_load_gpr(t0, rs);
15505 switch (op1) {
15506 case OPC_APPEND_DSP:
15507 switch (MASK_APPEND(ctx->opcode)) {
15508 case OPC_APPEND:
15509 if (sa != 0) {
15510 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
15512 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15513 break;
15514 case OPC_PREPEND:
15515 if (sa != 0) {
15516 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
15517 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
15518 tcg_gen_shli_tl(t0, t0, 32 - sa);
15519 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15521 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15522 break;
15523 case OPC_BALIGN:
15524 sa &= 3;
15525 if (sa != 0 && sa != 2) {
15526 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
15527 tcg_gen_ext32u_tl(t0, t0);
15528 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
15529 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15531 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15532 break;
15533 default: /* Invalid */
15534 MIPS_INVAL("MASK APPEND");
15535 generate_exception(ctx, EXCP_RI);
15536 break;
15538 break;
15539 #ifdef TARGET_MIPS64
15540 case OPC_DAPPEND_DSP:
15541 switch (MASK_DAPPEND(ctx->opcode)) {
15542 case OPC_DAPPEND:
15543 if (sa != 0) {
15544 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
15546 break;
15547 case OPC_PREPENDD:
15548 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
15549 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
15550 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
15551 break;
15552 case OPC_PREPENDW:
15553 if (sa != 0) {
15554 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
15555 tcg_gen_shli_tl(t0, t0, 64 - sa);
15556 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15558 break;
15559 case OPC_DBALIGN:
15560 sa &= 7;
15561 if (sa != 0 && sa != 2 && sa != 4) {
15562 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
15563 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
15564 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15566 break;
15567 default: /* Invalid */
15568 MIPS_INVAL("MASK DAPPEND");
15569 generate_exception(ctx, EXCP_RI);
15570 break;
15572 break;
15573 #endif
15575 tcg_temp_free(t0);
15576 (void)opn; /* avoid a compiler warning */
15577 MIPS_DEBUG("%s", opn);
15580 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
15581 int ret, int v1, int v2, int check_ret)
15584 const char *opn = "mipsdsp accumulator";
15585 TCGv t0;
15586 TCGv t1;
15587 TCGv v1_t;
15588 TCGv v2_t;
15589 int16_t imm;
15591 if ((ret == 0) && (check_ret == 1)) {
15592 /* Treat as NOP. */
15593 MIPS_DEBUG("NOP");
15594 return;
15597 t0 = tcg_temp_new();
15598 t1 = tcg_temp_new();
15599 v1_t = tcg_temp_new();
15600 v2_t = tcg_temp_new();
15602 gen_load_gpr(v1_t, v1);
15603 gen_load_gpr(v2_t, v2);
15605 switch (op1) {
15606 case OPC_EXTR_W_DSP:
15607 check_dsp(ctx);
15608 switch (op2) {
15609 case OPC_EXTR_W:
15610 tcg_gen_movi_tl(t0, v2);
15611 tcg_gen_movi_tl(t1, v1);
15612 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
15613 break;
15614 case OPC_EXTR_R_W:
15615 tcg_gen_movi_tl(t0, v2);
15616 tcg_gen_movi_tl(t1, v1);
15617 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
15618 break;
15619 case OPC_EXTR_RS_W:
15620 tcg_gen_movi_tl(t0, v2);
15621 tcg_gen_movi_tl(t1, v1);
15622 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
15623 break;
15624 case OPC_EXTR_S_H:
15625 tcg_gen_movi_tl(t0, v2);
15626 tcg_gen_movi_tl(t1, v1);
15627 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15628 break;
15629 case OPC_EXTRV_S_H:
15630 tcg_gen_movi_tl(t0, v2);
15631 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
15632 break;
15633 case OPC_EXTRV_W:
15634 tcg_gen_movi_tl(t0, v2);
15635 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15636 break;
15637 case OPC_EXTRV_R_W:
15638 tcg_gen_movi_tl(t0, v2);
15639 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15640 break;
15641 case OPC_EXTRV_RS_W:
15642 tcg_gen_movi_tl(t0, v2);
15643 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15644 break;
15645 case OPC_EXTP:
15646 tcg_gen_movi_tl(t0, v2);
15647 tcg_gen_movi_tl(t1, v1);
15648 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
15649 break;
15650 case OPC_EXTPV:
15651 tcg_gen_movi_tl(t0, v2);
15652 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
15653 break;
15654 case OPC_EXTPDP:
15655 tcg_gen_movi_tl(t0, v2);
15656 tcg_gen_movi_tl(t1, v1);
15657 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
15658 break;
15659 case OPC_EXTPDPV:
15660 tcg_gen_movi_tl(t0, v2);
15661 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
15662 break;
15663 case OPC_SHILO:
15664 imm = (ctx->opcode >> 20) & 0x3F;
15665 tcg_gen_movi_tl(t0, ret);
15666 tcg_gen_movi_tl(t1, imm);
15667 gen_helper_shilo(t0, t1, cpu_env);
15668 break;
15669 case OPC_SHILOV:
15670 tcg_gen_movi_tl(t0, ret);
15671 gen_helper_shilo(t0, v1_t, cpu_env);
15672 break;
15673 case OPC_MTHLIP:
15674 tcg_gen_movi_tl(t0, ret);
15675 gen_helper_mthlip(t0, v1_t, cpu_env);
15676 break;
15677 case OPC_WRDSP:
15678 imm = (ctx->opcode >> 11) & 0x3FF;
15679 tcg_gen_movi_tl(t0, imm);
15680 gen_helper_wrdsp(v1_t, t0, cpu_env);
15681 break;
15682 case OPC_RDDSP:
15683 imm = (ctx->opcode >> 16) & 0x03FF;
15684 tcg_gen_movi_tl(t0, imm);
15685 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
15686 break;
15688 break;
15689 #ifdef TARGET_MIPS64
15690 case OPC_DEXTR_W_DSP:
15691 check_dsp(ctx);
15692 switch (op2) {
15693 case OPC_DMTHLIP:
15694 tcg_gen_movi_tl(t0, ret);
15695 gen_helper_dmthlip(v1_t, t0, cpu_env);
15696 break;
15697 case OPC_DSHILO:
15699 int shift = (ctx->opcode >> 19) & 0x7F;
15700 int ac = (ctx->opcode >> 11) & 0x03;
15701 tcg_gen_movi_tl(t0, shift);
15702 tcg_gen_movi_tl(t1, ac);
15703 gen_helper_dshilo(t0, t1, cpu_env);
15704 break;
15706 case OPC_DSHILOV:
15708 int ac = (ctx->opcode >> 11) & 0x03;
15709 tcg_gen_movi_tl(t0, ac);
15710 gen_helper_dshilo(v1_t, t0, cpu_env);
15711 break;
15713 case OPC_DEXTP:
15714 tcg_gen_movi_tl(t0, v2);
15715 tcg_gen_movi_tl(t1, v1);
15717 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
15718 break;
15719 case OPC_DEXTPV:
15720 tcg_gen_movi_tl(t0, v2);
15721 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
15722 break;
15723 case OPC_DEXTPDP:
15724 tcg_gen_movi_tl(t0, v2);
15725 tcg_gen_movi_tl(t1, v1);
15726 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
15727 break;
15728 case OPC_DEXTPDPV:
15729 tcg_gen_movi_tl(t0, v2);
15730 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
15731 break;
15732 case OPC_DEXTR_L:
15733 tcg_gen_movi_tl(t0, v2);
15734 tcg_gen_movi_tl(t1, v1);
15735 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
15736 break;
15737 case OPC_DEXTR_R_L:
15738 tcg_gen_movi_tl(t0, v2);
15739 tcg_gen_movi_tl(t1, v1);
15740 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
15741 break;
15742 case OPC_DEXTR_RS_L:
15743 tcg_gen_movi_tl(t0, v2);
15744 tcg_gen_movi_tl(t1, v1);
15745 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
15746 break;
15747 case OPC_DEXTR_W:
15748 tcg_gen_movi_tl(t0, v2);
15749 tcg_gen_movi_tl(t1, v1);
15750 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
15751 break;
15752 case OPC_DEXTR_R_W:
15753 tcg_gen_movi_tl(t0, v2);
15754 tcg_gen_movi_tl(t1, v1);
15755 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
15756 break;
15757 case OPC_DEXTR_RS_W:
15758 tcg_gen_movi_tl(t0, v2);
15759 tcg_gen_movi_tl(t1, v1);
15760 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
15761 break;
15762 case OPC_DEXTR_S_H:
15763 tcg_gen_movi_tl(t0, v2);
15764 tcg_gen_movi_tl(t1, v1);
15765 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15766 break;
15767 case OPC_DEXTRV_S_H:
15768 tcg_gen_movi_tl(t0, v2);
15769 tcg_gen_movi_tl(t1, v1);
15770 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15771 break;
15772 case OPC_DEXTRV_L:
15773 tcg_gen_movi_tl(t0, v2);
15774 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15775 break;
15776 case OPC_DEXTRV_R_L:
15777 tcg_gen_movi_tl(t0, v2);
15778 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15779 break;
15780 case OPC_DEXTRV_RS_L:
15781 tcg_gen_movi_tl(t0, v2);
15782 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15783 break;
15784 case OPC_DEXTRV_W:
15785 tcg_gen_movi_tl(t0, v2);
15786 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15787 break;
15788 case OPC_DEXTRV_R_W:
15789 tcg_gen_movi_tl(t0, v2);
15790 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15791 break;
15792 case OPC_DEXTRV_RS_W:
15793 tcg_gen_movi_tl(t0, v2);
15794 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15795 break;
15797 break;
15798 #endif
15801 tcg_temp_free(t0);
15802 tcg_temp_free(t1);
15803 tcg_temp_free(v1_t);
15804 tcg_temp_free(v2_t);
15806 (void)opn; /* avoid a compiler warning */
15807 MIPS_DEBUG("%s", opn);
15810 /* End MIPSDSP functions. */
15812 /* Compact Branches */
15813 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
15814 int rs, int rt, int32_t offset)
15816 int bcond_compute = 0;
15817 TCGv t0 = tcg_temp_new();
15818 TCGv t1 = tcg_temp_new();
15820 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15821 #ifdef MIPS_DEBUG_DISAS
15822 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
15823 "\n", ctx->pc);
15824 #endif
15825 generate_exception(ctx, EXCP_RI);
15826 goto out;
15829 /* Load needed operands and calculate btarget */
15830 switch (opc) {
15831 /* compact branch */
15832 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
15833 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
15834 gen_load_gpr(t0, rs);
15835 gen_load_gpr(t1, rt);
15836 bcond_compute = 1;
15837 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15838 if (rs <= rt && rs == 0) {
15839 /* OPC_BEQZALC, OPC_BNEZALC */
15840 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15842 break;
15843 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
15844 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
15845 gen_load_gpr(t0, rs);
15846 gen_load_gpr(t1, rt);
15847 bcond_compute = 1;
15848 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15849 break;
15850 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
15851 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
15852 if (rs == 0 || rs == rt) {
15853 /* OPC_BLEZALC, OPC_BGEZALC */
15854 /* OPC_BGTZALC, OPC_BLTZALC */
15855 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15857 gen_load_gpr(t0, rs);
15858 gen_load_gpr(t1, rt);
15859 bcond_compute = 1;
15860 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15861 break;
15862 case OPC_BC:
15863 case OPC_BALC:
15864 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15865 break;
15866 case OPC_BEQZC:
15867 case OPC_BNEZC:
15868 if (rs != 0) {
15869 /* OPC_BEQZC, OPC_BNEZC */
15870 gen_load_gpr(t0, rs);
15871 bcond_compute = 1;
15872 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15873 } else {
15874 /* OPC_JIC, OPC_JIALC */
15875 TCGv tbase = tcg_temp_new();
15876 TCGv toffset = tcg_temp_new();
15878 gen_load_gpr(tbase, rt);
15879 tcg_gen_movi_tl(toffset, offset);
15880 gen_op_addr_add(ctx, btarget, tbase, toffset);
15881 tcg_temp_free(tbase);
15882 tcg_temp_free(toffset);
15884 break;
15885 default:
15886 MIPS_INVAL("Compact branch/jump");
15887 generate_exception(ctx, EXCP_RI);
15888 goto out;
15891 if (bcond_compute == 0) {
15892 /* Uncoditional compact branch */
15893 switch (opc) {
15894 case OPC_JIALC:
15895 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15896 /* Fallthrough */
15897 case OPC_JIC:
15898 ctx->hflags |= MIPS_HFLAG_BR;
15899 break;
15900 case OPC_BALC:
15901 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15902 /* Fallthrough */
15903 case OPC_BC:
15904 ctx->hflags |= MIPS_HFLAG_B;
15905 break;
15906 default:
15907 MIPS_INVAL("Compact branch/jump");
15908 generate_exception(ctx, EXCP_RI);
15909 goto out;
15912 /* Generating branch here as compact branches don't have delay slot */
15913 gen_branch(ctx, 4);
15914 } else {
15915 /* Conditional compact branch */
15916 int fs = gen_new_label();
15917 save_cpu_state(ctx, 0);
15919 switch (opc) {
15920 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
15921 if (rs == 0 && rt != 0) {
15922 /* OPC_BLEZALC */
15923 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
15924 } else if (rs != 0 && rt != 0 && rs == rt) {
15925 /* OPC_BGEZALC */
15926 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
15927 } else {
15928 /* OPC_BGEUC */
15929 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
15931 break;
15932 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
15933 if (rs == 0 && rt != 0) {
15934 /* OPC_BGTZALC */
15935 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
15936 } else if (rs != 0 && rt != 0 && rs == rt) {
15937 /* OPC_BLTZALC */
15938 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
15939 } else {
15940 /* OPC_BLTUC */
15941 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
15943 break;
15944 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
15945 if (rs == 0 && rt != 0) {
15946 /* OPC_BLEZC */
15947 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
15948 } else if (rs != 0 && rt != 0 && rs == rt) {
15949 /* OPC_BGEZC */
15950 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
15951 } else {
15952 /* OPC_BGEC */
15953 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
15955 break;
15956 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
15957 if (rs == 0 && rt != 0) {
15958 /* OPC_BGTZC */
15959 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
15960 } else if (rs != 0 && rt != 0 && rs == rt) {
15961 /* OPC_BLTZC */
15962 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
15963 } else {
15964 /* OPC_BLTC */
15965 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
15967 break;
15968 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
15969 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
15970 if (rs >= rt) {
15971 /* OPC_BOVC, OPC_BNVC */
15972 TCGv t2 = tcg_temp_new();
15973 TCGv t3 = tcg_temp_new();
15974 TCGv t4 = tcg_temp_new();
15975 TCGv input_overflow = tcg_temp_new();
15977 gen_load_gpr(t0, rs);
15978 gen_load_gpr(t1, rt);
15979 tcg_gen_ext32s_tl(t2, t0);
15980 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
15981 tcg_gen_ext32s_tl(t3, t1);
15982 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
15983 tcg_gen_or_tl(input_overflow, input_overflow, t4);
15985 tcg_gen_add_tl(t4, t2, t3);
15986 tcg_gen_ext32s_tl(t4, t4);
15987 tcg_gen_xor_tl(t2, t2, t3);
15988 tcg_gen_xor_tl(t3, t4, t3);
15989 tcg_gen_andc_tl(t2, t3, t2);
15990 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
15991 tcg_gen_or_tl(t4, t4, input_overflow);
15992 if (opc == OPC_BOVC) {
15993 /* OPC_BOVC */
15994 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
15995 } else {
15996 /* OPC_BNVC */
15997 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
15999 tcg_temp_free(input_overflow);
16000 tcg_temp_free(t4);
16001 tcg_temp_free(t3);
16002 tcg_temp_free(t2);
16003 } else if (rs < rt && rs == 0) {
16004 /* OPC_BEQZALC, OPC_BNEZALC */
16005 if (opc == OPC_BEQZALC) {
16006 /* OPC_BEQZALC */
16007 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
16008 } else {
16009 /* OPC_BNEZALC */
16010 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
16012 } else {
16013 /* OPC_BEQC, OPC_BNEC */
16014 if (opc == OPC_BEQC) {
16015 /* OPC_BEQC */
16016 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
16017 } else {
16018 /* OPC_BNEC */
16019 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
16022 break;
16023 case OPC_BEQZC:
16024 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
16025 break;
16026 case OPC_BNEZC:
16027 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
16028 break;
16029 default:
16030 MIPS_INVAL("Compact conditional branch/jump");
16031 generate_exception(ctx, EXCP_RI);
16032 goto out;
16035 /* Generating branch here as compact branches don't have delay slot */
16036 gen_goto_tb(ctx, 1, ctx->btarget);
16037 gen_set_label(fs);
16039 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
16040 MIPS_DEBUG("Compact conditional branch");
16043 out:
16044 tcg_temp_free(t0);
16045 tcg_temp_free(t1);
16048 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
16050 int rs, rt, rd, sa;
16051 uint32_t op1, op2;
16053 rs = (ctx->opcode >> 21) & 0x1f;
16054 rt = (ctx->opcode >> 16) & 0x1f;
16055 rd = (ctx->opcode >> 11) & 0x1f;
16056 sa = (ctx->opcode >> 6) & 0x1f;
16058 op1 = MASK_SPECIAL(ctx->opcode);
16059 switch (op1) {
16060 case OPC_LSA:
16061 if (rd != 0) {
16062 int imm2 = extract32(ctx->opcode, 6, 3);
16063 TCGv t0 = tcg_temp_new();
16064 TCGv t1 = tcg_temp_new();
16065 gen_load_gpr(t0, rs);
16066 gen_load_gpr(t1, rt);
16067 tcg_gen_shli_tl(t0, t0, imm2 + 1);
16068 tcg_gen_add_tl(t0, t0, t1);
16069 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
16070 tcg_temp_free(t1);
16071 tcg_temp_free(t0);
16073 break;
16074 case OPC_MULT ... OPC_DIVU:
16075 op2 = MASK_R6_MULDIV(ctx->opcode);
16076 switch (op2) {
16077 case R6_OPC_MUL:
16078 case R6_OPC_MUH:
16079 case R6_OPC_MULU:
16080 case R6_OPC_MUHU:
16081 case R6_OPC_DIV:
16082 case R6_OPC_MOD:
16083 case R6_OPC_DIVU:
16084 case R6_OPC_MODU:
16085 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16086 break;
16087 default:
16088 MIPS_INVAL("special_r6 muldiv");
16089 generate_exception(ctx, EXCP_RI);
16090 break;
16092 break;
16093 case OPC_SELEQZ:
16094 case OPC_SELNEZ:
16095 gen_cond_move(ctx, op1, rd, rs, rt);
16096 break;
16097 case R6_OPC_CLO:
16098 case R6_OPC_CLZ:
16099 if (rt == 0 && sa == 1) {
16100 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16101 We need additionally to check other fields */
16102 gen_cl(ctx, op1, rd, rs);
16103 } else {
16104 generate_exception(ctx, EXCP_RI);
16106 break;
16107 case R6_OPC_SDBBP:
16108 if (ctx->hflags & MIPS_HFLAG_SBRI) {
16109 generate_exception(ctx, EXCP_RI);
16110 } else {
16111 generate_exception(ctx, EXCP_DBp);
16113 break;
16114 #if defined(TARGET_MIPS64)
16115 case OPC_DLSA:
16116 check_mips_64(ctx);
16117 if (rd != 0) {
16118 int imm2 = extract32(ctx->opcode, 6, 3);
16119 TCGv t0 = tcg_temp_new();
16120 TCGv t1 = tcg_temp_new();
16121 gen_load_gpr(t0, rs);
16122 gen_load_gpr(t1, rt);
16123 tcg_gen_shli_tl(t0, t0, imm2 + 1);
16124 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
16125 tcg_temp_free(t1);
16126 tcg_temp_free(t0);
16128 break;
16129 case R6_OPC_DCLO:
16130 case R6_OPC_DCLZ:
16131 if (rt == 0 && sa == 1) {
16132 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16133 We need additionally to check other fields */
16134 check_mips_64(ctx);
16135 gen_cl(ctx, op1, rd, rs);
16136 } else {
16137 generate_exception(ctx, EXCP_RI);
16139 break;
16140 case OPC_DMULT ... OPC_DDIVU:
16141 op2 = MASK_R6_MULDIV(ctx->opcode);
16142 switch (op2) {
16143 case R6_OPC_DMUL:
16144 case R6_OPC_DMUH:
16145 case R6_OPC_DMULU:
16146 case R6_OPC_DMUHU:
16147 case R6_OPC_DDIV:
16148 case R6_OPC_DMOD:
16149 case R6_OPC_DDIVU:
16150 case R6_OPC_DMODU:
16151 check_mips_64(ctx);
16152 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16153 break;
16154 default:
16155 MIPS_INVAL("special_r6 muldiv");
16156 generate_exception(ctx, EXCP_RI);
16157 break;
16159 break;
16160 #endif
16161 default: /* Invalid */
16162 MIPS_INVAL("special_r6");
16163 generate_exception(ctx, EXCP_RI);
16164 break;
16168 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
16170 int rs, rt, rd, sa;
16171 uint32_t op1;
16173 rs = (ctx->opcode >> 21) & 0x1f;
16174 rt = (ctx->opcode >> 16) & 0x1f;
16175 rd = (ctx->opcode >> 11) & 0x1f;
16176 sa = (ctx->opcode >> 6) & 0x1f;
16178 op1 = MASK_SPECIAL(ctx->opcode);
16179 switch (op1) {
16180 case OPC_MOVN: /* Conditional move */
16181 case OPC_MOVZ:
16182 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
16183 INSN_LOONGSON2E | INSN_LOONGSON2F);
16184 gen_cond_move(ctx, op1, rd, rs, rt);
16185 break;
16186 case OPC_MFHI: /* Move from HI/LO */
16187 case OPC_MFLO:
16188 gen_HILO(ctx, op1, rs & 3, rd);
16189 break;
16190 case OPC_MTHI:
16191 case OPC_MTLO: /* Move to HI/LO */
16192 gen_HILO(ctx, op1, rd & 3, rs);
16193 break;
16194 case OPC_MOVCI:
16195 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
16196 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16197 check_cp1_enabled(ctx);
16198 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
16199 (ctx->opcode >> 16) & 1);
16200 } else {
16201 generate_exception_err(ctx, EXCP_CpU, 1);
16203 break;
16204 case OPC_MULT:
16205 case OPC_MULTU:
16206 if (sa) {
16207 check_insn(ctx, INSN_VR54XX);
16208 op1 = MASK_MUL_VR54XX(ctx->opcode);
16209 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
16210 } else {
16211 gen_muldiv(ctx, op1, rd & 3, rs, rt);
16213 break;
16214 case OPC_DIV:
16215 case OPC_DIVU:
16216 gen_muldiv(ctx, op1, 0, rs, rt);
16217 break;
16218 #if defined(TARGET_MIPS64)
16219 case OPC_DMULT ... OPC_DDIVU:
16220 check_insn(ctx, ISA_MIPS3);
16221 check_mips_64(ctx);
16222 gen_muldiv(ctx, op1, 0, rs, rt);
16223 break;
16224 #endif
16225 case OPC_JR:
16226 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
16227 break;
16228 case OPC_SPIM:
16229 #ifdef MIPS_STRICT_STANDARD
16230 MIPS_INVAL("SPIM");
16231 generate_exception(ctx, EXCP_RI);
16232 #else
16233 /* Implemented as RI exception for now. */
16234 MIPS_INVAL("spim (unofficial)");
16235 generate_exception(ctx, EXCP_RI);
16236 #endif
16237 break;
16238 default: /* Invalid */
16239 MIPS_INVAL("special_legacy");
16240 generate_exception(ctx, EXCP_RI);
16241 break;
16245 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
16247 int rs, rt, rd, sa;
16248 uint32_t op1;
16250 rs = (ctx->opcode >> 21) & 0x1f;
16251 rt = (ctx->opcode >> 16) & 0x1f;
16252 rd = (ctx->opcode >> 11) & 0x1f;
16253 sa = (ctx->opcode >> 6) & 0x1f;
16255 op1 = MASK_SPECIAL(ctx->opcode);
16256 switch (op1) {
16257 case OPC_SLL: /* Shift with immediate */
16258 if (sa == 5 && rd == 0 &&
16259 rs == 0 && rt == 0) { /* PAUSE */
16260 if ((ctx->insn_flags & ISA_MIPS32R6) &&
16261 (ctx->hflags & MIPS_HFLAG_BMASK)) {
16262 MIPS_DEBUG("CTI in delay / forbidden slot");
16263 generate_exception(ctx, EXCP_RI);
16264 break;
16267 /* Fallthrough */
16268 case OPC_SRA:
16269 gen_shift_imm(ctx, op1, rd, rt, sa);
16270 break;
16271 case OPC_SRL:
16272 switch ((ctx->opcode >> 21) & 0x1f) {
16273 case 1:
16274 /* rotr is decoded as srl on non-R2 CPUs */
16275 if (ctx->insn_flags & ISA_MIPS32R2) {
16276 op1 = OPC_ROTR;
16278 /* Fallthrough */
16279 case 0:
16280 gen_shift_imm(ctx, op1, rd, rt, sa);
16281 break;
16282 default:
16283 generate_exception(ctx, EXCP_RI);
16284 break;
16286 break;
16287 case OPC_ADD ... OPC_SUBU:
16288 gen_arith(ctx, op1, rd, rs, rt);
16289 break;
16290 case OPC_SLLV: /* Shifts */
16291 case OPC_SRAV:
16292 gen_shift(ctx, op1, rd, rs, rt);
16293 break;
16294 case OPC_SRLV:
16295 switch ((ctx->opcode >> 6) & 0x1f) {
16296 case 1:
16297 /* rotrv is decoded as srlv on non-R2 CPUs */
16298 if (ctx->insn_flags & ISA_MIPS32R2) {
16299 op1 = OPC_ROTRV;
16301 /* Fallthrough */
16302 case 0:
16303 gen_shift(ctx, op1, rd, rs, rt);
16304 break;
16305 default:
16306 generate_exception(ctx, EXCP_RI);
16307 break;
16309 break;
16310 case OPC_SLT: /* Set on less than */
16311 case OPC_SLTU:
16312 gen_slt(ctx, op1, rd, rs, rt);
16313 break;
16314 case OPC_AND: /* Logic*/
16315 case OPC_OR:
16316 case OPC_NOR:
16317 case OPC_XOR:
16318 gen_logic(ctx, op1, rd, rs, rt);
16319 break;
16320 case OPC_JALR:
16321 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
16322 break;
16323 case OPC_TGE ... OPC_TEQ: /* Traps */
16324 case OPC_TNE:
16325 gen_trap(ctx, op1, rs, rt, -1);
16326 break;
16327 case OPC_LSA: /* OPC_PMON */
16328 if ((ctx->insn_flags & ISA_MIPS32R6) ||
16329 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
16330 decode_opc_special_r6(env, ctx);
16331 } else {
16332 /* Pmon entry point, also R4010 selsl */
16333 #ifdef MIPS_STRICT_STANDARD
16334 MIPS_INVAL("PMON / selsl");
16335 generate_exception(ctx, EXCP_RI);
16336 #else
16337 gen_helper_0e0i(pmon, sa);
16338 #endif
16340 break;
16341 case OPC_SYSCALL:
16342 generate_exception(ctx, EXCP_SYSCALL);
16343 ctx->bstate = BS_STOP;
16344 break;
16345 case OPC_BREAK:
16346 generate_exception(ctx, EXCP_BREAK);
16347 break;
16348 case OPC_SYNC:
16349 /* Treat as NOP. */
16350 break;
16352 #if defined(TARGET_MIPS64)
16353 /* MIPS64 specific opcodes */
16354 case OPC_DSLL:
16355 case OPC_DSRA:
16356 case OPC_DSLL32:
16357 case OPC_DSRA32:
16358 check_insn(ctx, ISA_MIPS3);
16359 check_mips_64(ctx);
16360 gen_shift_imm(ctx, op1, rd, rt, sa);
16361 break;
16362 case OPC_DSRL:
16363 switch ((ctx->opcode >> 21) & 0x1f) {
16364 case 1:
16365 /* drotr is decoded as dsrl on non-R2 CPUs */
16366 if (ctx->insn_flags & ISA_MIPS32R2) {
16367 op1 = OPC_DROTR;
16369 /* Fallthrough */
16370 case 0:
16371 check_insn(ctx, ISA_MIPS3);
16372 check_mips_64(ctx);
16373 gen_shift_imm(ctx, op1, rd, rt, sa);
16374 break;
16375 default:
16376 generate_exception(ctx, EXCP_RI);
16377 break;
16379 break;
16380 case OPC_DSRL32:
16381 switch ((ctx->opcode >> 21) & 0x1f) {
16382 case 1:
16383 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
16384 if (ctx->insn_flags & ISA_MIPS32R2) {
16385 op1 = OPC_DROTR32;
16387 /* Fallthrough */
16388 case 0:
16389 check_insn(ctx, ISA_MIPS3);
16390 check_mips_64(ctx);
16391 gen_shift_imm(ctx, op1, rd, rt, sa);
16392 break;
16393 default:
16394 generate_exception(ctx, EXCP_RI);
16395 break;
16397 break;
16398 case OPC_DADD ... OPC_DSUBU:
16399 check_insn(ctx, ISA_MIPS3);
16400 check_mips_64(ctx);
16401 gen_arith(ctx, op1, rd, rs, rt);
16402 break;
16403 case OPC_DSLLV:
16404 case OPC_DSRAV:
16405 check_insn(ctx, ISA_MIPS3);
16406 check_mips_64(ctx);
16407 gen_shift(ctx, op1, rd, rs, rt);
16408 break;
16409 case OPC_DSRLV:
16410 switch ((ctx->opcode >> 6) & 0x1f) {
16411 case 1:
16412 /* drotrv is decoded as dsrlv on non-R2 CPUs */
16413 if (ctx->insn_flags & ISA_MIPS32R2) {
16414 op1 = OPC_DROTRV;
16416 /* Fallthrough */
16417 case 0:
16418 check_insn(ctx, ISA_MIPS3);
16419 check_mips_64(ctx);
16420 gen_shift(ctx, op1, rd, rs, rt);
16421 break;
16422 default:
16423 generate_exception(ctx, EXCP_RI);
16424 break;
16426 break;
16427 case OPC_DLSA:
16428 if ((ctx->insn_flags & ISA_MIPS32R6) ||
16429 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
16430 decode_opc_special_r6(env, ctx);
16432 break;
16433 #endif
16434 default:
16435 if (ctx->insn_flags & ISA_MIPS32R6) {
16436 decode_opc_special_r6(env, ctx);
16437 } else {
16438 decode_opc_special_legacy(env, ctx);
16443 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
16445 int rs, rt, rd;
16446 uint32_t op1;
16448 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16450 rs = (ctx->opcode >> 21) & 0x1f;
16451 rt = (ctx->opcode >> 16) & 0x1f;
16452 rd = (ctx->opcode >> 11) & 0x1f;
16454 op1 = MASK_SPECIAL2(ctx->opcode);
16455 switch (op1) {
16456 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
16457 case OPC_MSUB ... OPC_MSUBU:
16458 check_insn(ctx, ISA_MIPS32);
16459 gen_muldiv(ctx, op1, rd & 3, rs, rt);
16460 break;
16461 case OPC_MUL:
16462 gen_arith(ctx, op1, rd, rs, rt);
16463 break;
16464 case OPC_DIV_G_2F:
16465 case OPC_DIVU_G_2F:
16466 case OPC_MULT_G_2F:
16467 case OPC_MULTU_G_2F:
16468 case OPC_MOD_G_2F:
16469 case OPC_MODU_G_2F:
16470 check_insn(ctx, INSN_LOONGSON2F);
16471 gen_loongson_integer(ctx, op1, rd, rs, rt);
16472 break;
16473 case OPC_CLO:
16474 case OPC_CLZ:
16475 check_insn(ctx, ISA_MIPS32);
16476 gen_cl(ctx, op1, rd, rs);
16477 break;
16478 case OPC_SDBBP:
16479 /* XXX: not clear which exception should be raised
16480 * when in debug mode...
16482 check_insn(ctx, ISA_MIPS32);
16483 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
16484 generate_exception(ctx, EXCP_DBp);
16485 } else {
16486 generate_exception(ctx, EXCP_DBp);
16488 /* Treat as NOP. */
16489 break;
16490 #if defined(TARGET_MIPS64)
16491 case OPC_DCLO:
16492 case OPC_DCLZ:
16493 check_insn(ctx, ISA_MIPS64);
16494 check_mips_64(ctx);
16495 gen_cl(ctx, op1, rd, rs);
16496 break;
16497 case OPC_DMULT_G_2F:
16498 case OPC_DMULTU_G_2F:
16499 case OPC_DDIV_G_2F:
16500 case OPC_DDIVU_G_2F:
16501 case OPC_DMOD_G_2F:
16502 case OPC_DMODU_G_2F:
16503 check_insn(ctx, INSN_LOONGSON2F);
16504 gen_loongson_integer(ctx, op1, rd, rs, rt);
16505 break;
16506 #endif
16507 default: /* Invalid */
16508 MIPS_INVAL("special2_legacy");
16509 generate_exception(ctx, EXCP_RI);
16510 break;
16514 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
16516 int rs, rt, rd, sa;
16517 uint32_t op1, op2;
16518 int16_t imm;
16520 rs = (ctx->opcode >> 21) & 0x1f;
16521 rt = (ctx->opcode >> 16) & 0x1f;
16522 rd = (ctx->opcode >> 11) & 0x1f;
16523 sa = (ctx->opcode >> 6) & 0x1f;
16524 imm = (int16_t)ctx->opcode >> 7;
16526 op1 = MASK_SPECIAL3(ctx->opcode);
16527 switch (op1) {
16528 case R6_OPC_PREF:
16529 if (rt >= 24) {
16530 /* hint codes 24-31 are reserved and signal RI */
16531 generate_exception(ctx, EXCP_RI);
16533 /* Treat as NOP. */
16534 break;
16535 case R6_OPC_CACHE:
16536 /* Treat as NOP. */
16537 break;
16538 case R6_OPC_SC:
16539 gen_st_cond(ctx, op1, rt, rs, imm);
16540 break;
16541 case R6_OPC_LL:
16542 gen_ld(ctx, op1, rt, rs, imm);
16543 break;
16544 case OPC_BSHFL:
16546 if (rd == 0) {
16547 /* Treat as NOP. */
16548 break;
16550 TCGv t0 = tcg_temp_new();
16551 gen_load_gpr(t0, rt);
16553 op2 = MASK_BSHFL(ctx->opcode);
16554 switch (op2) {
16555 case OPC_ALIGN ... OPC_ALIGN_END:
16556 sa &= 3;
16557 if (sa == 0) {
16558 tcg_gen_mov_tl(cpu_gpr[rd], t0);
16559 } else {
16560 TCGv t1 = tcg_temp_new();
16561 TCGv_i64 t2 = tcg_temp_new_i64();
16562 gen_load_gpr(t1, rs);
16563 tcg_gen_concat_tl_i64(t2, t1, t0);
16564 tcg_gen_shri_i64(t2, t2, 8 * (4 - sa));
16565 #if defined(TARGET_MIPS64)
16566 tcg_gen_ext32s_i64(cpu_gpr[rd], t2);
16567 #else
16568 tcg_gen_trunc_i64_i32(cpu_gpr[rd], t2);
16569 #endif
16570 tcg_temp_free_i64(t2);
16571 tcg_temp_free(t1);
16573 break;
16574 case OPC_BITSWAP:
16575 gen_helper_bitswap(cpu_gpr[rd], t0);
16576 break;
16578 tcg_temp_free(t0);
16580 break;
16581 #if defined(TARGET_MIPS64)
16582 case R6_OPC_SCD:
16583 gen_st_cond(ctx, op1, rt, rs, imm);
16584 break;
16585 case R6_OPC_LLD:
16586 gen_ld(ctx, op1, rt, rs, imm);
16587 break;
16588 case OPC_DBSHFL:
16589 check_mips_64(ctx);
16591 if (rd == 0) {
16592 /* Treat as NOP. */
16593 break;
16595 TCGv t0 = tcg_temp_new();
16596 gen_load_gpr(t0, rt);
16598 op2 = MASK_DBSHFL(ctx->opcode);
16599 switch (op2) {
16600 case OPC_DALIGN ... OPC_DALIGN_END:
16601 sa &= 7;
16602 if (sa == 0) {
16603 tcg_gen_mov_tl(cpu_gpr[rd], t0);
16604 } else {
16605 TCGv t1 = tcg_temp_new();
16606 gen_load_gpr(t1, rs);
16607 tcg_gen_shli_tl(t0, t0, 8 * sa);
16608 tcg_gen_shri_tl(t1, t1, 8 * (8 - sa));
16609 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
16610 tcg_temp_free(t1);
16612 break;
16613 case OPC_DBITSWAP:
16614 gen_helper_dbitswap(cpu_gpr[rd], t0);
16615 break;
16617 tcg_temp_free(t0);
16619 break;
16620 #endif
16621 default: /* Invalid */
16622 MIPS_INVAL("special3_r6");
16623 generate_exception(ctx, EXCP_RI);
16624 break;
16628 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
16630 int rs, rt, rd;
16631 uint32_t op1, op2;
16633 rs = (ctx->opcode >> 21) & 0x1f;
16634 rt = (ctx->opcode >> 16) & 0x1f;
16635 rd = (ctx->opcode >> 11) & 0x1f;
16637 op1 = MASK_SPECIAL3(ctx->opcode);
16638 switch (op1) {
16639 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
16640 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
16641 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
16642 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
16643 * the same mask and op1. */
16644 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
16645 op2 = MASK_ADDUH_QB(ctx->opcode);
16646 switch (op2) {
16647 case OPC_ADDUH_QB:
16648 case OPC_ADDUH_R_QB:
16649 case OPC_ADDQH_PH:
16650 case OPC_ADDQH_R_PH:
16651 case OPC_ADDQH_W:
16652 case OPC_ADDQH_R_W:
16653 case OPC_SUBUH_QB:
16654 case OPC_SUBUH_R_QB:
16655 case OPC_SUBQH_PH:
16656 case OPC_SUBQH_R_PH:
16657 case OPC_SUBQH_W:
16658 case OPC_SUBQH_R_W:
16659 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16660 break;
16661 case OPC_MUL_PH:
16662 case OPC_MUL_S_PH:
16663 case OPC_MULQ_S_W:
16664 case OPC_MULQ_RS_W:
16665 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
16666 break;
16667 default:
16668 MIPS_INVAL("MASK ADDUH.QB");
16669 generate_exception(ctx, EXCP_RI);
16670 break;
16672 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
16673 gen_loongson_integer(ctx, op1, rd, rs, rt);
16674 } else {
16675 generate_exception(ctx, EXCP_RI);
16677 break;
16678 case OPC_LX_DSP:
16679 op2 = MASK_LX(ctx->opcode);
16680 switch (op2) {
16681 #if defined(TARGET_MIPS64)
16682 case OPC_LDX:
16683 #endif
16684 case OPC_LBUX:
16685 case OPC_LHX:
16686 case OPC_LWX:
16687 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
16688 break;
16689 default: /* Invalid */
16690 MIPS_INVAL("MASK LX");
16691 generate_exception(ctx, EXCP_RI);
16692 break;
16694 break;
16695 case OPC_ABSQ_S_PH_DSP:
16696 op2 = MASK_ABSQ_S_PH(ctx->opcode);
16697 switch (op2) {
16698 case OPC_ABSQ_S_QB:
16699 case OPC_ABSQ_S_PH:
16700 case OPC_ABSQ_S_W:
16701 case OPC_PRECEQ_W_PHL:
16702 case OPC_PRECEQ_W_PHR:
16703 case OPC_PRECEQU_PH_QBL:
16704 case OPC_PRECEQU_PH_QBR:
16705 case OPC_PRECEQU_PH_QBLA:
16706 case OPC_PRECEQU_PH_QBRA:
16707 case OPC_PRECEU_PH_QBL:
16708 case OPC_PRECEU_PH_QBR:
16709 case OPC_PRECEU_PH_QBLA:
16710 case OPC_PRECEU_PH_QBRA:
16711 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16712 break;
16713 case OPC_BITREV:
16714 case OPC_REPL_QB:
16715 case OPC_REPLV_QB:
16716 case OPC_REPL_PH:
16717 case OPC_REPLV_PH:
16718 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
16719 break;
16720 default:
16721 MIPS_INVAL("MASK ABSQ_S.PH");
16722 generate_exception(ctx, EXCP_RI);
16723 break;
16725 break;
16726 case OPC_ADDU_QB_DSP:
16727 op2 = MASK_ADDU_QB(ctx->opcode);
16728 switch (op2) {
16729 case OPC_ADDQ_PH:
16730 case OPC_ADDQ_S_PH:
16731 case OPC_ADDQ_S_W:
16732 case OPC_ADDU_QB:
16733 case OPC_ADDU_S_QB:
16734 case OPC_ADDU_PH:
16735 case OPC_ADDU_S_PH:
16736 case OPC_SUBQ_PH:
16737 case OPC_SUBQ_S_PH:
16738 case OPC_SUBQ_S_W:
16739 case OPC_SUBU_QB:
16740 case OPC_SUBU_S_QB:
16741 case OPC_SUBU_PH:
16742 case OPC_SUBU_S_PH:
16743 case OPC_ADDSC:
16744 case OPC_ADDWC:
16745 case OPC_MODSUB:
16746 case OPC_RADDU_W_QB:
16747 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16748 break;
16749 case OPC_MULEU_S_PH_QBL:
16750 case OPC_MULEU_S_PH_QBR:
16751 case OPC_MULQ_RS_PH:
16752 case OPC_MULEQ_S_W_PHL:
16753 case OPC_MULEQ_S_W_PHR:
16754 case OPC_MULQ_S_PH:
16755 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
16756 break;
16757 default: /* Invalid */
16758 MIPS_INVAL("MASK ADDU.QB");
16759 generate_exception(ctx, EXCP_RI);
16760 break;
16763 break;
16764 case OPC_CMPU_EQ_QB_DSP:
16765 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
16766 switch (op2) {
16767 case OPC_PRECR_SRA_PH_W:
16768 case OPC_PRECR_SRA_R_PH_W:
16769 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
16770 break;
16771 case OPC_PRECR_QB_PH:
16772 case OPC_PRECRQ_QB_PH:
16773 case OPC_PRECRQ_PH_W:
16774 case OPC_PRECRQ_RS_PH_W:
16775 case OPC_PRECRQU_S_QB_PH:
16776 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16777 break;
16778 case OPC_CMPU_EQ_QB:
16779 case OPC_CMPU_LT_QB:
16780 case OPC_CMPU_LE_QB:
16781 case OPC_CMP_EQ_PH:
16782 case OPC_CMP_LT_PH:
16783 case OPC_CMP_LE_PH:
16784 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
16785 break;
16786 case OPC_CMPGU_EQ_QB:
16787 case OPC_CMPGU_LT_QB:
16788 case OPC_CMPGU_LE_QB:
16789 case OPC_CMPGDU_EQ_QB:
16790 case OPC_CMPGDU_LT_QB:
16791 case OPC_CMPGDU_LE_QB:
16792 case OPC_PICK_QB:
16793 case OPC_PICK_PH:
16794 case OPC_PACKRL_PH:
16795 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
16796 break;
16797 default: /* Invalid */
16798 MIPS_INVAL("MASK CMPU.EQ.QB");
16799 generate_exception(ctx, EXCP_RI);
16800 break;
16802 break;
16803 case OPC_SHLL_QB_DSP:
16804 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
16805 break;
16806 case OPC_DPA_W_PH_DSP:
16807 op2 = MASK_DPA_W_PH(ctx->opcode);
16808 switch (op2) {
16809 case OPC_DPAU_H_QBL:
16810 case OPC_DPAU_H_QBR:
16811 case OPC_DPSU_H_QBL:
16812 case OPC_DPSU_H_QBR:
16813 case OPC_DPA_W_PH:
16814 case OPC_DPAX_W_PH:
16815 case OPC_DPAQ_S_W_PH:
16816 case OPC_DPAQX_S_W_PH:
16817 case OPC_DPAQX_SA_W_PH:
16818 case OPC_DPS_W_PH:
16819 case OPC_DPSX_W_PH:
16820 case OPC_DPSQ_S_W_PH:
16821 case OPC_DPSQX_S_W_PH:
16822 case OPC_DPSQX_SA_W_PH:
16823 case OPC_MULSAQ_S_W_PH:
16824 case OPC_DPAQ_SA_L_W:
16825 case OPC_DPSQ_SA_L_W:
16826 case OPC_MAQ_S_W_PHL:
16827 case OPC_MAQ_S_W_PHR:
16828 case OPC_MAQ_SA_W_PHL:
16829 case OPC_MAQ_SA_W_PHR:
16830 case OPC_MULSA_W_PH:
16831 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
16832 break;
16833 default: /* Invalid */
16834 MIPS_INVAL("MASK DPAW.PH");
16835 generate_exception(ctx, EXCP_RI);
16836 break;
16838 break;
16839 case OPC_INSV_DSP:
16840 op2 = MASK_INSV(ctx->opcode);
16841 switch (op2) {
16842 case OPC_INSV:
16843 check_dsp(ctx);
16845 TCGv t0, t1;
16847 if (rt == 0) {
16848 MIPS_DEBUG("NOP");
16849 break;
16852 t0 = tcg_temp_new();
16853 t1 = tcg_temp_new();
16855 gen_load_gpr(t0, rt);
16856 gen_load_gpr(t1, rs);
16858 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
16860 tcg_temp_free(t0);
16861 tcg_temp_free(t1);
16862 break;
16864 default: /* Invalid */
16865 MIPS_INVAL("MASK INSV");
16866 generate_exception(ctx, EXCP_RI);
16867 break;
16869 break;
16870 case OPC_APPEND_DSP:
16871 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
16872 break;
16873 case OPC_EXTR_W_DSP:
16874 op2 = MASK_EXTR_W(ctx->opcode);
16875 switch (op2) {
16876 case OPC_EXTR_W:
16877 case OPC_EXTR_R_W:
16878 case OPC_EXTR_RS_W:
16879 case OPC_EXTR_S_H:
16880 case OPC_EXTRV_S_H:
16881 case OPC_EXTRV_W:
16882 case OPC_EXTRV_R_W:
16883 case OPC_EXTRV_RS_W:
16884 case OPC_EXTP:
16885 case OPC_EXTPV:
16886 case OPC_EXTPDP:
16887 case OPC_EXTPDPV:
16888 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
16889 break;
16890 case OPC_RDDSP:
16891 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
16892 break;
16893 case OPC_SHILO:
16894 case OPC_SHILOV:
16895 case OPC_MTHLIP:
16896 case OPC_WRDSP:
16897 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
16898 break;
16899 default: /* Invalid */
16900 MIPS_INVAL("MASK EXTR.W");
16901 generate_exception(ctx, EXCP_RI);
16902 break;
16904 break;
16905 #if defined(TARGET_MIPS64)
16906 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
16907 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
16908 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
16909 check_insn(ctx, INSN_LOONGSON2E);
16910 gen_loongson_integer(ctx, op1, rd, rs, rt);
16911 break;
16912 case OPC_ABSQ_S_QH_DSP:
16913 op2 = MASK_ABSQ_S_QH(ctx->opcode);
16914 switch (op2) {
16915 case OPC_PRECEQ_L_PWL:
16916 case OPC_PRECEQ_L_PWR:
16917 case OPC_PRECEQ_PW_QHL:
16918 case OPC_PRECEQ_PW_QHR:
16919 case OPC_PRECEQ_PW_QHLA:
16920 case OPC_PRECEQ_PW_QHRA:
16921 case OPC_PRECEQU_QH_OBL:
16922 case OPC_PRECEQU_QH_OBR:
16923 case OPC_PRECEQU_QH_OBLA:
16924 case OPC_PRECEQU_QH_OBRA:
16925 case OPC_PRECEU_QH_OBL:
16926 case OPC_PRECEU_QH_OBR:
16927 case OPC_PRECEU_QH_OBLA:
16928 case OPC_PRECEU_QH_OBRA:
16929 case OPC_ABSQ_S_OB:
16930 case OPC_ABSQ_S_PW:
16931 case OPC_ABSQ_S_QH:
16932 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16933 break;
16934 case OPC_REPL_OB:
16935 case OPC_REPL_PW:
16936 case OPC_REPL_QH:
16937 case OPC_REPLV_OB:
16938 case OPC_REPLV_PW:
16939 case OPC_REPLV_QH:
16940 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
16941 break;
16942 default: /* Invalid */
16943 MIPS_INVAL("MASK ABSQ_S.QH");
16944 generate_exception(ctx, EXCP_RI);
16945 break;
16947 break;
16948 case OPC_ADDU_OB_DSP:
16949 op2 = MASK_ADDU_OB(ctx->opcode);
16950 switch (op2) {
16951 case OPC_RADDU_L_OB:
16952 case OPC_SUBQ_PW:
16953 case OPC_SUBQ_S_PW:
16954 case OPC_SUBQ_QH:
16955 case OPC_SUBQ_S_QH:
16956 case OPC_SUBU_OB:
16957 case OPC_SUBU_S_OB:
16958 case OPC_SUBU_QH:
16959 case OPC_SUBU_S_QH:
16960 case OPC_SUBUH_OB:
16961 case OPC_SUBUH_R_OB:
16962 case OPC_ADDQ_PW:
16963 case OPC_ADDQ_S_PW:
16964 case OPC_ADDQ_QH:
16965 case OPC_ADDQ_S_QH:
16966 case OPC_ADDU_OB:
16967 case OPC_ADDU_S_OB:
16968 case OPC_ADDU_QH:
16969 case OPC_ADDU_S_QH:
16970 case OPC_ADDUH_OB:
16971 case OPC_ADDUH_R_OB:
16972 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16973 break;
16974 case OPC_MULEQ_S_PW_QHL:
16975 case OPC_MULEQ_S_PW_QHR:
16976 case OPC_MULEU_S_QH_OBL:
16977 case OPC_MULEU_S_QH_OBR:
16978 case OPC_MULQ_RS_QH:
16979 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
16980 break;
16981 default: /* Invalid */
16982 MIPS_INVAL("MASK ADDU.OB");
16983 generate_exception(ctx, EXCP_RI);
16984 break;
16986 break;
16987 case OPC_CMPU_EQ_OB_DSP:
16988 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
16989 switch (op2) {
16990 case OPC_PRECR_SRA_QH_PW:
16991 case OPC_PRECR_SRA_R_QH_PW:
16992 /* Return value is rt. */
16993 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
16994 break;
16995 case OPC_PRECR_OB_QH:
16996 case OPC_PRECRQ_OB_QH:
16997 case OPC_PRECRQ_PW_L:
16998 case OPC_PRECRQ_QH_PW:
16999 case OPC_PRECRQ_RS_QH_PW:
17000 case OPC_PRECRQU_S_OB_QH:
17001 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17002 break;
17003 case OPC_CMPU_EQ_OB:
17004 case OPC_CMPU_LT_OB:
17005 case OPC_CMPU_LE_OB:
17006 case OPC_CMP_EQ_QH:
17007 case OPC_CMP_LT_QH:
17008 case OPC_CMP_LE_QH:
17009 case OPC_CMP_EQ_PW:
17010 case OPC_CMP_LT_PW:
17011 case OPC_CMP_LE_PW:
17012 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17013 break;
17014 case OPC_CMPGDU_EQ_OB:
17015 case OPC_CMPGDU_LT_OB:
17016 case OPC_CMPGDU_LE_OB:
17017 case OPC_CMPGU_EQ_OB:
17018 case OPC_CMPGU_LT_OB:
17019 case OPC_CMPGU_LE_OB:
17020 case OPC_PACKRL_PW:
17021 case OPC_PICK_OB:
17022 case OPC_PICK_PW:
17023 case OPC_PICK_QH:
17024 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17025 break;
17026 default: /* Invalid */
17027 MIPS_INVAL("MASK CMPU_EQ.OB");
17028 generate_exception(ctx, EXCP_RI);
17029 break;
17031 break;
17032 case OPC_DAPPEND_DSP:
17033 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17034 break;
17035 case OPC_DEXTR_W_DSP:
17036 op2 = MASK_DEXTR_W(ctx->opcode);
17037 switch (op2) {
17038 case OPC_DEXTP:
17039 case OPC_DEXTPDP:
17040 case OPC_DEXTPDPV:
17041 case OPC_DEXTPV:
17042 case OPC_DEXTR_L:
17043 case OPC_DEXTR_R_L:
17044 case OPC_DEXTR_RS_L:
17045 case OPC_DEXTR_W:
17046 case OPC_DEXTR_R_W:
17047 case OPC_DEXTR_RS_W:
17048 case OPC_DEXTR_S_H:
17049 case OPC_DEXTRV_L:
17050 case OPC_DEXTRV_R_L:
17051 case OPC_DEXTRV_RS_L:
17052 case OPC_DEXTRV_S_H:
17053 case OPC_DEXTRV_W:
17054 case OPC_DEXTRV_R_W:
17055 case OPC_DEXTRV_RS_W:
17056 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17057 break;
17058 case OPC_DMTHLIP:
17059 case OPC_DSHILO:
17060 case OPC_DSHILOV:
17061 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17062 break;
17063 default: /* Invalid */
17064 MIPS_INVAL("MASK EXTR.W");
17065 generate_exception(ctx, EXCP_RI);
17066 break;
17068 break;
17069 case OPC_DPAQ_W_QH_DSP:
17070 op2 = MASK_DPAQ_W_QH(ctx->opcode);
17071 switch (op2) {
17072 case OPC_DPAU_H_OBL:
17073 case OPC_DPAU_H_OBR:
17074 case OPC_DPSU_H_OBL:
17075 case OPC_DPSU_H_OBR:
17076 case OPC_DPA_W_QH:
17077 case OPC_DPAQ_S_W_QH:
17078 case OPC_DPS_W_QH:
17079 case OPC_DPSQ_S_W_QH:
17080 case OPC_MULSAQ_S_W_QH:
17081 case OPC_DPAQ_SA_L_PW:
17082 case OPC_DPSQ_SA_L_PW:
17083 case OPC_MULSAQ_S_L_PW:
17084 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17085 break;
17086 case OPC_MAQ_S_W_QHLL:
17087 case OPC_MAQ_S_W_QHLR:
17088 case OPC_MAQ_S_W_QHRL:
17089 case OPC_MAQ_S_W_QHRR:
17090 case OPC_MAQ_SA_W_QHLL:
17091 case OPC_MAQ_SA_W_QHLR:
17092 case OPC_MAQ_SA_W_QHRL:
17093 case OPC_MAQ_SA_W_QHRR:
17094 case OPC_MAQ_S_L_PWL:
17095 case OPC_MAQ_S_L_PWR:
17096 case OPC_DMADD:
17097 case OPC_DMADDU:
17098 case OPC_DMSUB:
17099 case OPC_DMSUBU:
17100 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17101 break;
17102 default: /* Invalid */
17103 MIPS_INVAL("MASK DPAQ.W.QH");
17104 generate_exception(ctx, EXCP_RI);
17105 break;
17107 break;
17108 case OPC_DINSV_DSP:
17109 op2 = MASK_INSV(ctx->opcode);
17110 switch (op2) {
17111 case OPC_DINSV:
17113 TCGv t0, t1;
17115 if (rt == 0) {
17116 MIPS_DEBUG("NOP");
17117 break;
17119 check_dsp(ctx);
17121 t0 = tcg_temp_new();
17122 t1 = tcg_temp_new();
17124 gen_load_gpr(t0, rt);
17125 gen_load_gpr(t1, rs);
17127 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
17129 tcg_temp_free(t0);
17130 tcg_temp_free(t1);
17131 break;
17133 default: /* Invalid */
17134 MIPS_INVAL("MASK DINSV");
17135 generate_exception(ctx, EXCP_RI);
17136 break;
17138 break;
17139 case OPC_SHLL_OB_DSP:
17140 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17141 break;
17142 #endif
17143 default: /* Invalid */
17144 MIPS_INVAL("special3_legacy");
17145 generate_exception(ctx, EXCP_RI);
17146 break;
17150 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
17152 int rs, rt, rd, sa;
17153 uint32_t op1, op2;
17155 rs = (ctx->opcode >> 21) & 0x1f;
17156 rt = (ctx->opcode >> 16) & 0x1f;
17157 rd = (ctx->opcode >> 11) & 0x1f;
17158 sa = (ctx->opcode >> 6) & 0x1f;
17160 op1 = MASK_SPECIAL3(ctx->opcode);
17161 switch (op1) {
17162 case OPC_EXT:
17163 case OPC_INS:
17164 check_insn(ctx, ISA_MIPS32R2);
17165 gen_bitops(ctx, op1, rt, rs, sa, rd);
17166 break;
17167 case OPC_BSHFL:
17168 op2 = MASK_BSHFL(ctx->opcode);
17169 switch (op2) {
17170 case OPC_ALIGN ... OPC_ALIGN_END:
17171 case OPC_BITSWAP:
17172 check_insn(ctx, ISA_MIPS32R6);
17173 decode_opc_special3_r6(env, ctx);
17174 break;
17175 default:
17176 check_insn(ctx, ISA_MIPS32R2);
17177 gen_bshfl(ctx, op2, rt, rd);
17178 break;
17180 break;
17181 #if defined(TARGET_MIPS64)
17182 case OPC_DEXTM ... OPC_DEXT:
17183 case OPC_DINSM ... OPC_DINS:
17184 check_insn(ctx, ISA_MIPS64R2);
17185 check_mips_64(ctx);
17186 gen_bitops(ctx, op1, rt, rs, sa, rd);
17187 break;
17188 case OPC_DBSHFL:
17189 op2 = MASK_DBSHFL(ctx->opcode);
17190 switch (op2) {
17191 case OPC_DALIGN ... OPC_DALIGN_END:
17192 case OPC_DBITSWAP:
17193 check_insn(ctx, ISA_MIPS32R6);
17194 decode_opc_special3_r6(env, ctx);
17195 break;
17196 default:
17197 check_insn(ctx, ISA_MIPS64R2);
17198 check_mips_64(ctx);
17199 op2 = MASK_DBSHFL(ctx->opcode);
17200 gen_bshfl(ctx, op2, rt, rd);
17201 break;
17203 break;
17204 #endif
17205 case OPC_RDHWR:
17206 gen_rdhwr(ctx, rt, rd);
17207 break;
17208 case OPC_FORK:
17209 check_insn(ctx, ASE_MT);
17211 TCGv t0 = tcg_temp_new();
17212 TCGv t1 = tcg_temp_new();
17214 gen_load_gpr(t0, rt);
17215 gen_load_gpr(t1, rs);
17216 gen_helper_fork(t0, t1);
17217 tcg_temp_free(t0);
17218 tcg_temp_free(t1);
17220 break;
17221 case OPC_YIELD:
17222 check_insn(ctx, ASE_MT);
17224 TCGv t0 = tcg_temp_new();
17226 save_cpu_state(ctx, 1);
17227 gen_load_gpr(t0, rs);
17228 gen_helper_yield(t0, cpu_env, t0);
17229 gen_store_gpr(t0, rd);
17230 tcg_temp_free(t0);
17232 break;
17233 default:
17234 if (ctx->insn_flags & ISA_MIPS32R6) {
17235 decode_opc_special3_r6(env, ctx);
17236 } else {
17237 decode_opc_special3_legacy(env, ctx);
17242 /* MIPS SIMD Architecture (MSA) */
17243 static inline int check_msa_access(DisasContext *ctx)
17245 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
17246 !(ctx->hflags & MIPS_HFLAG_F64))) {
17247 generate_exception(ctx, EXCP_RI);
17248 return 0;
17251 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
17252 if (ctx->insn_flags & ASE_MSA) {
17253 generate_exception(ctx, EXCP_MSADIS);
17254 return 0;
17255 } else {
17256 generate_exception(ctx, EXCP_RI);
17257 return 0;
17260 return 1;
17263 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
17265 /* generates tcg ops to check if any element is 0 */
17266 /* Note this function only works with MSA_WRLEN = 128 */
17267 uint64_t eval_zero_or_big = 0;
17268 uint64_t eval_big = 0;
17269 TCGv_i64 t0 = tcg_temp_new_i64();
17270 TCGv_i64 t1 = tcg_temp_new_i64();
17271 switch (df) {
17272 case DF_BYTE:
17273 eval_zero_or_big = 0x0101010101010101ULL;
17274 eval_big = 0x8080808080808080ULL;
17275 break;
17276 case DF_HALF:
17277 eval_zero_or_big = 0x0001000100010001ULL;
17278 eval_big = 0x8000800080008000ULL;
17279 break;
17280 case DF_WORD:
17281 eval_zero_or_big = 0x0000000100000001ULL;
17282 eval_big = 0x8000000080000000ULL;
17283 break;
17284 case DF_DOUBLE:
17285 eval_zero_or_big = 0x0000000000000001ULL;
17286 eval_big = 0x8000000000000000ULL;
17287 break;
17289 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
17290 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
17291 tcg_gen_andi_i64(t0, t0, eval_big);
17292 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
17293 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
17294 tcg_gen_andi_i64(t1, t1, eval_big);
17295 tcg_gen_or_i64(t0, t0, t1);
17296 /* if all bits are zero then all elements are not zero */
17297 /* if some bit is non-zero then some element is zero */
17298 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
17299 tcg_gen_trunc_i64_tl(tresult, t0);
17300 tcg_temp_free_i64(t0);
17301 tcg_temp_free_i64(t1);
17304 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
17306 uint8_t df = (ctx->opcode >> 21) & 0x3;
17307 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
17308 int64_t s16 = (int16_t)ctx->opcode;
17310 check_msa_access(ctx);
17312 if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
17313 MIPS_DEBUG("CTI in delay / forbidden slot");
17314 generate_exception(ctx, EXCP_RI);
17315 return;
17317 switch (op1) {
17318 case OPC_BZ_V:
17319 case OPC_BNZ_V:
17321 TCGv_i64 t0 = tcg_temp_new_i64();
17322 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
17323 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
17324 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
17325 tcg_gen_trunc_i64_tl(bcond, t0);
17326 tcg_temp_free_i64(t0);
17328 break;
17329 case OPC_BZ_B:
17330 case OPC_BZ_H:
17331 case OPC_BZ_W:
17332 case OPC_BZ_D:
17333 gen_check_zero_element(bcond, df, wt);
17334 break;
17335 case OPC_BNZ_B:
17336 case OPC_BNZ_H:
17337 case OPC_BNZ_W:
17338 case OPC_BNZ_D:
17339 gen_check_zero_element(bcond, df, wt);
17340 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
17341 break;
17344 ctx->btarget = ctx->pc + (s16 << 2) + 4;
17346 ctx->hflags |= MIPS_HFLAG_BC;
17347 ctx->hflags |= MIPS_HFLAG_BDS32;
17350 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
17352 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
17353 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
17354 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17355 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17357 TCGv_i32 twd = tcg_const_i32(wd);
17358 TCGv_i32 tws = tcg_const_i32(ws);
17359 TCGv_i32 ti8 = tcg_const_i32(i8);
17361 switch (MASK_MSA_I8(ctx->opcode)) {
17362 case OPC_ANDI_B:
17363 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
17364 break;
17365 case OPC_ORI_B:
17366 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
17367 break;
17368 case OPC_NORI_B:
17369 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
17370 break;
17371 case OPC_XORI_B:
17372 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
17373 break;
17374 case OPC_BMNZI_B:
17375 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
17376 break;
17377 case OPC_BMZI_B:
17378 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
17379 break;
17380 case OPC_BSELI_B:
17381 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
17382 break;
17383 case OPC_SHF_B:
17384 case OPC_SHF_H:
17385 case OPC_SHF_W:
17387 uint8_t df = (ctx->opcode >> 24) & 0x3;
17388 if (df == DF_DOUBLE) {
17389 generate_exception(ctx, EXCP_RI);
17390 } else {
17391 TCGv_i32 tdf = tcg_const_i32(df);
17392 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
17393 tcg_temp_free_i32(tdf);
17396 break;
17397 default:
17398 MIPS_INVAL("MSA instruction");
17399 generate_exception(ctx, EXCP_RI);
17400 break;
17403 tcg_temp_free_i32(twd);
17404 tcg_temp_free_i32(tws);
17405 tcg_temp_free_i32(ti8);
17408 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
17410 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
17411 uint8_t df = (ctx->opcode >> 21) & 0x3;
17412 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
17413 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
17414 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17415 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17417 TCGv_i32 tdf = tcg_const_i32(df);
17418 TCGv_i32 twd = tcg_const_i32(wd);
17419 TCGv_i32 tws = tcg_const_i32(ws);
17420 TCGv_i32 timm = tcg_temp_new_i32();
17421 tcg_gen_movi_i32(timm, u5);
17423 switch (MASK_MSA_I5(ctx->opcode)) {
17424 case OPC_ADDVI_df:
17425 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
17426 break;
17427 case OPC_SUBVI_df:
17428 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
17429 break;
17430 case OPC_MAXI_S_df:
17431 tcg_gen_movi_i32(timm, s5);
17432 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
17433 break;
17434 case OPC_MAXI_U_df:
17435 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
17436 break;
17437 case OPC_MINI_S_df:
17438 tcg_gen_movi_i32(timm, s5);
17439 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
17440 break;
17441 case OPC_MINI_U_df:
17442 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
17443 break;
17444 case OPC_CEQI_df:
17445 tcg_gen_movi_i32(timm, s5);
17446 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
17447 break;
17448 case OPC_CLTI_S_df:
17449 tcg_gen_movi_i32(timm, s5);
17450 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
17451 break;
17452 case OPC_CLTI_U_df:
17453 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
17454 break;
17455 case OPC_CLEI_S_df:
17456 tcg_gen_movi_i32(timm, s5);
17457 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
17458 break;
17459 case OPC_CLEI_U_df:
17460 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
17461 break;
17462 case OPC_LDI_df:
17464 int32_t s10 = sextract32(ctx->opcode, 11, 10);
17465 tcg_gen_movi_i32(timm, s10);
17466 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
17468 break;
17469 default:
17470 MIPS_INVAL("MSA instruction");
17471 generate_exception(ctx, EXCP_RI);
17472 break;
17475 tcg_temp_free_i32(tdf);
17476 tcg_temp_free_i32(twd);
17477 tcg_temp_free_i32(tws);
17478 tcg_temp_free_i32(timm);
17481 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
17483 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
17484 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
17485 uint32_t df = 0, m = 0;
17486 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17487 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17489 TCGv_i32 tdf;
17490 TCGv_i32 tm;
17491 TCGv_i32 twd;
17492 TCGv_i32 tws;
17494 if ((dfm & 0x40) == 0x00) {
17495 m = dfm & 0x3f;
17496 df = DF_DOUBLE;
17497 } else if ((dfm & 0x60) == 0x40) {
17498 m = dfm & 0x1f;
17499 df = DF_WORD;
17500 } else if ((dfm & 0x70) == 0x60) {
17501 m = dfm & 0x0f;
17502 df = DF_HALF;
17503 } else if ((dfm & 0x78) == 0x70) {
17504 m = dfm & 0x7;
17505 df = DF_BYTE;
17506 } else {
17507 generate_exception(ctx, EXCP_RI);
17508 return;
17511 tdf = tcg_const_i32(df);
17512 tm = tcg_const_i32(m);
17513 twd = tcg_const_i32(wd);
17514 tws = tcg_const_i32(ws);
17516 switch (MASK_MSA_BIT(ctx->opcode)) {
17517 case OPC_SLLI_df:
17518 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
17519 break;
17520 case OPC_SRAI_df:
17521 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
17522 break;
17523 case OPC_SRLI_df:
17524 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
17525 break;
17526 case OPC_BCLRI_df:
17527 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
17528 break;
17529 case OPC_BSETI_df:
17530 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
17531 break;
17532 case OPC_BNEGI_df:
17533 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
17534 break;
17535 case OPC_BINSLI_df:
17536 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
17537 break;
17538 case OPC_BINSRI_df:
17539 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
17540 break;
17541 case OPC_SAT_S_df:
17542 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
17543 break;
17544 case OPC_SAT_U_df:
17545 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
17546 break;
17547 case OPC_SRARI_df:
17548 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
17549 break;
17550 case OPC_SRLRI_df:
17551 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
17552 break;
17553 default:
17554 MIPS_INVAL("MSA instruction");
17555 generate_exception(ctx, EXCP_RI);
17556 break;
17559 tcg_temp_free_i32(tdf);
17560 tcg_temp_free_i32(tm);
17561 tcg_temp_free_i32(twd);
17562 tcg_temp_free_i32(tws);
17565 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
17567 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
17568 uint8_t df = (ctx->opcode >> 21) & 0x3;
17569 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
17570 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17571 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17573 TCGv_i32 tdf = tcg_const_i32(df);
17574 TCGv_i32 twd = tcg_const_i32(wd);
17575 TCGv_i32 tws = tcg_const_i32(ws);
17576 TCGv_i32 twt = tcg_const_i32(wt);
17578 switch (MASK_MSA_3R(ctx->opcode)) {
17579 case OPC_SLL_df:
17580 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
17581 break;
17582 case OPC_ADDV_df:
17583 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
17584 break;
17585 case OPC_CEQ_df:
17586 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
17587 break;
17588 case OPC_ADD_A_df:
17589 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
17590 break;
17591 case OPC_SUBS_S_df:
17592 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
17593 break;
17594 case OPC_MULV_df:
17595 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
17596 break;
17597 case OPC_SLD_df:
17598 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
17599 break;
17600 case OPC_VSHF_df:
17601 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
17602 break;
17603 case OPC_SRA_df:
17604 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
17605 break;
17606 case OPC_SUBV_df:
17607 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
17608 break;
17609 case OPC_ADDS_A_df:
17610 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
17611 break;
17612 case OPC_SUBS_U_df:
17613 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
17614 break;
17615 case OPC_MADDV_df:
17616 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
17617 break;
17618 case OPC_SPLAT_df:
17619 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
17620 break;
17621 case OPC_SRAR_df:
17622 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
17623 break;
17624 case OPC_SRL_df:
17625 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
17626 break;
17627 case OPC_MAX_S_df:
17628 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
17629 break;
17630 case OPC_CLT_S_df:
17631 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
17632 break;
17633 case OPC_ADDS_S_df:
17634 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
17635 break;
17636 case OPC_SUBSUS_U_df:
17637 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
17638 break;
17639 case OPC_MSUBV_df:
17640 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
17641 break;
17642 case OPC_PCKEV_df:
17643 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
17644 break;
17645 case OPC_SRLR_df:
17646 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
17647 break;
17648 case OPC_BCLR_df:
17649 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
17650 break;
17651 case OPC_MAX_U_df:
17652 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
17653 break;
17654 case OPC_CLT_U_df:
17655 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
17656 break;
17657 case OPC_ADDS_U_df:
17658 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
17659 break;
17660 case OPC_SUBSUU_S_df:
17661 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
17662 break;
17663 case OPC_PCKOD_df:
17664 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
17665 break;
17666 case OPC_BSET_df:
17667 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
17668 break;
17669 case OPC_MIN_S_df:
17670 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
17671 break;
17672 case OPC_CLE_S_df:
17673 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
17674 break;
17675 case OPC_AVE_S_df:
17676 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
17677 break;
17678 case OPC_ASUB_S_df:
17679 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
17680 break;
17681 case OPC_DIV_S_df:
17682 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
17683 break;
17684 case OPC_ILVL_df:
17685 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
17686 break;
17687 case OPC_BNEG_df:
17688 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
17689 break;
17690 case OPC_MIN_U_df:
17691 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
17692 break;
17693 case OPC_CLE_U_df:
17694 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
17695 break;
17696 case OPC_AVE_U_df:
17697 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
17698 break;
17699 case OPC_ASUB_U_df:
17700 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
17701 break;
17702 case OPC_DIV_U_df:
17703 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
17704 break;
17705 case OPC_ILVR_df:
17706 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
17707 break;
17708 case OPC_BINSL_df:
17709 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
17710 break;
17711 case OPC_MAX_A_df:
17712 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
17713 break;
17714 case OPC_AVER_S_df:
17715 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
17716 break;
17717 case OPC_MOD_S_df:
17718 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
17719 break;
17720 case OPC_ILVEV_df:
17721 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
17722 break;
17723 case OPC_BINSR_df:
17724 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
17725 break;
17726 case OPC_MIN_A_df:
17727 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
17728 break;
17729 case OPC_AVER_U_df:
17730 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
17731 break;
17732 case OPC_MOD_U_df:
17733 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
17734 break;
17735 case OPC_ILVOD_df:
17736 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
17737 break;
17739 case OPC_DOTP_S_df:
17740 case OPC_DOTP_U_df:
17741 case OPC_DPADD_S_df:
17742 case OPC_DPADD_U_df:
17743 case OPC_DPSUB_S_df:
17744 case OPC_HADD_S_df:
17745 case OPC_DPSUB_U_df:
17746 case OPC_HADD_U_df:
17747 case OPC_HSUB_S_df:
17748 case OPC_HSUB_U_df:
17749 if (df == DF_BYTE) {
17750 generate_exception(ctx, EXCP_RI);
17752 switch (MASK_MSA_3R(ctx->opcode)) {
17753 case OPC_DOTP_S_df:
17754 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
17755 break;
17756 case OPC_DOTP_U_df:
17757 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
17758 break;
17759 case OPC_DPADD_S_df:
17760 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
17761 break;
17762 case OPC_DPADD_U_df:
17763 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
17764 break;
17765 case OPC_DPSUB_S_df:
17766 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
17767 break;
17768 case OPC_HADD_S_df:
17769 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
17770 break;
17771 case OPC_DPSUB_U_df:
17772 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
17773 break;
17774 case OPC_HADD_U_df:
17775 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
17776 break;
17777 case OPC_HSUB_S_df:
17778 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
17779 break;
17780 case OPC_HSUB_U_df:
17781 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
17782 break;
17784 break;
17785 default:
17786 MIPS_INVAL("MSA instruction");
17787 generate_exception(ctx, EXCP_RI);
17788 break;
17790 tcg_temp_free_i32(twd);
17791 tcg_temp_free_i32(tws);
17792 tcg_temp_free_i32(twt);
17793 tcg_temp_free_i32(tdf);
17796 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
17798 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
17799 uint8_t source = (ctx->opcode >> 11) & 0x1f;
17800 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
17801 TCGv telm = tcg_temp_new();
17802 TCGv_i32 tsr = tcg_const_i32(source);
17803 TCGv_i32 tdt = tcg_const_i32(dest);
17805 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
17806 case OPC_CTCMSA:
17807 gen_load_gpr(telm, source);
17808 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
17809 break;
17810 case OPC_CFCMSA:
17811 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
17812 gen_store_gpr(telm, dest);
17813 break;
17814 case OPC_MOVE_V:
17815 gen_helper_msa_move_v(cpu_env, tdt, tsr);
17816 break;
17817 default:
17818 MIPS_INVAL("MSA instruction");
17819 generate_exception(ctx, EXCP_RI);
17820 break;
17823 tcg_temp_free(telm);
17824 tcg_temp_free_i32(tdt);
17825 tcg_temp_free_i32(tsr);
17828 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
17829 uint32_t n)
17831 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
17832 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17833 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17835 TCGv_i32 tws = tcg_const_i32(ws);
17836 TCGv_i32 twd = tcg_const_i32(wd);
17837 TCGv_i32 tn = tcg_const_i32(n);
17838 TCGv_i32 tdf = tcg_const_i32(df);
17840 switch (MASK_MSA_ELM(ctx->opcode)) {
17841 case OPC_SLDI_df:
17842 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
17843 break;
17844 case OPC_SPLATI_df:
17845 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
17846 break;
17847 case OPC_INSVE_df:
17848 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
17849 break;
17850 case OPC_COPY_S_df:
17851 case OPC_COPY_U_df:
17852 case OPC_INSERT_df:
17853 #if !defined(TARGET_MIPS64)
17854 /* Double format valid only for MIPS64 */
17855 if (df == DF_DOUBLE) {
17856 generate_exception(ctx, EXCP_RI);
17857 break;
17859 #endif
17860 switch (MASK_MSA_ELM(ctx->opcode)) {
17861 case OPC_COPY_S_df:
17862 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
17863 break;
17864 case OPC_COPY_U_df:
17865 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
17866 break;
17867 case OPC_INSERT_df:
17868 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
17869 break;
17871 break;
17872 default:
17873 MIPS_INVAL("MSA instruction");
17874 generate_exception(ctx, EXCP_RI);
17876 tcg_temp_free_i32(twd);
17877 tcg_temp_free_i32(tws);
17878 tcg_temp_free_i32(tn);
17879 tcg_temp_free_i32(tdf);
17882 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
17884 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
17885 uint32_t df = 0, n = 0;
17887 if ((dfn & 0x30) == 0x00) {
17888 n = dfn & 0x0f;
17889 df = DF_BYTE;
17890 } else if ((dfn & 0x38) == 0x20) {
17891 n = dfn & 0x07;
17892 df = DF_HALF;
17893 } else if ((dfn & 0x3c) == 0x30) {
17894 n = dfn & 0x03;
17895 df = DF_WORD;
17896 } else if ((dfn & 0x3e) == 0x38) {
17897 n = dfn & 0x01;
17898 df = DF_DOUBLE;
17899 } else if (dfn == 0x3E) {
17900 /* CTCMSA, CFCMSA, MOVE.V */
17901 gen_msa_elm_3e(env, ctx);
17902 return;
17903 } else {
17904 generate_exception(ctx, EXCP_RI);
17905 return;
17908 gen_msa_elm_df(env, ctx, df, n);
17911 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
17913 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
17914 uint8_t df = (ctx->opcode >> 21) & 0x1;
17915 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
17916 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17917 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17919 TCGv_i32 twd = tcg_const_i32(wd);
17920 TCGv_i32 tws = tcg_const_i32(ws);
17921 TCGv_i32 twt = tcg_const_i32(wt);
17922 TCGv_i32 tdf = tcg_temp_new_i32();
17924 /* adjust df value for floating-point instruction */
17925 tcg_gen_movi_i32(tdf, df + 2);
17927 switch (MASK_MSA_3RF(ctx->opcode)) {
17928 case OPC_FCAF_df:
17929 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
17930 break;
17931 case OPC_FADD_df:
17932 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
17933 break;
17934 case OPC_FCUN_df:
17935 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
17936 break;
17937 case OPC_FSUB_df:
17938 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
17939 break;
17940 case OPC_FCOR_df:
17941 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
17942 break;
17943 case OPC_FCEQ_df:
17944 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
17945 break;
17946 case OPC_FMUL_df:
17947 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
17948 break;
17949 case OPC_FCUNE_df:
17950 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
17951 break;
17952 case OPC_FCUEQ_df:
17953 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
17954 break;
17955 case OPC_FDIV_df:
17956 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
17957 break;
17958 case OPC_FCNE_df:
17959 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
17960 break;
17961 case OPC_FCLT_df:
17962 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
17963 break;
17964 case OPC_FMADD_df:
17965 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
17966 break;
17967 case OPC_MUL_Q_df:
17968 tcg_gen_movi_i32(tdf, df + 1);
17969 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
17970 break;
17971 case OPC_FCULT_df:
17972 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
17973 break;
17974 case OPC_FMSUB_df:
17975 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
17976 break;
17977 case OPC_MADD_Q_df:
17978 tcg_gen_movi_i32(tdf, df + 1);
17979 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
17980 break;
17981 case OPC_FCLE_df:
17982 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
17983 break;
17984 case OPC_MSUB_Q_df:
17985 tcg_gen_movi_i32(tdf, df + 1);
17986 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
17987 break;
17988 case OPC_FCULE_df:
17989 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
17990 break;
17991 case OPC_FEXP2_df:
17992 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
17993 break;
17994 case OPC_FSAF_df:
17995 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
17996 break;
17997 case OPC_FEXDO_df:
17998 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
17999 break;
18000 case OPC_FSUN_df:
18001 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
18002 break;
18003 case OPC_FSOR_df:
18004 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
18005 break;
18006 case OPC_FSEQ_df:
18007 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
18008 break;
18009 case OPC_FTQ_df:
18010 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
18011 break;
18012 case OPC_FSUNE_df:
18013 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
18014 break;
18015 case OPC_FSUEQ_df:
18016 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
18017 break;
18018 case OPC_FSNE_df:
18019 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
18020 break;
18021 case OPC_FSLT_df:
18022 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
18023 break;
18024 case OPC_FMIN_df:
18025 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
18026 break;
18027 case OPC_MULR_Q_df:
18028 tcg_gen_movi_i32(tdf, df + 1);
18029 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
18030 break;
18031 case OPC_FSULT_df:
18032 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
18033 break;
18034 case OPC_FMIN_A_df:
18035 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
18036 break;
18037 case OPC_MADDR_Q_df:
18038 tcg_gen_movi_i32(tdf, df + 1);
18039 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
18040 break;
18041 case OPC_FSLE_df:
18042 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
18043 break;
18044 case OPC_FMAX_df:
18045 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
18046 break;
18047 case OPC_MSUBR_Q_df:
18048 tcg_gen_movi_i32(tdf, df + 1);
18049 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
18050 break;
18051 case OPC_FSULE_df:
18052 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
18053 break;
18054 case OPC_FMAX_A_df:
18055 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
18056 break;
18057 default:
18058 MIPS_INVAL("MSA instruction");
18059 generate_exception(ctx, EXCP_RI);
18060 break;
18063 tcg_temp_free_i32(twd);
18064 tcg_temp_free_i32(tws);
18065 tcg_temp_free_i32(twt);
18066 tcg_temp_free_i32(tdf);
18069 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
18071 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18072 (op & (0x7 << 18)))
18073 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18074 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18075 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18076 uint8_t df = (ctx->opcode >> 16) & 0x3;
18077 TCGv_i32 twd = tcg_const_i32(wd);
18078 TCGv_i32 tws = tcg_const_i32(ws);
18079 TCGv_i32 twt = tcg_const_i32(wt);
18080 TCGv_i32 tdf = tcg_const_i32(df);
18082 switch (MASK_MSA_2R(ctx->opcode)) {
18083 case OPC_FILL_df:
18084 #if !defined(TARGET_MIPS64)
18085 /* Double format valid only for MIPS64 */
18086 if (df == DF_DOUBLE) {
18087 generate_exception(ctx, EXCP_RI);
18088 break;
18090 #endif
18091 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
18092 break;
18093 case OPC_PCNT_df:
18094 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
18095 break;
18096 case OPC_NLOC_df:
18097 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
18098 break;
18099 case OPC_NLZC_df:
18100 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
18101 break;
18102 default:
18103 MIPS_INVAL("MSA instruction");
18104 generate_exception(ctx, EXCP_RI);
18105 break;
18108 tcg_temp_free_i32(twd);
18109 tcg_temp_free_i32(tws);
18110 tcg_temp_free_i32(twt);
18111 tcg_temp_free_i32(tdf);
18114 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
18116 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18117 (op & (0xf << 17)))
18118 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18119 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18120 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18121 uint8_t df = (ctx->opcode >> 16) & 0x1;
18122 TCGv_i32 twd = tcg_const_i32(wd);
18123 TCGv_i32 tws = tcg_const_i32(ws);
18124 TCGv_i32 twt = tcg_const_i32(wt);
18125 /* adjust df value for floating-point instruction */
18126 TCGv_i32 tdf = tcg_const_i32(df + 2);
18128 switch (MASK_MSA_2RF(ctx->opcode)) {
18129 case OPC_FCLASS_df:
18130 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
18131 break;
18132 case OPC_FTRUNC_S_df:
18133 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
18134 break;
18135 case OPC_FTRUNC_U_df:
18136 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
18137 break;
18138 case OPC_FSQRT_df:
18139 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
18140 break;
18141 case OPC_FRSQRT_df:
18142 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
18143 break;
18144 case OPC_FRCP_df:
18145 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
18146 break;
18147 case OPC_FRINT_df:
18148 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
18149 break;
18150 case OPC_FLOG2_df:
18151 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
18152 break;
18153 case OPC_FEXUPL_df:
18154 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
18155 break;
18156 case OPC_FEXUPR_df:
18157 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
18158 break;
18159 case OPC_FFQL_df:
18160 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
18161 break;
18162 case OPC_FFQR_df:
18163 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
18164 break;
18165 case OPC_FTINT_S_df:
18166 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
18167 break;
18168 case OPC_FTINT_U_df:
18169 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
18170 break;
18171 case OPC_FFINT_S_df:
18172 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
18173 break;
18174 case OPC_FFINT_U_df:
18175 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
18176 break;
18179 tcg_temp_free_i32(twd);
18180 tcg_temp_free_i32(tws);
18181 tcg_temp_free_i32(twt);
18182 tcg_temp_free_i32(tdf);
18185 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
18187 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
18188 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18189 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18190 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18191 TCGv_i32 twd = tcg_const_i32(wd);
18192 TCGv_i32 tws = tcg_const_i32(ws);
18193 TCGv_i32 twt = tcg_const_i32(wt);
18195 switch (MASK_MSA_VEC(ctx->opcode)) {
18196 case OPC_AND_V:
18197 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
18198 break;
18199 case OPC_OR_V:
18200 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
18201 break;
18202 case OPC_NOR_V:
18203 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
18204 break;
18205 case OPC_XOR_V:
18206 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
18207 break;
18208 case OPC_BMNZ_V:
18209 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
18210 break;
18211 case OPC_BMZ_V:
18212 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
18213 break;
18214 case OPC_BSEL_V:
18215 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
18216 break;
18217 default:
18218 MIPS_INVAL("MSA instruction");
18219 generate_exception(ctx, EXCP_RI);
18220 break;
18223 tcg_temp_free_i32(twd);
18224 tcg_temp_free_i32(tws);
18225 tcg_temp_free_i32(twt);
18228 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
18230 switch (MASK_MSA_VEC(ctx->opcode)) {
18231 case OPC_AND_V:
18232 case OPC_OR_V:
18233 case OPC_NOR_V:
18234 case OPC_XOR_V:
18235 case OPC_BMNZ_V:
18236 case OPC_BMZ_V:
18237 case OPC_BSEL_V:
18238 gen_msa_vec_v(env, ctx);
18239 break;
18240 case OPC_MSA_2R:
18241 gen_msa_2r(env, ctx);
18242 break;
18243 case OPC_MSA_2RF:
18244 gen_msa_2rf(env, ctx);
18245 break;
18246 default:
18247 MIPS_INVAL("MSA instruction");
18248 generate_exception(ctx, EXCP_RI);
18249 break;
18253 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
18255 uint32_t opcode = ctx->opcode;
18256 check_insn(ctx, ASE_MSA);
18257 check_msa_access(ctx);
18259 switch (MASK_MSA_MINOR(opcode)) {
18260 case OPC_MSA_I8_00:
18261 case OPC_MSA_I8_01:
18262 case OPC_MSA_I8_02:
18263 gen_msa_i8(env, ctx);
18264 break;
18265 case OPC_MSA_I5_06:
18266 case OPC_MSA_I5_07:
18267 gen_msa_i5(env, ctx);
18268 break;
18269 case OPC_MSA_BIT_09:
18270 case OPC_MSA_BIT_0A:
18271 gen_msa_bit(env, ctx);
18272 break;
18273 case OPC_MSA_3R_0D:
18274 case OPC_MSA_3R_0E:
18275 case OPC_MSA_3R_0F:
18276 case OPC_MSA_3R_10:
18277 case OPC_MSA_3R_11:
18278 case OPC_MSA_3R_12:
18279 case OPC_MSA_3R_13:
18280 case OPC_MSA_3R_14:
18281 case OPC_MSA_3R_15:
18282 gen_msa_3r(env, ctx);
18283 break;
18284 case OPC_MSA_ELM:
18285 gen_msa_elm(env, ctx);
18286 break;
18287 case OPC_MSA_3RF_1A:
18288 case OPC_MSA_3RF_1B:
18289 case OPC_MSA_3RF_1C:
18290 gen_msa_3rf(env, ctx);
18291 break;
18292 case OPC_MSA_VEC:
18293 gen_msa_vec(env, ctx);
18294 break;
18295 case OPC_LD_B:
18296 case OPC_LD_H:
18297 case OPC_LD_W:
18298 case OPC_LD_D:
18299 case OPC_ST_B:
18300 case OPC_ST_H:
18301 case OPC_ST_W:
18302 case OPC_ST_D:
18304 int32_t s10 = sextract32(ctx->opcode, 16, 10);
18305 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
18306 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18307 uint8_t df = (ctx->opcode >> 0) & 0x3;
18309 TCGv_i32 tdf = tcg_const_i32(df);
18310 TCGv_i32 twd = tcg_const_i32(wd);
18311 TCGv_i32 trs = tcg_const_i32(rs);
18312 TCGv_i32 ts10 = tcg_const_i32(s10);
18314 switch (MASK_MSA_MINOR(opcode)) {
18315 case OPC_LD_B:
18316 case OPC_LD_H:
18317 case OPC_LD_W:
18318 case OPC_LD_D:
18319 gen_helper_msa_ld_df(cpu_env, tdf, twd, trs, ts10);
18320 break;
18321 case OPC_ST_B:
18322 case OPC_ST_H:
18323 case OPC_ST_W:
18324 case OPC_ST_D:
18325 gen_helper_msa_st_df(cpu_env, tdf, twd, trs, ts10);
18326 break;
18329 tcg_temp_free_i32(twd);
18330 tcg_temp_free_i32(tdf);
18331 tcg_temp_free_i32(trs);
18332 tcg_temp_free_i32(ts10);
18334 break;
18335 default:
18336 MIPS_INVAL("MSA instruction");
18337 generate_exception(ctx, EXCP_RI);
18338 break;
18343 static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
18345 int32_t offset;
18346 int rs, rt, rd, sa;
18347 uint32_t op, op1;
18348 int16_t imm;
18350 /* make sure instructions are on a word boundary */
18351 if (ctx->pc & 0x3) {
18352 env->CP0_BadVAddr = ctx->pc;
18353 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
18354 return;
18357 /* Handle blikely not taken case */
18358 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
18359 int l1 = gen_new_label();
18361 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
18362 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
18363 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
18364 gen_goto_tb(ctx, 1, ctx->pc + 4);
18365 gen_set_label(l1);
18368 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
18369 tcg_gen_debug_insn_start(ctx->pc);
18372 op = MASK_OP_MAJOR(ctx->opcode);
18373 rs = (ctx->opcode >> 21) & 0x1f;
18374 rt = (ctx->opcode >> 16) & 0x1f;
18375 rd = (ctx->opcode >> 11) & 0x1f;
18376 sa = (ctx->opcode >> 6) & 0x1f;
18377 imm = (int16_t)ctx->opcode;
18378 switch (op) {
18379 case OPC_SPECIAL:
18380 decode_opc_special(env, ctx);
18381 break;
18382 case OPC_SPECIAL2:
18383 decode_opc_special2_legacy(env, ctx);
18384 break;
18385 case OPC_SPECIAL3:
18386 decode_opc_special3(env, ctx);
18387 break;
18388 case OPC_REGIMM:
18389 op1 = MASK_REGIMM(ctx->opcode);
18390 switch (op1) {
18391 case OPC_BLTZL: /* REGIMM branches */
18392 case OPC_BGEZL:
18393 case OPC_BLTZALL:
18394 case OPC_BGEZALL:
18395 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18396 case OPC_BLTZ:
18397 case OPC_BGEZ:
18398 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
18399 break;
18400 case OPC_BLTZAL:
18401 case OPC_BGEZAL:
18402 if (ctx->insn_flags & ISA_MIPS32R6) {
18403 if (rs == 0) {
18404 /* OPC_NAL, OPC_BAL */
18405 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
18406 } else {
18407 generate_exception(ctx, EXCP_RI);
18409 } else {
18410 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
18412 break;
18413 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
18414 case OPC_TNEI:
18415 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18416 gen_trap(ctx, op1, rs, -1, imm);
18417 break;
18418 case OPC_SYNCI:
18419 check_insn(ctx, ISA_MIPS32R2);
18420 /* Break the TB to be able to sync copied instructions
18421 immediately */
18422 ctx->bstate = BS_STOP;
18423 break;
18424 case OPC_BPOSGE32: /* MIPS DSP branch */
18425 #if defined(TARGET_MIPS64)
18426 case OPC_BPOSGE64:
18427 #endif
18428 check_dsp(ctx);
18429 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
18430 break;
18431 #if defined(TARGET_MIPS64)
18432 case OPC_DAHI:
18433 check_insn(ctx, ISA_MIPS32R6);
18434 check_mips_64(ctx);
18435 if (rs != 0) {
18436 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
18438 MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm);
18439 break;
18440 case OPC_DATI:
18441 check_insn(ctx, ISA_MIPS32R6);
18442 check_mips_64(ctx);
18443 if (rs != 0) {
18444 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
18446 MIPS_DEBUG("dati %s, %04x", regnames[rs], imm);
18447 break;
18448 #endif
18449 default: /* Invalid */
18450 MIPS_INVAL("regimm");
18451 generate_exception(ctx, EXCP_RI);
18452 break;
18454 break;
18455 case OPC_CP0:
18456 check_cp0_enabled(ctx);
18457 op1 = MASK_CP0(ctx->opcode);
18458 switch (op1) {
18459 case OPC_MFC0:
18460 case OPC_MTC0:
18461 case OPC_MFTR:
18462 case OPC_MTTR:
18463 #if defined(TARGET_MIPS64)
18464 case OPC_DMFC0:
18465 case OPC_DMTC0:
18466 #endif
18467 #ifndef CONFIG_USER_ONLY
18468 gen_cp0(env, ctx, op1, rt, rd);
18469 #endif /* !CONFIG_USER_ONLY */
18470 break;
18471 case OPC_C0_FIRST ... OPC_C0_LAST:
18472 #ifndef CONFIG_USER_ONLY
18473 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
18474 #endif /* !CONFIG_USER_ONLY */
18475 break;
18476 case OPC_MFMC0:
18477 #ifndef CONFIG_USER_ONLY
18479 uint32_t op2;
18480 TCGv t0 = tcg_temp_new();
18482 op2 = MASK_MFMC0(ctx->opcode);
18483 switch (op2) {
18484 case OPC_DMT:
18485 check_insn(ctx, ASE_MT);
18486 gen_helper_dmt(t0);
18487 gen_store_gpr(t0, rt);
18488 break;
18489 case OPC_EMT:
18490 check_insn(ctx, ASE_MT);
18491 gen_helper_emt(t0);
18492 gen_store_gpr(t0, rt);
18493 break;
18494 case OPC_DVPE:
18495 check_insn(ctx, ASE_MT);
18496 gen_helper_dvpe(t0, cpu_env);
18497 gen_store_gpr(t0, rt);
18498 break;
18499 case OPC_EVPE:
18500 check_insn(ctx, ASE_MT);
18501 gen_helper_evpe(t0, cpu_env);
18502 gen_store_gpr(t0, rt);
18503 break;
18504 case OPC_DI:
18505 check_insn(ctx, ISA_MIPS32R2);
18506 save_cpu_state(ctx, 1);
18507 gen_helper_di(t0, cpu_env);
18508 gen_store_gpr(t0, rt);
18509 /* Stop translation as we may have switched the execution mode */
18510 ctx->bstate = BS_STOP;
18511 break;
18512 case OPC_EI:
18513 check_insn(ctx, ISA_MIPS32R2);
18514 save_cpu_state(ctx, 1);
18515 gen_helper_ei(t0, cpu_env);
18516 gen_store_gpr(t0, rt);
18517 /* Stop translation as we may have switched the execution mode */
18518 ctx->bstate = BS_STOP;
18519 break;
18520 default: /* Invalid */
18521 MIPS_INVAL("mfmc0");
18522 generate_exception(ctx, EXCP_RI);
18523 break;
18525 tcg_temp_free(t0);
18527 #endif /* !CONFIG_USER_ONLY */
18528 break;
18529 case OPC_RDPGPR:
18530 check_insn(ctx, ISA_MIPS32R2);
18531 gen_load_srsgpr(rt, rd);
18532 break;
18533 case OPC_WRPGPR:
18534 check_insn(ctx, ISA_MIPS32R2);
18535 gen_store_srsgpr(rt, rd);
18536 break;
18537 default:
18538 MIPS_INVAL("cp0");
18539 generate_exception(ctx, EXCP_RI);
18540 break;
18542 break;
18543 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
18544 if (ctx->insn_flags & ISA_MIPS32R6) {
18545 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
18546 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18547 } else {
18548 /* OPC_ADDI */
18549 /* Arithmetic with immediate opcode */
18550 gen_arith_imm(ctx, op, rt, rs, imm);
18552 break;
18553 case OPC_ADDIU:
18554 gen_arith_imm(ctx, op, rt, rs, imm);
18555 break;
18556 case OPC_SLTI: /* Set on less than with immediate opcode */
18557 case OPC_SLTIU:
18558 gen_slt_imm(ctx, op, rt, rs, imm);
18559 break;
18560 case OPC_ANDI: /* Arithmetic with immediate opcode */
18561 case OPC_LUI: /* OPC_AUI */
18562 case OPC_ORI:
18563 case OPC_XORI:
18564 gen_logic_imm(ctx, op, rt, rs, imm);
18565 break;
18566 case OPC_J ... OPC_JAL: /* Jump */
18567 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
18568 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
18569 break;
18570 /* Branch */
18571 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
18572 if (ctx->insn_flags & ISA_MIPS32R6) {
18573 if (rt == 0) {
18574 generate_exception(ctx, EXCP_RI);
18575 break;
18577 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
18578 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18579 } else {
18580 /* OPC_BLEZL */
18581 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18583 break;
18584 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
18585 if (ctx->insn_flags & ISA_MIPS32R6) {
18586 if (rt == 0) {
18587 generate_exception(ctx, EXCP_RI);
18588 break;
18590 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
18591 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18592 } else {
18593 /* OPC_BGTZL */
18594 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18596 break;
18597 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
18598 if (rt == 0) {
18599 /* OPC_BLEZ */
18600 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18601 } else {
18602 check_insn(ctx, ISA_MIPS32R6);
18603 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
18604 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18606 break;
18607 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
18608 if (rt == 0) {
18609 /* OPC_BGTZ */
18610 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18611 } else {
18612 check_insn(ctx, ISA_MIPS32R6);
18613 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
18614 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18616 break;
18617 case OPC_BEQL:
18618 case OPC_BNEL:
18619 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18620 case OPC_BEQ:
18621 case OPC_BNE:
18622 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
18623 break;
18624 case OPC_LWL: /* Load and stores */
18625 case OPC_LWR:
18626 case OPC_LL:
18627 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18628 case OPC_LB ... OPC_LH:
18629 case OPC_LW ... OPC_LHU:
18630 gen_ld(ctx, op, rt, rs, imm);
18631 break;
18632 case OPC_SWL:
18633 case OPC_SWR:
18634 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18635 case OPC_SB ... OPC_SH:
18636 case OPC_SW:
18637 gen_st(ctx, op, rt, rs, imm);
18638 break;
18639 case OPC_SC:
18640 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18641 gen_st_cond(ctx, op, rt, rs, imm);
18642 break;
18643 case OPC_CACHE:
18644 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18645 check_cp0_enabled(ctx);
18646 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
18647 /* Treat as NOP. */
18648 break;
18649 case OPC_PREF:
18650 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18651 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
18652 /* Treat as NOP. */
18653 break;
18655 /* Floating point (COP1). */
18656 case OPC_LWC1:
18657 case OPC_LDC1:
18658 case OPC_SWC1:
18659 case OPC_SDC1:
18660 gen_cop1_ldst(ctx, op, rt, rs, imm);
18661 break;
18663 case OPC_CP1:
18664 op1 = MASK_CP1(ctx->opcode);
18666 switch (op1) {
18667 case OPC_MFHC1:
18668 case OPC_MTHC1:
18669 check_cp1_enabled(ctx);
18670 check_insn(ctx, ISA_MIPS32R2);
18671 case OPC_MFC1:
18672 case OPC_CFC1:
18673 case OPC_MTC1:
18674 case OPC_CTC1:
18675 check_cp1_enabled(ctx);
18676 gen_cp1(ctx, op1, rt, rd);
18677 break;
18678 #if defined(TARGET_MIPS64)
18679 case OPC_DMFC1:
18680 case OPC_DMTC1:
18681 check_cp1_enabled(ctx);
18682 check_insn(ctx, ISA_MIPS3);
18683 gen_cp1(ctx, op1, rt, rd);
18684 break;
18685 #endif
18686 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
18687 check_cp1_enabled(ctx);
18688 if (ctx->insn_flags & ISA_MIPS32R6) {
18689 /* OPC_BC1EQZ */
18690 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
18691 rt, imm << 2);
18692 } else {
18693 /* OPC_BC1ANY2 */
18694 check_cop1x(ctx);
18695 check_insn(ctx, ASE_MIPS3D);
18696 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
18697 (rt >> 2) & 0x7, imm << 2);
18699 break;
18700 case OPC_BC1NEZ:
18701 check_cp1_enabled(ctx);
18702 check_insn(ctx, ISA_MIPS32R6);
18703 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
18704 rt, imm << 2);
18705 break;
18706 case OPC_BC1ANY4:
18707 check_cp1_enabled(ctx);
18708 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18709 check_cop1x(ctx);
18710 check_insn(ctx, ASE_MIPS3D);
18711 /* fall through */
18712 case OPC_BC1:
18713 check_cp1_enabled(ctx);
18714 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18715 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
18716 (rt >> 2) & 0x7, imm << 2);
18717 break;
18718 case OPC_PS_FMT:
18719 check_cp1_enabled(ctx);
18720 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18721 case OPC_S_FMT:
18722 case OPC_D_FMT:
18723 check_cp1_enabled(ctx);
18724 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
18725 (imm >> 8) & 0x7);
18726 break;
18727 case OPC_W_FMT:
18728 case OPC_L_FMT:
18730 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
18731 check_cp1_enabled(ctx);
18732 if (ctx->insn_flags & ISA_MIPS32R6) {
18733 switch (r6_op) {
18734 case R6_OPC_CMP_AF_S:
18735 case R6_OPC_CMP_UN_S:
18736 case R6_OPC_CMP_EQ_S:
18737 case R6_OPC_CMP_UEQ_S:
18738 case R6_OPC_CMP_LT_S:
18739 case R6_OPC_CMP_ULT_S:
18740 case R6_OPC_CMP_LE_S:
18741 case R6_OPC_CMP_ULE_S:
18742 case R6_OPC_CMP_SAF_S:
18743 case R6_OPC_CMP_SUN_S:
18744 case R6_OPC_CMP_SEQ_S:
18745 case R6_OPC_CMP_SEUQ_S:
18746 case R6_OPC_CMP_SLT_S:
18747 case R6_OPC_CMP_SULT_S:
18748 case R6_OPC_CMP_SLE_S:
18749 case R6_OPC_CMP_SULE_S:
18750 case R6_OPC_CMP_OR_S:
18751 case R6_OPC_CMP_UNE_S:
18752 case R6_OPC_CMP_NE_S:
18753 case R6_OPC_CMP_SOR_S:
18754 case R6_OPC_CMP_SUNE_S:
18755 case R6_OPC_CMP_SNE_S:
18756 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
18757 break;
18758 case R6_OPC_CMP_AF_D:
18759 case R6_OPC_CMP_UN_D:
18760 case R6_OPC_CMP_EQ_D:
18761 case R6_OPC_CMP_UEQ_D:
18762 case R6_OPC_CMP_LT_D:
18763 case R6_OPC_CMP_ULT_D:
18764 case R6_OPC_CMP_LE_D:
18765 case R6_OPC_CMP_ULE_D:
18766 case R6_OPC_CMP_SAF_D:
18767 case R6_OPC_CMP_SUN_D:
18768 case R6_OPC_CMP_SEQ_D:
18769 case R6_OPC_CMP_SEUQ_D:
18770 case R6_OPC_CMP_SLT_D:
18771 case R6_OPC_CMP_SULT_D:
18772 case R6_OPC_CMP_SLE_D:
18773 case R6_OPC_CMP_SULE_D:
18774 case R6_OPC_CMP_OR_D:
18775 case R6_OPC_CMP_UNE_D:
18776 case R6_OPC_CMP_NE_D:
18777 case R6_OPC_CMP_SOR_D:
18778 case R6_OPC_CMP_SUNE_D:
18779 case R6_OPC_CMP_SNE_D:
18780 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
18781 break;
18782 default:
18783 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
18784 (imm >> 8) & 0x7);
18785 break;
18787 } else {
18788 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
18789 (imm >> 8) & 0x7);
18791 break;
18793 case OPC_BZ_V:
18794 case OPC_BNZ_V:
18795 case OPC_BZ_B:
18796 case OPC_BZ_H:
18797 case OPC_BZ_W:
18798 case OPC_BZ_D:
18799 case OPC_BNZ_B:
18800 case OPC_BNZ_H:
18801 case OPC_BNZ_W:
18802 case OPC_BNZ_D:
18803 check_insn(ctx, ASE_MSA);
18804 gen_msa_branch(env, ctx, op1);
18805 break;
18806 default:
18807 MIPS_INVAL("cp1");
18808 generate_exception(ctx, EXCP_RI);
18809 break;
18811 break;
18813 /* Compact branches [R6] and COP2 [non-R6] */
18814 case OPC_BC: /* OPC_LWC2 */
18815 case OPC_BALC: /* OPC_SWC2 */
18816 if (ctx->insn_flags & ISA_MIPS32R6) {
18817 /* OPC_BC, OPC_BALC */
18818 gen_compute_compact_branch(ctx, op, 0, 0,
18819 sextract32(ctx->opcode << 2, 0, 28));
18820 } else {
18821 /* OPC_LWC2, OPC_SWC2 */
18822 /* COP2: Not implemented. */
18823 generate_exception_err(ctx, EXCP_CpU, 2);
18825 break;
18826 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
18827 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
18828 if (ctx->insn_flags & ISA_MIPS32R6) {
18829 if (rs != 0) {
18830 /* OPC_BEQZC, OPC_BNEZC */
18831 gen_compute_compact_branch(ctx, op, rs, 0,
18832 sextract32(ctx->opcode << 2, 0, 23));
18833 } else {
18834 /* OPC_JIC, OPC_JIALC */
18835 gen_compute_compact_branch(ctx, op, 0, rt, imm);
18837 } else {
18838 /* OPC_LWC2, OPC_SWC2 */
18839 /* COP2: Not implemented. */
18840 generate_exception_err(ctx, EXCP_CpU, 2);
18842 break;
18843 case OPC_CP2:
18844 check_insn(ctx, INSN_LOONGSON2F);
18845 /* Note that these instructions use different fields. */
18846 gen_loongson_multimedia(ctx, sa, rd, rt);
18847 break;
18849 case OPC_CP3:
18850 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18851 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
18852 check_cp1_enabled(ctx);
18853 op1 = MASK_CP3(ctx->opcode);
18854 switch (op1) {
18855 case OPC_LWXC1:
18856 case OPC_LDXC1:
18857 case OPC_LUXC1:
18858 case OPC_SWXC1:
18859 case OPC_SDXC1:
18860 case OPC_SUXC1:
18861 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
18862 break;
18863 case OPC_PREFX:
18864 /* Treat as NOP. */
18865 break;
18866 case OPC_ALNV_PS:
18867 case OPC_MADD_S:
18868 case OPC_MADD_D:
18869 case OPC_MADD_PS:
18870 case OPC_MSUB_S:
18871 case OPC_MSUB_D:
18872 case OPC_MSUB_PS:
18873 case OPC_NMADD_S:
18874 case OPC_NMADD_D:
18875 case OPC_NMADD_PS:
18876 case OPC_NMSUB_S:
18877 case OPC_NMSUB_D:
18878 case OPC_NMSUB_PS:
18879 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
18880 break;
18881 default:
18882 MIPS_INVAL("cp3");
18883 generate_exception (ctx, EXCP_RI);
18884 break;
18886 } else {
18887 generate_exception_err(ctx, EXCP_CpU, 1);
18889 break;
18891 #if defined(TARGET_MIPS64)
18892 /* MIPS64 opcodes */
18893 case OPC_LDL ... OPC_LDR:
18894 case OPC_LLD:
18895 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18896 case OPC_LWU:
18897 case OPC_LD:
18898 check_insn(ctx, ISA_MIPS3);
18899 check_mips_64(ctx);
18900 gen_ld(ctx, op, rt, rs, imm);
18901 break;
18902 case OPC_SDL ... OPC_SDR:
18903 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18904 case OPC_SD:
18905 check_insn(ctx, ISA_MIPS3);
18906 check_mips_64(ctx);
18907 gen_st(ctx, op, rt, rs, imm);
18908 break;
18909 case OPC_SCD:
18910 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18911 check_insn(ctx, ISA_MIPS3);
18912 check_mips_64(ctx);
18913 gen_st_cond(ctx, op, rt, rs, imm);
18914 break;
18915 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
18916 if (ctx->insn_flags & ISA_MIPS32R6) {
18917 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
18918 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18919 } else {
18920 /* OPC_DADDI */
18921 check_insn(ctx, ISA_MIPS3);
18922 check_mips_64(ctx);
18923 gen_arith_imm(ctx, op, rt, rs, imm);
18925 break;
18926 case OPC_DADDIU:
18927 check_insn(ctx, ISA_MIPS3);
18928 check_mips_64(ctx);
18929 gen_arith_imm(ctx, op, rt, rs, imm);
18930 break;
18931 #else
18932 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
18933 if (ctx->insn_flags & ISA_MIPS32R6) {
18934 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
18935 } else {
18936 MIPS_INVAL("major opcode");
18937 generate_exception(ctx, EXCP_RI);
18939 break;
18940 #endif
18941 case OPC_DAUI: /* OPC_JALX */
18942 if (ctx->insn_flags & ISA_MIPS32R6) {
18943 #if defined(TARGET_MIPS64)
18944 /* OPC_DAUI */
18945 check_mips_64(ctx);
18946 if (rt != 0) {
18947 TCGv t0 = tcg_temp_new();
18948 gen_load_gpr(t0, rs);
18949 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
18950 tcg_temp_free(t0);
18952 MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm);
18953 #else
18954 generate_exception(ctx, EXCP_RI);
18955 MIPS_INVAL("major opcode");
18956 #endif
18957 } else {
18958 /* OPC_JALX */
18959 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
18960 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
18961 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
18963 break;
18964 case OPC_MSA: /* OPC_MDMX */
18965 /* MDMX: Not implemented. */
18966 gen_msa(env, ctx);
18967 break;
18968 case OPC_PCREL:
18969 check_insn(ctx, ISA_MIPS32R6);
18970 gen_pcrel(ctx, rs, imm);
18971 break;
18972 default: /* Invalid */
18973 MIPS_INVAL("major opcode");
18974 generate_exception(ctx, EXCP_RI);
18975 break;
18979 static inline void
18980 gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
18981 bool search_pc)
18983 CPUState *cs = CPU(cpu);
18984 CPUMIPSState *env = &cpu->env;
18985 DisasContext ctx;
18986 target_ulong pc_start;
18987 uint16_t *gen_opc_end;
18988 CPUBreakpoint *bp;
18989 int j, lj = -1;
18990 int num_insns;
18991 int max_insns;
18992 int insn_bytes;
18993 int is_slot;
18995 if (search_pc)
18996 qemu_log("search pc %d\n", search_pc);
18998 pc_start = tb->pc;
18999 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
19000 ctx.pc = pc_start;
19001 ctx.saved_pc = -1;
19002 ctx.singlestep_enabled = cs->singlestep_enabled;
19003 ctx.insn_flags = env->insn_flags;
19004 ctx.CP0_Config1 = env->CP0_Config1;
19005 ctx.tb = tb;
19006 ctx.bstate = BS_NONE;
19007 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
19008 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
19009 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
19010 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
19011 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
19012 /* Restore delay slot state from the tb context. */
19013 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
19014 ctx.ulri = env->CP0_Config3 & (1 << CP0C3_ULRI);
19015 restore_cpu_state(env, &ctx);
19016 #ifdef CONFIG_USER_ONLY
19017 ctx.mem_idx = MIPS_HFLAG_UM;
19018 #else
19019 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
19020 #endif
19021 num_insns = 0;
19022 max_insns = tb->cflags & CF_COUNT_MASK;
19023 if (max_insns == 0)
19024 max_insns = CF_COUNT_MASK;
19025 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
19026 gen_tb_start();
19027 while (ctx.bstate == BS_NONE) {
19028 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
19029 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
19030 if (bp->pc == ctx.pc) {
19031 save_cpu_state(&ctx, 1);
19032 ctx.bstate = BS_BRANCH;
19033 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
19034 /* Include the breakpoint location or the tb won't
19035 * be flushed when it must be. */
19036 ctx.pc += 4;
19037 goto done_generating;
19042 if (search_pc) {
19043 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
19044 if (lj < j) {
19045 lj++;
19046 while (lj < j)
19047 tcg_ctx.gen_opc_instr_start[lj++] = 0;
19049 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
19050 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
19051 gen_opc_btarget[lj] = ctx.btarget;
19052 tcg_ctx.gen_opc_instr_start[lj] = 1;
19053 tcg_ctx.gen_opc_icount[lj] = num_insns;
19055 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
19056 gen_io_start();
19058 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
19059 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
19060 ctx.opcode = cpu_ldl_code(env, ctx.pc);
19061 insn_bytes = 4;
19062 decode_opc(env, &ctx);
19063 } else if (ctx.insn_flags & ASE_MICROMIPS) {
19064 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19065 insn_bytes = decode_micromips_opc(env, &ctx);
19066 } else if (ctx.insn_flags & ASE_MIPS16) {
19067 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19068 insn_bytes = decode_mips16_opc(env, &ctx);
19069 } else {
19070 generate_exception(&ctx, EXCP_RI);
19071 ctx.bstate = BS_STOP;
19072 break;
19075 if (ctx.hflags & MIPS_HFLAG_BMASK) {
19076 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
19077 MIPS_HFLAG_FBNSLOT))) {
19078 /* force to generate branch as there is neither delay nor
19079 forbidden slot */
19080 is_slot = 1;
19083 if (is_slot) {
19084 gen_branch(&ctx, insn_bytes);
19086 ctx.pc += insn_bytes;
19088 num_insns++;
19090 /* Execute a branch and its delay slot as a single instruction.
19091 This is what GDB expects and is consistent with what the
19092 hardware does (e.g. if a delay slot instruction faults, the
19093 reported PC is the PC of the branch). */
19094 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
19095 break;
19098 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
19099 break;
19101 if (tcg_ctx.gen_opc_ptr >= gen_opc_end) {
19102 break;
19105 if (num_insns >= max_insns)
19106 break;
19108 if (singlestep)
19109 break;
19111 if (tb->cflags & CF_LAST_IO) {
19112 gen_io_end();
19114 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
19115 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
19116 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
19117 } else {
19118 switch (ctx.bstate) {
19119 case BS_STOP:
19120 gen_goto_tb(&ctx, 0, ctx.pc);
19121 break;
19122 case BS_NONE:
19123 save_cpu_state(&ctx, 0);
19124 gen_goto_tb(&ctx, 0, ctx.pc);
19125 break;
19126 case BS_EXCP:
19127 tcg_gen_exit_tb(0);
19128 break;
19129 case BS_BRANCH:
19130 default:
19131 break;
19134 done_generating:
19135 gen_tb_end(tb, num_insns);
19136 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
19137 if (search_pc) {
19138 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
19139 lj++;
19140 while (lj <= j)
19141 tcg_ctx.gen_opc_instr_start[lj++] = 0;
19142 } else {
19143 tb->size = ctx.pc - pc_start;
19144 tb->icount = num_insns;
19146 #ifdef DEBUG_DISAS
19147 LOG_DISAS("\n");
19148 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
19149 qemu_log("IN: %s\n", lookup_symbol(pc_start));
19150 log_target_disas(env, pc_start, ctx.pc - pc_start, 0);
19151 qemu_log("\n");
19153 #endif
19156 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
19158 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
19161 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
19163 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
19166 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
19167 int flags)
19169 int i;
19170 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
19172 #define printfpr(fp) \
19173 do { \
19174 if (is_fpu64) \
19175 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19176 " fd:%13g fs:%13g psu: %13g\n", \
19177 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
19178 (double)(fp)->fd, \
19179 (double)(fp)->fs[FP_ENDIAN_IDX], \
19180 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
19181 else { \
19182 fpr_t tmp; \
19183 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
19184 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
19185 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19186 " fd:%13g fs:%13g psu:%13g\n", \
19187 tmp.w[FP_ENDIAN_IDX], tmp.d, \
19188 (double)tmp.fd, \
19189 (double)tmp.fs[FP_ENDIAN_IDX], \
19190 (double)tmp.fs[!FP_ENDIAN_IDX]); \
19192 } while(0)
19195 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
19196 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
19197 get_float_exception_flags(&env->active_fpu.fp_status));
19198 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
19199 fpu_fprintf(f, "%3s: ", fregnames[i]);
19200 printfpr(&env->active_fpu.fpr[i]);
19203 #undef printfpr
19206 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
19207 /* Debug help: The architecture requires 32bit code to maintain proper
19208 sign-extended values on 64bit machines. */
19210 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
19212 static void
19213 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
19214 fprintf_function cpu_fprintf,
19215 int flags)
19217 int i;
19219 if (!SIGN_EXT_P(env->active_tc.PC))
19220 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
19221 if (!SIGN_EXT_P(env->active_tc.HI[0]))
19222 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
19223 if (!SIGN_EXT_P(env->active_tc.LO[0]))
19224 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
19225 if (!SIGN_EXT_P(env->btarget))
19226 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
19228 for (i = 0; i < 32; i++) {
19229 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
19230 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
19233 if (!SIGN_EXT_P(env->CP0_EPC))
19234 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
19235 if (!SIGN_EXT_P(env->lladdr))
19236 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
19238 #endif
19240 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
19241 int flags)
19243 MIPSCPU *cpu = MIPS_CPU(cs);
19244 CPUMIPSState *env = &cpu->env;
19245 int i;
19247 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
19248 " LO=0x" TARGET_FMT_lx " ds %04x "
19249 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
19250 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
19251 env->hflags, env->btarget, env->bcond);
19252 for (i = 0; i < 32; i++) {
19253 if ((i & 3) == 0)
19254 cpu_fprintf(f, "GPR%02d:", i);
19255 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
19256 if ((i & 3) == 3)
19257 cpu_fprintf(f, "\n");
19260 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
19261 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
19262 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
19263 env->CP0_Config0, env->CP0_Config1, env->lladdr);
19264 if (env->hflags & MIPS_HFLAG_FPU)
19265 fpu_dump_state(env, f, cpu_fprintf, flags);
19266 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
19267 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
19268 #endif
19271 void mips_tcg_init(void)
19273 int i;
19274 static int inited;
19276 /* Initialize various static tables. */
19277 if (inited)
19278 return;
19280 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
19281 TCGV_UNUSED(cpu_gpr[0]);
19282 for (i = 1; i < 32; i++)
19283 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
19284 offsetof(CPUMIPSState, active_tc.gpr[i]),
19285 regnames[i]);
19287 for (i = 0; i < 32; i++) {
19288 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
19289 msa_wr_d[i * 2] =
19290 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]);
19291 /* The scalar floating-point unit (FPU) registers are mapped on
19292 * the MSA vector registers. */
19293 fpu_f64[i] = msa_wr_d[i * 2];
19294 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
19295 msa_wr_d[i * 2 + 1] =
19296 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + 1]);
19299 cpu_PC = tcg_global_mem_new(TCG_AREG0,
19300 offsetof(CPUMIPSState, active_tc.PC), "PC");
19301 for (i = 0; i < MIPS_DSP_ACC; i++) {
19302 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
19303 offsetof(CPUMIPSState, active_tc.HI[i]),
19304 regnames_HI[i]);
19305 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
19306 offsetof(CPUMIPSState, active_tc.LO[i]),
19307 regnames_LO[i]);
19309 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
19310 offsetof(CPUMIPSState, active_tc.DSPControl),
19311 "DSPControl");
19312 bcond = tcg_global_mem_new(TCG_AREG0,
19313 offsetof(CPUMIPSState, bcond), "bcond");
19314 btarget = tcg_global_mem_new(TCG_AREG0,
19315 offsetof(CPUMIPSState, btarget), "btarget");
19316 hflags = tcg_global_mem_new_i32(TCG_AREG0,
19317 offsetof(CPUMIPSState, hflags), "hflags");
19319 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
19320 offsetof(CPUMIPSState, active_fpu.fcr0),
19321 "fcr0");
19322 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
19323 offsetof(CPUMIPSState, active_fpu.fcr31),
19324 "fcr31");
19326 inited = 1;
19329 #include "translate_init.c"
19331 MIPSCPU *cpu_mips_init(const char *cpu_model)
19333 MIPSCPU *cpu;
19334 CPUMIPSState *env;
19335 const mips_def_t *def;
19337 def = cpu_mips_find_by_name(cpu_model);
19338 if (!def)
19339 return NULL;
19340 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
19341 env = &cpu->env;
19342 env->cpu_model = def;
19344 #ifndef CONFIG_USER_ONLY
19345 mmu_init(env, def);
19346 #endif
19347 fpu_init(env, def);
19348 mvp_init(env, def);
19350 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
19352 return cpu;
19355 void cpu_state_reset(CPUMIPSState *env)
19357 MIPSCPU *cpu = mips_env_get_cpu(env);
19358 CPUState *cs = CPU(cpu);
19360 /* Reset registers to their default values */
19361 env->CP0_PRid = env->cpu_model->CP0_PRid;
19362 env->CP0_Config0 = env->cpu_model->CP0_Config0;
19363 #ifdef TARGET_WORDS_BIGENDIAN
19364 env->CP0_Config0 |= (1 << CP0C0_BE);
19365 #endif
19366 env->CP0_Config1 = env->cpu_model->CP0_Config1;
19367 env->CP0_Config2 = env->cpu_model->CP0_Config2;
19368 env->CP0_Config3 = env->cpu_model->CP0_Config3;
19369 env->CP0_Config4 = env->cpu_model->CP0_Config4;
19370 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
19371 env->CP0_Config5 = env->cpu_model->CP0_Config5;
19372 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
19373 env->CP0_Config6 = env->cpu_model->CP0_Config6;
19374 env->CP0_Config7 = env->cpu_model->CP0_Config7;
19375 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
19376 << env->cpu_model->CP0_LLAddr_shift;
19377 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
19378 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
19379 env->CCRes = env->cpu_model->CCRes;
19380 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
19381 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
19382 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
19383 env->current_tc = 0;
19384 env->SEGBITS = env->cpu_model->SEGBITS;
19385 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
19386 #if defined(TARGET_MIPS64)
19387 if (env->cpu_model->insn_flags & ISA_MIPS3) {
19388 env->SEGMask |= 3ULL << 62;
19390 #endif
19391 env->PABITS = env->cpu_model->PABITS;
19392 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
19393 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
19394 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
19395 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
19396 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
19397 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
19398 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
19399 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
19400 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
19401 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
19402 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
19403 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
19404 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
19405 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
19406 env->msair = env->cpu_model->MSAIR;
19407 env->insn_flags = env->cpu_model->insn_flags;
19409 #if defined(CONFIG_USER_ONLY)
19410 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
19411 # ifdef TARGET_MIPS64
19412 /* Enable 64-bit register mode. */
19413 env->CP0_Status |= (1 << CP0St_PX);
19414 # endif
19415 # ifdef TARGET_ABI_MIPSN64
19416 /* Enable 64-bit address mode. */
19417 env->CP0_Status |= (1 << CP0St_UX);
19418 # endif
19419 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
19420 hardware registers. */
19421 env->CP0_HWREna |= 0x0000000F;
19422 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
19423 env->CP0_Status |= (1 << CP0St_CU1);
19425 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
19426 env->CP0_Status |= (1 << CP0St_MX);
19428 # if defined(TARGET_MIPS64)
19429 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
19430 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
19431 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
19432 env->CP0_Status |= (1 << CP0St_FR);
19434 # endif
19435 #else
19436 if (env->hflags & MIPS_HFLAG_BMASK) {
19437 /* If the exception was raised from a delay slot,
19438 come back to the jump. */
19439 env->CP0_ErrorEPC = env->active_tc.PC - 4;
19440 } else {
19441 env->CP0_ErrorEPC = env->active_tc.PC;
19443 env->active_tc.PC = (int32_t)0xBFC00000;
19444 env->CP0_Random = env->tlb->nb_tlb - 1;
19445 env->tlb->tlb_in_use = env->tlb->nb_tlb;
19446 env->CP0_Wired = 0;
19447 env->CP0_EBase = (cs->cpu_index & 0x3FF);
19448 if (kvm_enabled()) {
19449 env->CP0_EBase |= 0x40000000;
19450 } else {
19451 env->CP0_EBase |= 0x80000000;
19453 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
19454 /* vectored interrupts not implemented, timer on int 7,
19455 no performance counters. */
19456 env->CP0_IntCtl = 0xe0000000;
19458 int i;
19460 for (i = 0; i < 7; i++) {
19461 env->CP0_WatchLo[i] = 0;
19462 env->CP0_WatchHi[i] = 0x80000000;
19464 env->CP0_WatchLo[7] = 0;
19465 env->CP0_WatchHi[7] = 0;
19467 /* Count register increments in debug mode, EJTAG version 1 */
19468 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
19470 cpu_mips_store_count(env, 1);
19472 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
19473 int i;
19475 /* Only TC0 on VPE 0 starts as active. */
19476 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
19477 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
19478 env->tcs[i].CP0_TCHalt = 1;
19480 env->active_tc.CP0_TCHalt = 1;
19481 cs->halted = 1;
19483 if (cs->cpu_index == 0) {
19484 /* VPE0 starts up enabled. */
19485 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
19486 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
19488 /* TC0 starts up unhalted. */
19489 cs->halted = 0;
19490 env->active_tc.CP0_TCHalt = 0;
19491 env->tcs[0].CP0_TCHalt = 0;
19492 /* With thread 0 active. */
19493 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
19494 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
19497 #endif
19498 if ((env->insn_flags & ISA_MIPS32R6) &&
19499 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
19500 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
19501 env->CP0_Status |= (1 << CP0St_FR);
19504 /* MSA */
19505 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
19506 msa_reset(env);
19509 compute_hflags(env);
19510 cs->exception_index = EXCP_NONE;
19513 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
19515 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
19516 env->hflags &= ~MIPS_HFLAG_BMASK;
19517 env->hflags |= gen_opc_hflags[pc_pos];
19518 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
19519 case MIPS_HFLAG_BR:
19520 break;
19521 case MIPS_HFLAG_BC:
19522 case MIPS_HFLAG_BL:
19523 case MIPS_HFLAG_B:
19524 env->btarget = gen_opc_btarget[pc_pos];
19525 break;