virtio-net: remove useless codes
[qemu/ar7.git] / target-mips / translate.c
blob22ef84df9eab0f549cbd01d4d6371e985c7db503
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "cpu.h"
25 #include "disas/disas.h"
26 #include "tcg-op.h"
27 #include "exec/cpu_ldst.h"
29 #include "exec/helper-proto.h"
30 #include "exec/helper-gen.h"
31 #include "sysemu/kvm.h"
32 #include "exec/semihost.h"
34 #include "trace-tcg.h"
37 #define MIPS_DEBUG_DISAS 0
38 //#define MIPS_DEBUG_SIGN_EXTENSIONS
40 /* MIPS major opcodes */
41 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
43 enum {
44 /* indirect opcode tables */
45 OPC_SPECIAL = (0x00 << 26),
46 OPC_REGIMM = (0x01 << 26),
47 OPC_CP0 = (0x10 << 26),
48 OPC_CP1 = (0x11 << 26),
49 OPC_CP2 = (0x12 << 26),
50 OPC_CP3 = (0x13 << 26),
51 OPC_SPECIAL2 = (0x1C << 26),
52 OPC_SPECIAL3 = (0x1F << 26),
53 /* arithmetic with immediate */
54 OPC_ADDI = (0x08 << 26),
55 OPC_ADDIU = (0x09 << 26),
56 OPC_SLTI = (0x0A << 26),
57 OPC_SLTIU = (0x0B << 26),
58 /* logic with immediate */
59 OPC_ANDI = (0x0C << 26),
60 OPC_ORI = (0x0D << 26),
61 OPC_XORI = (0x0E << 26),
62 OPC_LUI = (0x0F << 26),
63 /* arithmetic with immediate */
64 OPC_DADDI = (0x18 << 26),
65 OPC_DADDIU = (0x19 << 26),
66 /* Jump and branches */
67 OPC_J = (0x02 << 26),
68 OPC_JAL = (0x03 << 26),
69 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
70 OPC_BEQL = (0x14 << 26),
71 OPC_BNE = (0x05 << 26),
72 OPC_BNEL = (0x15 << 26),
73 OPC_BLEZ = (0x06 << 26),
74 OPC_BLEZL = (0x16 << 26),
75 OPC_BGTZ = (0x07 << 26),
76 OPC_BGTZL = (0x17 << 26),
77 OPC_JALX = (0x1D << 26),
78 OPC_DAUI = (0x1D << 26),
79 /* Load and stores */
80 OPC_LDL = (0x1A << 26),
81 OPC_LDR = (0x1B << 26),
82 OPC_LB = (0x20 << 26),
83 OPC_LH = (0x21 << 26),
84 OPC_LWL = (0x22 << 26),
85 OPC_LW = (0x23 << 26),
86 OPC_LWPC = OPC_LW | 0x5,
87 OPC_LBU = (0x24 << 26),
88 OPC_LHU = (0x25 << 26),
89 OPC_LWR = (0x26 << 26),
90 OPC_LWU = (0x27 << 26),
91 OPC_SB = (0x28 << 26),
92 OPC_SH = (0x29 << 26),
93 OPC_SWL = (0x2A << 26),
94 OPC_SW = (0x2B << 26),
95 OPC_SDL = (0x2C << 26),
96 OPC_SDR = (0x2D << 26),
97 OPC_SWR = (0x2E << 26),
98 OPC_LL = (0x30 << 26),
99 OPC_LLD = (0x34 << 26),
100 OPC_LD = (0x37 << 26),
101 OPC_LDPC = OPC_LD | 0x5,
102 OPC_SC = (0x38 << 26),
103 OPC_SCD = (0x3C << 26),
104 OPC_SD = (0x3F << 26),
105 /* Floating point load/store */
106 OPC_LWC1 = (0x31 << 26),
107 OPC_LWC2 = (0x32 << 26),
108 OPC_LDC1 = (0x35 << 26),
109 OPC_LDC2 = (0x36 << 26),
110 OPC_SWC1 = (0x39 << 26),
111 OPC_SWC2 = (0x3A << 26),
112 OPC_SDC1 = (0x3D << 26),
113 OPC_SDC2 = (0x3E << 26),
114 /* Compact Branches */
115 OPC_BLEZALC = (0x06 << 26),
116 OPC_BGEZALC = (0x06 << 26),
117 OPC_BGEUC = (0x06 << 26),
118 OPC_BGTZALC = (0x07 << 26),
119 OPC_BLTZALC = (0x07 << 26),
120 OPC_BLTUC = (0x07 << 26),
121 OPC_BOVC = (0x08 << 26),
122 OPC_BEQZALC = (0x08 << 26),
123 OPC_BEQC = (0x08 << 26),
124 OPC_BLEZC = (0x16 << 26),
125 OPC_BGEZC = (0x16 << 26),
126 OPC_BGEC = (0x16 << 26),
127 OPC_BGTZC = (0x17 << 26),
128 OPC_BLTZC = (0x17 << 26),
129 OPC_BLTC = (0x17 << 26),
130 OPC_BNVC = (0x18 << 26),
131 OPC_BNEZALC = (0x18 << 26),
132 OPC_BNEC = (0x18 << 26),
133 OPC_BC = (0x32 << 26),
134 OPC_BEQZC = (0x36 << 26),
135 OPC_JIC = (0x36 << 26),
136 OPC_BALC = (0x3A << 26),
137 OPC_BNEZC = (0x3E << 26),
138 OPC_JIALC = (0x3E << 26),
139 /* MDMX ASE specific */
140 OPC_MDMX = (0x1E << 26),
141 /* MSA ASE, same as MDMX */
142 OPC_MSA = OPC_MDMX,
143 /* Cache and prefetch */
144 OPC_CACHE = (0x2F << 26),
145 OPC_PREF = (0x33 << 26),
146 /* PC-relative address computation / loads */
147 OPC_PCREL = (0x3B << 26),
150 /* PC-relative address computation / loads */
151 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
152 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
153 enum {
154 /* Instructions determined by bits 19 and 20 */
155 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
156 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
157 OPC_LWUPC = OPC_PCREL | (2 << 19),
159 /* Instructions determined by bits 16 ... 20 */
160 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
161 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
163 /* Other */
164 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
167 /* MIPS special opcodes */
168 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
170 enum {
171 /* Shifts */
172 OPC_SLL = 0x00 | OPC_SPECIAL,
173 /* NOP is SLL r0, r0, 0 */
174 /* SSNOP is SLL r0, r0, 1 */
175 /* EHB is SLL r0, r0, 3 */
176 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
177 OPC_ROTR = OPC_SRL | (1 << 21),
178 OPC_SRA = 0x03 | OPC_SPECIAL,
179 OPC_SLLV = 0x04 | OPC_SPECIAL,
180 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
181 OPC_ROTRV = OPC_SRLV | (1 << 6),
182 OPC_SRAV = 0x07 | OPC_SPECIAL,
183 OPC_DSLLV = 0x14 | OPC_SPECIAL,
184 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
185 OPC_DROTRV = OPC_DSRLV | (1 << 6),
186 OPC_DSRAV = 0x17 | OPC_SPECIAL,
187 OPC_DSLL = 0x38 | OPC_SPECIAL,
188 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
189 OPC_DROTR = OPC_DSRL | (1 << 21),
190 OPC_DSRA = 0x3B | OPC_SPECIAL,
191 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
192 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
193 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
194 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
195 /* Multiplication / division */
196 OPC_MULT = 0x18 | OPC_SPECIAL,
197 OPC_MULTU = 0x19 | OPC_SPECIAL,
198 OPC_DIV = 0x1A | OPC_SPECIAL,
199 OPC_DIVU = 0x1B | OPC_SPECIAL,
200 OPC_DMULT = 0x1C | OPC_SPECIAL,
201 OPC_DMULTU = 0x1D | OPC_SPECIAL,
202 OPC_DDIV = 0x1E | OPC_SPECIAL,
203 OPC_DDIVU = 0x1F | OPC_SPECIAL,
205 /* 2 registers arithmetic / logic */
206 OPC_ADD = 0x20 | OPC_SPECIAL,
207 OPC_ADDU = 0x21 | OPC_SPECIAL,
208 OPC_SUB = 0x22 | OPC_SPECIAL,
209 OPC_SUBU = 0x23 | OPC_SPECIAL,
210 OPC_AND = 0x24 | OPC_SPECIAL,
211 OPC_OR = 0x25 | OPC_SPECIAL,
212 OPC_XOR = 0x26 | OPC_SPECIAL,
213 OPC_NOR = 0x27 | OPC_SPECIAL,
214 OPC_SLT = 0x2A | OPC_SPECIAL,
215 OPC_SLTU = 0x2B | OPC_SPECIAL,
216 OPC_DADD = 0x2C | OPC_SPECIAL,
217 OPC_DADDU = 0x2D | OPC_SPECIAL,
218 OPC_DSUB = 0x2E | OPC_SPECIAL,
219 OPC_DSUBU = 0x2F | OPC_SPECIAL,
220 /* Jumps */
221 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
222 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
223 /* Traps */
224 OPC_TGE = 0x30 | OPC_SPECIAL,
225 OPC_TGEU = 0x31 | OPC_SPECIAL,
226 OPC_TLT = 0x32 | OPC_SPECIAL,
227 OPC_TLTU = 0x33 | OPC_SPECIAL,
228 OPC_TEQ = 0x34 | OPC_SPECIAL,
229 OPC_TNE = 0x36 | OPC_SPECIAL,
230 /* HI / LO registers load & stores */
231 OPC_MFHI = 0x10 | OPC_SPECIAL,
232 OPC_MTHI = 0x11 | OPC_SPECIAL,
233 OPC_MFLO = 0x12 | OPC_SPECIAL,
234 OPC_MTLO = 0x13 | OPC_SPECIAL,
235 /* Conditional moves */
236 OPC_MOVZ = 0x0A | OPC_SPECIAL,
237 OPC_MOVN = 0x0B | OPC_SPECIAL,
239 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
240 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
242 OPC_MOVCI = 0x01 | OPC_SPECIAL,
244 /* Special */
245 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
246 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
247 OPC_BREAK = 0x0D | OPC_SPECIAL,
248 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
249 OPC_SYNC = 0x0F | OPC_SPECIAL,
251 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
252 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
253 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
254 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
257 /* R6 Multiply and Divide instructions have the same Opcode
258 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
259 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
261 enum {
262 R6_OPC_MUL = OPC_MULT | (2 << 6),
263 R6_OPC_MUH = OPC_MULT | (3 << 6),
264 R6_OPC_MULU = OPC_MULTU | (2 << 6),
265 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
266 R6_OPC_DIV = OPC_DIV | (2 << 6),
267 R6_OPC_MOD = OPC_DIV | (3 << 6),
268 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
269 R6_OPC_MODU = OPC_DIVU | (3 << 6),
271 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
272 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
273 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
274 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
275 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
276 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
277 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
278 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
280 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
281 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
282 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
283 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
284 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
286 OPC_LSA = 0x05 | OPC_SPECIAL,
287 OPC_DLSA = 0x15 | OPC_SPECIAL,
290 /* Multiplication variants of the vr54xx. */
291 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
293 enum {
294 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
295 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
296 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
297 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
298 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
299 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
300 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
301 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
302 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
303 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
304 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
305 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
306 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
307 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
310 /* REGIMM (rt field) opcodes */
311 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
313 enum {
314 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
315 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
316 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
317 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
318 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
319 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
320 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
321 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
322 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
323 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
324 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
325 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
326 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
327 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
328 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
330 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
331 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
334 /* Special2 opcodes */
335 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
337 enum {
338 /* Multiply & xxx operations */
339 OPC_MADD = 0x00 | OPC_SPECIAL2,
340 OPC_MADDU = 0x01 | OPC_SPECIAL2,
341 OPC_MUL = 0x02 | OPC_SPECIAL2,
342 OPC_MSUB = 0x04 | OPC_SPECIAL2,
343 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
344 /* Loongson 2F */
345 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
346 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
347 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
348 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
349 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
350 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
351 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
352 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
353 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
354 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
355 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
356 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
357 /* Misc */
358 OPC_CLZ = 0x20 | OPC_SPECIAL2,
359 OPC_CLO = 0x21 | OPC_SPECIAL2,
360 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
361 OPC_DCLO = 0x25 | OPC_SPECIAL2,
362 /* Special */
363 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
366 /* Special3 opcodes */
367 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
369 enum {
370 OPC_EXT = 0x00 | OPC_SPECIAL3,
371 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
372 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
373 OPC_DEXT = 0x03 | OPC_SPECIAL3,
374 OPC_INS = 0x04 | OPC_SPECIAL3,
375 OPC_DINSM = 0x05 | OPC_SPECIAL3,
376 OPC_DINSU = 0x06 | OPC_SPECIAL3,
377 OPC_DINS = 0x07 | OPC_SPECIAL3,
378 OPC_FORK = 0x08 | OPC_SPECIAL3,
379 OPC_YIELD = 0x09 | OPC_SPECIAL3,
380 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
381 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
382 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
384 /* Loongson 2E */
385 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
386 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
387 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
388 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
389 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
390 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
391 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
392 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
393 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
394 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
395 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
396 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
398 /* MIPS DSP Load */
399 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
400 /* MIPS DSP Arithmetic */
401 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
402 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
403 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
404 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
405 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
406 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
407 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
408 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
409 /* MIPS DSP GPR-Based Shift Sub-class */
410 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
411 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
412 /* MIPS DSP Multiply Sub-class insns */
413 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
414 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
415 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
416 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
417 /* DSP Bit/Manipulation Sub-class */
418 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
419 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
420 /* MIPS DSP Append Sub-class */
421 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
422 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
423 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
424 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
425 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
427 /* R6 */
428 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
429 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
430 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
431 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
432 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
433 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
436 /* BSHFL opcodes */
437 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
439 enum {
440 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
441 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
442 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
443 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
444 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
445 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
448 /* DBSHFL opcodes */
449 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
451 enum {
452 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
453 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
454 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
455 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
456 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
459 /* MIPS DSP REGIMM opcodes */
460 enum {
461 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
462 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
465 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
466 /* MIPS DSP Load */
467 enum {
468 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
469 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
470 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
471 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
474 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
475 enum {
476 /* MIPS DSP Arithmetic Sub-class */
477 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
478 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
479 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
480 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
481 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
482 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
483 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
484 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
485 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
486 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
487 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
488 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
489 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
490 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
491 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
492 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
493 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
494 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
495 /* MIPS DSP Multiply Sub-class insns */
496 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
497 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
498 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
499 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
500 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
501 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
504 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
505 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
506 enum {
507 /* MIPS DSP Arithmetic Sub-class */
508 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
509 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
510 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
511 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
512 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
513 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
514 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
515 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
516 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
517 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
518 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
519 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
520 /* MIPS DSP Multiply Sub-class insns */
521 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
522 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
523 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
524 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
527 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
528 enum {
529 /* MIPS DSP Arithmetic Sub-class */
530 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
531 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
532 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
533 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
534 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
535 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
536 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
537 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
538 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
539 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
540 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
541 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
542 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
543 /* DSP Bit/Manipulation Sub-class */
544 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
545 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
546 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
547 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
548 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
551 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
552 enum {
553 /* MIPS DSP Arithmetic Sub-class */
554 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
555 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
556 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
557 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
558 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
559 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
560 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
561 /* DSP Compare-Pick Sub-class */
562 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
563 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
564 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
565 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
566 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
567 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
568 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
569 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
570 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
571 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
572 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
573 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
574 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
575 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
576 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
579 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
580 enum {
581 /* MIPS DSP GPR-Based Shift Sub-class */
582 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
583 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
584 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
585 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
586 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
587 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
588 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
589 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
590 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
591 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
592 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
593 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
594 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
595 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
596 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
597 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
598 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
599 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
600 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
601 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
602 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
603 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
606 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
607 enum {
608 /* MIPS DSP Multiply Sub-class insns */
609 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
610 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
611 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
612 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
613 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
614 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
615 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
616 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
617 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
618 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
619 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
620 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
621 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
622 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
623 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
624 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
625 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
626 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
627 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
628 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
629 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
630 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
633 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
634 enum {
635 /* DSP Bit/Manipulation Sub-class */
636 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
639 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
640 enum {
641 /* MIPS DSP Append Sub-class */
642 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
643 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
644 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
647 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
648 enum {
649 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
650 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
651 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
652 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
653 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
654 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
655 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
656 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
657 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
658 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
659 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
660 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
661 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
662 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
663 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
664 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
665 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
666 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
669 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
670 enum {
671 /* MIPS DSP Arithmetic Sub-class */
672 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
673 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
674 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
675 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
676 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
677 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
678 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
679 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
680 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
681 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
682 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
683 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
684 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
685 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
686 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
687 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
688 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
689 /* DSP Bit/Manipulation Sub-class */
690 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
691 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
692 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
693 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
694 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
695 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
698 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
699 enum {
700 /* MIPS DSP Multiply Sub-class insns */
701 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
702 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
703 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
704 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
705 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
706 /* MIPS DSP Arithmetic Sub-class */
707 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
708 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
709 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
710 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
711 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
712 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
713 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
714 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
715 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
716 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
717 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
718 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
719 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
720 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
721 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
722 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
723 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
724 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
725 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
726 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
727 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
730 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
731 enum {
732 /* DSP Compare-Pick Sub-class */
733 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
734 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
735 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
736 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
737 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
738 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
739 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
740 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
741 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
742 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
743 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
744 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
745 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
746 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
747 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
748 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
749 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
750 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
751 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
752 /* MIPS DSP Arithmetic Sub-class */
753 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
754 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
755 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
756 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
763 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
764 enum {
765 /* DSP Append Sub-class */
766 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
767 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
768 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
769 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
772 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
773 enum {
774 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
775 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
776 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
777 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
778 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
779 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
780 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
781 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
782 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
783 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
784 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
785 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
786 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
787 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
788 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
789 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
790 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
791 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
792 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
793 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
794 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
795 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
798 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
799 enum {
800 /* DSP Bit/Manipulation Sub-class */
801 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
804 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
805 enum {
806 /* MIPS DSP Multiply Sub-class insns */
807 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
808 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
809 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
810 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
811 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
812 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
813 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
814 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
815 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
816 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
817 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
818 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
819 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
820 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
821 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
822 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
823 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
824 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
825 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
826 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
827 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
828 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
829 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
830 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
835 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
836 enum {
837 /* MIPS DSP GPR-Based Shift Sub-class */
838 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
839 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
840 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
841 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
842 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
843 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
844 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
845 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
846 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
847 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
848 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
849 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
850 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
851 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
852 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
853 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
854 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
855 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
856 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
857 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
858 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
859 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
860 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
861 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
866 /* Coprocessor 0 (rs field) */
867 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
869 enum {
870 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
871 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
872 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
873 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
874 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
875 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
876 OPC_MFTR = (0x08 << 21) | OPC_CP0,
877 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
878 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
879 OPC_MTTR = (0x0C << 21) | OPC_CP0,
880 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
881 OPC_C0 = (0x10 << 21) | OPC_CP0,
882 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
883 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
886 /* MFMC0 opcodes */
887 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
889 enum {
890 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
891 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
892 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
893 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
894 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
895 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
898 /* Coprocessor 0 (with rs == C0) */
899 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
901 enum {
902 OPC_TLBR = 0x01 | OPC_C0,
903 OPC_TLBWI = 0x02 | OPC_C0,
904 OPC_TLBINV = 0x03 | OPC_C0,
905 OPC_TLBINVF = 0x04 | OPC_C0,
906 OPC_TLBWR = 0x06 | OPC_C0,
907 OPC_TLBP = 0x08 | OPC_C0,
908 OPC_RFE = 0x10 | OPC_C0,
909 OPC_ERET = 0x18 | OPC_C0,
910 OPC_DERET = 0x1F | OPC_C0,
911 OPC_WAIT = 0x20 | OPC_C0,
914 /* Coprocessor 1 (rs field) */
915 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
917 /* Values for the fmt field in FP instructions */
918 enum {
919 /* 0 - 15 are reserved */
920 FMT_S = 16, /* single fp */
921 FMT_D = 17, /* double fp */
922 FMT_E = 18, /* extended fp */
923 FMT_Q = 19, /* quad fp */
924 FMT_W = 20, /* 32-bit fixed */
925 FMT_L = 21, /* 64-bit fixed */
926 FMT_PS = 22, /* paired single fp */
927 /* 23 - 31 are reserved */
930 enum {
931 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
932 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
933 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
934 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
935 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
936 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
937 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
938 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
939 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
940 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
941 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
942 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
943 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
944 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
945 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
946 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
947 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
948 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
949 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
950 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
951 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
952 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
953 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
954 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
955 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
956 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
957 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
958 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
959 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
960 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
963 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
964 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
966 enum {
967 OPC_BC1F = (0x00 << 16) | OPC_BC1,
968 OPC_BC1T = (0x01 << 16) | OPC_BC1,
969 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
970 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
973 enum {
974 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
975 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
978 enum {
979 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
980 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
983 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
985 enum {
986 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
987 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
988 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
989 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
990 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
991 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
992 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
993 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
994 OPC_BC2 = (0x08 << 21) | OPC_CP2,
995 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
996 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
999 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1001 enum {
1002 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1003 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1004 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1005 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1006 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1007 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1008 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1009 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1011 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1012 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1013 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1014 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1015 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1016 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1018 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1020 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1021 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1022 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1023 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1024 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1025 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1026 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1027 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1029 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1030 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1031 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1032 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1033 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1034 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1035 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1036 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1038 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1039 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1040 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1041 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1042 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1043 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1045 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1046 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1047 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1048 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1049 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1050 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1052 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1053 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1054 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1055 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1056 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1057 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1059 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1060 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1061 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1062 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1063 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1064 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1066 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1067 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1068 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1069 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1070 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1071 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1073 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1074 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1075 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1076 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1077 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1078 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1080 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1081 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1082 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1083 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1084 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1085 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1087 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1088 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1089 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1090 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1091 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1092 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1096 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1098 enum {
1099 OPC_LWXC1 = 0x00 | OPC_CP3,
1100 OPC_LDXC1 = 0x01 | OPC_CP3,
1101 OPC_LUXC1 = 0x05 | OPC_CP3,
1102 OPC_SWXC1 = 0x08 | OPC_CP3,
1103 OPC_SDXC1 = 0x09 | OPC_CP3,
1104 OPC_SUXC1 = 0x0D | OPC_CP3,
1105 OPC_PREFX = 0x0F | OPC_CP3,
1106 OPC_ALNV_PS = 0x1E | OPC_CP3,
1107 OPC_MADD_S = 0x20 | OPC_CP3,
1108 OPC_MADD_D = 0x21 | OPC_CP3,
1109 OPC_MADD_PS = 0x26 | OPC_CP3,
1110 OPC_MSUB_S = 0x28 | OPC_CP3,
1111 OPC_MSUB_D = 0x29 | OPC_CP3,
1112 OPC_MSUB_PS = 0x2E | OPC_CP3,
1113 OPC_NMADD_S = 0x30 | OPC_CP3,
1114 OPC_NMADD_D = 0x31 | OPC_CP3,
1115 OPC_NMADD_PS= 0x36 | OPC_CP3,
1116 OPC_NMSUB_S = 0x38 | OPC_CP3,
1117 OPC_NMSUB_D = 0x39 | OPC_CP3,
1118 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1121 /* MSA Opcodes */
1122 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1123 enum {
1124 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1125 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1126 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1127 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1128 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1129 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1130 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1131 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1132 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1133 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1134 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1135 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1136 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1137 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1138 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1139 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1140 OPC_MSA_ELM = 0x19 | OPC_MSA,
1141 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1142 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1143 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1144 OPC_MSA_VEC = 0x1E | OPC_MSA,
1146 /* MI10 instruction */
1147 OPC_LD_B = (0x20) | OPC_MSA,
1148 OPC_LD_H = (0x21) | OPC_MSA,
1149 OPC_LD_W = (0x22) | OPC_MSA,
1150 OPC_LD_D = (0x23) | OPC_MSA,
1151 OPC_ST_B = (0x24) | OPC_MSA,
1152 OPC_ST_H = (0x25) | OPC_MSA,
1153 OPC_ST_W = (0x26) | OPC_MSA,
1154 OPC_ST_D = (0x27) | OPC_MSA,
1157 enum {
1158 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1159 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1160 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1161 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1162 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1163 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1164 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1165 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1166 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1167 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1168 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1169 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1170 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1172 /* I8 instruction */
1173 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1174 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1175 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1176 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1177 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1178 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1179 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1180 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1181 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1182 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1184 /* VEC/2R/2RF instruction */
1185 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1186 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1187 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1188 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1189 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1190 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1191 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1193 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1194 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1196 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1197 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1198 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1199 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1200 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1202 /* 2RF instruction df(bit 16) = _w, _d */
1203 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1204 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1205 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1206 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1207 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1208 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1209 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1210 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1211 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1212 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1213 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1214 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1215 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1216 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1217 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1218 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1220 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1221 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1222 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1223 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1224 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1225 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1226 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1227 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1228 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1229 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1230 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1231 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1232 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1233 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1234 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1235 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1236 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1237 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1238 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1239 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1240 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1241 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1242 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1243 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1244 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1245 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1246 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1247 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1248 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1249 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1250 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1251 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1252 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1253 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1254 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1255 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1256 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1257 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1258 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1259 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1260 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1261 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1262 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1263 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1264 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1265 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1266 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1267 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1268 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1269 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1270 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1271 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1272 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1273 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1274 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1275 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1276 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1277 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1278 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1279 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1280 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1281 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1282 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1283 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1285 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1286 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1287 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1288 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1289 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1290 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1291 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1292 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1293 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1294 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1296 /* 3RF instruction _df(bit 21) = _w, _d */
1297 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1298 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1299 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1300 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1301 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1302 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1303 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1304 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1305 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1306 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1307 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1308 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1309 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1310 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1311 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1312 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1313 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1314 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1315 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1316 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1317 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1318 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1319 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1320 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1321 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1322 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1323 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1324 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1325 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1326 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1327 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1328 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1329 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1330 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1331 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1332 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1333 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1334 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1335 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1336 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1337 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1339 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1340 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1341 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1342 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1343 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1344 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1345 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1346 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1347 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1348 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1349 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1350 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1351 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1354 /* global register indices */
1355 static TCGv_ptr cpu_env;
1356 static TCGv cpu_gpr[32], cpu_PC;
1357 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1358 static TCGv cpu_dspctrl, btarget, bcond;
1359 static TCGv_i32 hflags;
1360 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1361 static TCGv_i64 fpu_f64[32];
1362 static TCGv_i64 msa_wr_d[64];
1364 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
1365 static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
1367 #include "exec/gen-icount.h"
1369 #define gen_helper_0e0i(name, arg) do { \
1370 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1371 gen_helper_##name(cpu_env, helper_tmp); \
1372 tcg_temp_free_i32(helper_tmp); \
1373 } while(0)
1375 #define gen_helper_0e1i(name, arg1, arg2) do { \
1376 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1377 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1378 tcg_temp_free_i32(helper_tmp); \
1379 } while(0)
1381 #define gen_helper_1e0i(name, ret, arg1) do { \
1382 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1383 gen_helper_##name(ret, cpu_env, helper_tmp); \
1384 tcg_temp_free_i32(helper_tmp); \
1385 } while(0)
1387 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1388 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1389 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1390 tcg_temp_free_i32(helper_tmp); \
1391 } while(0)
1393 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1394 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1395 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1396 tcg_temp_free_i32(helper_tmp); \
1397 } while(0)
1399 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1400 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1401 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1402 tcg_temp_free_i32(helper_tmp); \
1403 } while(0)
1405 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1406 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1407 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1408 tcg_temp_free_i32(helper_tmp); \
1409 } while(0)
1411 typedef struct DisasContext {
1412 struct TranslationBlock *tb;
1413 target_ulong pc, saved_pc;
1414 uint32_t opcode;
1415 int singlestep_enabled;
1416 int insn_flags;
1417 int32_t CP0_Config1;
1418 /* Routine used to access memory */
1419 int mem_idx;
1420 TCGMemOp default_tcg_memop_mask;
1421 uint32_t hflags, saved_hflags;
1422 int bstate;
1423 target_ulong btarget;
1424 bool ulri;
1425 int kscrexist;
1426 bool rxi;
1427 int ie;
1428 bool bi;
1429 bool bp;
1430 uint64_t PAMask;
1431 bool mvh;
1432 int CP0_LLAddr_shift;
1433 bool ps;
1434 } DisasContext;
1436 enum {
1437 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1438 * exception condition */
1439 BS_STOP = 1, /* We want to stop translation for any reason */
1440 BS_BRANCH = 2, /* We reached a branch condition */
1441 BS_EXCP = 3, /* We reached an exception condition */
1444 static const char * const regnames[] = {
1445 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1446 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1447 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1448 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1451 static const char * const regnames_HI[] = {
1452 "HI0", "HI1", "HI2", "HI3",
1455 static const char * const regnames_LO[] = {
1456 "LO0", "LO1", "LO2", "LO3",
1459 static const char * const fregnames[] = {
1460 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1461 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1462 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1463 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1466 static const char * const msaregnames[] = {
1467 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1468 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1469 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1470 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1471 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1472 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1473 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1474 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1475 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1476 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1477 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1478 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1479 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1480 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1481 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1482 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1485 #define MIPS_DEBUG(fmt, ...) \
1486 do { \
1487 if (MIPS_DEBUG_DISAS) { \
1488 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1489 TARGET_FMT_lx ": %08x " fmt "\n", \
1490 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
1492 } while (0)
1494 #define LOG_DISAS(...) \
1495 do { \
1496 if (MIPS_DEBUG_DISAS) { \
1497 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1499 } while (0)
1501 #define MIPS_INVAL(op) \
1502 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
1503 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
1505 /* General purpose registers moves. */
1506 static inline void gen_load_gpr (TCGv t, int reg)
1508 if (reg == 0)
1509 tcg_gen_movi_tl(t, 0);
1510 else
1511 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1514 static inline void gen_store_gpr (TCGv t, int reg)
1516 if (reg != 0)
1517 tcg_gen_mov_tl(cpu_gpr[reg], t);
1520 /* Moves to/from shadow registers. */
1521 static inline void gen_load_srsgpr (int from, int to)
1523 TCGv t0 = tcg_temp_new();
1525 if (from == 0)
1526 tcg_gen_movi_tl(t0, 0);
1527 else {
1528 TCGv_i32 t2 = tcg_temp_new_i32();
1529 TCGv_ptr addr = tcg_temp_new_ptr();
1531 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1532 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1533 tcg_gen_andi_i32(t2, t2, 0xf);
1534 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1535 tcg_gen_ext_i32_ptr(addr, t2);
1536 tcg_gen_add_ptr(addr, cpu_env, addr);
1538 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1539 tcg_temp_free_ptr(addr);
1540 tcg_temp_free_i32(t2);
1542 gen_store_gpr(t0, to);
1543 tcg_temp_free(t0);
1546 static inline void gen_store_srsgpr (int from, int to)
1548 if (to != 0) {
1549 TCGv t0 = tcg_temp_new();
1550 TCGv_i32 t2 = tcg_temp_new_i32();
1551 TCGv_ptr addr = tcg_temp_new_ptr();
1553 gen_load_gpr(t0, from);
1554 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1555 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1556 tcg_gen_andi_i32(t2, t2, 0xf);
1557 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1558 tcg_gen_ext_i32_ptr(addr, t2);
1559 tcg_gen_add_ptr(addr, cpu_env, addr);
1561 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1562 tcg_temp_free_ptr(addr);
1563 tcg_temp_free_i32(t2);
1564 tcg_temp_free(t0);
1568 /* Tests */
1569 static inline void gen_save_pc(target_ulong pc)
1571 tcg_gen_movi_tl(cpu_PC, pc);
1574 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1576 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1577 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1578 gen_save_pc(ctx->pc);
1579 ctx->saved_pc = ctx->pc;
1581 if (ctx->hflags != ctx->saved_hflags) {
1582 tcg_gen_movi_i32(hflags, ctx->hflags);
1583 ctx->saved_hflags = ctx->hflags;
1584 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1585 case MIPS_HFLAG_BR:
1586 break;
1587 case MIPS_HFLAG_BC:
1588 case MIPS_HFLAG_BL:
1589 case MIPS_HFLAG_B:
1590 tcg_gen_movi_tl(btarget, ctx->btarget);
1591 break;
1596 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1598 ctx->saved_hflags = ctx->hflags;
1599 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1600 case MIPS_HFLAG_BR:
1601 break;
1602 case MIPS_HFLAG_BC:
1603 case MIPS_HFLAG_BL:
1604 case MIPS_HFLAG_B:
1605 ctx->btarget = env->btarget;
1606 break;
1610 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1612 TCGv_i32 texcp = tcg_const_i32(excp);
1613 TCGv_i32 terr = tcg_const_i32(err);
1614 save_cpu_state(ctx, 1);
1615 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1616 tcg_temp_free_i32(terr);
1617 tcg_temp_free_i32(texcp);
1620 static inline void generate_exception(DisasContext *ctx, int excp)
1622 save_cpu_state(ctx, 1);
1623 gen_helper_0e0i(raise_exception, excp);
1626 /* Floating point register moves. */
1627 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1629 if (ctx->hflags & MIPS_HFLAG_FRE) {
1630 generate_exception(ctx, EXCP_RI);
1632 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
1635 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1637 TCGv_i64 t64;
1638 if (ctx->hflags & MIPS_HFLAG_FRE) {
1639 generate_exception(ctx, EXCP_RI);
1641 t64 = tcg_temp_new_i64();
1642 tcg_gen_extu_i32_i64(t64, t);
1643 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1644 tcg_temp_free_i64(t64);
1647 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1649 if (ctx->hflags & MIPS_HFLAG_F64) {
1650 TCGv_i64 t64 = tcg_temp_new_i64();
1651 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
1652 tcg_gen_trunc_i64_i32(t, t64);
1653 tcg_temp_free_i64(t64);
1654 } else {
1655 gen_load_fpr32(ctx, t, reg | 1);
1659 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1661 if (ctx->hflags & MIPS_HFLAG_F64) {
1662 TCGv_i64 t64 = tcg_temp_new_i64();
1663 tcg_gen_extu_i32_i64(t64, t);
1664 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1665 tcg_temp_free_i64(t64);
1666 } else {
1667 gen_store_fpr32(ctx, t, reg | 1);
1671 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1673 if (ctx->hflags & MIPS_HFLAG_F64) {
1674 tcg_gen_mov_i64(t, fpu_f64[reg]);
1675 } else {
1676 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1680 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1682 if (ctx->hflags & MIPS_HFLAG_F64) {
1683 tcg_gen_mov_i64(fpu_f64[reg], t);
1684 } else {
1685 TCGv_i64 t0;
1686 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1687 t0 = tcg_temp_new_i64();
1688 tcg_gen_shri_i64(t0, t, 32);
1689 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1690 tcg_temp_free_i64(t0);
1694 static inline int get_fp_bit (int cc)
1696 if (cc)
1697 return 24 + cc;
1698 else
1699 return 23;
1702 /* Addresses computation */
1703 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1705 tcg_gen_add_tl(ret, arg0, arg1);
1707 #if defined(TARGET_MIPS64)
1708 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1709 tcg_gen_ext32s_i64(ret, ret);
1711 #endif
1714 /* Addresses computation (translation time) */
1715 static target_long addr_add(DisasContext *ctx, target_long base,
1716 target_long offset)
1718 target_long sum = base + offset;
1720 #if defined(TARGET_MIPS64)
1721 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1722 sum = (int32_t)sum;
1724 #endif
1725 return sum;
1728 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
1730 #if defined(TARGET_MIPS64)
1731 tcg_gen_ext32s_tl(ret, arg);
1732 #else
1733 tcg_gen_trunc_i64_tl(ret, arg);
1734 #endif
1737 static inline void check_cp0_enabled(DisasContext *ctx)
1739 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1740 generate_exception_err(ctx, EXCP_CpU, 0);
1743 static inline void check_cp1_enabled(DisasContext *ctx)
1745 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1746 generate_exception_err(ctx, EXCP_CpU, 1);
1749 /* Verify that the processor is running with COP1X instructions enabled.
1750 This is associated with the nabla symbol in the MIPS32 and MIPS64
1751 opcode tables. */
1753 static inline void check_cop1x(DisasContext *ctx)
1755 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1756 generate_exception(ctx, EXCP_RI);
1759 /* Verify that the processor is running with 64-bit floating-point
1760 operations enabled. */
1762 static inline void check_cp1_64bitmode(DisasContext *ctx)
1764 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1765 generate_exception(ctx, EXCP_RI);
1769 * Verify if floating point register is valid; an operation is not defined
1770 * if bit 0 of any register specification is set and the FR bit in the
1771 * Status register equals zero, since the register numbers specify an
1772 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1773 * in the Status register equals one, both even and odd register numbers
1774 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1776 * Multiple 64 bit wide registers can be checked by calling
1777 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1779 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1781 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1782 generate_exception(ctx, EXCP_RI);
1785 /* Verify that the processor is running with DSP instructions enabled.
1786 This is enabled by CP0 Status register MX(24) bit.
1789 static inline void check_dsp(DisasContext *ctx)
1791 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1792 if (ctx->insn_flags & ASE_DSP) {
1793 generate_exception(ctx, EXCP_DSPDIS);
1794 } else {
1795 generate_exception(ctx, EXCP_RI);
1800 static inline void check_dspr2(DisasContext *ctx)
1802 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1803 if (ctx->insn_flags & ASE_DSP) {
1804 generate_exception(ctx, EXCP_DSPDIS);
1805 } else {
1806 generate_exception(ctx, EXCP_RI);
1811 /* This code generates a "reserved instruction" exception if the
1812 CPU does not support the instruction set corresponding to flags. */
1813 static inline void check_insn(DisasContext *ctx, int flags)
1815 if (unlikely(!(ctx->insn_flags & flags))) {
1816 generate_exception(ctx, EXCP_RI);
1820 /* This code generates a "reserved instruction" exception if the
1821 CPU has corresponding flag set which indicates that the instruction
1822 has been removed. */
1823 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1825 if (unlikely(ctx->insn_flags & flags)) {
1826 generate_exception(ctx, EXCP_RI);
1830 /* This code generates a "reserved instruction" exception if the
1831 CPU does not support 64-bit paired-single (PS) floating point data type */
1832 static inline void check_ps(DisasContext *ctx)
1834 if (unlikely(!ctx->ps)) {
1835 generate_exception(ctx, EXCP_RI);
1837 check_cp1_64bitmode(ctx);
1840 #ifdef TARGET_MIPS64
1841 /* This code generates a "reserved instruction" exception if 64-bit
1842 instructions are not enabled. */
1843 static inline void check_mips_64(DisasContext *ctx)
1845 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1846 generate_exception(ctx, EXCP_RI);
1848 #endif
1850 #ifndef CONFIG_USER_ONLY
1851 static inline void check_mvh(DisasContext *ctx)
1853 if (unlikely(!ctx->mvh)) {
1854 generate_exception(ctx, EXCP_RI);
1857 #endif
1859 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1860 calling interface for 32 and 64-bit FPRs. No sense in changing
1861 all callers for gen_load_fpr32 when we need the CTX parameter for
1862 this one use. */
1863 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1864 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1865 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1866 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1867 int ft, int fs, int cc) \
1869 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1870 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1871 switch (ifmt) { \
1872 case FMT_PS: \
1873 check_ps(ctx); \
1874 break; \
1875 case FMT_D: \
1876 if (abs) { \
1877 check_cop1x(ctx); \
1879 check_cp1_registers(ctx, fs | ft); \
1880 break; \
1881 case FMT_S: \
1882 if (abs) { \
1883 check_cop1x(ctx); \
1885 break; \
1887 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1888 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1889 switch (n) { \
1890 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1891 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1892 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1893 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1894 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1895 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1896 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1897 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1898 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1899 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1900 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1901 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1902 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1903 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1904 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1905 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1906 default: abort(); \
1908 tcg_temp_free_i##bits (fp0); \
1909 tcg_temp_free_i##bits (fp1); \
1912 FOP_CONDS(, 0, d, FMT_D, 64)
1913 FOP_CONDS(abs, 1, d, FMT_D, 64)
1914 FOP_CONDS(, 0, s, FMT_S, 32)
1915 FOP_CONDS(abs, 1, s, FMT_S, 32)
1916 FOP_CONDS(, 0, ps, FMT_PS, 64)
1917 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1918 #undef FOP_CONDS
1920 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1921 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1922 int ft, int fs, int fd) \
1924 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1925 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1926 if (ifmt == FMT_D) { \
1927 check_cp1_registers(ctx, fs | ft | fd); \
1929 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1930 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1931 switch (n) { \
1932 case 0: \
1933 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1934 break; \
1935 case 1: \
1936 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1937 break; \
1938 case 2: \
1939 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1940 break; \
1941 case 3: \
1942 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1943 break; \
1944 case 4: \
1945 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1946 break; \
1947 case 5: \
1948 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1949 break; \
1950 case 6: \
1951 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1952 break; \
1953 case 7: \
1954 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1955 break; \
1956 case 8: \
1957 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1958 break; \
1959 case 9: \
1960 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1961 break; \
1962 case 10: \
1963 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1964 break; \
1965 case 11: \
1966 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1967 break; \
1968 case 12: \
1969 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1970 break; \
1971 case 13: \
1972 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1973 break; \
1974 case 14: \
1975 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1976 break; \
1977 case 15: \
1978 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1979 break; \
1980 case 17: \
1981 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1982 break; \
1983 case 18: \
1984 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1985 break; \
1986 case 19: \
1987 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1988 break; \
1989 case 25: \
1990 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1991 break; \
1992 case 26: \
1993 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
1994 break; \
1995 case 27: \
1996 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
1997 break; \
1998 default: \
1999 abort(); \
2001 STORE; \
2002 tcg_temp_free_i ## bits (fp0); \
2003 tcg_temp_free_i ## bits (fp1); \
2006 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2007 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2008 #undef FOP_CONDNS
2009 #undef gen_ldcmp_fpr32
2010 #undef gen_ldcmp_fpr64
2012 /* load/store instructions. */
2013 #ifdef CONFIG_USER_ONLY
2014 #define OP_LD_ATOMIC(insn,fname) \
2015 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2017 TCGv t0 = tcg_temp_new(); \
2018 tcg_gen_mov_tl(t0, arg1); \
2019 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2020 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2021 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2022 tcg_temp_free(t0); \
2024 #else
2025 #define OP_LD_ATOMIC(insn,fname) \
2026 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2028 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
2030 #endif
2031 OP_LD_ATOMIC(ll,ld32s);
2032 #if defined(TARGET_MIPS64)
2033 OP_LD_ATOMIC(lld,ld64);
2034 #endif
2035 #undef OP_LD_ATOMIC
2037 #ifdef CONFIG_USER_ONLY
2038 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2039 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2041 TCGv t0 = tcg_temp_new(); \
2042 TCGLabel *l1 = gen_new_label(); \
2043 TCGLabel *l2 = gen_new_label(); \
2045 tcg_gen_andi_tl(t0, arg2, almask); \
2046 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2047 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2048 generate_exception(ctx, EXCP_AdES); \
2049 gen_set_label(l1); \
2050 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2051 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2052 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2053 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2054 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2055 gen_helper_0e0i(raise_exception, EXCP_SC); \
2056 gen_set_label(l2); \
2057 tcg_gen_movi_tl(t0, 0); \
2058 gen_store_gpr(t0, rt); \
2059 tcg_temp_free(t0); \
2061 #else
2062 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2063 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2065 TCGv t0 = tcg_temp_new(); \
2066 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
2067 gen_store_gpr(t0, rt); \
2068 tcg_temp_free(t0); \
2070 #endif
2071 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2072 #if defined(TARGET_MIPS64)
2073 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2074 #endif
2075 #undef OP_ST_ATOMIC
2077 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2078 int base, int16_t offset)
2080 if (base == 0) {
2081 tcg_gen_movi_tl(addr, offset);
2082 } else if (offset == 0) {
2083 gen_load_gpr(addr, base);
2084 } else {
2085 tcg_gen_movi_tl(addr, offset);
2086 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2090 static target_ulong pc_relative_pc (DisasContext *ctx)
2092 target_ulong pc = ctx->pc;
2094 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2095 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2097 pc -= branch_bytes;
2100 pc &= ~(target_ulong)3;
2101 return pc;
2104 /* Load */
2105 static void gen_ld(DisasContext *ctx, uint32_t opc,
2106 int rt, int base, int16_t offset)
2108 const char *opn = "ld";
2109 TCGv t0, t1, t2;
2111 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2112 /* Loongson CPU uses a load to zero register for prefetch.
2113 We emulate it as a NOP. On other CPU we must perform the
2114 actual memory access. */
2115 MIPS_DEBUG("NOP");
2116 return;
2119 t0 = tcg_temp_new();
2120 gen_base_offset_addr(ctx, t0, base, offset);
2122 switch (opc) {
2123 #if defined(TARGET_MIPS64)
2124 case OPC_LWU:
2125 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL |
2126 ctx->default_tcg_memop_mask);
2127 gen_store_gpr(t0, rt);
2128 opn = "lwu";
2129 break;
2130 case OPC_LD:
2131 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
2132 ctx->default_tcg_memop_mask);
2133 gen_store_gpr(t0, rt);
2134 opn = "ld";
2135 break;
2136 case OPC_LLD:
2137 case R6_OPC_LLD:
2138 save_cpu_state(ctx, 1);
2139 op_ld_lld(t0, t0, ctx);
2140 gen_store_gpr(t0, rt);
2141 opn = "lld";
2142 break;
2143 case OPC_LDL:
2144 t1 = tcg_temp_new();
2145 /* Do a byte access to possibly trigger a page
2146 fault with the unaligned address. */
2147 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2148 tcg_gen_andi_tl(t1, t0, 7);
2149 #ifndef TARGET_WORDS_BIGENDIAN
2150 tcg_gen_xori_tl(t1, t1, 7);
2151 #endif
2152 tcg_gen_shli_tl(t1, t1, 3);
2153 tcg_gen_andi_tl(t0, t0, ~7);
2154 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2155 tcg_gen_shl_tl(t0, t0, t1);
2156 tcg_gen_xori_tl(t1, t1, 63);
2157 t2 = tcg_const_tl(0x7fffffffffffffffull);
2158 tcg_gen_shr_tl(t2, t2, t1);
2159 gen_load_gpr(t1, rt);
2160 tcg_gen_and_tl(t1, t1, t2);
2161 tcg_temp_free(t2);
2162 tcg_gen_or_tl(t0, t0, t1);
2163 tcg_temp_free(t1);
2164 gen_store_gpr(t0, rt);
2165 opn = "ldl";
2166 break;
2167 case OPC_LDR:
2168 t1 = tcg_temp_new();
2169 /* Do a byte access to possibly trigger a page
2170 fault with the unaligned address. */
2171 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2172 tcg_gen_andi_tl(t1, t0, 7);
2173 #ifdef TARGET_WORDS_BIGENDIAN
2174 tcg_gen_xori_tl(t1, t1, 7);
2175 #endif
2176 tcg_gen_shli_tl(t1, t1, 3);
2177 tcg_gen_andi_tl(t0, t0, ~7);
2178 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2179 tcg_gen_shr_tl(t0, t0, t1);
2180 tcg_gen_xori_tl(t1, t1, 63);
2181 t2 = tcg_const_tl(0xfffffffffffffffeull);
2182 tcg_gen_shl_tl(t2, t2, t1);
2183 gen_load_gpr(t1, rt);
2184 tcg_gen_and_tl(t1, t1, t2);
2185 tcg_temp_free(t2);
2186 tcg_gen_or_tl(t0, t0, t1);
2187 tcg_temp_free(t1);
2188 gen_store_gpr(t0, rt);
2189 opn = "ldr";
2190 break;
2191 case OPC_LDPC:
2192 t1 = tcg_const_tl(pc_relative_pc(ctx));
2193 gen_op_addr_add(ctx, t0, t0, t1);
2194 tcg_temp_free(t1);
2195 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2196 gen_store_gpr(t0, rt);
2197 opn = "ldpc";
2198 break;
2199 #endif
2200 case OPC_LWPC:
2201 t1 = tcg_const_tl(pc_relative_pc(ctx));
2202 gen_op_addr_add(ctx, t0, t0, t1);
2203 tcg_temp_free(t1);
2204 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2205 gen_store_gpr(t0, rt);
2206 opn = "lwpc";
2207 break;
2208 case OPC_LW:
2209 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
2210 ctx->default_tcg_memop_mask);
2211 gen_store_gpr(t0, rt);
2212 opn = "lw";
2213 break;
2214 case OPC_LH:
2215 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
2216 ctx->default_tcg_memop_mask);
2217 gen_store_gpr(t0, rt);
2218 opn = "lh";
2219 break;
2220 case OPC_LHU:
2221 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW |
2222 ctx->default_tcg_memop_mask);
2223 gen_store_gpr(t0, rt);
2224 opn = "lhu";
2225 break;
2226 case OPC_LB:
2227 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
2228 gen_store_gpr(t0, rt);
2229 opn = "lb";
2230 break;
2231 case OPC_LBU:
2232 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
2233 gen_store_gpr(t0, rt);
2234 opn = "lbu";
2235 break;
2236 case OPC_LWL:
2237 t1 = tcg_temp_new();
2238 /* Do a byte access to possibly trigger a page
2239 fault with the unaligned address. */
2240 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2241 tcg_gen_andi_tl(t1, t0, 3);
2242 #ifndef TARGET_WORDS_BIGENDIAN
2243 tcg_gen_xori_tl(t1, t1, 3);
2244 #endif
2245 tcg_gen_shli_tl(t1, t1, 3);
2246 tcg_gen_andi_tl(t0, t0, ~3);
2247 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2248 tcg_gen_shl_tl(t0, t0, t1);
2249 tcg_gen_xori_tl(t1, t1, 31);
2250 t2 = tcg_const_tl(0x7fffffffull);
2251 tcg_gen_shr_tl(t2, t2, t1);
2252 gen_load_gpr(t1, rt);
2253 tcg_gen_and_tl(t1, t1, t2);
2254 tcg_temp_free(t2);
2255 tcg_gen_or_tl(t0, t0, t1);
2256 tcg_temp_free(t1);
2257 tcg_gen_ext32s_tl(t0, t0);
2258 gen_store_gpr(t0, rt);
2259 opn = "lwl";
2260 break;
2261 case OPC_LWR:
2262 t1 = tcg_temp_new();
2263 /* Do a byte access to possibly trigger a page
2264 fault with the unaligned address. */
2265 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2266 tcg_gen_andi_tl(t1, t0, 3);
2267 #ifdef TARGET_WORDS_BIGENDIAN
2268 tcg_gen_xori_tl(t1, t1, 3);
2269 #endif
2270 tcg_gen_shli_tl(t1, t1, 3);
2271 tcg_gen_andi_tl(t0, t0, ~3);
2272 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2273 tcg_gen_shr_tl(t0, t0, t1);
2274 tcg_gen_xori_tl(t1, t1, 31);
2275 t2 = tcg_const_tl(0xfffffffeull);
2276 tcg_gen_shl_tl(t2, t2, t1);
2277 gen_load_gpr(t1, rt);
2278 tcg_gen_and_tl(t1, t1, t2);
2279 tcg_temp_free(t2);
2280 tcg_gen_or_tl(t0, t0, t1);
2281 tcg_temp_free(t1);
2282 tcg_gen_ext32s_tl(t0, t0);
2283 gen_store_gpr(t0, rt);
2284 opn = "lwr";
2285 break;
2286 case OPC_LL:
2287 case R6_OPC_LL:
2288 save_cpu_state(ctx, 1);
2289 op_ld_ll(t0, t0, ctx);
2290 gen_store_gpr(t0, rt);
2291 opn = "ll";
2292 break;
2294 (void)opn; /* avoid a compiler warning */
2295 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2296 tcg_temp_free(t0);
2299 /* Store */
2300 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2301 int base, int16_t offset)
2303 const char *opn = "st";
2304 TCGv t0 = tcg_temp_new();
2305 TCGv t1 = tcg_temp_new();
2307 gen_base_offset_addr(ctx, t0, base, offset);
2308 gen_load_gpr(t1, rt);
2309 switch (opc) {
2310 #if defined(TARGET_MIPS64)
2311 case OPC_SD:
2312 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
2313 ctx->default_tcg_memop_mask);
2314 opn = "sd";
2315 break;
2316 case OPC_SDL:
2317 save_cpu_state(ctx, 1);
2318 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
2319 opn = "sdl";
2320 break;
2321 case OPC_SDR:
2322 save_cpu_state(ctx, 1);
2323 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2324 opn = "sdr";
2325 break;
2326 #endif
2327 case OPC_SW:
2328 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
2329 ctx->default_tcg_memop_mask);
2330 opn = "sw";
2331 break;
2332 case OPC_SH:
2333 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
2334 ctx->default_tcg_memop_mask);
2335 opn = "sh";
2336 break;
2337 case OPC_SB:
2338 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2339 opn = "sb";
2340 break;
2341 case OPC_SWL:
2342 save_cpu_state(ctx, 1);
2343 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2344 opn = "swl";
2345 break;
2346 case OPC_SWR:
2347 save_cpu_state(ctx, 1);
2348 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2349 opn = "swr";
2350 break;
2352 (void)opn; /* avoid a compiler warning */
2353 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2354 tcg_temp_free(t0);
2355 tcg_temp_free(t1);
2359 /* Store conditional */
2360 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2361 int base, int16_t offset)
2363 const char *opn = "st_cond";
2364 TCGv t0, t1;
2366 #ifdef CONFIG_USER_ONLY
2367 t0 = tcg_temp_local_new();
2368 t1 = tcg_temp_local_new();
2369 #else
2370 t0 = tcg_temp_new();
2371 t1 = tcg_temp_new();
2372 #endif
2373 gen_base_offset_addr(ctx, t0, base, offset);
2374 gen_load_gpr(t1, rt);
2375 switch (opc) {
2376 #if defined(TARGET_MIPS64)
2377 case OPC_SCD:
2378 case R6_OPC_SCD:
2379 save_cpu_state(ctx, 1);
2380 op_st_scd(t1, t0, rt, ctx);
2381 opn = "scd";
2382 break;
2383 #endif
2384 case OPC_SC:
2385 case R6_OPC_SC:
2386 save_cpu_state(ctx, 1);
2387 op_st_sc(t1, t0, rt, ctx);
2388 opn = "sc";
2389 break;
2391 (void)opn; /* avoid a compiler warning */
2392 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2393 tcg_temp_free(t1);
2394 tcg_temp_free(t0);
2397 /* Load and store */
2398 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2399 int base, int16_t offset)
2401 const char *opn = "flt_ldst";
2402 TCGv t0 = tcg_temp_new();
2404 gen_base_offset_addr(ctx, t0, base, offset);
2405 /* Don't do NOP if destination is zero: we must perform the actual
2406 memory access. */
2407 switch (opc) {
2408 case OPC_LWC1:
2410 TCGv_i32 fp0 = tcg_temp_new_i32();
2411 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2412 ctx->default_tcg_memop_mask);
2413 gen_store_fpr32(ctx, fp0, ft);
2414 tcg_temp_free_i32(fp0);
2416 opn = "lwc1";
2417 break;
2418 case OPC_SWC1:
2420 TCGv_i32 fp0 = tcg_temp_new_i32();
2421 gen_load_fpr32(ctx, fp0, ft);
2422 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2423 ctx->default_tcg_memop_mask);
2424 tcg_temp_free_i32(fp0);
2426 opn = "swc1";
2427 break;
2428 case OPC_LDC1:
2430 TCGv_i64 fp0 = tcg_temp_new_i64();
2431 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2432 ctx->default_tcg_memop_mask);
2433 gen_store_fpr64(ctx, fp0, ft);
2434 tcg_temp_free_i64(fp0);
2436 opn = "ldc1";
2437 break;
2438 case OPC_SDC1:
2440 TCGv_i64 fp0 = tcg_temp_new_i64();
2441 gen_load_fpr64(ctx, fp0, ft);
2442 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2443 ctx->default_tcg_memop_mask);
2444 tcg_temp_free_i64(fp0);
2446 opn = "sdc1";
2447 break;
2448 default:
2449 MIPS_INVAL(opn);
2450 generate_exception(ctx, EXCP_RI);
2451 goto out;
2453 (void)opn; /* avoid a compiler warning */
2454 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
2455 out:
2456 tcg_temp_free(t0);
2459 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2460 int rs, int16_t imm)
2462 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2463 check_cp1_enabled(ctx);
2464 switch (op) {
2465 case OPC_LDC1:
2466 case OPC_SDC1:
2467 check_insn(ctx, ISA_MIPS2);
2468 /* Fallthrough */
2469 default:
2470 gen_flt_ldst(ctx, op, rt, rs, imm);
2472 } else {
2473 generate_exception_err(ctx, EXCP_CpU, 1);
2477 /* Arithmetic with immediate operand */
2478 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2479 int rt, int rs, int16_t imm)
2481 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2482 const char *opn = "imm arith";
2484 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2485 /* If no destination, treat it as a NOP.
2486 For addi, we must generate the overflow exception when needed. */
2487 MIPS_DEBUG("NOP");
2488 return;
2490 switch (opc) {
2491 case OPC_ADDI:
2493 TCGv t0 = tcg_temp_local_new();
2494 TCGv t1 = tcg_temp_new();
2495 TCGv t2 = tcg_temp_new();
2496 TCGLabel *l1 = gen_new_label();
2498 gen_load_gpr(t1, rs);
2499 tcg_gen_addi_tl(t0, t1, uimm);
2500 tcg_gen_ext32s_tl(t0, t0);
2502 tcg_gen_xori_tl(t1, t1, ~uimm);
2503 tcg_gen_xori_tl(t2, t0, uimm);
2504 tcg_gen_and_tl(t1, t1, t2);
2505 tcg_temp_free(t2);
2506 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2507 tcg_temp_free(t1);
2508 /* operands of same sign, result different sign */
2509 generate_exception(ctx, EXCP_OVERFLOW);
2510 gen_set_label(l1);
2511 tcg_gen_ext32s_tl(t0, t0);
2512 gen_store_gpr(t0, rt);
2513 tcg_temp_free(t0);
2515 opn = "addi";
2516 break;
2517 case OPC_ADDIU:
2518 if (rs != 0) {
2519 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2520 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2521 } else {
2522 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2524 opn = "addiu";
2525 break;
2526 #if defined(TARGET_MIPS64)
2527 case OPC_DADDI:
2529 TCGv t0 = tcg_temp_local_new();
2530 TCGv t1 = tcg_temp_new();
2531 TCGv t2 = tcg_temp_new();
2532 TCGLabel *l1 = gen_new_label();
2534 gen_load_gpr(t1, rs);
2535 tcg_gen_addi_tl(t0, t1, uimm);
2537 tcg_gen_xori_tl(t1, t1, ~uimm);
2538 tcg_gen_xori_tl(t2, t0, uimm);
2539 tcg_gen_and_tl(t1, t1, t2);
2540 tcg_temp_free(t2);
2541 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2542 tcg_temp_free(t1);
2543 /* operands of same sign, result different sign */
2544 generate_exception(ctx, EXCP_OVERFLOW);
2545 gen_set_label(l1);
2546 gen_store_gpr(t0, rt);
2547 tcg_temp_free(t0);
2549 opn = "daddi";
2550 break;
2551 case OPC_DADDIU:
2552 if (rs != 0) {
2553 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2554 } else {
2555 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2557 opn = "daddiu";
2558 break;
2559 #endif
2561 (void)opn; /* avoid a compiler warning */
2562 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2565 /* Logic with immediate operand */
2566 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2567 int rt, int rs, int16_t imm)
2569 target_ulong uimm;
2571 if (rt == 0) {
2572 /* If no destination, treat it as a NOP. */
2573 MIPS_DEBUG("NOP");
2574 return;
2576 uimm = (uint16_t)imm;
2577 switch (opc) {
2578 case OPC_ANDI:
2579 if (likely(rs != 0))
2580 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2581 else
2582 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2583 MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
2584 regnames[rs], uimm);
2585 break;
2586 case OPC_ORI:
2587 if (rs != 0)
2588 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2589 else
2590 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2591 MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
2592 regnames[rs], uimm);
2593 break;
2594 case OPC_XORI:
2595 if (likely(rs != 0))
2596 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2597 else
2598 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2599 MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
2600 regnames[rs], uimm);
2601 break;
2602 case OPC_LUI:
2603 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2604 /* OPC_AUI */
2605 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2606 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2607 MIPS_DEBUG("aui %s, %s, %04x", regnames[rt], regnames[rs], imm);
2608 } else {
2609 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2610 MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
2612 break;
2614 default:
2615 MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
2616 break;
2620 /* Set on less than with immediate operand */
2621 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2622 int rt, int rs, int16_t imm)
2624 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2625 const char *opn = "imm arith";
2626 TCGv t0;
2628 if (rt == 0) {
2629 /* If no destination, treat it as a NOP. */
2630 MIPS_DEBUG("NOP");
2631 return;
2633 t0 = tcg_temp_new();
2634 gen_load_gpr(t0, rs);
2635 switch (opc) {
2636 case OPC_SLTI:
2637 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2638 opn = "slti";
2639 break;
2640 case OPC_SLTIU:
2641 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2642 opn = "sltiu";
2643 break;
2645 (void)opn; /* avoid a compiler warning */
2646 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2647 tcg_temp_free(t0);
2650 /* Shifts with immediate operand */
2651 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2652 int rt, int rs, int16_t imm)
2654 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2655 const char *opn = "imm shift";
2656 TCGv t0;
2658 if (rt == 0) {
2659 /* If no destination, treat it as a NOP. */
2660 MIPS_DEBUG("NOP");
2661 return;
2664 t0 = tcg_temp_new();
2665 gen_load_gpr(t0, rs);
2666 switch (opc) {
2667 case OPC_SLL:
2668 tcg_gen_shli_tl(t0, t0, uimm);
2669 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2670 opn = "sll";
2671 break;
2672 case OPC_SRA:
2673 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2674 opn = "sra";
2675 break;
2676 case OPC_SRL:
2677 if (uimm != 0) {
2678 tcg_gen_ext32u_tl(t0, t0);
2679 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2680 } else {
2681 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2683 opn = "srl";
2684 break;
2685 case OPC_ROTR:
2686 if (uimm != 0) {
2687 TCGv_i32 t1 = tcg_temp_new_i32();
2689 tcg_gen_trunc_tl_i32(t1, t0);
2690 tcg_gen_rotri_i32(t1, t1, uimm);
2691 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2692 tcg_temp_free_i32(t1);
2693 } else {
2694 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2696 opn = "rotr";
2697 break;
2698 #if defined(TARGET_MIPS64)
2699 case OPC_DSLL:
2700 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2701 opn = "dsll";
2702 break;
2703 case OPC_DSRA:
2704 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2705 opn = "dsra";
2706 break;
2707 case OPC_DSRL:
2708 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2709 opn = "dsrl";
2710 break;
2711 case OPC_DROTR:
2712 if (uimm != 0) {
2713 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2714 } else {
2715 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2717 opn = "drotr";
2718 break;
2719 case OPC_DSLL32:
2720 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2721 opn = "dsll32";
2722 break;
2723 case OPC_DSRA32:
2724 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2725 opn = "dsra32";
2726 break;
2727 case OPC_DSRL32:
2728 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2729 opn = "dsrl32";
2730 break;
2731 case OPC_DROTR32:
2732 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2733 opn = "drotr32";
2734 break;
2735 #endif
2737 (void)opn; /* avoid a compiler warning */
2738 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2739 tcg_temp_free(t0);
2742 /* Arithmetic */
2743 static void gen_arith(DisasContext *ctx, uint32_t opc,
2744 int rd, int rs, int rt)
2746 const char *opn = "arith";
2748 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2749 && opc != OPC_DADD && opc != OPC_DSUB) {
2750 /* If no destination, treat it as a NOP.
2751 For add & sub, we must generate the overflow exception when needed. */
2752 MIPS_DEBUG("NOP");
2753 return;
2756 switch (opc) {
2757 case OPC_ADD:
2759 TCGv t0 = tcg_temp_local_new();
2760 TCGv t1 = tcg_temp_new();
2761 TCGv t2 = tcg_temp_new();
2762 TCGLabel *l1 = gen_new_label();
2764 gen_load_gpr(t1, rs);
2765 gen_load_gpr(t2, rt);
2766 tcg_gen_add_tl(t0, t1, t2);
2767 tcg_gen_ext32s_tl(t0, t0);
2768 tcg_gen_xor_tl(t1, t1, t2);
2769 tcg_gen_xor_tl(t2, t0, t2);
2770 tcg_gen_andc_tl(t1, t2, t1);
2771 tcg_temp_free(t2);
2772 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2773 tcg_temp_free(t1);
2774 /* operands of same sign, result different sign */
2775 generate_exception(ctx, EXCP_OVERFLOW);
2776 gen_set_label(l1);
2777 gen_store_gpr(t0, rd);
2778 tcg_temp_free(t0);
2780 opn = "add";
2781 break;
2782 case OPC_ADDU:
2783 if (rs != 0 && rt != 0) {
2784 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2785 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2786 } else if (rs == 0 && rt != 0) {
2787 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2788 } else if (rs != 0 && rt == 0) {
2789 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2790 } else {
2791 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2793 opn = "addu";
2794 break;
2795 case OPC_SUB:
2797 TCGv t0 = tcg_temp_local_new();
2798 TCGv t1 = tcg_temp_new();
2799 TCGv t2 = tcg_temp_new();
2800 TCGLabel *l1 = gen_new_label();
2802 gen_load_gpr(t1, rs);
2803 gen_load_gpr(t2, rt);
2804 tcg_gen_sub_tl(t0, t1, t2);
2805 tcg_gen_ext32s_tl(t0, t0);
2806 tcg_gen_xor_tl(t2, t1, t2);
2807 tcg_gen_xor_tl(t1, t0, t1);
2808 tcg_gen_and_tl(t1, t1, t2);
2809 tcg_temp_free(t2);
2810 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2811 tcg_temp_free(t1);
2812 /* operands of different sign, first operand and result different sign */
2813 generate_exception(ctx, EXCP_OVERFLOW);
2814 gen_set_label(l1);
2815 gen_store_gpr(t0, rd);
2816 tcg_temp_free(t0);
2818 opn = "sub";
2819 break;
2820 case OPC_SUBU:
2821 if (rs != 0 && rt != 0) {
2822 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2823 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2824 } else if (rs == 0 && rt != 0) {
2825 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2826 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2827 } else if (rs != 0 && rt == 0) {
2828 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2829 } else {
2830 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2832 opn = "subu";
2833 break;
2834 #if defined(TARGET_MIPS64)
2835 case OPC_DADD:
2837 TCGv t0 = tcg_temp_local_new();
2838 TCGv t1 = tcg_temp_new();
2839 TCGv t2 = tcg_temp_new();
2840 TCGLabel *l1 = gen_new_label();
2842 gen_load_gpr(t1, rs);
2843 gen_load_gpr(t2, rt);
2844 tcg_gen_add_tl(t0, t1, t2);
2845 tcg_gen_xor_tl(t1, t1, t2);
2846 tcg_gen_xor_tl(t2, t0, t2);
2847 tcg_gen_andc_tl(t1, t2, t1);
2848 tcg_temp_free(t2);
2849 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2850 tcg_temp_free(t1);
2851 /* operands of same sign, result different sign */
2852 generate_exception(ctx, EXCP_OVERFLOW);
2853 gen_set_label(l1);
2854 gen_store_gpr(t0, rd);
2855 tcg_temp_free(t0);
2857 opn = "dadd";
2858 break;
2859 case OPC_DADDU:
2860 if (rs != 0 && rt != 0) {
2861 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2862 } else if (rs == 0 && rt != 0) {
2863 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2864 } else if (rs != 0 && rt == 0) {
2865 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2866 } else {
2867 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2869 opn = "daddu";
2870 break;
2871 case OPC_DSUB:
2873 TCGv t0 = tcg_temp_local_new();
2874 TCGv t1 = tcg_temp_new();
2875 TCGv t2 = tcg_temp_new();
2876 TCGLabel *l1 = gen_new_label();
2878 gen_load_gpr(t1, rs);
2879 gen_load_gpr(t2, rt);
2880 tcg_gen_sub_tl(t0, t1, t2);
2881 tcg_gen_xor_tl(t2, t1, t2);
2882 tcg_gen_xor_tl(t1, t0, t1);
2883 tcg_gen_and_tl(t1, t1, t2);
2884 tcg_temp_free(t2);
2885 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2886 tcg_temp_free(t1);
2887 /* operands of different sign, first operand and result different sign */
2888 generate_exception(ctx, EXCP_OVERFLOW);
2889 gen_set_label(l1);
2890 gen_store_gpr(t0, rd);
2891 tcg_temp_free(t0);
2893 opn = "dsub";
2894 break;
2895 case OPC_DSUBU:
2896 if (rs != 0 && rt != 0) {
2897 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2898 } else if (rs == 0 && rt != 0) {
2899 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2900 } else if (rs != 0 && rt == 0) {
2901 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2902 } else {
2903 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2905 opn = "dsubu";
2906 break;
2907 #endif
2908 case OPC_MUL:
2909 if (likely(rs != 0 && rt != 0)) {
2910 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2911 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2912 } else {
2913 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2915 opn = "mul";
2916 break;
2918 (void)opn; /* avoid a compiler warning */
2919 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2922 /* Conditional move */
2923 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2924 int rd, int rs, int rt)
2926 const char *opn = "cond move";
2927 TCGv t0, t1, t2;
2929 if (rd == 0) {
2930 /* If no destination, treat it as a NOP. */
2931 MIPS_DEBUG("NOP");
2932 return;
2935 t0 = tcg_temp_new();
2936 gen_load_gpr(t0, rt);
2937 t1 = tcg_const_tl(0);
2938 t2 = tcg_temp_new();
2939 gen_load_gpr(t2, rs);
2940 switch (opc) {
2941 case OPC_MOVN:
2942 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2943 opn = "movn";
2944 break;
2945 case OPC_MOVZ:
2946 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2947 opn = "movz";
2948 break;
2949 case OPC_SELNEZ:
2950 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2951 opn = "selnez";
2952 break;
2953 case OPC_SELEQZ:
2954 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2955 opn = "seleqz";
2956 break;
2958 tcg_temp_free(t2);
2959 tcg_temp_free(t1);
2960 tcg_temp_free(t0);
2962 (void)opn; /* avoid a compiler warning */
2963 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2966 /* Logic */
2967 static void gen_logic(DisasContext *ctx, uint32_t opc,
2968 int rd, int rs, int rt)
2970 const char *opn = "logic";
2972 if (rd == 0) {
2973 /* If no destination, treat it as a NOP. */
2974 MIPS_DEBUG("NOP");
2975 return;
2978 switch (opc) {
2979 case OPC_AND:
2980 if (likely(rs != 0 && rt != 0)) {
2981 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2982 } else {
2983 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2985 opn = "and";
2986 break;
2987 case OPC_NOR:
2988 if (rs != 0 && rt != 0) {
2989 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2990 } else if (rs == 0 && rt != 0) {
2991 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2992 } else if (rs != 0 && rt == 0) {
2993 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2994 } else {
2995 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2997 opn = "nor";
2998 break;
2999 case OPC_OR:
3000 if (likely(rs != 0 && rt != 0)) {
3001 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3002 } else if (rs == 0 && rt != 0) {
3003 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3004 } else if (rs != 0 && rt == 0) {
3005 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3006 } else {
3007 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3009 opn = "or";
3010 break;
3011 case OPC_XOR:
3012 if (likely(rs != 0 && rt != 0)) {
3013 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3014 } else if (rs == 0 && rt != 0) {
3015 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3016 } else if (rs != 0 && rt == 0) {
3017 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3018 } else {
3019 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3021 opn = "xor";
3022 break;
3024 (void)opn; /* avoid a compiler warning */
3025 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3028 /* Set on lower than */
3029 static void gen_slt(DisasContext *ctx, uint32_t opc,
3030 int rd, int rs, int rt)
3032 const char *opn = "slt";
3033 TCGv t0, t1;
3035 if (rd == 0) {
3036 /* If no destination, treat it as a NOP. */
3037 MIPS_DEBUG("NOP");
3038 return;
3041 t0 = tcg_temp_new();
3042 t1 = tcg_temp_new();
3043 gen_load_gpr(t0, rs);
3044 gen_load_gpr(t1, rt);
3045 switch (opc) {
3046 case OPC_SLT:
3047 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3048 opn = "slt";
3049 break;
3050 case OPC_SLTU:
3051 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3052 opn = "sltu";
3053 break;
3055 (void)opn; /* avoid a compiler warning */
3056 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3057 tcg_temp_free(t0);
3058 tcg_temp_free(t1);
3061 /* Shifts */
3062 static void gen_shift(DisasContext *ctx, uint32_t opc,
3063 int rd, int rs, int rt)
3065 const char *opn = "shifts";
3066 TCGv t0, t1;
3068 if (rd == 0) {
3069 /* If no destination, treat it as a NOP.
3070 For add & sub, we must generate the overflow exception when needed. */
3071 MIPS_DEBUG("NOP");
3072 return;
3075 t0 = tcg_temp_new();
3076 t1 = tcg_temp_new();
3077 gen_load_gpr(t0, rs);
3078 gen_load_gpr(t1, rt);
3079 switch (opc) {
3080 case OPC_SLLV:
3081 tcg_gen_andi_tl(t0, t0, 0x1f);
3082 tcg_gen_shl_tl(t0, t1, t0);
3083 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3084 opn = "sllv";
3085 break;
3086 case OPC_SRAV:
3087 tcg_gen_andi_tl(t0, t0, 0x1f);
3088 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3089 opn = "srav";
3090 break;
3091 case OPC_SRLV:
3092 tcg_gen_ext32u_tl(t1, t1);
3093 tcg_gen_andi_tl(t0, t0, 0x1f);
3094 tcg_gen_shr_tl(t0, t1, t0);
3095 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3096 opn = "srlv";
3097 break;
3098 case OPC_ROTRV:
3100 TCGv_i32 t2 = tcg_temp_new_i32();
3101 TCGv_i32 t3 = tcg_temp_new_i32();
3103 tcg_gen_trunc_tl_i32(t2, t0);
3104 tcg_gen_trunc_tl_i32(t3, t1);
3105 tcg_gen_andi_i32(t2, t2, 0x1f);
3106 tcg_gen_rotr_i32(t2, t3, t2);
3107 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3108 tcg_temp_free_i32(t2);
3109 tcg_temp_free_i32(t3);
3110 opn = "rotrv";
3112 break;
3113 #if defined(TARGET_MIPS64)
3114 case OPC_DSLLV:
3115 tcg_gen_andi_tl(t0, t0, 0x3f);
3116 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3117 opn = "dsllv";
3118 break;
3119 case OPC_DSRAV:
3120 tcg_gen_andi_tl(t0, t0, 0x3f);
3121 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3122 opn = "dsrav";
3123 break;
3124 case OPC_DSRLV:
3125 tcg_gen_andi_tl(t0, t0, 0x3f);
3126 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3127 opn = "dsrlv";
3128 break;
3129 case OPC_DROTRV:
3130 tcg_gen_andi_tl(t0, t0, 0x3f);
3131 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3132 opn = "drotrv";
3133 break;
3134 #endif
3136 (void)opn; /* avoid a compiler warning */
3137 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3138 tcg_temp_free(t0);
3139 tcg_temp_free(t1);
3142 /* Arithmetic on HI/LO registers */
3143 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3145 const char *opn = "hilo";
3147 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3148 /* Treat as NOP. */
3149 MIPS_DEBUG("NOP");
3150 return;
3153 if (acc != 0) {
3154 check_dsp(ctx);
3157 switch (opc) {
3158 case OPC_MFHI:
3159 #if defined(TARGET_MIPS64)
3160 if (acc != 0) {
3161 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3162 } else
3163 #endif
3165 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3167 opn = "mfhi";
3168 break;
3169 case OPC_MFLO:
3170 #if defined(TARGET_MIPS64)
3171 if (acc != 0) {
3172 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3173 } else
3174 #endif
3176 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3178 opn = "mflo";
3179 break;
3180 case OPC_MTHI:
3181 if (reg != 0) {
3182 #if defined(TARGET_MIPS64)
3183 if (acc != 0) {
3184 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3185 } else
3186 #endif
3188 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3190 } else {
3191 tcg_gen_movi_tl(cpu_HI[acc], 0);
3193 opn = "mthi";
3194 break;
3195 case OPC_MTLO:
3196 if (reg != 0) {
3197 #if defined(TARGET_MIPS64)
3198 if (acc != 0) {
3199 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3200 } else
3201 #endif
3203 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3205 } else {
3206 tcg_gen_movi_tl(cpu_LO[acc], 0);
3208 opn = "mtlo";
3209 break;
3211 (void)opn; /* avoid a compiler warning */
3212 MIPS_DEBUG("%s %s", opn, regnames[reg]);
3215 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3216 TCGMemOp memop)
3218 TCGv t0 = tcg_const_tl(addr);
3219 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3220 gen_store_gpr(t0, reg);
3221 tcg_temp_free(t0);
3224 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3225 int rs)
3227 target_long offset;
3228 target_long addr;
3230 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3231 case OPC_ADDIUPC:
3232 if (rs != 0) {
3233 offset = sextract32(ctx->opcode << 2, 0, 21);
3234 addr = addr_add(ctx, pc, offset);
3235 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3237 break;
3238 case R6_OPC_LWPC:
3239 offset = sextract32(ctx->opcode << 2, 0, 21);
3240 addr = addr_add(ctx, pc, offset);
3241 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3242 break;
3243 #if defined(TARGET_MIPS64)
3244 case OPC_LWUPC:
3245 check_mips_64(ctx);
3246 offset = sextract32(ctx->opcode << 2, 0, 21);
3247 addr = addr_add(ctx, pc, offset);
3248 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3249 break;
3250 #endif
3251 default:
3252 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3253 case OPC_AUIPC:
3254 if (rs != 0) {
3255 offset = sextract32(ctx->opcode, 0, 16) << 16;
3256 addr = addr_add(ctx, pc, offset);
3257 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3259 break;
3260 case OPC_ALUIPC:
3261 if (rs != 0) {
3262 offset = sextract32(ctx->opcode, 0, 16) << 16;
3263 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3264 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3266 break;
3267 #if defined(TARGET_MIPS64)
3268 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3269 case R6_OPC_LDPC + (1 << 16):
3270 case R6_OPC_LDPC + (2 << 16):
3271 case R6_OPC_LDPC + (3 << 16):
3272 check_mips_64(ctx);
3273 offset = sextract32(ctx->opcode << 3, 0, 21);
3274 addr = addr_add(ctx, (pc & ~0x7), offset);
3275 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3276 break;
3277 #endif
3278 default:
3279 MIPS_INVAL("OPC_PCREL");
3280 generate_exception(ctx, EXCP_RI);
3281 break;
3283 break;
3287 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3289 const char *opn = "r6 mul/div";
3290 TCGv t0, t1;
3292 if (rd == 0) {
3293 /* Treat as NOP. */
3294 MIPS_DEBUG("NOP");
3295 return;
3298 t0 = tcg_temp_new();
3299 t1 = tcg_temp_new();
3301 gen_load_gpr(t0, rs);
3302 gen_load_gpr(t1, rt);
3304 switch (opc) {
3305 case R6_OPC_DIV:
3307 TCGv t2 = tcg_temp_new();
3308 TCGv t3 = tcg_temp_new();
3309 tcg_gen_ext32s_tl(t0, t0);
3310 tcg_gen_ext32s_tl(t1, t1);
3311 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3312 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3313 tcg_gen_and_tl(t2, t2, t3);
3314 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3315 tcg_gen_or_tl(t2, t2, t3);
3316 tcg_gen_movi_tl(t3, 0);
3317 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3318 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3319 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3320 tcg_temp_free(t3);
3321 tcg_temp_free(t2);
3323 opn = "div";
3324 break;
3325 case R6_OPC_MOD:
3327 TCGv t2 = tcg_temp_new();
3328 TCGv t3 = tcg_temp_new();
3329 tcg_gen_ext32s_tl(t0, t0);
3330 tcg_gen_ext32s_tl(t1, t1);
3331 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3332 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3333 tcg_gen_and_tl(t2, t2, t3);
3334 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3335 tcg_gen_or_tl(t2, t2, t3);
3336 tcg_gen_movi_tl(t3, 0);
3337 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3338 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3339 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3340 tcg_temp_free(t3);
3341 tcg_temp_free(t2);
3343 opn = "mod";
3344 break;
3345 case R6_OPC_DIVU:
3347 TCGv t2 = tcg_const_tl(0);
3348 TCGv t3 = tcg_const_tl(1);
3349 tcg_gen_ext32u_tl(t0, t0);
3350 tcg_gen_ext32u_tl(t1, t1);
3351 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3352 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3353 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3354 tcg_temp_free(t3);
3355 tcg_temp_free(t2);
3357 opn = "divu";
3358 break;
3359 case R6_OPC_MODU:
3361 TCGv t2 = tcg_const_tl(0);
3362 TCGv t3 = tcg_const_tl(1);
3363 tcg_gen_ext32u_tl(t0, t0);
3364 tcg_gen_ext32u_tl(t1, t1);
3365 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3366 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3367 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3368 tcg_temp_free(t3);
3369 tcg_temp_free(t2);
3371 opn = "modu";
3372 break;
3373 case R6_OPC_MUL:
3375 TCGv_i32 t2 = tcg_temp_new_i32();
3376 TCGv_i32 t3 = tcg_temp_new_i32();
3377 tcg_gen_trunc_tl_i32(t2, t0);
3378 tcg_gen_trunc_tl_i32(t3, t1);
3379 tcg_gen_mul_i32(t2, t2, t3);
3380 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3381 tcg_temp_free_i32(t2);
3382 tcg_temp_free_i32(t3);
3384 opn = "mul";
3385 break;
3386 case R6_OPC_MUH:
3388 TCGv_i32 t2 = tcg_temp_new_i32();
3389 TCGv_i32 t3 = tcg_temp_new_i32();
3390 tcg_gen_trunc_tl_i32(t2, t0);
3391 tcg_gen_trunc_tl_i32(t3, t1);
3392 tcg_gen_muls2_i32(t2, t3, t2, t3);
3393 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3394 tcg_temp_free_i32(t2);
3395 tcg_temp_free_i32(t3);
3397 opn = "muh";
3398 break;
3399 case R6_OPC_MULU:
3401 TCGv_i32 t2 = tcg_temp_new_i32();
3402 TCGv_i32 t3 = tcg_temp_new_i32();
3403 tcg_gen_trunc_tl_i32(t2, t0);
3404 tcg_gen_trunc_tl_i32(t3, t1);
3405 tcg_gen_mul_i32(t2, t2, t3);
3406 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3407 tcg_temp_free_i32(t2);
3408 tcg_temp_free_i32(t3);
3410 opn = "mulu";
3411 break;
3412 case R6_OPC_MUHU:
3414 TCGv_i32 t2 = tcg_temp_new_i32();
3415 TCGv_i32 t3 = tcg_temp_new_i32();
3416 tcg_gen_trunc_tl_i32(t2, t0);
3417 tcg_gen_trunc_tl_i32(t3, t1);
3418 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3419 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3420 tcg_temp_free_i32(t2);
3421 tcg_temp_free_i32(t3);
3423 opn = "muhu";
3424 break;
3425 #if defined(TARGET_MIPS64)
3426 case R6_OPC_DDIV:
3428 TCGv t2 = tcg_temp_new();
3429 TCGv t3 = tcg_temp_new();
3430 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3431 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3432 tcg_gen_and_tl(t2, t2, t3);
3433 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3434 tcg_gen_or_tl(t2, t2, t3);
3435 tcg_gen_movi_tl(t3, 0);
3436 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3437 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3438 tcg_temp_free(t3);
3439 tcg_temp_free(t2);
3441 opn = "ddiv";
3442 break;
3443 case R6_OPC_DMOD:
3445 TCGv t2 = tcg_temp_new();
3446 TCGv t3 = tcg_temp_new();
3447 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3448 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3449 tcg_gen_and_tl(t2, t2, t3);
3450 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3451 tcg_gen_or_tl(t2, t2, t3);
3452 tcg_gen_movi_tl(t3, 0);
3453 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3454 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3455 tcg_temp_free(t3);
3456 tcg_temp_free(t2);
3458 opn = "dmod";
3459 break;
3460 case R6_OPC_DDIVU:
3462 TCGv t2 = tcg_const_tl(0);
3463 TCGv t3 = tcg_const_tl(1);
3464 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3465 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3466 tcg_temp_free(t3);
3467 tcg_temp_free(t2);
3469 opn = "ddivu";
3470 break;
3471 case R6_OPC_DMODU:
3473 TCGv t2 = tcg_const_tl(0);
3474 TCGv t3 = tcg_const_tl(1);
3475 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3476 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3477 tcg_temp_free(t3);
3478 tcg_temp_free(t2);
3480 opn = "dmodu";
3481 break;
3482 case R6_OPC_DMUL:
3483 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3484 opn = "dmul";
3485 break;
3486 case R6_OPC_DMUH:
3488 TCGv t2 = tcg_temp_new();
3489 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3490 tcg_temp_free(t2);
3492 opn = "dmuh";
3493 break;
3494 case R6_OPC_DMULU:
3495 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3496 opn = "dmulu";
3497 break;
3498 case R6_OPC_DMUHU:
3500 TCGv t2 = tcg_temp_new();
3501 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3502 tcg_temp_free(t2);
3504 opn = "dmuhu";
3505 break;
3506 #endif
3507 default:
3508 MIPS_INVAL(opn);
3509 generate_exception(ctx, EXCP_RI);
3510 goto out;
3512 (void)opn; /* avoid a compiler warning */
3513 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3514 out:
3515 tcg_temp_free(t0);
3516 tcg_temp_free(t1);
3519 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3520 int acc, int rs, int rt)
3522 const char *opn = "mul/div";
3523 TCGv t0, t1;
3525 t0 = tcg_temp_new();
3526 t1 = tcg_temp_new();
3528 gen_load_gpr(t0, rs);
3529 gen_load_gpr(t1, rt);
3531 if (acc != 0) {
3532 check_dsp(ctx);
3535 switch (opc) {
3536 case OPC_DIV:
3538 TCGv t2 = tcg_temp_new();
3539 TCGv t3 = tcg_temp_new();
3540 tcg_gen_ext32s_tl(t0, t0);
3541 tcg_gen_ext32s_tl(t1, t1);
3542 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3543 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3544 tcg_gen_and_tl(t2, t2, t3);
3545 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3546 tcg_gen_or_tl(t2, t2, t3);
3547 tcg_gen_movi_tl(t3, 0);
3548 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3549 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3550 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3551 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3552 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3553 tcg_temp_free(t3);
3554 tcg_temp_free(t2);
3556 opn = "div";
3557 break;
3558 case OPC_DIVU:
3560 TCGv t2 = tcg_const_tl(0);
3561 TCGv t3 = tcg_const_tl(1);
3562 tcg_gen_ext32u_tl(t0, t0);
3563 tcg_gen_ext32u_tl(t1, t1);
3564 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3565 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3566 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3567 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3568 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3569 tcg_temp_free(t3);
3570 tcg_temp_free(t2);
3572 opn = "divu";
3573 break;
3574 case OPC_MULT:
3576 TCGv_i32 t2 = tcg_temp_new_i32();
3577 TCGv_i32 t3 = tcg_temp_new_i32();
3578 tcg_gen_trunc_tl_i32(t2, t0);
3579 tcg_gen_trunc_tl_i32(t3, t1);
3580 tcg_gen_muls2_i32(t2, t3, t2, t3);
3581 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3582 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3583 tcg_temp_free_i32(t2);
3584 tcg_temp_free_i32(t3);
3586 opn = "mult";
3587 break;
3588 case OPC_MULTU:
3590 TCGv_i32 t2 = tcg_temp_new_i32();
3591 TCGv_i32 t3 = tcg_temp_new_i32();
3592 tcg_gen_trunc_tl_i32(t2, t0);
3593 tcg_gen_trunc_tl_i32(t3, t1);
3594 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3595 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3596 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3597 tcg_temp_free_i32(t2);
3598 tcg_temp_free_i32(t3);
3600 opn = "multu";
3601 break;
3602 #if defined(TARGET_MIPS64)
3603 case OPC_DDIV:
3605 TCGv t2 = tcg_temp_new();
3606 TCGv t3 = tcg_temp_new();
3607 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3608 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3609 tcg_gen_and_tl(t2, t2, t3);
3610 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3611 tcg_gen_or_tl(t2, t2, t3);
3612 tcg_gen_movi_tl(t3, 0);
3613 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3614 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3615 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3616 tcg_temp_free(t3);
3617 tcg_temp_free(t2);
3619 opn = "ddiv";
3620 break;
3621 case OPC_DDIVU:
3623 TCGv t2 = tcg_const_tl(0);
3624 TCGv t3 = tcg_const_tl(1);
3625 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3626 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3627 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3628 tcg_temp_free(t3);
3629 tcg_temp_free(t2);
3631 opn = "ddivu";
3632 break;
3633 case OPC_DMULT:
3634 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3635 opn = "dmult";
3636 break;
3637 case OPC_DMULTU:
3638 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3639 opn = "dmultu";
3640 break;
3641 #endif
3642 case OPC_MADD:
3644 TCGv_i64 t2 = tcg_temp_new_i64();
3645 TCGv_i64 t3 = tcg_temp_new_i64();
3647 tcg_gen_ext_tl_i64(t2, t0);
3648 tcg_gen_ext_tl_i64(t3, t1);
3649 tcg_gen_mul_i64(t2, t2, t3);
3650 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3651 tcg_gen_add_i64(t2, t2, t3);
3652 tcg_temp_free_i64(t3);
3653 tcg_gen_trunc_i64_tl(t0, t2);
3654 tcg_gen_shri_i64(t2, t2, 32);
3655 tcg_gen_trunc_i64_tl(t1, t2);
3656 tcg_temp_free_i64(t2);
3657 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3658 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3660 opn = "madd";
3661 break;
3662 case OPC_MADDU:
3664 TCGv_i64 t2 = tcg_temp_new_i64();
3665 TCGv_i64 t3 = tcg_temp_new_i64();
3667 tcg_gen_ext32u_tl(t0, t0);
3668 tcg_gen_ext32u_tl(t1, t1);
3669 tcg_gen_extu_tl_i64(t2, t0);
3670 tcg_gen_extu_tl_i64(t3, t1);
3671 tcg_gen_mul_i64(t2, t2, t3);
3672 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3673 tcg_gen_add_i64(t2, t2, t3);
3674 tcg_temp_free_i64(t3);
3675 tcg_gen_trunc_i64_tl(t0, t2);
3676 tcg_gen_shri_i64(t2, t2, 32);
3677 tcg_gen_trunc_i64_tl(t1, t2);
3678 tcg_temp_free_i64(t2);
3679 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3680 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3682 opn = "maddu";
3683 break;
3684 case OPC_MSUB:
3686 TCGv_i64 t2 = tcg_temp_new_i64();
3687 TCGv_i64 t3 = tcg_temp_new_i64();
3689 tcg_gen_ext_tl_i64(t2, t0);
3690 tcg_gen_ext_tl_i64(t3, t1);
3691 tcg_gen_mul_i64(t2, t2, t3);
3692 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3693 tcg_gen_sub_i64(t2, t3, t2);
3694 tcg_temp_free_i64(t3);
3695 tcg_gen_trunc_i64_tl(t0, t2);
3696 tcg_gen_shri_i64(t2, t2, 32);
3697 tcg_gen_trunc_i64_tl(t1, t2);
3698 tcg_temp_free_i64(t2);
3699 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3700 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3702 opn = "msub";
3703 break;
3704 case OPC_MSUBU:
3706 TCGv_i64 t2 = tcg_temp_new_i64();
3707 TCGv_i64 t3 = tcg_temp_new_i64();
3709 tcg_gen_ext32u_tl(t0, t0);
3710 tcg_gen_ext32u_tl(t1, t1);
3711 tcg_gen_extu_tl_i64(t2, t0);
3712 tcg_gen_extu_tl_i64(t3, t1);
3713 tcg_gen_mul_i64(t2, t2, t3);
3714 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3715 tcg_gen_sub_i64(t2, t3, t2);
3716 tcg_temp_free_i64(t3);
3717 tcg_gen_trunc_i64_tl(t0, t2);
3718 tcg_gen_shri_i64(t2, t2, 32);
3719 tcg_gen_trunc_i64_tl(t1, t2);
3720 tcg_temp_free_i64(t2);
3721 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3722 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3724 opn = "msubu";
3725 break;
3726 default:
3727 MIPS_INVAL(opn);
3728 generate_exception(ctx, EXCP_RI);
3729 goto out;
3731 (void)opn; /* avoid a compiler warning */
3732 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3733 out:
3734 tcg_temp_free(t0);
3735 tcg_temp_free(t1);
3738 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3739 int rd, int rs, int rt)
3741 const char *opn = "mul vr54xx";
3742 TCGv t0 = tcg_temp_new();
3743 TCGv t1 = tcg_temp_new();
3745 gen_load_gpr(t0, rs);
3746 gen_load_gpr(t1, rt);
3748 switch (opc) {
3749 case OPC_VR54XX_MULS:
3750 gen_helper_muls(t0, cpu_env, t0, t1);
3751 opn = "muls";
3752 break;
3753 case OPC_VR54XX_MULSU:
3754 gen_helper_mulsu(t0, cpu_env, t0, t1);
3755 opn = "mulsu";
3756 break;
3757 case OPC_VR54XX_MACC:
3758 gen_helper_macc(t0, cpu_env, t0, t1);
3759 opn = "macc";
3760 break;
3761 case OPC_VR54XX_MACCU:
3762 gen_helper_maccu(t0, cpu_env, t0, t1);
3763 opn = "maccu";
3764 break;
3765 case OPC_VR54XX_MSAC:
3766 gen_helper_msac(t0, cpu_env, t0, t1);
3767 opn = "msac";
3768 break;
3769 case OPC_VR54XX_MSACU:
3770 gen_helper_msacu(t0, cpu_env, t0, t1);
3771 opn = "msacu";
3772 break;
3773 case OPC_VR54XX_MULHI:
3774 gen_helper_mulhi(t0, cpu_env, t0, t1);
3775 opn = "mulhi";
3776 break;
3777 case OPC_VR54XX_MULHIU:
3778 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3779 opn = "mulhiu";
3780 break;
3781 case OPC_VR54XX_MULSHI:
3782 gen_helper_mulshi(t0, cpu_env, t0, t1);
3783 opn = "mulshi";
3784 break;
3785 case OPC_VR54XX_MULSHIU:
3786 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3787 opn = "mulshiu";
3788 break;
3789 case OPC_VR54XX_MACCHI:
3790 gen_helper_macchi(t0, cpu_env, t0, t1);
3791 opn = "macchi";
3792 break;
3793 case OPC_VR54XX_MACCHIU:
3794 gen_helper_macchiu(t0, cpu_env, t0, t1);
3795 opn = "macchiu";
3796 break;
3797 case OPC_VR54XX_MSACHI:
3798 gen_helper_msachi(t0, cpu_env, t0, t1);
3799 opn = "msachi";
3800 break;
3801 case OPC_VR54XX_MSACHIU:
3802 gen_helper_msachiu(t0, cpu_env, t0, t1);
3803 opn = "msachiu";
3804 break;
3805 default:
3806 MIPS_INVAL("mul vr54xx");
3807 generate_exception(ctx, EXCP_RI);
3808 goto out;
3810 gen_store_gpr(t0, rd);
3811 (void)opn; /* avoid a compiler warning */
3812 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3814 out:
3815 tcg_temp_free(t0);
3816 tcg_temp_free(t1);
3819 static void gen_cl (DisasContext *ctx, uint32_t opc,
3820 int rd, int rs)
3822 const char *opn = "CLx";
3823 TCGv t0;
3825 if (rd == 0) {
3826 /* Treat as NOP. */
3827 MIPS_DEBUG("NOP");
3828 return;
3830 t0 = tcg_temp_new();
3831 gen_load_gpr(t0, rs);
3832 switch (opc) {
3833 case OPC_CLO:
3834 case R6_OPC_CLO:
3835 gen_helper_clo(cpu_gpr[rd], t0);
3836 opn = "clo";
3837 break;
3838 case OPC_CLZ:
3839 case R6_OPC_CLZ:
3840 gen_helper_clz(cpu_gpr[rd], t0);
3841 opn = "clz";
3842 break;
3843 #if defined(TARGET_MIPS64)
3844 case OPC_DCLO:
3845 case R6_OPC_DCLO:
3846 gen_helper_dclo(cpu_gpr[rd], t0);
3847 opn = "dclo";
3848 break;
3849 case OPC_DCLZ:
3850 case R6_OPC_DCLZ:
3851 gen_helper_dclz(cpu_gpr[rd], t0);
3852 opn = "dclz";
3853 break;
3854 #endif
3856 (void)opn; /* avoid a compiler warning */
3857 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3858 tcg_temp_free(t0);
3861 /* Godson integer instructions */
3862 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3863 int rd, int rs, int rt)
3865 const char *opn = "loongson";
3866 TCGv t0, t1;
3868 if (rd == 0) {
3869 /* Treat as NOP. */
3870 MIPS_DEBUG("NOP");
3871 return;
3874 switch (opc) {
3875 case OPC_MULT_G_2E:
3876 case OPC_MULT_G_2F:
3877 case OPC_MULTU_G_2E:
3878 case OPC_MULTU_G_2F:
3879 #if defined(TARGET_MIPS64)
3880 case OPC_DMULT_G_2E:
3881 case OPC_DMULT_G_2F:
3882 case OPC_DMULTU_G_2E:
3883 case OPC_DMULTU_G_2F:
3884 #endif
3885 t0 = tcg_temp_new();
3886 t1 = tcg_temp_new();
3887 break;
3888 default:
3889 t0 = tcg_temp_local_new();
3890 t1 = tcg_temp_local_new();
3891 break;
3894 gen_load_gpr(t0, rs);
3895 gen_load_gpr(t1, rt);
3897 switch (opc) {
3898 case OPC_MULT_G_2E:
3899 case OPC_MULT_G_2F:
3900 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3901 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3902 opn = "mult.g";
3903 break;
3904 case OPC_MULTU_G_2E:
3905 case OPC_MULTU_G_2F:
3906 tcg_gen_ext32u_tl(t0, t0);
3907 tcg_gen_ext32u_tl(t1, t1);
3908 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3909 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3910 opn = "multu.g";
3911 break;
3912 case OPC_DIV_G_2E:
3913 case OPC_DIV_G_2F:
3915 TCGLabel *l1 = gen_new_label();
3916 TCGLabel *l2 = gen_new_label();
3917 TCGLabel *l3 = gen_new_label();
3918 tcg_gen_ext32s_tl(t0, t0);
3919 tcg_gen_ext32s_tl(t1, t1);
3920 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3921 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3922 tcg_gen_br(l3);
3923 gen_set_label(l1);
3924 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3925 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3926 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3927 tcg_gen_br(l3);
3928 gen_set_label(l2);
3929 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3930 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3931 gen_set_label(l3);
3933 opn = "div.g";
3934 break;
3935 case OPC_DIVU_G_2E:
3936 case OPC_DIVU_G_2F:
3938 TCGLabel *l1 = gen_new_label();
3939 TCGLabel *l2 = gen_new_label();
3940 tcg_gen_ext32u_tl(t0, t0);
3941 tcg_gen_ext32u_tl(t1, t1);
3942 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3943 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3944 tcg_gen_br(l2);
3945 gen_set_label(l1);
3946 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3947 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3948 gen_set_label(l2);
3950 opn = "divu.g";
3951 break;
3952 case OPC_MOD_G_2E:
3953 case OPC_MOD_G_2F:
3955 TCGLabel *l1 = gen_new_label();
3956 TCGLabel *l2 = gen_new_label();
3957 TCGLabel *l3 = gen_new_label();
3958 tcg_gen_ext32u_tl(t0, t0);
3959 tcg_gen_ext32u_tl(t1, t1);
3960 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3961 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3962 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3963 gen_set_label(l1);
3964 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3965 tcg_gen_br(l3);
3966 gen_set_label(l2);
3967 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3968 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3969 gen_set_label(l3);
3971 opn = "mod.g";
3972 break;
3973 case OPC_MODU_G_2E:
3974 case OPC_MODU_G_2F:
3976 TCGLabel *l1 = gen_new_label();
3977 TCGLabel *l2 = gen_new_label();
3978 tcg_gen_ext32u_tl(t0, t0);
3979 tcg_gen_ext32u_tl(t1, t1);
3980 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3981 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3982 tcg_gen_br(l2);
3983 gen_set_label(l1);
3984 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3985 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3986 gen_set_label(l2);
3988 opn = "modu.g";
3989 break;
3990 #if defined(TARGET_MIPS64)
3991 case OPC_DMULT_G_2E:
3992 case OPC_DMULT_G_2F:
3993 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3994 opn = "dmult.g";
3995 break;
3996 case OPC_DMULTU_G_2E:
3997 case OPC_DMULTU_G_2F:
3998 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3999 opn = "dmultu.g";
4000 break;
4001 case OPC_DDIV_G_2E:
4002 case OPC_DDIV_G_2F:
4004 TCGLabel *l1 = gen_new_label();
4005 TCGLabel *l2 = gen_new_label();
4006 TCGLabel *l3 = gen_new_label();
4007 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4008 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4009 tcg_gen_br(l3);
4010 gen_set_label(l1);
4011 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4012 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4013 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4014 tcg_gen_br(l3);
4015 gen_set_label(l2);
4016 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4017 gen_set_label(l3);
4019 opn = "ddiv.g";
4020 break;
4021 case OPC_DDIVU_G_2E:
4022 case OPC_DDIVU_G_2F:
4024 TCGLabel *l1 = gen_new_label();
4025 TCGLabel *l2 = gen_new_label();
4026 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4027 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4028 tcg_gen_br(l2);
4029 gen_set_label(l1);
4030 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4031 gen_set_label(l2);
4033 opn = "ddivu.g";
4034 break;
4035 case OPC_DMOD_G_2E:
4036 case OPC_DMOD_G_2F:
4038 TCGLabel *l1 = gen_new_label();
4039 TCGLabel *l2 = gen_new_label();
4040 TCGLabel *l3 = gen_new_label();
4041 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4042 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4043 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4044 gen_set_label(l1);
4045 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4046 tcg_gen_br(l3);
4047 gen_set_label(l2);
4048 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4049 gen_set_label(l3);
4051 opn = "dmod.g";
4052 break;
4053 case OPC_DMODU_G_2E:
4054 case OPC_DMODU_G_2F:
4056 TCGLabel *l1 = gen_new_label();
4057 TCGLabel *l2 = gen_new_label();
4058 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4059 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4060 tcg_gen_br(l2);
4061 gen_set_label(l1);
4062 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4063 gen_set_label(l2);
4065 opn = "dmodu.g";
4066 break;
4067 #endif
4070 (void)opn; /* avoid a compiler warning */
4071 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
4072 tcg_temp_free(t0);
4073 tcg_temp_free(t1);
4076 /* Loongson multimedia instructions */
4077 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4079 const char *opn = "loongson_cp2";
4080 uint32_t opc, shift_max;
4081 TCGv_i64 t0, t1;
4083 opc = MASK_LMI(ctx->opcode);
4084 switch (opc) {
4085 case OPC_ADD_CP2:
4086 case OPC_SUB_CP2:
4087 case OPC_DADD_CP2:
4088 case OPC_DSUB_CP2:
4089 t0 = tcg_temp_local_new_i64();
4090 t1 = tcg_temp_local_new_i64();
4091 break;
4092 default:
4093 t0 = tcg_temp_new_i64();
4094 t1 = tcg_temp_new_i64();
4095 break;
4098 gen_load_fpr64(ctx, t0, rs);
4099 gen_load_fpr64(ctx, t1, rt);
4101 #define LMI_HELPER(UP, LO) \
4102 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
4103 #define LMI_HELPER_1(UP, LO) \
4104 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
4105 #define LMI_DIRECT(UP, LO, OP) \
4106 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
4108 switch (opc) {
4109 LMI_HELPER(PADDSH, paddsh);
4110 LMI_HELPER(PADDUSH, paddush);
4111 LMI_HELPER(PADDH, paddh);
4112 LMI_HELPER(PADDW, paddw);
4113 LMI_HELPER(PADDSB, paddsb);
4114 LMI_HELPER(PADDUSB, paddusb);
4115 LMI_HELPER(PADDB, paddb);
4117 LMI_HELPER(PSUBSH, psubsh);
4118 LMI_HELPER(PSUBUSH, psubush);
4119 LMI_HELPER(PSUBH, psubh);
4120 LMI_HELPER(PSUBW, psubw);
4121 LMI_HELPER(PSUBSB, psubsb);
4122 LMI_HELPER(PSUBUSB, psubusb);
4123 LMI_HELPER(PSUBB, psubb);
4125 LMI_HELPER(PSHUFH, pshufh);
4126 LMI_HELPER(PACKSSWH, packsswh);
4127 LMI_HELPER(PACKSSHB, packsshb);
4128 LMI_HELPER(PACKUSHB, packushb);
4130 LMI_HELPER(PUNPCKLHW, punpcklhw);
4131 LMI_HELPER(PUNPCKHHW, punpckhhw);
4132 LMI_HELPER(PUNPCKLBH, punpcklbh);
4133 LMI_HELPER(PUNPCKHBH, punpckhbh);
4134 LMI_HELPER(PUNPCKLWD, punpcklwd);
4135 LMI_HELPER(PUNPCKHWD, punpckhwd);
4137 LMI_HELPER(PAVGH, pavgh);
4138 LMI_HELPER(PAVGB, pavgb);
4139 LMI_HELPER(PMAXSH, pmaxsh);
4140 LMI_HELPER(PMINSH, pminsh);
4141 LMI_HELPER(PMAXUB, pmaxub);
4142 LMI_HELPER(PMINUB, pminub);
4144 LMI_HELPER(PCMPEQW, pcmpeqw);
4145 LMI_HELPER(PCMPGTW, pcmpgtw);
4146 LMI_HELPER(PCMPEQH, pcmpeqh);
4147 LMI_HELPER(PCMPGTH, pcmpgth);
4148 LMI_HELPER(PCMPEQB, pcmpeqb);
4149 LMI_HELPER(PCMPGTB, pcmpgtb);
4151 LMI_HELPER(PSLLW, psllw);
4152 LMI_HELPER(PSLLH, psllh);
4153 LMI_HELPER(PSRLW, psrlw);
4154 LMI_HELPER(PSRLH, psrlh);
4155 LMI_HELPER(PSRAW, psraw);
4156 LMI_HELPER(PSRAH, psrah);
4158 LMI_HELPER(PMULLH, pmullh);
4159 LMI_HELPER(PMULHH, pmulhh);
4160 LMI_HELPER(PMULHUH, pmulhuh);
4161 LMI_HELPER(PMADDHW, pmaddhw);
4163 LMI_HELPER(PASUBUB, pasubub);
4164 LMI_HELPER_1(BIADD, biadd);
4165 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4167 LMI_DIRECT(PADDD, paddd, add);
4168 LMI_DIRECT(PSUBD, psubd, sub);
4169 LMI_DIRECT(XOR_CP2, xor, xor);
4170 LMI_DIRECT(NOR_CP2, nor, nor);
4171 LMI_DIRECT(AND_CP2, and, and);
4172 LMI_DIRECT(PANDN, pandn, andc);
4173 LMI_DIRECT(OR, or, or);
4175 case OPC_PINSRH_0:
4176 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4177 opn = "pinsrh_0";
4178 break;
4179 case OPC_PINSRH_1:
4180 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4181 opn = "pinsrh_1";
4182 break;
4183 case OPC_PINSRH_2:
4184 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4185 opn = "pinsrh_2";
4186 break;
4187 case OPC_PINSRH_3:
4188 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4189 opn = "pinsrh_3";
4190 break;
4192 case OPC_PEXTRH:
4193 tcg_gen_andi_i64(t1, t1, 3);
4194 tcg_gen_shli_i64(t1, t1, 4);
4195 tcg_gen_shr_i64(t0, t0, t1);
4196 tcg_gen_ext16u_i64(t0, t0);
4197 opn = "pextrh";
4198 break;
4200 case OPC_ADDU_CP2:
4201 tcg_gen_add_i64(t0, t0, t1);
4202 tcg_gen_ext32s_i64(t0, t0);
4203 opn = "addu";
4204 break;
4205 case OPC_SUBU_CP2:
4206 tcg_gen_sub_i64(t0, t0, t1);
4207 tcg_gen_ext32s_i64(t0, t0);
4208 opn = "addu";
4209 break;
4211 case OPC_SLL_CP2:
4212 opn = "sll";
4213 shift_max = 32;
4214 goto do_shift;
4215 case OPC_SRL_CP2:
4216 opn = "srl";
4217 shift_max = 32;
4218 goto do_shift;
4219 case OPC_SRA_CP2:
4220 opn = "sra";
4221 shift_max = 32;
4222 goto do_shift;
4223 case OPC_DSLL_CP2:
4224 opn = "dsll";
4225 shift_max = 64;
4226 goto do_shift;
4227 case OPC_DSRL_CP2:
4228 opn = "dsrl";
4229 shift_max = 64;
4230 goto do_shift;
4231 case OPC_DSRA_CP2:
4232 opn = "dsra";
4233 shift_max = 64;
4234 goto do_shift;
4235 do_shift:
4236 /* Make sure shift count isn't TCG undefined behaviour. */
4237 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4239 switch (opc) {
4240 case OPC_SLL_CP2:
4241 case OPC_DSLL_CP2:
4242 tcg_gen_shl_i64(t0, t0, t1);
4243 break;
4244 case OPC_SRA_CP2:
4245 case OPC_DSRA_CP2:
4246 /* Since SRA is UndefinedResult without sign-extended inputs,
4247 we can treat SRA and DSRA the same. */
4248 tcg_gen_sar_i64(t0, t0, t1);
4249 break;
4250 case OPC_SRL_CP2:
4251 /* We want to shift in zeros for SRL; zero-extend first. */
4252 tcg_gen_ext32u_i64(t0, t0);
4253 /* FALLTHRU */
4254 case OPC_DSRL_CP2:
4255 tcg_gen_shr_i64(t0, t0, t1);
4256 break;
4259 if (shift_max == 32) {
4260 tcg_gen_ext32s_i64(t0, t0);
4263 /* Shifts larger than MAX produce zero. */
4264 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4265 tcg_gen_neg_i64(t1, t1);
4266 tcg_gen_and_i64(t0, t0, t1);
4267 break;
4269 case OPC_ADD_CP2:
4270 case OPC_DADD_CP2:
4272 TCGv_i64 t2 = tcg_temp_new_i64();
4273 TCGLabel *lab = gen_new_label();
4275 tcg_gen_mov_i64(t2, t0);
4276 tcg_gen_add_i64(t0, t1, t2);
4277 if (opc == OPC_ADD_CP2) {
4278 tcg_gen_ext32s_i64(t0, t0);
4280 tcg_gen_xor_i64(t1, t1, t2);
4281 tcg_gen_xor_i64(t2, t2, t0);
4282 tcg_gen_andc_i64(t1, t2, t1);
4283 tcg_temp_free_i64(t2);
4284 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4285 generate_exception(ctx, EXCP_OVERFLOW);
4286 gen_set_label(lab);
4288 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
4289 break;
4292 case OPC_SUB_CP2:
4293 case OPC_DSUB_CP2:
4295 TCGv_i64 t2 = tcg_temp_new_i64();
4296 TCGLabel *lab = gen_new_label();
4298 tcg_gen_mov_i64(t2, t0);
4299 tcg_gen_sub_i64(t0, t1, t2);
4300 if (opc == OPC_SUB_CP2) {
4301 tcg_gen_ext32s_i64(t0, t0);
4303 tcg_gen_xor_i64(t1, t1, t2);
4304 tcg_gen_xor_i64(t2, t2, t0);
4305 tcg_gen_and_i64(t1, t1, t2);
4306 tcg_temp_free_i64(t2);
4307 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4308 generate_exception(ctx, EXCP_OVERFLOW);
4309 gen_set_label(lab);
4311 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
4312 break;
4315 case OPC_PMULUW:
4316 tcg_gen_ext32u_i64(t0, t0);
4317 tcg_gen_ext32u_i64(t1, t1);
4318 tcg_gen_mul_i64(t0, t0, t1);
4319 opn = "pmuluw";
4320 break;
4322 case OPC_SEQU_CP2:
4323 case OPC_SEQ_CP2:
4324 case OPC_SLTU_CP2:
4325 case OPC_SLT_CP2:
4326 case OPC_SLEU_CP2:
4327 case OPC_SLE_CP2:
4328 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4329 FD field is the CC field? */
4330 default:
4331 MIPS_INVAL(opn);
4332 generate_exception(ctx, EXCP_RI);
4333 return;
4336 #undef LMI_HELPER
4337 #undef LMI_DIRECT
4339 gen_store_fpr64(ctx, t0, rd);
4341 (void)opn; /* avoid a compiler warning */
4342 MIPS_DEBUG("%s %s, %s, %s", opn,
4343 fregnames[rd], fregnames[rs], fregnames[rt]);
4344 tcg_temp_free_i64(t0);
4345 tcg_temp_free_i64(t1);
4348 /* Traps */
4349 static void gen_trap (DisasContext *ctx, uint32_t opc,
4350 int rs, int rt, int16_t imm)
4352 int cond;
4353 TCGv t0 = tcg_temp_new();
4354 TCGv t1 = tcg_temp_new();
4356 cond = 0;
4357 /* Load needed operands */
4358 switch (opc) {
4359 case OPC_TEQ:
4360 case OPC_TGE:
4361 case OPC_TGEU:
4362 case OPC_TLT:
4363 case OPC_TLTU:
4364 case OPC_TNE:
4365 /* Compare two registers */
4366 if (rs != rt) {
4367 gen_load_gpr(t0, rs);
4368 gen_load_gpr(t1, rt);
4369 cond = 1;
4371 break;
4372 case OPC_TEQI:
4373 case OPC_TGEI:
4374 case OPC_TGEIU:
4375 case OPC_TLTI:
4376 case OPC_TLTIU:
4377 case OPC_TNEI:
4378 /* Compare register to immediate */
4379 if (rs != 0 || imm != 0) {
4380 gen_load_gpr(t0, rs);
4381 tcg_gen_movi_tl(t1, (int32_t)imm);
4382 cond = 1;
4384 break;
4386 if (cond == 0) {
4387 switch (opc) {
4388 case OPC_TEQ: /* rs == rs */
4389 case OPC_TEQI: /* r0 == 0 */
4390 case OPC_TGE: /* rs >= rs */
4391 case OPC_TGEI: /* r0 >= 0 */
4392 case OPC_TGEU: /* rs >= rs unsigned */
4393 case OPC_TGEIU: /* r0 >= 0 unsigned */
4394 /* Always trap */
4395 generate_exception(ctx, EXCP_TRAP);
4396 break;
4397 case OPC_TLT: /* rs < rs */
4398 case OPC_TLTI: /* r0 < 0 */
4399 case OPC_TLTU: /* rs < rs unsigned */
4400 case OPC_TLTIU: /* r0 < 0 unsigned */
4401 case OPC_TNE: /* rs != rs */
4402 case OPC_TNEI: /* r0 != 0 */
4403 /* Never trap: treat as NOP. */
4404 break;
4406 } else {
4407 TCGLabel *l1 = gen_new_label();
4409 switch (opc) {
4410 case OPC_TEQ:
4411 case OPC_TEQI:
4412 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4413 break;
4414 case OPC_TGE:
4415 case OPC_TGEI:
4416 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4417 break;
4418 case OPC_TGEU:
4419 case OPC_TGEIU:
4420 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4421 break;
4422 case OPC_TLT:
4423 case OPC_TLTI:
4424 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4425 break;
4426 case OPC_TLTU:
4427 case OPC_TLTIU:
4428 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4429 break;
4430 case OPC_TNE:
4431 case OPC_TNEI:
4432 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4433 break;
4435 generate_exception(ctx, EXCP_TRAP);
4436 gen_set_label(l1);
4438 tcg_temp_free(t0);
4439 tcg_temp_free(t1);
4442 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4444 TranslationBlock *tb;
4445 tb = ctx->tb;
4446 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
4447 likely(!ctx->singlestep_enabled)) {
4448 tcg_gen_goto_tb(n);
4449 gen_save_pc(dest);
4450 tcg_gen_exit_tb((uintptr_t)tb + n);
4451 } else {
4452 gen_save_pc(dest);
4453 if (ctx->singlestep_enabled) {
4454 save_cpu_state(ctx, 0);
4455 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
4457 tcg_gen_exit_tb(0);
4461 /* Branches (before delay slot) */
4462 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4463 int insn_bytes,
4464 int rs, int rt, int32_t offset,
4465 int delayslot_size)
4467 target_ulong btgt = -1;
4468 int blink = 0;
4469 int bcond_compute = 0;
4470 TCGv t0 = tcg_temp_new();
4471 TCGv t1 = tcg_temp_new();
4473 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4474 #ifdef MIPS_DEBUG_DISAS
4475 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4476 TARGET_FMT_lx "\n", ctx->pc);
4477 #endif
4478 generate_exception(ctx, EXCP_RI);
4479 goto out;
4482 /* Load needed operands */
4483 switch (opc) {
4484 case OPC_BEQ:
4485 case OPC_BEQL:
4486 case OPC_BNE:
4487 case OPC_BNEL:
4488 /* Compare two registers */
4489 if (rs != rt) {
4490 gen_load_gpr(t0, rs);
4491 gen_load_gpr(t1, rt);
4492 bcond_compute = 1;
4494 btgt = ctx->pc + insn_bytes + offset;
4495 break;
4496 case OPC_BGEZ:
4497 case OPC_BGEZAL:
4498 case OPC_BGEZALL:
4499 case OPC_BGEZL:
4500 case OPC_BGTZ:
4501 case OPC_BGTZL:
4502 case OPC_BLEZ:
4503 case OPC_BLEZL:
4504 case OPC_BLTZ:
4505 case OPC_BLTZAL:
4506 case OPC_BLTZALL:
4507 case OPC_BLTZL:
4508 /* Compare to zero */
4509 if (rs != 0) {
4510 gen_load_gpr(t0, rs);
4511 bcond_compute = 1;
4513 btgt = ctx->pc + insn_bytes + offset;
4514 break;
4515 case OPC_BPOSGE32:
4516 #if defined(TARGET_MIPS64)
4517 case OPC_BPOSGE64:
4518 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4519 #else
4520 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4521 #endif
4522 bcond_compute = 1;
4523 btgt = ctx->pc + insn_bytes + offset;
4524 break;
4525 case OPC_J:
4526 case OPC_JAL:
4527 case OPC_JALX:
4528 /* Jump to immediate */
4529 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4530 break;
4531 case OPC_JR:
4532 case OPC_JALR:
4533 /* Jump to register */
4534 if (offset != 0 && offset != 16) {
4535 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4536 others are reserved. */
4537 MIPS_INVAL("jump hint");
4538 generate_exception(ctx, EXCP_RI);
4539 goto out;
4541 gen_load_gpr(btarget, rs);
4542 break;
4543 default:
4544 MIPS_INVAL("branch/jump");
4545 generate_exception(ctx, EXCP_RI);
4546 goto out;
4548 if (bcond_compute == 0) {
4549 /* No condition to be computed */
4550 switch (opc) {
4551 case OPC_BEQ: /* rx == rx */
4552 case OPC_BEQL: /* rx == rx likely */
4553 case OPC_BGEZ: /* 0 >= 0 */
4554 case OPC_BGEZL: /* 0 >= 0 likely */
4555 case OPC_BLEZ: /* 0 <= 0 */
4556 case OPC_BLEZL: /* 0 <= 0 likely */
4557 /* Always take */
4558 ctx->hflags |= MIPS_HFLAG_B;
4559 MIPS_DEBUG("balways");
4560 break;
4561 case OPC_BGEZAL: /* 0 >= 0 */
4562 case OPC_BGEZALL: /* 0 >= 0 likely */
4563 /* Always take and link */
4564 blink = 31;
4565 ctx->hflags |= MIPS_HFLAG_B;
4566 MIPS_DEBUG("balways and link");
4567 break;
4568 case OPC_BNE: /* rx != rx */
4569 case OPC_BGTZ: /* 0 > 0 */
4570 case OPC_BLTZ: /* 0 < 0 */
4571 /* Treat as NOP. */
4572 MIPS_DEBUG("bnever (NOP)");
4573 goto out;
4574 case OPC_BLTZAL: /* 0 < 0 */
4575 /* Handle as an unconditional branch to get correct delay
4576 slot checking. */
4577 blink = 31;
4578 btgt = ctx->pc + insn_bytes + delayslot_size;
4579 ctx->hflags |= MIPS_HFLAG_B;
4580 MIPS_DEBUG("bnever and link");
4581 break;
4582 case OPC_BLTZALL: /* 0 < 0 likely */
4583 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4584 /* Skip the instruction in the delay slot */
4585 MIPS_DEBUG("bnever, link and skip");
4586 ctx->pc += 4;
4587 goto out;
4588 case OPC_BNEL: /* rx != rx likely */
4589 case OPC_BGTZL: /* 0 > 0 likely */
4590 case OPC_BLTZL: /* 0 < 0 likely */
4591 /* Skip the instruction in the delay slot */
4592 MIPS_DEBUG("bnever and skip");
4593 ctx->pc += 4;
4594 goto out;
4595 case OPC_J:
4596 ctx->hflags |= MIPS_HFLAG_B;
4597 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
4598 break;
4599 case OPC_JALX:
4600 ctx->hflags |= MIPS_HFLAG_BX;
4601 /* Fallthrough */
4602 case OPC_JAL:
4603 blink = 31;
4604 ctx->hflags |= MIPS_HFLAG_B;
4605 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
4606 break;
4607 case OPC_JR:
4608 ctx->hflags |= MIPS_HFLAG_BR;
4609 MIPS_DEBUG("jr %s", regnames[rs]);
4610 break;
4611 case OPC_JALR:
4612 blink = rt;
4613 ctx->hflags |= MIPS_HFLAG_BR;
4614 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
4615 break;
4616 default:
4617 MIPS_INVAL("branch/jump");
4618 generate_exception(ctx, EXCP_RI);
4619 goto out;
4621 } else {
4622 switch (opc) {
4623 case OPC_BEQ:
4624 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4625 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
4626 regnames[rs], regnames[rt], btgt);
4627 goto not_likely;
4628 case OPC_BEQL:
4629 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4630 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
4631 regnames[rs], regnames[rt], btgt);
4632 goto likely;
4633 case OPC_BNE:
4634 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4635 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
4636 regnames[rs], regnames[rt], btgt);
4637 goto not_likely;
4638 case OPC_BNEL:
4639 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4640 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
4641 regnames[rs], regnames[rt], btgt);
4642 goto likely;
4643 case OPC_BGEZ:
4644 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4645 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4646 goto not_likely;
4647 case OPC_BGEZL:
4648 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4649 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4650 goto likely;
4651 case OPC_BGEZAL:
4652 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4653 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4654 blink = 31;
4655 goto not_likely;
4656 case OPC_BGEZALL:
4657 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4658 blink = 31;
4659 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4660 goto likely;
4661 case OPC_BGTZ:
4662 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4663 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4664 goto not_likely;
4665 case OPC_BGTZL:
4666 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4667 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4668 goto likely;
4669 case OPC_BLEZ:
4670 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4671 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4672 goto not_likely;
4673 case OPC_BLEZL:
4674 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4675 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4676 goto likely;
4677 case OPC_BLTZ:
4678 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4679 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4680 goto not_likely;
4681 case OPC_BLTZL:
4682 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4683 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4684 goto likely;
4685 case OPC_BPOSGE32:
4686 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4687 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
4688 goto not_likely;
4689 #if defined(TARGET_MIPS64)
4690 case OPC_BPOSGE64:
4691 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4692 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
4693 goto not_likely;
4694 #endif
4695 case OPC_BLTZAL:
4696 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4697 blink = 31;
4698 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4699 not_likely:
4700 ctx->hflags |= MIPS_HFLAG_BC;
4701 break;
4702 case OPC_BLTZALL:
4703 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4704 blink = 31;
4705 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4706 likely:
4707 ctx->hflags |= MIPS_HFLAG_BL;
4708 break;
4709 default:
4710 MIPS_INVAL("conditional branch/jump");
4711 generate_exception(ctx, EXCP_RI);
4712 goto out;
4715 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
4716 blink, ctx->hflags, btgt);
4718 ctx->btarget = btgt;
4720 switch (delayslot_size) {
4721 case 2:
4722 ctx->hflags |= MIPS_HFLAG_BDS16;
4723 break;
4724 case 4:
4725 ctx->hflags |= MIPS_HFLAG_BDS32;
4726 break;
4729 if (blink > 0) {
4730 int post_delay = insn_bytes + delayslot_size;
4731 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4733 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4736 out:
4737 if (insn_bytes == 2)
4738 ctx->hflags |= MIPS_HFLAG_B16;
4739 tcg_temp_free(t0);
4740 tcg_temp_free(t1);
4743 /* special3 bitfield operations */
4744 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4745 int rs, int lsb, int msb)
4747 TCGv t0 = tcg_temp_new();
4748 TCGv t1 = tcg_temp_new();
4750 gen_load_gpr(t1, rs);
4751 switch (opc) {
4752 case OPC_EXT:
4753 if (lsb + msb > 31) {
4754 goto fail;
4756 tcg_gen_shri_tl(t0, t1, lsb);
4757 if (msb != 31) {
4758 tcg_gen_andi_tl(t0, t0, (1U << (msb + 1)) - 1);
4759 } else {
4760 tcg_gen_ext32s_tl(t0, t0);
4762 break;
4763 #if defined(TARGET_MIPS64)
4764 case OPC_DEXTU:
4765 lsb += 32;
4766 goto do_dext;
4767 case OPC_DEXTM:
4768 msb += 32;
4769 goto do_dext;
4770 case OPC_DEXT:
4771 do_dext:
4772 if (lsb + msb > 63) {
4773 goto fail;
4775 tcg_gen_shri_tl(t0, t1, lsb);
4776 if (msb != 63) {
4777 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4779 break;
4780 #endif
4781 case OPC_INS:
4782 if (lsb > msb) {
4783 goto fail;
4785 gen_load_gpr(t0, rt);
4786 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4787 tcg_gen_ext32s_tl(t0, t0);
4788 break;
4789 #if defined(TARGET_MIPS64)
4790 case OPC_DINSU:
4791 lsb += 32;
4792 /* FALLTHRU */
4793 case OPC_DINSM:
4794 msb += 32;
4795 /* FALLTHRU */
4796 case OPC_DINS:
4797 if (lsb > msb) {
4798 goto fail;
4800 gen_load_gpr(t0, rt);
4801 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4802 break;
4803 #endif
4804 default:
4805 fail:
4806 MIPS_INVAL("bitops");
4807 generate_exception(ctx, EXCP_RI);
4808 tcg_temp_free(t0);
4809 tcg_temp_free(t1);
4810 return;
4812 gen_store_gpr(t0, rt);
4813 tcg_temp_free(t0);
4814 tcg_temp_free(t1);
4817 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4819 TCGv t0;
4821 if (rd == 0) {
4822 /* If no destination, treat it as a NOP. */
4823 MIPS_DEBUG("NOP");
4824 return;
4827 t0 = tcg_temp_new();
4828 gen_load_gpr(t0, rt);
4829 switch (op2) {
4830 case OPC_WSBH:
4832 TCGv t1 = tcg_temp_new();
4834 tcg_gen_shri_tl(t1, t0, 8);
4835 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4836 tcg_gen_shli_tl(t0, t0, 8);
4837 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4838 tcg_gen_or_tl(t0, t0, t1);
4839 tcg_temp_free(t1);
4840 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4842 break;
4843 case OPC_SEB:
4844 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4845 break;
4846 case OPC_SEH:
4847 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4848 break;
4849 #if defined(TARGET_MIPS64)
4850 case OPC_DSBH:
4852 TCGv t1 = tcg_temp_new();
4854 tcg_gen_shri_tl(t1, t0, 8);
4855 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4856 tcg_gen_shli_tl(t0, t0, 8);
4857 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4858 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4859 tcg_temp_free(t1);
4861 break;
4862 case OPC_DSHD:
4864 TCGv t1 = tcg_temp_new();
4866 tcg_gen_shri_tl(t1, t0, 16);
4867 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4868 tcg_gen_shli_tl(t0, t0, 16);
4869 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4870 tcg_gen_or_tl(t0, t0, t1);
4871 tcg_gen_shri_tl(t1, t0, 32);
4872 tcg_gen_shli_tl(t0, t0, 32);
4873 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4874 tcg_temp_free(t1);
4876 break;
4877 #endif
4878 default:
4879 MIPS_INVAL("bsfhl");
4880 generate_exception(ctx, EXCP_RI);
4881 tcg_temp_free(t0);
4882 return;
4884 tcg_temp_free(t0);
4887 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4888 int imm2)
4890 TCGv t0;
4891 TCGv t1;
4892 if (rd == 0) {
4893 /* Treat as NOP. */
4894 return;
4896 t0 = tcg_temp_new();
4897 t1 = tcg_temp_new();
4898 gen_load_gpr(t0, rs);
4899 gen_load_gpr(t1, rt);
4900 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4901 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4902 if (opc == OPC_LSA) {
4903 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4906 tcg_temp_free(t1);
4907 tcg_temp_free(t0);
4909 return;
4912 static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
4913 int bp)
4915 TCGv t0;
4916 if (rd == 0) {
4917 /* Treat as NOP. */
4918 return;
4920 t0 = tcg_temp_new();
4921 gen_load_gpr(t0, rt);
4922 if (bp == 0) {
4923 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4924 } else {
4925 TCGv t1 = tcg_temp_new();
4926 gen_load_gpr(t1, rs);
4927 switch (opc) {
4928 case OPC_ALIGN:
4930 TCGv_i64 t2 = tcg_temp_new_i64();
4931 tcg_gen_concat_tl_i64(t2, t1, t0);
4932 tcg_gen_shri_i64(t2, t2, 8 * (4 - bp));
4933 gen_move_low32(cpu_gpr[rd], t2);
4934 tcg_temp_free_i64(t2);
4936 break;
4937 #if defined(TARGET_MIPS64)
4938 case OPC_DALIGN:
4939 tcg_gen_shli_tl(t0, t0, 8 * bp);
4940 tcg_gen_shri_tl(t1, t1, 8 * (8 - bp));
4941 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4942 break;
4943 #endif
4945 tcg_temp_free(t1);
4948 tcg_temp_free(t0);
4951 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4953 TCGv t0;
4954 if (rd == 0) {
4955 /* Treat as NOP. */
4956 return;
4958 t0 = tcg_temp_new();
4959 gen_load_gpr(t0, rt);
4960 switch (opc) {
4961 case OPC_BITSWAP:
4962 gen_helper_bitswap(cpu_gpr[rd], t0);
4963 break;
4964 #if defined(TARGET_MIPS64)
4965 case OPC_DBITSWAP:
4966 gen_helper_dbitswap(cpu_gpr[rd], t0);
4967 break;
4968 #endif
4970 tcg_temp_free(t0);
4973 #ifndef CONFIG_USER_ONLY
4974 /* CP0 (MMU and control) */
4975 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4977 TCGv_i64 t0 = tcg_temp_new_i64();
4978 TCGv_i64 t1 = tcg_temp_new_i64();
4980 tcg_gen_ext_tl_i64(t0, arg);
4981 tcg_gen_ld_i64(t1, cpu_env, off);
4982 #if defined(TARGET_MIPS64)
4983 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4984 #else
4985 tcg_gen_concat32_i64(t1, t1, t0);
4986 #endif
4987 tcg_gen_st_i64(t1, cpu_env, off);
4988 tcg_temp_free_i64(t1);
4989 tcg_temp_free_i64(t0);
4992 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4994 TCGv_i64 t0 = tcg_temp_new_i64();
4995 TCGv_i64 t1 = tcg_temp_new_i64();
4997 tcg_gen_ext_tl_i64(t0, arg);
4998 tcg_gen_ld_i64(t1, cpu_env, off);
4999 tcg_gen_concat32_i64(t1, t1, t0);
5000 tcg_gen_st_i64(t1, cpu_env, off);
5001 tcg_temp_free_i64(t1);
5002 tcg_temp_free_i64(t0);
5005 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5007 TCGv_i64 t0 = tcg_temp_new_i64();
5009 tcg_gen_ld_i64(t0, cpu_env, off);
5010 #if defined(TARGET_MIPS64)
5011 tcg_gen_shri_i64(t0, t0, 30);
5012 #else
5013 tcg_gen_shri_i64(t0, t0, 32);
5014 #endif
5015 gen_move_low32(arg, t0);
5016 tcg_temp_free_i64(t0);
5019 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5021 TCGv_i64 t0 = tcg_temp_new_i64();
5023 tcg_gen_ld_i64(t0, cpu_env, off);
5024 tcg_gen_shri_i64(t0, t0, 32 + shift);
5025 gen_move_low32(arg, t0);
5026 tcg_temp_free_i64(t0);
5029 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
5031 TCGv_i32 t0 = tcg_temp_new_i32();
5033 tcg_gen_ld_i32(t0, cpu_env, off);
5034 tcg_gen_ext_i32_tl(arg, t0);
5035 tcg_temp_free_i32(t0);
5038 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
5040 tcg_gen_ld_tl(arg, cpu_env, off);
5041 tcg_gen_ext32s_tl(arg, arg);
5044 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
5046 TCGv_i32 t0 = tcg_temp_new_i32();
5048 tcg_gen_trunc_tl_i32(t0, arg);
5049 tcg_gen_st_i32(t0, cpu_env, off);
5050 tcg_temp_free_i32(t0);
5053 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
5055 tcg_gen_ext32s_tl(arg, arg);
5056 tcg_gen_st_tl(arg, cpu_env, off);
5059 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5061 const char *rn = "invalid";
5063 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
5064 goto mfhc0_read_zero;
5067 switch (reg) {
5068 case 2:
5069 switch (sel) {
5070 case 0:
5071 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5072 rn = "EntryLo0";
5073 break;
5074 default:
5075 goto mfhc0_read_zero;
5077 break;
5078 case 3:
5079 switch (sel) {
5080 case 0:
5081 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5082 rn = "EntryLo1";
5083 break;
5084 default:
5085 goto mfhc0_read_zero;
5087 break;
5088 case 17:
5089 switch (sel) {
5090 case 0:
5091 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
5092 ctx->CP0_LLAddr_shift);
5093 rn = "LLAddr";
5094 break;
5095 default:
5096 goto mfhc0_read_zero;
5098 break;
5099 case 28:
5100 switch (sel) {
5101 case 0:
5102 case 2:
5103 case 4:
5104 case 6:
5105 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5106 rn = "TagLo";
5107 break;
5108 default:
5109 goto mfhc0_read_zero;
5111 break;
5112 default:
5113 goto mfhc0_read_zero;
5116 (void)rn; /* avoid a compiler warning */
5117 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5118 return;
5120 mfhc0_read_zero:
5121 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5122 tcg_gen_movi_tl(arg, 0);
5125 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5127 const char *rn = "invalid";
5128 uint64_t mask = ctx->PAMask >> 36;
5130 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
5131 goto mthc0_nop;
5134 switch (reg) {
5135 case 2:
5136 switch (sel) {
5137 case 0:
5138 tcg_gen_andi_tl(arg, arg, mask);
5139 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5140 rn = "EntryLo0";
5141 break;
5142 default:
5143 goto mthc0_nop;
5145 break;
5146 case 3:
5147 switch (sel) {
5148 case 0:
5149 tcg_gen_andi_tl(arg, arg, mask);
5150 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5151 rn = "EntryLo1";
5152 break;
5153 default:
5154 goto mthc0_nop;
5156 break;
5157 case 17:
5158 switch (sel) {
5159 case 0:
5160 /* LLAddr is read-only (the only exception is bit 0 if LLB is
5161 supported); the CP0_LLAddr_rw_bitmask does not seem to be
5162 relevant for modern MIPS cores supporting MTHC0, therefore
5163 treating MTHC0 to LLAddr as NOP. */
5164 rn = "LLAddr";
5165 break;
5166 default:
5167 goto mthc0_nop;
5169 break;
5170 case 28:
5171 switch (sel) {
5172 case 0:
5173 case 2:
5174 case 4:
5175 case 6:
5176 tcg_gen_andi_tl(arg, arg, mask);
5177 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5178 rn = "TagLo";
5179 break;
5180 default:
5181 goto mthc0_nop;
5183 break;
5184 default:
5185 goto mthc0_nop;
5188 (void)rn; /* avoid a compiler warning */
5189 mthc0_nop:
5190 LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
5193 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5195 if (ctx->insn_flags & ISA_MIPS32R6) {
5196 tcg_gen_movi_tl(arg, 0);
5197 } else {
5198 tcg_gen_movi_tl(arg, ~0);
5202 #define CP0_CHECK(c) \
5203 do { \
5204 if (!(c)) { \
5205 goto cp0_unimplemented; \
5207 } while (0)
5209 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5211 const char *rn = "invalid";
5213 if (sel != 0)
5214 check_insn(ctx, ISA_MIPS32);
5216 switch (reg) {
5217 case 0:
5218 switch (sel) {
5219 case 0:
5220 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5221 rn = "Index";
5222 break;
5223 case 1:
5224 CP0_CHECK(ctx->insn_flags & ASE_MT);
5225 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5226 rn = "MVPControl";
5227 break;
5228 case 2:
5229 CP0_CHECK(ctx->insn_flags & ASE_MT);
5230 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5231 rn = "MVPConf0";
5232 break;
5233 case 3:
5234 CP0_CHECK(ctx->insn_flags & ASE_MT);
5235 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5236 rn = "MVPConf1";
5237 break;
5238 default:
5239 goto cp0_unimplemented;
5241 break;
5242 case 1:
5243 switch (sel) {
5244 case 0:
5245 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5246 gen_helper_mfc0_random(arg, cpu_env);
5247 rn = "Random";
5248 break;
5249 case 1:
5250 CP0_CHECK(ctx->insn_flags & ASE_MT);
5251 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5252 rn = "VPEControl";
5253 break;
5254 case 2:
5255 CP0_CHECK(ctx->insn_flags & ASE_MT);
5256 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5257 rn = "VPEConf0";
5258 break;
5259 case 3:
5260 CP0_CHECK(ctx->insn_flags & ASE_MT);
5261 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5262 rn = "VPEConf1";
5263 break;
5264 case 4:
5265 CP0_CHECK(ctx->insn_flags & ASE_MT);
5266 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5267 rn = "YQMask";
5268 break;
5269 case 5:
5270 CP0_CHECK(ctx->insn_flags & ASE_MT);
5271 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5272 rn = "VPESchedule";
5273 break;
5274 case 6:
5275 CP0_CHECK(ctx->insn_flags & ASE_MT);
5276 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5277 rn = "VPEScheFBack";
5278 break;
5279 case 7:
5280 CP0_CHECK(ctx->insn_flags & ASE_MT);
5281 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5282 rn = "VPEOpt";
5283 break;
5284 default:
5285 goto cp0_unimplemented;
5287 break;
5288 case 2:
5289 switch (sel) {
5290 case 0:
5292 TCGv_i64 tmp = tcg_temp_new_i64();
5293 tcg_gen_ld_i64(tmp, cpu_env,
5294 offsetof(CPUMIPSState, CP0_EntryLo0));
5295 #if defined(TARGET_MIPS64)
5296 if (ctx->rxi) {
5297 /* Move RI/XI fields to bits 31:30 */
5298 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5299 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5301 #endif
5302 gen_move_low32(arg, tmp);
5303 tcg_temp_free_i64(tmp);
5305 rn = "EntryLo0";
5306 break;
5307 case 1:
5308 CP0_CHECK(ctx->insn_flags & ASE_MT);
5309 gen_helper_mfc0_tcstatus(arg, cpu_env);
5310 rn = "TCStatus";
5311 break;
5312 case 2:
5313 CP0_CHECK(ctx->insn_flags & ASE_MT);
5314 gen_helper_mfc0_tcbind(arg, cpu_env);
5315 rn = "TCBind";
5316 break;
5317 case 3:
5318 CP0_CHECK(ctx->insn_flags & ASE_MT);
5319 gen_helper_mfc0_tcrestart(arg, cpu_env);
5320 rn = "TCRestart";
5321 break;
5322 case 4:
5323 CP0_CHECK(ctx->insn_flags & ASE_MT);
5324 gen_helper_mfc0_tchalt(arg, cpu_env);
5325 rn = "TCHalt";
5326 break;
5327 case 5:
5328 CP0_CHECK(ctx->insn_flags & ASE_MT);
5329 gen_helper_mfc0_tccontext(arg, cpu_env);
5330 rn = "TCContext";
5331 break;
5332 case 6:
5333 CP0_CHECK(ctx->insn_flags & ASE_MT);
5334 gen_helper_mfc0_tcschedule(arg, cpu_env);
5335 rn = "TCSchedule";
5336 break;
5337 case 7:
5338 CP0_CHECK(ctx->insn_flags & ASE_MT);
5339 gen_helper_mfc0_tcschefback(arg, cpu_env);
5340 rn = "TCScheFBack";
5341 break;
5342 default:
5343 goto cp0_unimplemented;
5345 break;
5346 case 3:
5347 switch (sel) {
5348 case 0:
5350 TCGv_i64 tmp = tcg_temp_new_i64();
5351 tcg_gen_ld_i64(tmp, cpu_env,
5352 offsetof(CPUMIPSState, CP0_EntryLo1));
5353 #if defined(TARGET_MIPS64)
5354 if (ctx->rxi) {
5355 /* Move RI/XI fields to bits 31:30 */
5356 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5357 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5359 #endif
5360 gen_move_low32(arg, tmp);
5361 tcg_temp_free_i64(tmp);
5363 rn = "EntryLo1";
5364 break;
5365 default:
5366 goto cp0_unimplemented;
5368 break;
5369 case 4:
5370 switch (sel) {
5371 case 0:
5372 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5373 tcg_gen_ext32s_tl(arg, arg);
5374 rn = "Context";
5375 break;
5376 case 1:
5377 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5378 rn = "ContextConfig";
5379 goto cp0_unimplemented;
5380 // break;
5381 case 2:
5382 CP0_CHECK(ctx->ulri);
5383 tcg_gen_ld32s_tl(arg, cpu_env,
5384 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5385 rn = "UserLocal";
5386 break;
5387 default:
5388 goto cp0_unimplemented;
5390 break;
5391 case 5:
5392 switch (sel) {
5393 case 0:
5394 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5395 rn = "PageMask";
5396 break;
5397 case 1:
5398 check_insn(ctx, ISA_MIPS32R2);
5399 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5400 rn = "PageGrain";
5401 break;
5402 default:
5403 goto cp0_unimplemented;
5405 break;
5406 case 6:
5407 switch (sel) {
5408 case 0:
5409 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5410 rn = "Wired";
5411 break;
5412 case 1:
5413 check_insn(ctx, ISA_MIPS32R2);
5414 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5415 rn = "SRSConf0";
5416 break;
5417 case 2:
5418 check_insn(ctx, ISA_MIPS32R2);
5419 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5420 rn = "SRSConf1";
5421 break;
5422 case 3:
5423 check_insn(ctx, ISA_MIPS32R2);
5424 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5425 rn = "SRSConf2";
5426 break;
5427 case 4:
5428 check_insn(ctx, ISA_MIPS32R2);
5429 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5430 rn = "SRSConf3";
5431 break;
5432 case 5:
5433 check_insn(ctx, ISA_MIPS32R2);
5434 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5435 rn = "SRSConf4";
5436 break;
5437 default:
5438 goto cp0_unimplemented;
5440 break;
5441 case 7:
5442 switch (sel) {
5443 case 0:
5444 check_insn(ctx, ISA_MIPS32R2);
5445 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5446 rn = "HWREna";
5447 break;
5448 default:
5449 goto cp0_unimplemented;
5451 break;
5452 case 8:
5453 switch (sel) {
5454 case 0:
5455 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5456 tcg_gen_ext32s_tl(arg, arg);
5457 rn = "BadVAddr";
5458 break;
5459 case 1:
5460 CP0_CHECK(ctx->bi);
5461 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5462 rn = "BadInstr";
5463 break;
5464 case 2:
5465 CP0_CHECK(ctx->bp);
5466 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5467 rn = "BadInstrP";
5468 break;
5469 default:
5470 goto cp0_unimplemented;
5472 break;
5473 case 9:
5474 switch (sel) {
5475 case 0:
5476 /* Mark as an IO operation because we read the time. */
5477 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5478 gen_io_start();
5480 gen_helper_mfc0_count(arg, cpu_env);
5481 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5482 gen_io_end();
5484 /* Break the TB to be able to take timer interrupts immediately
5485 after reading count. */
5486 ctx->bstate = BS_STOP;
5487 rn = "Count";
5488 break;
5489 /* 6,7 are implementation dependent */
5490 default:
5491 goto cp0_unimplemented;
5493 break;
5494 case 10:
5495 switch (sel) {
5496 case 0:
5497 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5498 tcg_gen_ext32s_tl(arg, arg);
5499 rn = "EntryHi";
5500 break;
5501 default:
5502 goto cp0_unimplemented;
5504 break;
5505 case 11:
5506 switch (sel) {
5507 case 0:
5508 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5509 rn = "Compare";
5510 break;
5511 /* 6,7 are implementation dependent */
5512 default:
5513 goto cp0_unimplemented;
5515 break;
5516 case 12:
5517 switch (sel) {
5518 case 0:
5519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5520 rn = "Status";
5521 break;
5522 case 1:
5523 check_insn(ctx, ISA_MIPS32R2);
5524 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5525 rn = "IntCtl";
5526 break;
5527 case 2:
5528 check_insn(ctx, ISA_MIPS32R2);
5529 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5530 rn = "SRSCtl";
5531 break;
5532 case 3:
5533 check_insn(ctx, ISA_MIPS32R2);
5534 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5535 rn = "SRSMap";
5536 break;
5537 default:
5538 goto cp0_unimplemented;
5540 break;
5541 case 13:
5542 switch (sel) {
5543 case 0:
5544 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5545 rn = "Cause";
5546 break;
5547 default:
5548 goto cp0_unimplemented;
5550 break;
5551 case 14:
5552 switch (sel) {
5553 case 0:
5554 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5555 tcg_gen_ext32s_tl(arg, arg);
5556 rn = "EPC";
5557 break;
5558 default:
5559 goto cp0_unimplemented;
5561 break;
5562 case 15:
5563 switch (sel) {
5564 case 0:
5565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5566 rn = "PRid";
5567 break;
5568 case 1:
5569 check_insn(ctx, ISA_MIPS32R2);
5570 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5571 rn = "EBase";
5572 break;
5573 default:
5574 goto cp0_unimplemented;
5576 break;
5577 case 16:
5578 switch (sel) {
5579 case 0:
5580 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5581 rn = "Config";
5582 break;
5583 case 1:
5584 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5585 rn = "Config1";
5586 break;
5587 case 2:
5588 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5589 rn = "Config2";
5590 break;
5591 case 3:
5592 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5593 rn = "Config3";
5594 break;
5595 case 4:
5596 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5597 rn = "Config4";
5598 break;
5599 case 5:
5600 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5601 rn = "Config5";
5602 break;
5603 /* 6,7 are implementation dependent */
5604 case 6:
5605 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5606 rn = "Config6";
5607 break;
5608 case 7:
5609 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5610 rn = "Config7";
5611 break;
5612 default:
5613 goto cp0_unimplemented;
5615 break;
5616 case 17:
5617 switch (sel) {
5618 case 0:
5619 gen_helper_mfc0_lladdr(arg, cpu_env);
5620 rn = "LLAddr";
5621 break;
5622 default:
5623 goto cp0_unimplemented;
5625 break;
5626 case 18:
5627 switch (sel) {
5628 case 0 ... 7:
5629 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5630 rn = "WatchLo";
5631 break;
5632 default:
5633 goto cp0_unimplemented;
5635 break;
5636 case 19:
5637 switch (sel) {
5638 case 0 ...7:
5639 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5640 rn = "WatchHi";
5641 break;
5642 default:
5643 goto cp0_unimplemented;
5645 break;
5646 case 20:
5647 switch (sel) {
5648 case 0:
5649 #if defined(TARGET_MIPS64)
5650 check_insn(ctx, ISA_MIPS3);
5651 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5652 tcg_gen_ext32s_tl(arg, arg);
5653 rn = "XContext";
5654 break;
5655 #endif
5656 default:
5657 goto cp0_unimplemented;
5659 break;
5660 case 21:
5661 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5662 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5663 switch (sel) {
5664 case 0:
5665 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5666 rn = "Framemask";
5667 break;
5668 default:
5669 goto cp0_unimplemented;
5671 break;
5672 case 22:
5673 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5674 rn = "'Diagnostic"; /* implementation dependent */
5675 break;
5676 case 23:
5677 switch (sel) {
5678 case 0:
5679 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5680 rn = "Debug";
5681 break;
5682 case 1:
5683 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5684 rn = "TraceControl";
5685 // break;
5686 case 2:
5687 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5688 rn = "TraceControl2";
5689 // break;
5690 case 3:
5691 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5692 rn = "UserTraceData";
5693 // break;
5694 case 4:
5695 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5696 rn = "TraceBPC";
5697 // break;
5698 default:
5699 goto cp0_unimplemented;
5701 break;
5702 case 24:
5703 switch (sel) {
5704 case 0:
5705 /* EJTAG support */
5706 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5707 tcg_gen_ext32s_tl(arg, arg);
5708 rn = "DEPC";
5709 break;
5710 default:
5711 goto cp0_unimplemented;
5713 break;
5714 case 25:
5715 switch (sel) {
5716 case 0:
5717 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5718 rn = "Performance0";
5719 break;
5720 case 1:
5721 // gen_helper_mfc0_performance1(arg);
5722 rn = "Performance1";
5723 // break;
5724 case 2:
5725 // gen_helper_mfc0_performance2(arg);
5726 rn = "Performance2";
5727 // break;
5728 case 3:
5729 // gen_helper_mfc0_performance3(arg);
5730 rn = "Performance3";
5731 // break;
5732 case 4:
5733 // gen_helper_mfc0_performance4(arg);
5734 rn = "Performance4";
5735 // break;
5736 case 5:
5737 // gen_helper_mfc0_performance5(arg);
5738 rn = "Performance5";
5739 // break;
5740 case 6:
5741 // gen_helper_mfc0_performance6(arg);
5742 rn = "Performance6";
5743 // break;
5744 case 7:
5745 // gen_helper_mfc0_performance7(arg);
5746 rn = "Performance7";
5747 // break;
5748 default:
5749 goto cp0_unimplemented;
5751 break;
5752 case 26:
5753 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5754 rn = "ECC";
5755 break;
5756 case 27:
5757 switch (sel) {
5758 case 0 ... 3:
5759 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5760 rn = "CacheErr";
5761 break;
5762 default:
5763 goto cp0_unimplemented;
5765 break;
5766 case 28:
5767 switch (sel) {
5768 case 0:
5769 case 2:
5770 case 4:
5771 case 6:
5773 TCGv_i64 tmp = tcg_temp_new_i64();
5774 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5775 gen_move_low32(arg, tmp);
5776 tcg_temp_free_i64(tmp);
5778 rn = "TagLo";
5779 break;
5780 case 1:
5781 case 3:
5782 case 5:
5783 case 7:
5784 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5785 rn = "DataLo";
5786 break;
5787 default:
5788 goto cp0_unimplemented;
5790 break;
5791 case 29:
5792 switch (sel) {
5793 case 0:
5794 case 2:
5795 case 4:
5796 case 6:
5797 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5798 rn = "TagHi";
5799 break;
5800 case 1:
5801 case 3:
5802 case 5:
5803 case 7:
5804 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5805 rn = "DataHi";
5806 break;
5807 default:
5808 goto cp0_unimplemented;
5810 break;
5811 case 30:
5812 switch (sel) {
5813 case 0:
5814 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5815 tcg_gen_ext32s_tl(arg, arg);
5816 rn = "ErrorEPC";
5817 break;
5818 default:
5819 goto cp0_unimplemented;
5821 break;
5822 case 31:
5823 switch (sel) {
5824 case 0:
5825 /* EJTAG support */
5826 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5827 rn = "DESAVE";
5828 break;
5829 case 2 ... 7:
5830 CP0_CHECK(ctx->kscrexist & (1 << sel));
5831 tcg_gen_ld_tl(arg, cpu_env,
5832 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5833 tcg_gen_ext32s_tl(arg, arg);
5834 rn = "KScratch";
5835 break;
5836 default:
5837 goto cp0_unimplemented;
5839 break;
5840 default:
5841 goto cp0_unimplemented;
5843 (void)rn; /* avoid a compiler warning */
5844 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5845 return;
5847 cp0_unimplemented:
5848 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5849 gen_mfc0_unimplemented(ctx, arg);
5852 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5854 const char *rn = "invalid";
5856 if (sel != 0)
5857 check_insn(ctx, ISA_MIPS32);
5859 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5860 gen_io_start();
5863 switch (reg) {
5864 case 0:
5865 switch (sel) {
5866 case 0:
5867 gen_helper_mtc0_index(cpu_env, arg);
5868 rn = "Index";
5869 break;
5870 case 1:
5871 CP0_CHECK(ctx->insn_flags & ASE_MT);
5872 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5873 rn = "MVPControl";
5874 break;
5875 case 2:
5876 CP0_CHECK(ctx->insn_flags & ASE_MT);
5877 /* ignored */
5878 rn = "MVPConf0";
5879 break;
5880 case 3:
5881 CP0_CHECK(ctx->insn_flags & ASE_MT);
5882 /* ignored */
5883 rn = "MVPConf1";
5884 break;
5885 default:
5886 goto cp0_unimplemented;
5888 break;
5889 case 1:
5890 switch (sel) {
5891 case 0:
5892 /* ignored */
5893 rn = "Random";
5894 break;
5895 case 1:
5896 CP0_CHECK(ctx->insn_flags & ASE_MT);
5897 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5898 rn = "VPEControl";
5899 break;
5900 case 2:
5901 CP0_CHECK(ctx->insn_flags & ASE_MT);
5902 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5903 rn = "VPEConf0";
5904 break;
5905 case 3:
5906 CP0_CHECK(ctx->insn_flags & ASE_MT);
5907 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5908 rn = "VPEConf1";
5909 break;
5910 case 4:
5911 CP0_CHECK(ctx->insn_flags & ASE_MT);
5912 gen_helper_mtc0_yqmask(cpu_env, arg);
5913 rn = "YQMask";
5914 break;
5915 case 5:
5916 CP0_CHECK(ctx->insn_flags & ASE_MT);
5917 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5918 rn = "VPESchedule";
5919 break;
5920 case 6:
5921 CP0_CHECK(ctx->insn_flags & ASE_MT);
5922 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5923 rn = "VPEScheFBack";
5924 break;
5925 case 7:
5926 CP0_CHECK(ctx->insn_flags & ASE_MT);
5927 gen_helper_mtc0_vpeopt(cpu_env, arg);
5928 rn = "VPEOpt";
5929 break;
5930 default:
5931 goto cp0_unimplemented;
5933 break;
5934 case 2:
5935 switch (sel) {
5936 case 0:
5937 gen_helper_mtc0_entrylo0(cpu_env, arg);
5938 rn = "EntryLo0";
5939 break;
5940 case 1:
5941 CP0_CHECK(ctx->insn_flags & ASE_MT);
5942 gen_helper_mtc0_tcstatus(cpu_env, arg);
5943 rn = "TCStatus";
5944 break;
5945 case 2:
5946 CP0_CHECK(ctx->insn_flags & ASE_MT);
5947 gen_helper_mtc0_tcbind(cpu_env, arg);
5948 rn = "TCBind";
5949 break;
5950 case 3:
5951 CP0_CHECK(ctx->insn_flags & ASE_MT);
5952 gen_helper_mtc0_tcrestart(cpu_env, arg);
5953 rn = "TCRestart";
5954 break;
5955 case 4:
5956 CP0_CHECK(ctx->insn_flags & ASE_MT);
5957 gen_helper_mtc0_tchalt(cpu_env, arg);
5958 rn = "TCHalt";
5959 break;
5960 case 5:
5961 CP0_CHECK(ctx->insn_flags & ASE_MT);
5962 gen_helper_mtc0_tccontext(cpu_env, arg);
5963 rn = "TCContext";
5964 break;
5965 case 6:
5966 CP0_CHECK(ctx->insn_flags & ASE_MT);
5967 gen_helper_mtc0_tcschedule(cpu_env, arg);
5968 rn = "TCSchedule";
5969 break;
5970 case 7:
5971 CP0_CHECK(ctx->insn_flags & ASE_MT);
5972 gen_helper_mtc0_tcschefback(cpu_env, arg);
5973 rn = "TCScheFBack";
5974 break;
5975 default:
5976 goto cp0_unimplemented;
5978 break;
5979 case 3:
5980 switch (sel) {
5981 case 0:
5982 gen_helper_mtc0_entrylo1(cpu_env, arg);
5983 rn = "EntryLo1";
5984 break;
5985 default:
5986 goto cp0_unimplemented;
5988 break;
5989 case 4:
5990 switch (sel) {
5991 case 0:
5992 gen_helper_mtc0_context(cpu_env, arg);
5993 rn = "Context";
5994 break;
5995 case 1:
5996 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5997 rn = "ContextConfig";
5998 goto cp0_unimplemented;
5999 // break;
6000 case 2:
6001 CP0_CHECK(ctx->ulri);
6002 tcg_gen_st_tl(arg, cpu_env,
6003 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6004 rn = "UserLocal";
6005 break;
6006 default:
6007 goto cp0_unimplemented;
6009 break;
6010 case 5:
6011 switch (sel) {
6012 case 0:
6013 gen_helper_mtc0_pagemask(cpu_env, arg);
6014 rn = "PageMask";
6015 break;
6016 case 1:
6017 check_insn(ctx, ISA_MIPS32R2);
6018 gen_helper_mtc0_pagegrain(cpu_env, arg);
6019 rn = "PageGrain";
6020 ctx->bstate = BS_STOP;
6021 break;
6022 default:
6023 goto cp0_unimplemented;
6025 break;
6026 case 6:
6027 switch (sel) {
6028 case 0:
6029 gen_helper_mtc0_wired(cpu_env, arg);
6030 rn = "Wired";
6031 break;
6032 case 1:
6033 check_insn(ctx, ISA_MIPS32R2);
6034 gen_helper_mtc0_srsconf0(cpu_env, arg);
6035 rn = "SRSConf0";
6036 break;
6037 case 2:
6038 check_insn(ctx, ISA_MIPS32R2);
6039 gen_helper_mtc0_srsconf1(cpu_env, arg);
6040 rn = "SRSConf1";
6041 break;
6042 case 3:
6043 check_insn(ctx, ISA_MIPS32R2);
6044 gen_helper_mtc0_srsconf2(cpu_env, arg);
6045 rn = "SRSConf2";
6046 break;
6047 case 4:
6048 check_insn(ctx, ISA_MIPS32R2);
6049 gen_helper_mtc0_srsconf3(cpu_env, arg);
6050 rn = "SRSConf3";
6051 break;
6052 case 5:
6053 check_insn(ctx, ISA_MIPS32R2);
6054 gen_helper_mtc0_srsconf4(cpu_env, arg);
6055 rn = "SRSConf4";
6056 break;
6057 default:
6058 goto cp0_unimplemented;
6060 break;
6061 case 7:
6062 switch (sel) {
6063 case 0:
6064 check_insn(ctx, ISA_MIPS32R2);
6065 gen_helper_mtc0_hwrena(cpu_env, arg);
6066 ctx->bstate = BS_STOP;
6067 rn = "HWREna";
6068 break;
6069 default:
6070 goto cp0_unimplemented;
6072 break;
6073 case 8:
6074 switch (sel) {
6075 case 0:
6076 /* ignored */
6077 rn = "BadVAddr";
6078 break;
6079 case 1:
6080 /* ignored */
6081 rn = "BadInstr";
6082 break;
6083 case 2:
6084 /* ignored */
6085 rn = "BadInstrP";
6086 break;
6087 default:
6088 goto cp0_unimplemented;
6090 break;
6091 case 9:
6092 switch (sel) {
6093 case 0:
6094 gen_helper_mtc0_count(cpu_env, arg);
6095 rn = "Count";
6096 break;
6097 /* 6,7 are implementation dependent */
6098 default:
6099 goto cp0_unimplemented;
6101 break;
6102 case 10:
6103 switch (sel) {
6104 case 0:
6105 gen_helper_mtc0_entryhi(cpu_env, arg);
6106 rn = "EntryHi";
6107 break;
6108 default:
6109 goto cp0_unimplemented;
6111 break;
6112 case 11:
6113 switch (sel) {
6114 case 0:
6115 gen_helper_mtc0_compare(cpu_env, arg);
6116 rn = "Compare";
6117 break;
6118 /* 6,7 are implementation dependent */
6119 default:
6120 goto cp0_unimplemented;
6122 break;
6123 case 12:
6124 switch (sel) {
6125 case 0:
6126 save_cpu_state(ctx, 1);
6127 gen_helper_mtc0_status(cpu_env, arg);
6128 /* BS_STOP isn't good enough here, hflags may have changed. */
6129 gen_save_pc(ctx->pc + 4);
6130 ctx->bstate = BS_EXCP;
6131 rn = "Status";
6132 break;
6133 case 1:
6134 check_insn(ctx, ISA_MIPS32R2);
6135 gen_helper_mtc0_intctl(cpu_env, arg);
6136 /* Stop translation as we may have switched the execution mode */
6137 ctx->bstate = BS_STOP;
6138 rn = "IntCtl";
6139 break;
6140 case 2:
6141 check_insn(ctx, ISA_MIPS32R2);
6142 gen_helper_mtc0_srsctl(cpu_env, arg);
6143 /* Stop translation as we may have switched the execution mode */
6144 ctx->bstate = BS_STOP;
6145 rn = "SRSCtl";
6146 break;
6147 case 3:
6148 check_insn(ctx, ISA_MIPS32R2);
6149 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6150 /* Stop translation as we may have switched the execution mode */
6151 ctx->bstate = BS_STOP;
6152 rn = "SRSMap";
6153 break;
6154 default:
6155 goto cp0_unimplemented;
6157 break;
6158 case 13:
6159 switch (sel) {
6160 case 0:
6161 save_cpu_state(ctx, 1);
6162 gen_helper_mtc0_cause(cpu_env, arg);
6163 rn = "Cause";
6164 break;
6165 default:
6166 goto cp0_unimplemented;
6168 break;
6169 case 14:
6170 switch (sel) {
6171 case 0:
6172 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
6173 rn = "EPC";
6174 break;
6175 default:
6176 goto cp0_unimplemented;
6178 break;
6179 case 15:
6180 switch (sel) {
6181 case 0:
6182 /* ignored */
6183 rn = "PRid";
6184 break;
6185 case 1:
6186 check_insn(ctx, ISA_MIPS32R2);
6187 gen_helper_mtc0_ebase(cpu_env, arg);
6188 rn = "EBase";
6189 break;
6190 default:
6191 goto cp0_unimplemented;
6193 break;
6194 case 16:
6195 switch (sel) {
6196 case 0:
6197 gen_helper_mtc0_config0(cpu_env, arg);
6198 rn = "Config";
6199 /* Stop translation as we may have switched the execution mode */
6200 ctx->bstate = BS_STOP;
6201 break;
6202 case 1:
6203 /* ignored, read only */
6204 rn = "Config1";
6205 break;
6206 case 2:
6207 gen_helper_mtc0_config2(cpu_env, arg);
6208 rn = "Config2";
6209 /* Stop translation as we may have switched the execution mode */
6210 ctx->bstate = BS_STOP;
6211 break;
6212 case 3:
6213 gen_helper_mtc0_config3(cpu_env, arg);
6214 rn = "Config3";
6215 /* Stop translation as we may have switched the execution mode */
6216 ctx->bstate = BS_STOP;
6217 break;
6218 case 4:
6219 gen_helper_mtc0_config4(cpu_env, arg);
6220 rn = "Config4";
6221 ctx->bstate = BS_STOP;
6222 break;
6223 case 5:
6224 gen_helper_mtc0_config5(cpu_env, arg);
6225 rn = "Config5";
6226 /* Stop translation as we may have switched the execution mode */
6227 ctx->bstate = BS_STOP;
6228 break;
6229 /* 6,7 are implementation dependent */
6230 case 6:
6231 /* ignored */
6232 rn = "Config6";
6233 break;
6234 case 7:
6235 /* ignored */
6236 rn = "Config7";
6237 break;
6238 default:
6239 rn = "Invalid config selector";
6240 goto cp0_unimplemented;
6242 break;
6243 case 17:
6244 switch (sel) {
6245 case 0:
6246 gen_helper_mtc0_lladdr(cpu_env, arg);
6247 rn = "LLAddr";
6248 break;
6249 default:
6250 goto cp0_unimplemented;
6252 break;
6253 case 18:
6254 switch (sel) {
6255 case 0 ... 7:
6256 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6257 rn = "WatchLo";
6258 break;
6259 default:
6260 goto cp0_unimplemented;
6262 break;
6263 case 19:
6264 switch (sel) {
6265 case 0 ... 7:
6266 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6267 rn = "WatchHi";
6268 break;
6269 default:
6270 goto cp0_unimplemented;
6272 break;
6273 case 20:
6274 switch (sel) {
6275 case 0:
6276 #if defined(TARGET_MIPS64)
6277 check_insn(ctx, ISA_MIPS3);
6278 gen_helper_mtc0_xcontext(cpu_env, arg);
6279 rn = "XContext";
6280 break;
6281 #endif
6282 default:
6283 goto cp0_unimplemented;
6285 break;
6286 case 21:
6287 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6288 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6289 switch (sel) {
6290 case 0:
6291 gen_helper_mtc0_framemask(cpu_env, arg);
6292 rn = "Framemask";
6293 break;
6294 default:
6295 goto cp0_unimplemented;
6297 break;
6298 case 22:
6299 /* ignored */
6300 rn = "Diagnostic"; /* implementation dependent */
6301 break;
6302 case 23:
6303 switch (sel) {
6304 case 0:
6305 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6306 /* BS_STOP isn't good enough here, hflags may have changed. */
6307 gen_save_pc(ctx->pc + 4);
6308 ctx->bstate = BS_EXCP;
6309 rn = "Debug";
6310 break;
6311 case 1:
6312 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6313 rn = "TraceControl";
6314 /* Stop translation as we may have switched the execution mode */
6315 ctx->bstate = BS_STOP;
6316 // break;
6317 case 2:
6318 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6319 rn = "TraceControl2";
6320 /* Stop translation as we may have switched the execution mode */
6321 ctx->bstate = BS_STOP;
6322 // break;
6323 case 3:
6324 /* Stop translation as we may have switched the execution mode */
6325 ctx->bstate = BS_STOP;
6326 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6327 rn = "UserTraceData";
6328 /* Stop translation as we may have switched the execution mode */
6329 ctx->bstate = BS_STOP;
6330 // break;
6331 case 4:
6332 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6333 /* Stop translation as we may have switched the execution mode */
6334 ctx->bstate = BS_STOP;
6335 rn = "TraceBPC";
6336 // break;
6337 default:
6338 goto cp0_unimplemented;
6340 break;
6341 case 24:
6342 switch (sel) {
6343 case 0:
6344 /* EJTAG support */
6345 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
6346 rn = "DEPC";
6347 break;
6348 default:
6349 goto cp0_unimplemented;
6351 break;
6352 case 25:
6353 switch (sel) {
6354 case 0:
6355 gen_helper_mtc0_performance0(cpu_env, arg);
6356 rn = "Performance0";
6357 break;
6358 case 1:
6359 // gen_helper_mtc0_performance1(arg);
6360 rn = "Performance1";
6361 // break;
6362 case 2:
6363 // gen_helper_mtc0_performance2(arg);
6364 rn = "Performance2";
6365 // break;
6366 case 3:
6367 // gen_helper_mtc0_performance3(arg);
6368 rn = "Performance3";
6369 // break;
6370 case 4:
6371 // gen_helper_mtc0_performance4(arg);
6372 rn = "Performance4";
6373 // break;
6374 case 5:
6375 // gen_helper_mtc0_performance5(arg);
6376 rn = "Performance5";
6377 // break;
6378 case 6:
6379 // gen_helper_mtc0_performance6(arg);
6380 rn = "Performance6";
6381 // break;
6382 case 7:
6383 // gen_helper_mtc0_performance7(arg);
6384 rn = "Performance7";
6385 // break;
6386 default:
6387 goto cp0_unimplemented;
6389 break;
6390 case 26:
6391 /* ignored */
6392 rn = "ECC";
6393 break;
6394 case 27:
6395 switch (sel) {
6396 case 0 ... 3:
6397 /* ignored */
6398 rn = "CacheErr";
6399 break;
6400 default:
6401 goto cp0_unimplemented;
6403 break;
6404 case 28:
6405 switch (sel) {
6406 case 0:
6407 case 2:
6408 case 4:
6409 case 6:
6410 gen_helper_mtc0_taglo(cpu_env, arg);
6411 rn = "TagLo";
6412 break;
6413 case 1:
6414 case 3:
6415 case 5:
6416 case 7:
6417 gen_helper_mtc0_datalo(cpu_env, arg);
6418 rn = "DataLo";
6419 break;
6420 default:
6421 goto cp0_unimplemented;
6423 break;
6424 case 29:
6425 switch (sel) {
6426 case 0:
6427 case 2:
6428 case 4:
6429 case 6:
6430 gen_helper_mtc0_taghi(cpu_env, arg);
6431 rn = "TagHi";
6432 break;
6433 case 1:
6434 case 3:
6435 case 5:
6436 case 7:
6437 gen_helper_mtc0_datahi(cpu_env, arg);
6438 rn = "DataHi";
6439 break;
6440 default:
6441 rn = "invalid sel";
6442 goto cp0_unimplemented;
6444 break;
6445 case 30:
6446 switch (sel) {
6447 case 0:
6448 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
6449 rn = "ErrorEPC";
6450 break;
6451 default:
6452 goto cp0_unimplemented;
6454 break;
6455 case 31:
6456 switch (sel) {
6457 case 0:
6458 /* EJTAG support */
6459 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6460 rn = "DESAVE";
6461 break;
6462 case 2 ... 7:
6463 CP0_CHECK(ctx->kscrexist & (1 << sel));
6464 tcg_gen_st_tl(arg, cpu_env,
6465 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6466 rn = "KScratch";
6467 break;
6468 default:
6469 goto cp0_unimplemented;
6471 /* Stop translation as we may have switched the execution mode */
6472 ctx->bstate = BS_STOP;
6473 break;
6474 default:
6475 goto cp0_unimplemented;
6477 (void)rn; /* avoid a compiler warning */
6478 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6479 /* For simplicity assume that all writes can cause interrupts. */
6480 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6481 gen_io_end();
6482 ctx->bstate = BS_STOP;
6484 return;
6486 cp0_unimplemented:
6487 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6490 #if defined(TARGET_MIPS64)
6491 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6493 const char *rn = "invalid";
6495 if (sel != 0)
6496 check_insn(ctx, ISA_MIPS64);
6498 switch (reg) {
6499 case 0:
6500 switch (sel) {
6501 case 0:
6502 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6503 rn = "Index";
6504 break;
6505 case 1:
6506 CP0_CHECK(ctx->insn_flags & ASE_MT);
6507 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6508 rn = "MVPControl";
6509 break;
6510 case 2:
6511 CP0_CHECK(ctx->insn_flags & ASE_MT);
6512 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6513 rn = "MVPConf0";
6514 break;
6515 case 3:
6516 CP0_CHECK(ctx->insn_flags & ASE_MT);
6517 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6518 rn = "MVPConf1";
6519 break;
6520 default:
6521 goto cp0_unimplemented;
6523 break;
6524 case 1:
6525 switch (sel) {
6526 case 0:
6527 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6528 gen_helper_mfc0_random(arg, cpu_env);
6529 rn = "Random";
6530 break;
6531 case 1:
6532 CP0_CHECK(ctx->insn_flags & ASE_MT);
6533 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6534 rn = "VPEControl";
6535 break;
6536 case 2:
6537 CP0_CHECK(ctx->insn_flags & ASE_MT);
6538 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6539 rn = "VPEConf0";
6540 break;
6541 case 3:
6542 CP0_CHECK(ctx->insn_flags & ASE_MT);
6543 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6544 rn = "VPEConf1";
6545 break;
6546 case 4:
6547 CP0_CHECK(ctx->insn_flags & ASE_MT);
6548 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6549 rn = "YQMask";
6550 break;
6551 case 5:
6552 CP0_CHECK(ctx->insn_flags & ASE_MT);
6553 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6554 rn = "VPESchedule";
6555 break;
6556 case 6:
6557 CP0_CHECK(ctx->insn_flags & ASE_MT);
6558 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6559 rn = "VPEScheFBack";
6560 break;
6561 case 7:
6562 CP0_CHECK(ctx->insn_flags & ASE_MT);
6563 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6564 rn = "VPEOpt";
6565 break;
6566 default:
6567 goto cp0_unimplemented;
6569 break;
6570 case 2:
6571 switch (sel) {
6572 case 0:
6573 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6574 rn = "EntryLo0";
6575 break;
6576 case 1:
6577 CP0_CHECK(ctx->insn_flags & ASE_MT);
6578 gen_helper_mfc0_tcstatus(arg, cpu_env);
6579 rn = "TCStatus";
6580 break;
6581 case 2:
6582 CP0_CHECK(ctx->insn_flags & ASE_MT);
6583 gen_helper_mfc0_tcbind(arg, cpu_env);
6584 rn = "TCBind";
6585 break;
6586 case 3:
6587 CP0_CHECK(ctx->insn_flags & ASE_MT);
6588 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6589 rn = "TCRestart";
6590 break;
6591 case 4:
6592 CP0_CHECK(ctx->insn_flags & ASE_MT);
6593 gen_helper_dmfc0_tchalt(arg, cpu_env);
6594 rn = "TCHalt";
6595 break;
6596 case 5:
6597 CP0_CHECK(ctx->insn_flags & ASE_MT);
6598 gen_helper_dmfc0_tccontext(arg, cpu_env);
6599 rn = "TCContext";
6600 break;
6601 case 6:
6602 CP0_CHECK(ctx->insn_flags & ASE_MT);
6603 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6604 rn = "TCSchedule";
6605 break;
6606 case 7:
6607 CP0_CHECK(ctx->insn_flags & ASE_MT);
6608 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6609 rn = "TCScheFBack";
6610 break;
6611 default:
6612 goto cp0_unimplemented;
6614 break;
6615 case 3:
6616 switch (sel) {
6617 case 0:
6618 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6619 rn = "EntryLo1";
6620 break;
6621 default:
6622 goto cp0_unimplemented;
6624 break;
6625 case 4:
6626 switch (sel) {
6627 case 0:
6628 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6629 rn = "Context";
6630 break;
6631 case 1:
6632 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6633 rn = "ContextConfig";
6634 goto cp0_unimplemented;
6635 // break;
6636 case 2:
6637 CP0_CHECK(ctx->ulri);
6638 tcg_gen_ld_tl(arg, cpu_env,
6639 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6640 rn = "UserLocal";
6641 break;
6642 default:
6643 goto cp0_unimplemented;
6645 break;
6646 case 5:
6647 switch (sel) {
6648 case 0:
6649 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6650 rn = "PageMask";
6651 break;
6652 case 1:
6653 check_insn(ctx, ISA_MIPS32R2);
6654 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6655 rn = "PageGrain";
6656 break;
6657 default:
6658 goto cp0_unimplemented;
6660 break;
6661 case 6:
6662 switch (sel) {
6663 case 0:
6664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6665 rn = "Wired";
6666 break;
6667 case 1:
6668 check_insn(ctx, ISA_MIPS32R2);
6669 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6670 rn = "SRSConf0";
6671 break;
6672 case 2:
6673 check_insn(ctx, ISA_MIPS32R2);
6674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6675 rn = "SRSConf1";
6676 break;
6677 case 3:
6678 check_insn(ctx, ISA_MIPS32R2);
6679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6680 rn = "SRSConf2";
6681 break;
6682 case 4:
6683 check_insn(ctx, ISA_MIPS32R2);
6684 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6685 rn = "SRSConf3";
6686 break;
6687 case 5:
6688 check_insn(ctx, ISA_MIPS32R2);
6689 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6690 rn = "SRSConf4";
6691 break;
6692 default:
6693 goto cp0_unimplemented;
6695 break;
6696 case 7:
6697 switch (sel) {
6698 case 0:
6699 check_insn(ctx, ISA_MIPS32R2);
6700 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6701 rn = "HWREna";
6702 break;
6703 default:
6704 goto cp0_unimplemented;
6706 break;
6707 case 8:
6708 switch (sel) {
6709 case 0:
6710 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6711 rn = "BadVAddr";
6712 break;
6713 case 1:
6714 CP0_CHECK(ctx->bi);
6715 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6716 rn = "BadInstr";
6717 break;
6718 case 2:
6719 CP0_CHECK(ctx->bp);
6720 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6721 rn = "BadInstrP";
6722 break;
6723 default:
6724 goto cp0_unimplemented;
6726 break;
6727 case 9:
6728 switch (sel) {
6729 case 0:
6730 /* Mark as an IO operation because we read the time. */
6731 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6732 gen_io_start();
6734 gen_helper_mfc0_count(arg, cpu_env);
6735 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6736 gen_io_end();
6738 /* Break the TB to be able to take timer interrupts immediately
6739 after reading count. */
6740 ctx->bstate = BS_STOP;
6741 rn = "Count";
6742 break;
6743 /* 6,7 are implementation dependent */
6744 default:
6745 goto cp0_unimplemented;
6747 break;
6748 case 10:
6749 switch (sel) {
6750 case 0:
6751 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6752 rn = "EntryHi";
6753 break;
6754 default:
6755 goto cp0_unimplemented;
6757 break;
6758 case 11:
6759 switch (sel) {
6760 case 0:
6761 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6762 rn = "Compare";
6763 break;
6764 /* 6,7 are implementation dependent */
6765 default:
6766 goto cp0_unimplemented;
6768 break;
6769 case 12:
6770 switch (sel) {
6771 case 0:
6772 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6773 rn = "Status";
6774 break;
6775 case 1:
6776 check_insn(ctx, ISA_MIPS32R2);
6777 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6778 rn = "IntCtl";
6779 break;
6780 case 2:
6781 check_insn(ctx, ISA_MIPS32R2);
6782 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6783 rn = "SRSCtl";
6784 break;
6785 case 3:
6786 check_insn(ctx, ISA_MIPS32R2);
6787 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6788 rn = "SRSMap";
6789 break;
6790 default:
6791 goto cp0_unimplemented;
6793 break;
6794 case 13:
6795 switch (sel) {
6796 case 0:
6797 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6798 rn = "Cause";
6799 break;
6800 default:
6801 goto cp0_unimplemented;
6803 break;
6804 case 14:
6805 switch (sel) {
6806 case 0:
6807 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6808 rn = "EPC";
6809 break;
6810 default:
6811 goto cp0_unimplemented;
6813 break;
6814 case 15:
6815 switch (sel) {
6816 case 0:
6817 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6818 rn = "PRid";
6819 break;
6820 case 1:
6821 check_insn(ctx, ISA_MIPS32R2);
6822 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6823 rn = "EBase";
6824 break;
6825 default:
6826 goto cp0_unimplemented;
6828 break;
6829 case 16:
6830 switch (sel) {
6831 case 0:
6832 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6833 rn = "Config";
6834 break;
6835 case 1:
6836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6837 rn = "Config1";
6838 break;
6839 case 2:
6840 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6841 rn = "Config2";
6842 break;
6843 case 3:
6844 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6845 rn = "Config3";
6846 break;
6847 case 4:
6848 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6849 rn = "Config4";
6850 break;
6851 case 5:
6852 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6853 rn = "Config5";
6854 break;
6855 /* 6,7 are implementation dependent */
6856 case 6:
6857 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6858 rn = "Config6";
6859 break;
6860 case 7:
6861 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6862 rn = "Config7";
6863 break;
6864 default:
6865 goto cp0_unimplemented;
6867 break;
6868 case 17:
6869 switch (sel) {
6870 case 0:
6871 gen_helper_dmfc0_lladdr(arg, cpu_env);
6872 rn = "LLAddr";
6873 break;
6874 default:
6875 goto cp0_unimplemented;
6877 break;
6878 case 18:
6879 switch (sel) {
6880 case 0 ... 7:
6881 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6882 rn = "WatchLo";
6883 break;
6884 default:
6885 goto cp0_unimplemented;
6887 break;
6888 case 19:
6889 switch (sel) {
6890 case 0 ... 7:
6891 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6892 rn = "WatchHi";
6893 break;
6894 default:
6895 goto cp0_unimplemented;
6897 break;
6898 case 20:
6899 switch (sel) {
6900 case 0:
6901 check_insn(ctx, ISA_MIPS3);
6902 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6903 rn = "XContext";
6904 break;
6905 default:
6906 goto cp0_unimplemented;
6908 break;
6909 case 21:
6910 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6911 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6912 switch (sel) {
6913 case 0:
6914 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6915 rn = "Framemask";
6916 break;
6917 default:
6918 goto cp0_unimplemented;
6920 break;
6921 case 22:
6922 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6923 rn = "'Diagnostic"; /* implementation dependent */
6924 break;
6925 case 23:
6926 switch (sel) {
6927 case 0:
6928 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6929 rn = "Debug";
6930 break;
6931 case 1:
6932 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6933 rn = "TraceControl";
6934 // break;
6935 case 2:
6936 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6937 rn = "TraceControl2";
6938 // break;
6939 case 3:
6940 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6941 rn = "UserTraceData";
6942 // break;
6943 case 4:
6944 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6945 rn = "TraceBPC";
6946 // break;
6947 default:
6948 goto cp0_unimplemented;
6950 break;
6951 case 24:
6952 switch (sel) {
6953 case 0:
6954 /* EJTAG support */
6955 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6956 rn = "DEPC";
6957 break;
6958 default:
6959 goto cp0_unimplemented;
6961 break;
6962 case 25:
6963 switch (sel) {
6964 case 0:
6965 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6966 rn = "Performance0";
6967 break;
6968 case 1:
6969 // gen_helper_dmfc0_performance1(arg);
6970 rn = "Performance1";
6971 // break;
6972 case 2:
6973 // gen_helper_dmfc0_performance2(arg);
6974 rn = "Performance2";
6975 // break;
6976 case 3:
6977 // gen_helper_dmfc0_performance3(arg);
6978 rn = "Performance3";
6979 // break;
6980 case 4:
6981 // gen_helper_dmfc0_performance4(arg);
6982 rn = "Performance4";
6983 // break;
6984 case 5:
6985 // gen_helper_dmfc0_performance5(arg);
6986 rn = "Performance5";
6987 // break;
6988 case 6:
6989 // gen_helper_dmfc0_performance6(arg);
6990 rn = "Performance6";
6991 // break;
6992 case 7:
6993 // gen_helper_dmfc0_performance7(arg);
6994 rn = "Performance7";
6995 // break;
6996 default:
6997 goto cp0_unimplemented;
6999 break;
7000 case 26:
7001 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7002 rn = "ECC";
7003 break;
7004 case 27:
7005 switch (sel) {
7006 /* ignored */
7007 case 0 ... 3:
7008 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7009 rn = "CacheErr";
7010 break;
7011 default:
7012 goto cp0_unimplemented;
7014 break;
7015 case 28:
7016 switch (sel) {
7017 case 0:
7018 case 2:
7019 case 4:
7020 case 6:
7021 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
7022 rn = "TagLo";
7023 break;
7024 case 1:
7025 case 3:
7026 case 5:
7027 case 7:
7028 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7029 rn = "DataLo";
7030 break;
7031 default:
7032 goto cp0_unimplemented;
7034 break;
7035 case 29:
7036 switch (sel) {
7037 case 0:
7038 case 2:
7039 case 4:
7040 case 6:
7041 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7042 rn = "TagHi";
7043 break;
7044 case 1:
7045 case 3:
7046 case 5:
7047 case 7:
7048 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7049 rn = "DataHi";
7050 break;
7051 default:
7052 goto cp0_unimplemented;
7054 break;
7055 case 30:
7056 switch (sel) {
7057 case 0:
7058 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7059 rn = "ErrorEPC";
7060 break;
7061 default:
7062 goto cp0_unimplemented;
7064 break;
7065 case 31:
7066 switch (sel) {
7067 case 0:
7068 /* EJTAG support */
7069 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7070 rn = "DESAVE";
7071 break;
7072 case 2 ... 7:
7073 CP0_CHECK(ctx->kscrexist & (1 << sel));
7074 tcg_gen_ld_tl(arg, cpu_env,
7075 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7076 rn = "KScratch";
7077 break;
7078 default:
7079 goto cp0_unimplemented;
7081 break;
7082 default:
7083 goto cp0_unimplemented;
7085 (void)rn; /* avoid a compiler warning */
7086 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7087 return;
7089 cp0_unimplemented:
7090 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7091 gen_mfc0_unimplemented(ctx, arg);
7094 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7096 const char *rn = "invalid";
7098 if (sel != 0)
7099 check_insn(ctx, ISA_MIPS64);
7101 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7102 gen_io_start();
7105 switch (reg) {
7106 case 0:
7107 switch (sel) {
7108 case 0:
7109 gen_helper_mtc0_index(cpu_env, arg);
7110 rn = "Index";
7111 break;
7112 case 1:
7113 CP0_CHECK(ctx->insn_flags & ASE_MT);
7114 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7115 rn = "MVPControl";
7116 break;
7117 case 2:
7118 CP0_CHECK(ctx->insn_flags & ASE_MT);
7119 /* ignored */
7120 rn = "MVPConf0";
7121 break;
7122 case 3:
7123 CP0_CHECK(ctx->insn_flags & ASE_MT);
7124 /* ignored */
7125 rn = "MVPConf1";
7126 break;
7127 default:
7128 goto cp0_unimplemented;
7130 break;
7131 case 1:
7132 switch (sel) {
7133 case 0:
7134 /* ignored */
7135 rn = "Random";
7136 break;
7137 case 1:
7138 CP0_CHECK(ctx->insn_flags & ASE_MT);
7139 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7140 rn = "VPEControl";
7141 break;
7142 case 2:
7143 CP0_CHECK(ctx->insn_flags & ASE_MT);
7144 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7145 rn = "VPEConf0";
7146 break;
7147 case 3:
7148 CP0_CHECK(ctx->insn_flags & ASE_MT);
7149 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7150 rn = "VPEConf1";
7151 break;
7152 case 4:
7153 CP0_CHECK(ctx->insn_flags & ASE_MT);
7154 gen_helper_mtc0_yqmask(cpu_env, arg);
7155 rn = "YQMask";
7156 break;
7157 case 5:
7158 CP0_CHECK(ctx->insn_flags & ASE_MT);
7159 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7160 rn = "VPESchedule";
7161 break;
7162 case 6:
7163 CP0_CHECK(ctx->insn_flags & ASE_MT);
7164 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7165 rn = "VPEScheFBack";
7166 break;
7167 case 7:
7168 CP0_CHECK(ctx->insn_flags & ASE_MT);
7169 gen_helper_mtc0_vpeopt(cpu_env, arg);
7170 rn = "VPEOpt";
7171 break;
7172 default:
7173 goto cp0_unimplemented;
7175 break;
7176 case 2:
7177 switch (sel) {
7178 case 0:
7179 gen_helper_dmtc0_entrylo0(cpu_env, arg);
7180 rn = "EntryLo0";
7181 break;
7182 case 1:
7183 CP0_CHECK(ctx->insn_flags & ASE_MT);
7184 gen_helper_mtc0_tcstatus(cpu_env, arg);
7185 rn = "TCStatus";
7186 break;
7187 case 2:
7188 CP0_CHECK(ctx->insn_flags & ASE_MT);
7189 gen_helper_mtc0_tcbind(cpu_env, arg);
7190 rn = "TCBind";
7191 break;
7192 case 3:
7193 CP0_CHECK(ctx->insn_flags & ASE_MT);
7194 gen_helper_mtc0_tcrestart(cpu_env, arg);
7195 rn = "TCRestart";
7196 break;
7197 case 4:
7198 CP0_CHECK(ctx->insn_flags & ASE_MT);
7199 gen_helper_mtc0_tchalt(cpu_env, arg);
7200 rn = "TCHalt";
7201 break;
7202 case 5:
7203 CP0_CHECK(ctx->insn_flags & ASE_MT);
7204 gen_helper_mtc0_tccontext(cpu_env, arg);
7205 rn = "TCContext";
7206 break;
7207 case 6:
7208 CP0_CHECK(ctx->insn_flags & ASE_MT);
7209 gen_helper_mtc0_tcschedule(cpu_env, arg);
7210 rn = "TCSchedule";
7211 break;
7212 case 7:
7213 CP0_CHECK(ctx->insn_flags & ASE_MT);
7214 gen_helper_mtc0_tcschefback(cpu_env, arg);
7215 rn = "TCScheFBack";
7216 break;
7217 default:
7218 goto cp0_unimplemented;
7220 break;
7221 case 3:
7222 switch (sel) {
7223 case 0:
7224 gen_helper_dmtc0_entrylo1(cpu_env, arg);
7225 rn = "EntryLo1";
7226 break;
7227 default:
7228 goto cp0_unimplemented;
7230 break;
7231 case 4:
7232 switch (sel) {
7233 case 0:
7234 gen_helper_mtc0_context(cpu_env, arg);
7235 rn = "Context";
7236 break;
7237 case 1:
7238 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7239 rn = "ContextConfig";
7240 goto cp0_unimplemented;
7241 // break;
7242 case 2:
7243 CP0_CHECK(ctx->ulri);
7244 tcg_gen_st_tl(arg, cpu_env,
7245 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7246 rn = "UserLocal";
7247 break;
7248 default:
7249 goto cp0_unimplemented;
7251 break;
7252 case 5:
7253 switch (sel) {
7254 case 0:
7255 gen_helper_mtc0_pagemask(cpu_env, arg);
7256 rn = "PageMask";
7257 break;
7258 case 1:
7259 check_insn(ctx, ISA_MIPS32R2);
7260 gen_helper_mtc0_pagegrain(cpu_env, arg);
7261 rn = "PageGrain";
7262 break;
7263 default:
7264 goto cp0_unimplemented;
7266 break;
7267 case 6:
7268 switch (sel) {
7269 case 0:
7270 gen_helper_mtc0_wired(cpu_env, arg);
7271 rn = "Wired";
7272 break;
7273 case 1:
7274 check_insn(ctx, ISA_MIPS32R2);
7275 gen_helper_mtc0_srsconf0(cpu_env, arg);
7276 rn = "SRSConf0";
7277 break;
7278 case 2:
7279 check_insn(ctx, ISA_MIPS32R2);
7280 gen_helper_mtc0_srsconf1(cpu_env, arg);
7281 rn = "SRSConf1";
7282 break;
7283 case 3:
7284 check_insn(ctx, ISA_MIPS32R2);
7285 gen_helper_mtc0_srsconf2(cpu_env, arg);
7286 rn = "SRSConf2";
7287 break;
7288 case 4:
7289 check_insn(ctx, ISA_MIPS32R2);
7290 gen_helper_mtc0_srsconf3(cpu_env, arg);
7291 rn = "SRSConf3";
7292 break;
7293 case 5:
7294 check_insn(ctx, ISA_MIPS32R2);
7295 gen_helper_mtc0_srsconf4(cpu_env, arg);
7296 rn = "SRSConf4";
7297 break;
7298 default:
7299 goto cp0_unimplemented;
7301 break;
7302 case 7:
7303 switch (sel) {
7304 case 0:
7305 check_insn(ctx, ISA_MIPS32R2);
7306 gen_helper_mtc0_hwrena(cpu_env, arg);
7307 ctx->bstate = BS_STOP;
7308 rn = "HWREna";
7309 break;
7310 default:
7311 goto cp0_unimplemented;
7313 break;
7314 case 8:
7315 switch (sel) {
7316 case 0:
7317 /* ignored */
7318 rn = "BadVAddr";
7319 break;
7320 case 1:
7321 /* ignored */
7322 rn = "BadInstr";
7323 break;
7324 case 2:
7325 /* ignored */
7326 rn = "BadInstrP";
7327 break;
7328 default:
7329 goto cp0_unimplemented;
7331 break;
7332 case 9:
7333 switch (sel) {
7334 case 0:
7335 gen_helper_mtc0_count(cpu_env, arg);
7336 rn = "Count";
7337 break;
7338 /* 6,7 are implementation dependent */
7339 default:
7340 goto cp0_unimplemented;
7342 /* Stop translation as we may have switched the execution mode */
7343 ctx->bstate = BS_STOP;
7344 break;
7345 case 10:
7346 switch (sel) {
7347 case 0:
7348 gen_helper_mtc0_entryhi(cpu_env, arg);
7349 rn = "EntryHi";
7350 break;
7351 default:
7352 goto cp0_unimplemented;
7354 break;
7355 case 11:
7356 switch (sel) {
7357 case 0:
7358 gen_helper_mtc0_compare(cpu_env, arg);
7359 rn = "Compare";
7360 break;
7361 /* 6,7 are implementation dependent */
7362 default:
7363 goto cp0_unimplemented;
7365 /* Stop translation as we may have switched the execution mode */
7366 ctx->bstate = BS_STOP;
7367 break;
7368 case 12:
7369 switch (sel) {
7370 case 0:
7371 save_cpu_state(ctx, 1);
7372 gen_helper_mtc0_status(cpu_env, arg);
7373 /* BS_STOP isn't good enough here, hflags may have changed. */
7374 gen_save_pc(ctx->pc + 4);
7375 ctx->bstate = BS_EXCP;
7376 rn = "Status";
7377 break;
7378 case 1:
7379 check_insn(ctx, ISA_MIPS32R2);
7380 gen_helper_mtc0_intctl(cpu_env, arg);
7381 /* Stop translation as we may have switched the execution mode */
7382 ctx->bstate = BS_STOP;
7383 rn = "IntCtl";
7384 break;
7385 case 2:
7386 check_insn(ctx, ISA_MIPS32R2);
7387 gen_helper_mtc0_srsctl(cpu_env, arg);
7388 /* Stop translation as we may have switched the execution mode */
7389 ctx->bstate = BS_STOP;
7390 rn = "SRSCtl";
7391 break;
7392 case 3:
7393 check_insn(ctx, ISA_MIPS32R2);
7394 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7395 /* Stop translation as we may have switched the execution mode */
7396 ctx->bstate = BS_STOP;
7397 rn = "SRSMap";
7398 break;
7399 default:
7400 goto cp0_unimplemented;
7402 break;
7403 case 13:
7404 switch (sel) {
7405 case 0:
7406 save_cpu_state(ctx, 1);
7407 /* Mark as an IO operation because we may trigger a software
7408 interrupt. */
7409 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7410 gen_io_start();
7412 gen_helper_mtc0_cause(cpu_env, arg);
7413 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7414 gen_io_end();
7416 /* Stop translation as we may have triggered an intetrupt */
7417 ctx->bstate = BS_STOP;
7418 rn = "Cause";
7419 break;
7420 default:
7421 goto cp0_unimplemented;
7423 break;
7424 case 14:
7425 switch (sel) {
7426 case 0:
7427 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7428 rn = "EPC";
7429 break;
7430 default:
7431 goto cp0_unimplemented;
7433 break;
7434 case 15:
7435 switch (sel) {
7436 case 0:
7437 /* ignored */
7438 rn = "PRid";
7439 break;
7440 case 1:
7441 check_insn(ctx, ISA_MIPS32R2);
7442 gen_helper_mtc0_ebase(cpu_env, arg);
7443 rn = "EBase";
7444 break;
7445 default:
7446 goto cp0_unimplemented;
7448 break;
7449 case 16:
7450 switch (sel) {
7451 case 0:
7452 gen_helper_mtc0_config0(cpu_env, arg);
7453 rn = "Config";
7454 /* Stop translation as we may have switched the execution mode */
7455 ctx->bstate = BS_STOP;
7456 break;
7457 case 1:
7458 /* ignored, read only */
7459 rn = "Config1";
7460 break;
7461 case 2:
7462 gen_helper_mtc0_config2(cpu_env, arg);
7463 rn = "Config2";
7464 /* Stop translation as we may have switched the execution mode */
7465 ctx->bstate = BS_STOP;
7466 break;
7467 case 3:
7468 gen_helper_mtc0_config3(cpu_env, arg);
7469 rn = "Config3";
7470 /* Stop translation as we may have switched the execution mode */
7471 ctx->bstate = BS_STOP;
7472 break;
7473 case 4:
7474 /* currently ignored */
7475 rn = "Config4";
7476 break;
7477 case 5:
7478 gen_helper_mtc0_config5(cpu_env, arg);
7479 rn = "Config5";
7480 /* Stop translation as we may have switched the execution mode */
7481 ctx->bstate = BS_STOP;
7482 break;
7483 /* 6,7 are implementation dependent */
7484 default:
7485 rn = "Invalid config selector";
7486 goto cp0_unimplemented;
7488 break;
7489 case 17:
7490 switch (sel) {
7491 case 0:
7492 gen_helper_mtc0_lladdr(cpu_env, arg);
7493 rn = "LLAddr";
7494 break;
7495 default:
7496 goto cp0_unimplemented;
7498 break;
7499 case 18:
7500 switch (sel) {
7501 case 0 ... 7:
7502 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7503 rn = "WatchLo";
7504 break;
7505 default:
7506 goto cp0_unimplemented;
7508 break;
7509 case 19:
7510 switch (sel) {
7511 case 0 ... 7:
7512 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7513 rn = "WatchHi";
7514 break;
7515 default:
7516 goto cp0_unimplemented;
7518 break;
7519 case 20:
7520 switch (sel) {
7521 case 0:
7522 check_insn(ctx, ISA_MIPS3);
7523 gen_helper_mtc0_xcontext(cpu_env, arg);
7524 rn = "XContext";
7525 break;
7526 default:
7527 goto cp0_unimplemented;
7529 break;
7530 case 21:
7531 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7532 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7533 switch (sel) {
7534 case 0:
7535 gen_helper_mtc0_framemask(cpu_env, arg);
7536 rn = "Framemask";
7537 break;
7538 default:
7539 goto cp0_unimplemented;
7541 break;
7542 case 22:
7543 /* ignored */
7544 rn = "Diagnostic"; /* implementation dependent */
7545 break;
7546 case 23:
7547 switch (sel) {
7548 case 0:
7549 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7550 /* BS_STOP isn't good enough here, hflags may have changed. */
7551 gen_save_pc(ctx->pc + 4);
7552 ctx->bstate = BS_EXCP;
7553 rn = "Debug";
7554 break;
7555 case 1:
7556 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7557 /* Stop translation as we may have switched the execution mode */
7558 ctx->bstate = BS_STOP;
7559 rn = "TraceControl";
7560 // break;
7561 case 2:
7562 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7563 /* Stop translation as we may have switched the execution mode */
7564 ctx->bstate = BS_STOP;
7565 rn = "TraceControl2";
7566 // break;
7567 case 3:
7568 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7569 /* Stop translation as we may have switched the execution mode */
7570 ctx->bstate = BS_STOP;
7571 rn = "UserTraceData";
7572 // break;
7573 case 4:
7574 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7575 /* Stop translation as we may have switched the execution mode */
7576 ctx->bstate = BS_STOP;
7577 rn = "TraceBPC";
7578 // break;
7579 default:
7580 goto cp0_unimplemented;
7582 break;
7583 case 24:
7584 switch (sel) {
7585 case 0:
7586 /* EJTAG support */
7587 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7588 rn = "DEPC";
7589 break;
7590 default:
7591 goto cp0_unimplemented;
7593 break;
7594 case 25:
7595 switch (sel) {
7596 case 0:
7597 gen_helper_mtc0_performance0(cpu_env, arg);
7598 rn = "Performance0";
7599 break;
7600 case 1:
7601 // gen_helper_mtc0_performance1(cpu_env, arg);
7602 rn = "Performance1";
7603 // break;
7604 case 2:
7605 // gen_helper_mtc0_performance2(cpu_env, arg);
7606 rn = "Performance2";
7607 // break;
7608 case 3:
7609 // gen_helper_mtc0_performance3(cpu_env, arg);
7610 rn = "Performance3";
7611 // break;
7612 case 4:
7613 // gen_helper_mtc0_performance4(cpu_env, arg);
7614 rn = "Performance4";
7615 // break;
7616 case 5:
7617 // gen_helper_mtc0_performance5(cpu_env, arg);
7618 rn = "Performance5";
7619 // break;
7620 case 6:
7621 // gen_helper_mtc0_performance6(cpu_env, arg);
7622 rn = "Performance6";
7623 // break;
7624 case 7:
7625 // gen_helper_mtc0_performance7(cpu_env, arg);
7626 rn = "Performance7";
7627 // break;
7628 default:
7629 goto cp0_unimplemented;
7631 break;
7632 case 26:
7633 /* ignored */
7634 rn = "ECC";
7635 break;
7636 case 27:
7637 switch (sel) {
7638 case 0 ... 3:
7639 /* ignored */
7640 rn = "CacheErr";
7641 break;
7642 default:
7643 goto cp0_unimplemented;
7645 break;
7646 case 28:
7647 switch (sel) {
7648 case 0:
7649 case 2:
7650 case 4:
7651 case 6:
7652 gen_helper_mtc0_taglo(cpu_env, arg);
7653 rn = "TagLo";
7654 break;
7655 case 1:
7656 case 3:
7657 case 5:
7658 case 7:
7659 gen_helper_mtc0_datalo(cpu_env, arg);
7660 rn = "DataLo";
7661 break;
7662 default:
7663 goto cp0_unimplemented;
7665 break;
7666 case 29:
7667 switch (sel) {
7668 case 0:
7669 case 2:
7670 case 4:
7671 case 6:
7672 gen_helper_mtc0_taghi(cpu_env, arg);
7673 rn = "TagHi";
7674 break;
7675 case 1:
7676 case 3:
7677 case 5:
7678 case 7:
7679 gen_helper_mtc0_datahi(cpu_env, arg);
7680 rn = "DataHi";
7681 break;
7682 default:
7683 rn = "invalid sel";
7684 goto cp0_unimplemented;
7686 break;
7687 case 30:
7688 switch (sel) {
7689 case 0:
7690 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7691 rn = "ErrorEPC";
7692 break;
7693 default:
7694 goto cp0_unimplemented;
7696 break;
7697 case 31:
7698 switch (sel) {
7699 case 0:
7700 /* EJTAG support */
7701 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7702 rn = "DESAVE";
7703 break;
7704 case 2 ... 7:
7705 CP0_CHECK(ctx->kscrexist & (1 << sel));
7706 tcg_gen_st_tl(arg, cpu_env,
7707 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7708 rn = "KScratch";
7709 break;
7710 default:
7711 goto cp0_unimplemented;
7713 /* Stop translation as we may have switched the execution mode */
7714 ctx->bstate = BS_STOP;
7715 break;
7716 default:
7717 goto cp0_unimplemented;
7719 (void)rn; /* avoid a compiler warning */
7720 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7721 /* For simplicity assume that all writes can cause interrupts. */
7722 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7723 gen_io_end();
7724 ctx->bstate = BS_STOP;
7726 return;
7728 cp0_unimplemented:
7729 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7731 #endif /* TARGET_MIPS64 */
7733 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7734 int u, int sel, int h)
7736 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7737 TCGv t0 = tcg_temp_local_new();
7739 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7740 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7741 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7742 tcg_gen_movi_tl(t0, -1);
7743 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7744 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7745 tcg_gen_movi_tl(t0, -1);
7746 else if (u == 0) {
7747 switch (rt) {
7748 case 1:
7749 switch (sel) {
7750 case 1:
7751 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7752 break;
7753 case 2:
7754 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7755 break;
7756 default:
7757 goto die;
7758 break;
7760 break;
7761 case 2:
7762 switch (sel) {
7763 case 1:
7764 gen_helper_mftc0_tcstatus(t0, cpu_env);
7765 break;
7766 case 2:
7767 gen_helper_mftc0_tcbind(t0, cpu_env);
7768 break;
7769 case 3:
7770 gen_helper_mftc0_tcrestart(t0, cpu_env);
7771 break;
7772 case 4:
7773 gen_helper_mftc0_tchalt(t0, cpu_env);
7774 break;
7775 case 5:
7776 gen_helper_mftc0_tccontext(t0, cpu_env);
7777 break;
7778 case 6:
7779 gen_helper_mftc0_tcschedule(t0, cpu_env);
7780 break;
7781 case 7:
7782 gen_helper_mftc0_tcschefback(t0, cpu_env);
7783 break;
7784 default:
7785 gen_mfc0(ctx, t0, rt, sel);
7786 break;
7788 break;
7789 case 10:
7790 switch (sel) {
7791 case 0:
7792 gen_helper_mftc0_entryhi(t0, cpu_env);
7793 break;
7794 default:
7795 gen_mfc0(ctx, t0, rt, sel);
7796 break;
7798 case 12:
7799 switch (sel) {
7800 case 0:
7801 gen_helper_mftc0_status(t0, cpu_env);
7802 break;
7803 default:
7804 gen_mfc0(ctx, t0, rt, sel);
7805 break;
7807 case 13:
7808 switch (sel) {
7809 case 0:
7810 gen_helper_mftc0_cause(t0, cpu_env);
7811 break;
7812 default:
7813 goto die;
7814 break;
7816 break;
7817 case 14:
7818 switch (sel) {
7819 case 0:
7820 gen_helper_mftc0_epc(t0, cpu_env);
7821 break;
7822 default:
7823 goto die;
7824 break;
7826 break;
7827 case 15:
7828 switch (sel) {
7829 case 1:
7830 gen_helper_mftc0_ebase(t0, cpu_env);
7831 break;
7832 default:
7833 goto die;
7834 break;
7836 break;
7837 case 16:
7838 switch (sel) {
7839 case 0 ... 7:
7840 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7841 break;
7842 default:
7843 goto die;
7844 break;
7846 break;
7847 case 23:
7848 switch (sel) {
7849 case 0:
7850 gen_helper_mftc0_debug(t0, cpu_env);
7851 break;
7852 default:
7853 gen_mfc0(ctx, t0, rt, sel);
7854 break;
7856 break;
7857 default:
7858 gen_mfc0(ctx, t0, rt, sel);
7860 } else switch (sel) {
7861 /* GPR registers. */
7862 case 0:
7863 gen_helper_1e0i(mftgpr, t0, rt);
7864 break;
7865 /* Auxiliary CPU registers */
7866 case 1:
7867 switch (rt) {
7868 case 0:
7869 gen_helper_1e0i(mftlo, t0, 0);
7870 break;
7871 case 1:
7872 gen_helper_1e0i(mfthi, t0, 0);
7873 break;
7874 case 2:
7875 gen_helper_1e0i(mftacx, t0, 0);
7876 break;
7877 case 4:
7878 gen_helper_1e0i(mftlo, t0, 1);
7879 break;
7880 case 5:
7881 gen_helper_1e0i(mfthi, t0, 1);
7882 break;
7883 case 6:
7884 gen_helper_1e0i(mftacx, t0, 1);
7885 break;
7886 case 8:
7887 gen_helper_1e0i(mftlo, t0, 2);
7888 break;
7889 case 9:
7890 gen_helper_1e0i(mfthi, t0, 2);
7891 break;
7892 case 10:
7893 gen_helper_1e0i(mftacx, t0, 2);
7894 break;
7895 case 12:
7896 gen_helper_1e0i(mftlo, t0, 3);
7897 break;
7898 case 13:
7899 gen_helper_1e0i(mfthi, t0, 3);
7900 break;
7901 case 14:
7902 gen_helper_1e0i(mftacx, t0, 3);
7903 break;
7904 case 16:
7905 gen_helper_mftdsp(t0, cpu_env);
7906 break;
7907 default:
7908 goto die;
7910 break;
7911 /* Floating point (COP1). */
7912 case 2:
7913 /* XXX: For now we support only a single FPU context. */
7914 if (h == 0) {
7915 TCGv_i32 fp0 = tcg_temp_new_i32();
7917 gen_load_fpr32(ctx, fp0, rt);
7918 tcg_gen_ext_i32_tl(t0, fp0);
7919 tcg_temp_free_i32(fp0);
7920 } else {
7921 TCGv_i32 fp0 = tcg_temp_new_i32();
7923 gen_load_fpr32h(ctx, fp0, rt);
7924 tcg_gen_ext_i32_tl(t0, fp0);
7925 tcg_temp_free_i32(fp0);
7927 break;
7928 case 3:
7929 /* XXX: For now we support only a single FPU context. */
7930 gen_helper_1e0i(cfc1, t0, rt);
7931 break;
7932 /* COP2: Not implemented. */
7933 case 4:
7934 case 5:
7935 /* fall through */
7936 default:
7937 goto die;
7939 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7940 gen_store_gpr(t0, rd);
7941 tcg_temp_free(t0);
7942 return;
7944 die:
7945 tcg_temp_free(t0);
7946 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7947 generate_exception(ctx, EXCP_RI);
7950 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7951 int u, int sel, int h)
7953 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7954 TCGv t0 = tcg_temp_local_new();
7956 gen_load_gpr(t0, rt);
7957 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7958 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7959 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7960 /* NOP */ ;
7961 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7962 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7963 /* NOP */ ;
7964 else if (u == 0) {
7965 switch (rd) {
7966 case 1:
7967 switch (sel) {
7968 case 1:
7969 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7970 break;
7971 case 2:
7972 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7973 break;
7974 default:
7975 goto die;
7976 break;
7978 break;
7979 case 2:
7980 switch (sel) {
7981 case 1:
7982 gen_helper_mttc0_tcstatus(cpu_env, t0);
7983 break;
7984 case 2:
7985 gen_helper_mttc0_tcbind(cpu_env, t0);
7986 break;
7987 case 3:
7988 gen_helper_mttc0_tcrestart(cpu_env, t0);
7989 break;
7990 case 4:
7991 gen_helper_mttc0_tchalt(cpu_env, t0);
7992 break;
7993 case 5:
7994 gen_helper_mttc0_tccontext(cpu_env, t0);
7995 break;
7996 case 6:
7997 gen_helper_mttc0_tcschedule(cpu_env, t0);
7998 break;
7999 case 7:
8000 gen_helper_mttc0_tcschefback(cpu_env, t0);
8001 break;
8002 default:
8003 gen_mtc0(ctx, t0, rd, sel);
8004 break;
8006 break;
8007 case 10:
8008 switch (sel) {
8009 case 0:
8010 gen_helper_mttc0_entryhi(cpu_env, t0);
8011 break;
8012 default:
8013 gen_mtc0(ctx, t0, rd, sel);
8014 break;
8016 case 12:
8017 switch (sel) {
8018 case 0:
8019 gen_helper_mttc0_status(cpu_env, t0);
8020 break;
8021 default:
8022 gen_mtc0(ctx, t0, rd, sel);
8023 break;
8025 case 13:
8026 switch (sel) {
8027 case 0:
8028 gen_helper_mttc0_cause(cpu_env, t0);
8029 break;
8030 default:
8031 goto die;
8032 break;
8034 break;
8035 case 15:
8036 switch (sel) {
8037 case 1:
8038 gen_helper_mttc0_ebase(cpu_env, t0);
8039 break;
8040 default:
8041 goto die;
8042 break;
8044 break;
8045 case 23:
8046 switch (sel) {
8047 case 0:
8048 gen_helper_mttc0_debug(cpu_env, t0);
8049 break;
8050 default:
8051 gen_mtc0(ctx, t0, rd, sel);
8052 break;
8054 break;
8055 default:
8056 gen_mtc0(ctx, t0, rd, sel);
8058 } else switch (sel) {
8059 /* GPR registers. */
8060 case 0:
8061 gen_helper_0e1i(mttgpr, t0, rd);
8062 break;
8063 /* Auxiliary CPU registers */
8064 case 1:
8065 switch (rd) {
8066 case 0:
8067 gen_helper_0e1i(mttlo, t0, 0);
8068 break;
8069 case 1:
8070 gen_helper_0e1i(mtthi, t0, 0);
8071 break;
8072 case 2:
8073 gen_helper_0e1i(mttacx, t0, 0);
8074 break;
8075 case 4:
8076 gen_helper_0e1i(mttlo, t0, 1);
8077 break;
8078 case 5:
8079 gen_helper_0e1i(mtthi, t0, 1);
8080 break;
8081 case 6:
8082 gen_helper_0e1i(mttacx, t0, 1);
8083 break;
8084 case 8:
8085 gen_helper_0e1i(mttlo, t0, 2);
8086 break;
8087 case 9:
8088 gen_helper_0e1i(mtthi, t0, 2);
8089 break;
8090 case 10:
8091 gen_helper_0e1i(mttacx, t0, 2);
8092 break;
8093 case 12:
8094 gen_helper_0e1i(mttlo, t0, 3);
8095 break;
8096 case 13:
8097 gen_helper_0e1i(mtthi, t0, 3);
8098 break;
8099 case 14:
8100 gen_helper_0e1i(mttacx, t0, 3);
8101 break;
8102 case 16:
8103 gen_helper_mttdsp(cpu_env, t0);
8104 break;
8105 default:
8106 goto die;
8108 break;
8109 /* Floating point (COP1). */
8110 case 2:
8111 /* XXX: For now we support only a single FPU context. */
8112 if (h == 0) {
8113 TCGv_i32 fp0 = tcg_temp_new_i32();
8115 tcg_gen_trunc_tl_i32(fp0, t0);
8116 gen_store_fpr32(ctx, fp0, rd);
8117 tcg_temp_free_i32(fp0);
8118 } else {
8119 TCGv_i32 fp0 = tcg_temp_new_i32();
8121 tcg_gen_trunc_tl_i32(fp0, t0);
8122 gen_store_fpr32h(ctx, fp0, rd);
8123 tcg_temp_free_i32(fp0);
8125 break;
8126 case 3:
8127 /* XXX: For now we support only a single FPU context. */
8128 save_cpu_state(ctx, 1);
8130 TCGv_i32 fs_tmp = tcg_const_i32(rd);
8132 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8133 tcg_temp_free_i32(fs_tmp);
8135 /* Stop translation as we may have changed hflags */
8136 ctx->bstate = BS_STOP;
8137 break;
8138 /* COP2: Not implemented. */
8139 case 4:
8140 case 5:
8141 /* fall through */
8142 default:
8143 goto die;
8145 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8146 tcg_temp_free(t0);
8147 return;
8149 die:
8150 tcg_temp_free(t0);
8151 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8152 generate_exception(ctx, EXCP_RI);
8155 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
8157 const char *opn = "ldst";
8159 check_cp0_enabled(ctx);
8160 switch (opc) {
8161 case OPC_MFC0:
8162 if (rt == 0) {
8163 /* Treat as NOP. */
8164 return;
8166 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8167 opn = "mfc0";
8168 break;
8169 case OPC_MTC0:
8171 TCGv t0 = tcg_temp_new();
8173 gen_load_gpr(t0, rt);
8174 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8175 tcg_temp_free(t0);
8177 opn = "mtc0";
8178 break;
8179 #if defined(TARGET_MIPS64)
8180 case OPC_DMFC0:
8181 check_insn(ctx, ISA_MIPS3);
8182 if (rt == 0) {
8183 /* Treat as NOP. */
8184 return;
8186 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8187 opn = "dmfc0";
8188 break;
8189 case OPC_DMTC0:
8190 check_insn(ctx, ISA_MIPS3);
8192 TCGv t0 = tcg_temp_new();
8194 gen_load_gpr(t0, rt);
8195 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8196 tcg_temp_free(t0);
8198 opn = "dmtc0";
8199 break;
8200 #endif
8201 case OPC_MFHC0:
8202 check_mvh(ctx);
8203 if (rt == 0) {
8204 /* Treat as NOP. */
8205 return;
8207 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8208 opn = "mfhc0";
8209 break;
8210 case OPC_MTHC0:
8211 check_mvh(ctx);
8213 TCGv t0 = tcg_temp_new();
8214 gen_load_gpr(t0, rt);
8215 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8216 tcg_temp_free(t0);
8218 opn = "mthc0";
8219 break;
8220 case OPC_MFTR:
8221 check_insn(ctx, ASE_MT);
8222 if (rd == 0) {
8223 /* Treat as NOP. */
8224 return;
8226 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8227 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8228 opn = "mftr";
8229 break;
8230 case OPC_MTTR:
8231 check_insn(ctx, ASE_MT);
8232 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8233 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8234 opn = "mttr";
8235 break;
8236 case OPC_TLBWI:
8237 opn = "tlbwi";
8238 if (!env->tlb->helper_tlbwi)
8239 goto die;
8240 gen_helper_tlbwi(cpu_env);
8241 break;
8242 case OPC_TLBINV:
8243 opn = "tlbinv";
8244 if (ctx->ie >= 2) {
8245 if (!env->tlb->helper_tlbinv) {
8246 goto die;
8248 gen_helper_tlbinv(cpu_env);
8249 } /* treat as nop if TLBINV not supported */
8250 break;
8251 case OPC_TLBINVF:
8252 opn = "tlbinvf";
8253 if (ctx->ie >= 2) {
8254 if (!env->tlb->helper_tlbinvf) {
8255 goto die;
8257 gen_helper_tlbinvf(cpu_env);
8258 } /* treat as nop if TLBINV not supported */
8259 break;
8260 case OPC_TLBWR:
8261 opn = "tlbwr";
8262 if (!env->tlb->helper_tlbwr)
8263 goto die;
8264 gen_helper_tlbwr(cpu_env);
8265 break;
8266 case OPC_TLBP:
8267 opn = "tlbp";
8268 if (!env->tlb->helper_tlbp)
8269 goto die;
8270 gen_helper_tlbp(cpu_env);
8271 break;
8272 case OPC_TLBR:
8273 opn = "tlbr";
8274 if (!env->tlb->helper_tlbr)
8275 goto die;
8276 gen_helper_tlbr(cpu_env);
8277 break;
8278 case OPC_ERET: /* OPC_ERETNC */
8279 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8280 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8281 MIPS_DEBUG("CTI in delay / forbidden slot");
8282 goto die;
8283 } else {
8284 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8285 if (ctx->opcode & (1 << bit_shift)) {
8286 /* OPC_ERETNC */
8287 opn = "eretnc";
8288 check_insn(ctx, ISA_MIPS32R5);
8289 gen_helper_eretnc(cpu_env);
8290 } else {
8291 /* OPC_ERET */
8292 opn = "eret";
8293 check_insn(ctx, ISA_MIPS2);
8294 gen_helper_eret(cpu_env);
8296 ctx->bstate = BS_EXCP;
8298 break;
8299 case OPC_DERET:
8300 opn = "deret";
8301 check_insn(ctx, ISA_MIPS32);
8302 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8303 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8304 MIPS_DEBUG("CTI in delay / forbidden slot");
8305 goto die;
8307 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8308 MIPS_INVAL(opn);
8309 generate_exception(ctx, EXCP_RI);
8310 } else {
8311 gen_helper_deret(cpu_env);
8312 ctx->bstate = BS_EXCP;
8314 break;
8315 case OPC_WAIT:
8316 opn = "wait";
8317 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8318 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8319 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8320 MIPS_DEBUG("CTI in delay / forbidden slot");
8321 goto die;
8323 /* If we get an exception, we want to restart at next instruction */
8324 ctx->pc += 4;
8325 save_cpu_state(ctx, 1);
8326 ctx->pc -= 4;
8327 gen_helper_wait(cpu_env);
8328 ctx->bstate = BS_EXCP;
8329 break;
8330 default:
8331 die:
8332 MIPS_INVAL(opn);
8333 generate_exception(ctx, EXCP_RI);
8334 return;
8336 (void)opn; /* avoid a compiler warning */
8337 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
8339 #endif /* !CONFIG_USER_ONLY */
8341 /* CP1 Branches (before delay slot) */
8342 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8343 int32_t cc, int32_t offset)
8345 target_ulong btarget;
8346 const char *opn = "cp1 cond branch";
8347 TCGv_i32 t0 = tcg_temp_new_i32();
8349 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8350 MIPS_DEBUG("CTI in delay / forbidden slot");
8351 generate_exception(ctx, EXCP_RI);
8352 goto out;
8355 if (cc != 0)
8356 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8358 btarget = ctx->pc + 4 + offset;
8360 switch (op) {
8361 case OPC_BC1F:
8362 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8363 tcg_gen_not_i32(t0, t0);
8364 tcg_gen_andi_i32(t0, t0, 1);
8365 tcg_gen_extu_i32_tl(bcond, t0);
8366 opn = "bc1f";
8367 goto not_likely;
8368 case OPC_BC1FL:
8369 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8370 tcg_gen_not_i32(t0, t0);
8371 tcg_gen_andi_i32(t0, t0, 1);
8372 tcg_gen_extu_i32_tl(bcond, t0);
8373 opn = "bc1fl";
8374 goto likely;
8375 case OPC_BC1T:
8376 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8377 tcg_gen_andi_i32(t0, t0, 1);
8378 tcg_gen_extu_i32_tl(bcond, t0);
8379 opn = "bc1t";
8380 goto not_likely;
8381 case OPC_BC1TL:
8382 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8383 tcg_gen_andi_i32(t0, t0, 1);
8384 tcg_gen_extu_i32_tl(bcond, t0);
8385 opn = "bc1tl";
8386 likely:
8387 ctx->hflags |= MIPS_HFLAG_BL;
8388 break;
8389 case OPC_BC1FANY2:
8391 TCGv_i32 t1 = tcg_temp_new_i32();
8392 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8393 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8394 tcg_gen_nand_i32(t0, t0, t1);
8395 tcg_temp_free_i32(t1);
8396 tcg_gen_andi_i32(t0, t0, 1);
8397 tcg_gen_extu_i32_tl(bcond, t0);
8399 opn = "bc1any2f";
8400 goto not_likely;
8401 case OPC_BC1TANY2:
8403 TCGv_i32 t1 = tcg_temp_new_i32();
8404 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8405 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8406 tcg_gen_or_i32(t0, t0, t1);
8407 tcg_temp_free_i32(t1);
8408 tcg_gen_andi_i32(t0, t0, 1);
8409 tcg_gen_extu_i32_tl(bcond, t0);
8411 opn = "bc1any2t";
8412 goto not_likely;
8413 case OPC_BC1FANY4:
8415 TCGv_i32 t1 = tcg_temp_new_i32();
8416 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8417 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8418 tcg_gen_and_i32(t0, t0, t1);
8419 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8420 tcg_gen_and_i32(t0, t0, t1);
8421 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8422 tcg_gen_nand_i32(t0, t0, t1);
8423 tcg_temp_free_i32(t1);
8424 tcg_gen_andi_i32(t0, t0, 1);
8425 tcg_gen_extu_i32_tl(bcond, t0);
8427 opn = "bc1any4f";
8428 goto not_likely;
8429 case OPC_BC1TANY4:
8431 TCGv_i32 t1 = tcg_temp_new_i32();
8432 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8433 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8434 tcg_gen_or_i32(t0, t0, t1);
8435 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8436 tcg_gen_or_i32(t0, t0, t1);
8437 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8438 tcg_gen_or_i32(t0, t0, t1);
8439 tcg_temp_free_i32(t1);
8440 tcg_gen_andi_i32(t0, t0, 1);
8441 tcg_gen_extu_i32_tl(bcond, t0);
8443 opn = "bc1any4t";
8444 not_likely:
8445 ctx->hflags |= MIPS_HFLAG_BC;
8446 break;
8447 default:
8448 MIPS_INVAL(opn);
8449 generate_exception (ctx, EXCP_RI);
8450 goto out;
8452 (void)opn; /* avoid a compiler warning */
8453 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8454 ctx->hflags, btarget);
8455 ctx->btarget = btarget;
8456 ctx->hflags |= MIPS_HFLAG_BDS32;
8457 out:
8458 tcg_temp_free_i32(t0);
8461 /* R6 CP1 Branches */
8462 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8463 int32_t ft, int32_t offset,
8464 int delayslot_size)
8466 target_ulong btarget;
8467 const char *opn = "cp1 cond branch";
8468 TCGv_i64 t0 = tcg_temp_new_i64();
8470 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8471 #ifdef MIPS_DEBUG_DISAS
8472 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8473 "\n", ctx->pc);
8474 #endif
8475 generate_exception(ctx, EXCP_RI);
8476 goto out;
8479 gen_load_fpr64(ctx, t0, ft);
8480 tcg_gen_andi_i64(t0, t0, 1);
8482 btarget = addr_add(ctx, ctx->pc + 4, offset);
8484 switch (op) {
8485 case OPC_BC1EQZ:
8486 tcg_gen_xori_i64(t0, t0, 1);
8487 opn = "bc1eqz";
8488 ctx->hflags |= MIPS_HFLAG_BC;
8489 break;
8490 case OPC_BC1NEZ:
8491 /* t0 already set */
8492 opn = "bc1nez";
8493 ctx->hflags |= MIPS_HFLAG_BC;
8494 break;
8495 default:
8496 MIPS_INVAL(opn);
8497 generate_exception(ctx, EXCP_RI);
8498 goto out;
8501 tcg_gen_trunc_i64_tl(bcond, t0);
8503 (void)opn; /* avoid a compiler warning */
8504 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8505 ctx->hflags, btarget);
8506 ctx->btarget = btarget;
8508 switch (delayslot_size) {
8509 case 2:
8510 ctx->hflags |= MIPS_HFLAG_BDS16;
8511 break;
8512 case 4:
8513 ctx->hflags |= MIPS_HFLAG_BDS32;
8514 break;
8517 out:
8518 tcg_temp_free_i64(t0);
8521 /* Coprocessor 1 (FPU) */
8523 #define FOP(func, fmt) (((fmt) << 21) | (func))
8525 enum fopcode {
8526 OPC_ADD_S = FOP(0, FMT_S),
8527 OPC_SUB_S = FOP(1, FMT_S),
8528 OPC_MUL_S = FOP(2, FMT_S),
8529 OPC_DIV_S = FOP(3, FMT_S),
8530 OPC_SQRT_S = FOP(4, FMT_S),
8531 OPC_ABS_S = FOP(5, FMT_S),
8532 OPC_MOV_S = FOP(6, FMT_S),
8533 OPC_NEG_S = FOP(7, FMT_S),
8534 OPC_ROUND_L_S = FOP(8, FMT_S),
8535 OPC_TRUNC_L_S = FOP(9, FMT_S),
8536 OPC_CEIL_L_S = FOP(10, FMT_S),
8537 OPC_FLOOR_L_S = FOP(11, FMT_S),
8538 OPC_ROUND_W_S = FOP(12, FMT_S),
8539 OPC_TRUNC_W_S = FOP(13, FMT_S),
8540 OPC_CEIL_W_S = FOP(14, FMT_S),
8541 OPC_FLOOR_W_S = FOP(15, FMT_S),
8542 OPC_SEL_S = FOP(16, FMT_S),
8543 OPC_MOVCF_S = FOP(17, FMT_S),
8544 OPC_MOVZ_S = FOP(18, FMT_S),
8545 OPC_MOVN_S = FOP(19, FMT_S),
8546 OPC_SELEQZ_S = FOP(20, FMT_S),
8547 OPC_RECIP_S = FOP(21, FMT_S),
8548 OPC_RSQRT_S = FOP(22, FMT_S),
8549 OPC_SELNEZ_S = FOP(23, FMT_S),
8550 OPC_MADDF_S = FOP(24, FMT_S),
8551 OPC_MSUBF_S = FOP(25, FMT_S),
8552 OPC_RINT_S = FOP(26, FMT_S),
8553 OPC_CLASS_S = FOP(27, FMT_S),
8554 OPC_MIN_S = FOP(28, FMT_S),
8555 OPC_RECIP2_S = FOP(28, FMT_S),
8556 OPC_MINA_S = FOP(29, FMT_S),
8557 OPC_RECIP1_S = FOP(29, FMT_S),
8558 OPC_MAX_S = FOP(30, FMT_S),
8559 OPC_RSQRT1_S = FOP(30, FMT_S),
8560 OPC_MAXA_S = FOP(31, FMT_S),
8561 OPC_RSQRT2_S = FOP(31, FMT_S),
8562 OPC_CVT_D_S = FOP(33, FMT_S),
8563 OPC_CVT_W_S = FOP(36, FMT_S),
8564 OPC_CVT_L_S = FOP(37, FMT_S),
8565 OPC_CVT_PS_S = FOP(38, FMT_S),
8566 OPC_CMP_F_S = FOP (48, FMT_S),
8567 OPC_CMP_UN_S = FOP (49, FMT_S),
8568 OPC_CMP_EQ_S = FOP (50, FMT_S),
8569 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8570 OPC_CMP_OLT_S = FOP (52, FMT_S),
8571 OPC_CMP_ULT_S = FOP (53, FMT_S),
8572 OPC_CMP_OLE_S = FOP (54, FMT_S),
8573 OPC_CMP_ULE_S = FOP (55, FMT_S),
8574 OPC_CMP_SF_S = FOP (56, FMT_S),
8575 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8576 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8577 OPC_CMP_NGL_S = FOP (59, FMT_S),
8578 OPC_CMP_LT_S = FOP (60, FMT_S),
8579 OPC_CMP_NGE_S = FOP (61, FMT_S),
8580 OPC_CMP_LE_S = FOP (62, FMT_S),
8581 OPC_CMP_NGT_S = FOP (63, FMT_S),
8583 OPC_ADD_D = FOP(0, FMT_D),
8584 OPC_SUB_D = FOP(1, FMT_D),
8585 OPC_MUL_D = FOP(2, FMT_D),
8586 OPC_DIV_D = FOP(3, FMT_D),
8587 OPC_SQRT_D = FOP(4, FMT_D),
8588 OPC_ABS_D = FOP(5, FMT_D),
8589 OPC_MOV_D = FOP(6, FMT_D),
8590 OPC_NEG_D = FOP(7, FMT_D),
8591 OPC_ROUND_L_D = FOP(8, FMT_D),
8592 OPC_TRUNC_L_D = FOP(9, FMT_D),
8593 OPC_CEIL_L_D = FOP(10, FMT_D),
8594 OPC_FLOOR_L_D = FOP(11, FMT_D),
8595 OPC_ROUND_W_D = FOP(12, FMT_D),
8596 OPC_TRUNC_W_D = FOP(13, FMT_D),
8597 OPC_CEIL_W_D = FOP(14, FMT_D),
8598 OPC_FLOOR_W_D = FOP(15, FMT_D),
8599 OPC_SEL_D = FOP(16, FMT_D),
8600 OPC_MOVCF_D = FOP(17, FMT_D),
8601 OPC_MOVZ_D = FOP(18, FMT_D),
8602 OPC_MOVN_D = FOP(19, FMT_D),
8603 OPC_SELEQZ_D = FOP(20, FMT_D),
8604 OPC_RECIP_D = FOP(21, FMT_D),
8605 OPC_RSQRT_D = FOP(22, FMT_D),
8606 OPC_SELNEZ_D = FOP(23, FMT_D),
8607 OPC_MADDF_D = FOP(24, FMT_D),
8608 OPC_MSUBF_D = FOP(25, FMT_D),
8609 OPC_RINT_D = FOP(26, FMT_D),
8610 OPC_CLASS_D = FOP(27, FMT_D),
8611 OPC_MIN_D = FOP(28, FMT_D),
8612 OPC_RECIP2_D = FOP(28, FMT_D),
8613 OPC_MINA_D = FOP(29, FMT_D),
8614 OPC_RECIP1_D = FOP(29, FMT_D),
8615 OPC_MAX_D = FOP(30, FMT_D),
8616 OPC_RSQRT1_D = FOP(30, FMT_D),
8617 OPC_MAXA_D = FOP(31, FMT_D),
8618 OPC_RSQRT2_D = FOP(31, FMT_D),
8619 OPC_CVT_S_D = FOP(32, FMT_D),
8620 OPC_CVT_W_D = FOP(36, FMT_D),
8621 OPC_CVT_L_D = FOP(37, FMT_D),
8622 OPC_CMP_F_D = FOP (48, FMT_D),
8623 OPC_CMP_UN_D = FOP (49, FMT_D),
8624 OPC_CMP_EQ_D = FOP (50, FMT_D),
8625 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8626 OPC_CMP_OLT_D = FOP (52, FMT_D),
8627 OPC_CMP_ULT_D = FOP (53, FMT_D),
8628 OPC_CMP_OLE_D = FOP (54, FMT_D),
8629 OPC_CMP_ULE_D = FOP (55, FMT_D),
8630 OPC_CMP_SF_D = FOP (56, FMT_D),
8631 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8632 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8633 OPC_CMP_NGL_D = FOP (59, FMT_D),
8634 OPC_CMP_LT_D = FOP (60, FMT_D),
8635 OPC_CMP_NGE_D = FOP (61, FMT_D),
8636 OPC_CMP_LE_D = FOP (62, FMT_D),
8637 OPC_CMP_NGT_D = FOP (63, FMT_D),
8639 OPC_CVT_S_W = FOP(32, FMT_W),
8640 OPC_CVT_D_W = FOP(33, FMT_W),
8641 OPC_CVT_S_L = FOP(32, FMT_L),
8642 OPC_CVT_D_L = FOP(33, FMT_L),
8643 OPC_CVT_PS_PW = FOP(38, FMT_W),
8645 OPC_ADD_PS = FOP(0, FMT_PS),
8646 OPC_SUB_PS = FOP(1, FMT_PS),
8647 OPC_MUL_PS = FOP(2, FMT_PS),
8648 OPC_DIV_PS = FOP(3, FMT_PS),
8649 OPC_ABS_PS = FOP(5, FMT_PS),
8650 OPC_MOV_PS = FOP(6, FMT_PS),
8651 OPC_NEG_PS = FOP(7, FMT_PS),
8652 OPC_MOVCF_PS = FOP(17, FMT_PS),
8653 OPC_MOVZ_PS = FOP(18, FMT_PS),
8654 OPC_MOVN_PS = FOP(19, FMT_PS),
8655 OPC_ADDR_PS = FOP(24, FMT_PS),
8656 OPC_MULR_PS = FOP(26, FMT_PS),
8657 OPC_RECIP2_PS = FOP(28, FMT_PS),
8658 OPC_RECIP1_PS = FOP(29, FMT_PS),
8659 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8660 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8662 OPC_CVT_S_PU = FOP(32, FMT_PS),
8663 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8664 OPC_CVT_S_PL = FOP(40, FMT_PS),
8665 OPC_PLL_PS = FOP(44, FMT_PS),
8666 OPC_PLU_PS = FOP(45, FMT_PS),
8667 OPC_PUL_PS = FOP(46, FMT_PS),
8668 OPC_PUU_PS = FOP(47, FMT_PS),
8669 OPC_CMP_F_PS = FOP (48, FMT_PS),
8670 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8671 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8672 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8673 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8674 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8675 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8676 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8677 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8678 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8679 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8680 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8681 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8682 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8683 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8684 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8687 enum r6_f_cmp_op {
8688 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8689 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8690 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8691 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8692 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8693 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8694 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8695 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8696 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8697 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8698 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8699 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8700 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8701 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8702 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8703 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8704 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8705 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8706 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8707 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8708 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8709 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8711 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8712 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8713 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8714 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8715 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8716 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8717 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8718 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8719 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8720 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8721 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8722 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8723 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8724 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8725 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8726 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8727 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8728 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8729 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8730 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8731 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8732 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8734 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8736 const char *opn = "cp1 move";
8737 TCGv t0 = tcg_temp_new();
8739 switch (opc) {
8740 case OPC_MFC1:
8742 TCGv_i32 fp0 = tcg_temp_new_i32();
8744 gen_load_fpr32(ctx, fp0, fs);
8745 tcg_gen_ext_i32_tl(t0, fp0);
8746 tcg_temp_free_i32(fp0);
8748 gen_store_gpr(t0, rt);
8749 opn = "mfc1";
8750 break;
8751 case OPC_MTC1:
8752 gen_load_gpr(t0, rt);
8754 TCGv_i32 fp0 = tcg_temp_new_i32();
8756 tcg_gen_trunc_tl_i32(fp0, t0);
8757 gen_store_fpr32(ctx, fp0, fs);
8758 tcg_temp_free_i32(fp0);
8760 opn = "mtc1";
8761 break;
8762 case OPC_CFC1:
8763 gen_helper_1e0i(cfc1, t0, fs);
8764 gen_store_gpr(t0, rt);
8765 opn = "cfc1";
8766 break;
8767 case OPC_CTC1:
8768 gen_load_gpr(t0, rt);
8769 save_cpu_state(ctx, 1);
8771 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8773 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8774 tcg_temp_free_i32(fs_tmp);
8776 /* Stop translation as we may have changed hflags */
8777 ctx->bstate = BS_STOP;
8778 opn = "ctc1";
8779 break;
8780 #if defined(TARGET_MIPS64)
8781 case OPC_DMFC1:
8782 gen_load_fpr64(ctx, t0, fs);
8783 gen_store_gpr(t0, rt);
8784 opn = "dmfc1";
8785 break;
8786 case OPC_DMTC1:
8787 gen_load_gpr(t0, rt);
8788 gen_store_fpr64(ctx, t0, fs);
8789 opn = "dmtc1";
8790 break;
8791 #endif
8792 case OPC_MFHC1:
8794 TCGv_i32 fp0 = tcg_temp_new_i32();
8796 gen_load_fpr32h(ctx, fp0, fs);
8797 tcg_gen_ext_i32_tl(t0, fp0);
8798 tcg_temp_free_i32(fp0);
8800 gen_store_gpr(t0, rt);
8801 opn = "mfhc1";
8802 break;
8803 case OPC_MTHC1:
8804 gen_load_gpr(t0, rt);
8806 TCGv_i32 fp0 = tcg_temp_new_i32();
8808 tcg_gen_trunc_tl_i32(fp0, t0);
8809 gen_store_fpr32h(ctx, fp0, fs);
8810 tcg_temp_free_i32(fp0);
8812 opn = "mthc1";
8813 break;
8814 default:
8815 MIPS_INVAL(opn);
8816 generate_exception (ctx, EXCP_RI);
8817 goto out;
8819 (void)opn; /* avoid a compiler warning */
8820 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
8822 out:
8823 tcg_temp_free(t0);
8826 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8828 TCGLabel *l1;
8829 TCGCond cond;
8830 TCGv_i32 t0;
8832 if (rd == 0) {
8833 /* Treat as NOP. */
8834 return;
8837 if (tf)
8838 cond = TCG_COND_EQ;
8839 else
8840 cond = TCG_COND_NE;
8842 l1 = gen_new_label();
8843 t0 = tcg_temp_new_i32();
8844 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8845 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8846 tcg_temp_free_i32(t0);
8847 if (rs == 0) {
8848 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8849 } else {
8850 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8852 gen_set_label(l1);
8855 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
8856 int tf)
8858 int cond;
8859 TCGv_i32 t0 = tcg_temp_new_i32();
8860 TCGLabel *l1 = gen_new_label();
8862 if (tf)
8863 cond = TCG_COND_EQ;
8864 else
8865 cond = TCG_COND_NE;
8867 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8868 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8869 gen_load_fpr32(ctx, t0, fs);
8870 gen_store_fpr32(ctx, t0, fd);
8871 gen_set_label(l1);
8872 tcg_temp_free_i32(t0);
8875 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8877 int cond;
8878 TCGv_i32 t0 = tcg_temp_new_i32();
8879 TCGv_i64 fp0;
8880 TCGLabel *l1 = gen_new_label();
8882 if (tf)
8883 cond = TCG_COND_EQ;
8884 else
8885 cond = TCG_COND_NE;
8887 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8888 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8889 tcg_temp_free_i32(t0);
8890 fp0 = tcg_temp_new_i64();
8891 gen_load_fpr64(ctx, fp0, fs);
8892 gen_store_fpr64(ctx, fp0, fd);
8893 tcg_temp_free_i64(fp0);
8894 gen_set_label(l1);
8897 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8898 int cc, int tf)
8900 int cond;
8901 TCGv_i32 t0 = tcg_temp_new_i32();
8902 TCGLabel *l1 = gen_new_label();
8903 TCGLabel *l2 = gen_new_label();
8905 if (tf)
8906 cond = TCG_COND_EQ;
8907 else
8908 cond = TCG_COND_NE;
8910 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8911 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8912 gen_load_fpr32(ctx, t0, fs);
8913 gen_store_fpr32(ctx, t0, fd);
8914 gen_set_label(l1);
8916 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8917 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8918 gen_load_fpr32h(ctx, t0, fs);
8919 gen_store_fpr32h(ctx, t0, fd);
8920 tcg_temp_free_i32(t0);
8921 gen_set_label(l2);
8924 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8925 int fs)
8927 TCGv_i32 t1 = tcg_const_i32(0);
8928 TCGv_i32 fp0 = tcg_temp_new_i32();
8929 TCGv_i32 fp1 = tcg_temp_new_i32();
8930 TCGv_i32 fp2 = tcg_temp_new_i32();
8931 gen_load_fpr32(ctx, fp0, fd);
8932 gen_load_fpr32(ctx, fp1, ft);
8933 gen_load_fpr32(ctx, fp2, fs);
8935 switch (op1) {
8936 case OPC_SEL_S:
8937 tcg_gen_andi_i32(fp0, fp0, 1);
8938 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8939 break;
8940 case OPC_SELEQZ_S:
8941 tcg_gen_andi_i32(fp1, fp1, 1);
8942 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8943 break;
8944 case OPC_SELNEZ_S:
8945 tcg_gen_andi_i32(fp1, fp1, 1);
8946 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8947 break;
8948 default:
8949 MIPS_INVAL("gen_sel_s");
8950 generate_exception (ctx, EXCP_RI);
8951 break;
8954 gen_store_fpr32(ctx, fp0, fd);
8955 tcg_temp_free_i32(fp2);
8956 tcg_temp_free_i32(fp1);
8957 tcg_temp_free_i32(fp0);
8958 tcg_temp_free_i32(t1);
8961 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8962 int fs)
8964 TCGv_i64 t1 = tcg_const_i64(0);
8965 TCGv_i64 fp0 = tcg_temp_new_i64();
8966 TCGv_i64 fp1 = tcg_temp_new_i64();
8967 TCGv_i64 fp2 = tcg_temp_new_i64();
8968 gen_load_fpr64(ctx, fp0, fd);
8969 gen_load_fpr64(ctx, fp1, ft);
8970 gen_load_fpr64(ctx, fp2, fs);
8972 switch (op1) {
8973 case OPC_SEL_D:
8974 tcg_gen_andi_i64(fp0, fp0, 1);
8975 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8976 break;
8977 case OPC_SELEQZ_D:
8978 tcg_gen_andi_i64(fp1, fp1, 1);
8979 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8980 break;
8981 case OPC_SELNEZ_D:
8982 tcg_gen_andi_i64(fp1, fp1, 1);
8983 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8984 break;
8985 default:
8986 MIPS_INVAL("gen_sel_d");
8987 generate_exception (ctx, EXCP_RI);
8988 break;
8991 gen_store_fpr64(ctx, fp0, fd);
8992 tcg_temp_free_i64(fp2);
8993 tcg_temp_free_i64(fp1);
8994 tcg_temp_free_i64(fp0);
8995 tcg_temp_free_i64(t1);
8998 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8999 int ft, int fs, int fd, int cc)
9001 const char *opn = "farith";
9002 const char *condnames[] = {
9003 "c.f",
9004 "c.un",
9005 "c.eq",
9006 "c.ueq",
9007 "c.olt",
9008 "c.ult",
9009 "c.ole",
9010 "c.ule",
9011 "c.sf",
9012 "c.ngle",
9013 "c.seq",
9014 "c.ngl",
9015 "c.lt",
9016 "c.nge",
9017 "c.le",
9018 "c.ngt",
9020 const char *condnames_abs[] = {
9021 "cabs.f",
9022 "cabs.un",
9023 "cabs.eq",
9024 "cabs.ueq",
9025 "cabs.olt",
9026 "cabs.ult",
9027 "cabs.ole",
9028 "cabs.ule",
9029 "cabs.sf",
9030 "cabs.ngle",
9031 "cabs.seq",
9032 "cabs.ngl",
9033 "cabs.lt",
9034 "cabs.nge",
9035 "cabs.le",
9036 "cabs.ngt",
9038 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
9039 uint32_t func = ctx->opcode & 0x3f;
9040 switch (op1) {
9041 case OPC_ADD_S:
9043 TCGv_i32 fp0 = tcg_temp_new_i32();
9044 TCGv_i32 fp1 = tcg_temp_new_i32();
9046 gen_load_fpr32(ctx, fp0, fs);
9047 gen_load_fpr32(ctx, fp1, ft);
9048 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
9049 tcg_temp_free_i32(fp1);
9050 gen_store_fpr32(ctx, fp0, fd);
9051 tcg_temp_free_i32(fp0);
9053 opn = "add.s";
9054 optype = BINOP;
9055 break;
9056 case OPC_SUB_S:
9058 TCGv_i32 fp0 = tcg_temp_new_i32();
9059 TCGv_i32 fp1 = tcg_temp_new_i32();
9061 gen_load_fpr32(ctx, fp0, fs);
9062 gen_load_fpr32(ctx, fp1, ft);
9063 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
9064 tcg_temp_free_i32(fp1);
9065 gen_store_fpr32(ctx, fp0, fd);
9066 tcg_temp_free_i32(fp0);
9068 opn = "sub.s";
9069 optype = BINOP;
9070 break;
9071 case OPC_MUL_S:
9073 TCGv_i32 fp0 = tcg_temp_new_i32();
9074 TCGv_i32 fp1 = tcg_temp_new_i32();
9076 gen_load_fpr32(ctx, fp0, fs);
9077 gen_load_fpr32(ctx, fp1, ft);
9078 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
9079 tcg_temp_free_i32(fp1);
9080 gen_store_fpr32(ctx, fp0, fd);
9081 tcg_temp_free_i32(fp0);
9083 opn = "mul.s";
9084 optype = BINOP;
9085 break;
9086 case OPC_DIV_S:
9088 TCGv_i32 fp0 = tcg_temp_new_i32();
9089 TCGv_i32 fp1 = tcg_temp_new_i32();
9091 gen_load_fpr32(ctx, fp0, fs);
9092 gen_load_fpr32(ctx, fp1, ft);
9093 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
9094 tcg_temp_free_i32(fp1);
9095 gen_store_fpr32(ctx, fp0, fd);
9096 tcg_temp_free_i32(fp0);
9098 opn = "div.s";
9099 optype = BINOP;
9100 break;
9101 case OPC_SQRT_S:
9103 TCGv_i32 fp0 = tcg_temp_new_i32();
9105 gen_load_fpr32(ctx, fp0, fs);
9106 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
9107 gen_store_fpr32(ctx, fp0, fd);
9108 tcg_temp_free_i32(fp0);
9110 opn = "sqrt.s";
9111 break;
9112 case OPC_ABS_S:
9114 TCGv_i32 fp0 = tcg_temp_new_i32();
9116 gen_load_fpr32(ctx, fp0, fs);
9117 gen_helper_float_abs_s(fp0, fp0);
9118 gen_store_fpr32(ctx, fp0, fd);
9119 tcg_temp_free_i32(fp0);
9121 opn = "abs.s";
9122 break;
9123 case OPC_MOV_S:
9125 TCGv_i32 fp0 = tcg_temp_new_i32();
9127 gen_load_fpr32(ctx, fp0, fs);
9128 gen_store_fpr32(ctx, fp0, fd);
9129 tcg_temp_free_i32(fp0);
9131 opn = "mov.s";
9132 break;
9133 case OPC_NEG_S:
9135 TCGv_i32 fp0 = tcg_temp_new_i32();
9137 gen_load_fpr32(ctx, fp0, fs);
9138 gen_helper_float_chs_s(fp0, fp0);
9139 gen_store_fpr32(ctx, fp0, fd);
9140 tcg_temp_free_i32(fp0);
9142 opn = "neg.s";
9143 break;
9144 case OPC_ROUND_L_S:
9145 check_cp1_64bitmode(ctx);
9147 TCGv_i32 fp32 = tcg_temp_new_i32();
9148 TCGv_i64 fp64 = tcg_temp_new_i64();
9150 gen_load_fpr32(ctx, fp32, fs);
9151 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
9152 tcg_temp_free_i32(fp32);
9153 gen_store_fpr64(ctx, fp64, fd);
9154 tcg_temp_free_i64(fp64);
9156 opn = "round.l.s";
9157 break;
9158 case OPC_TRUNC_L_S:
9159 check_cp1_64bitmode(ctx);
9161 TCGv_i32 fp32 = tcg_temp_new_i32();
9162 TCGv_i64 fp64 = tcg_temp_new_i64();
9164 gen_load_fpr32(ctx, fp32, fs);
9165 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
9166 tcg_temp_free_i32(fp32);
9167 gen_store_fpr64(ctx, fp64, fd);
9168 tcg_temp_free_i64(fp64);
9170 opn = "trunc.l.s";
9171 break;
9172 case OPC_CEIL_L_S:
9173 check_cp1_64bitmode(ctx);
9175 TCGv_i32 fp32 = tcg_temp_new_i32();
9176 TCGv_i64 fp64 = tcg_temp_new_i64();
9178 gen_load_fpr32(ctx, fp32, fs);
9179 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
9180 tcg_temp_free_i32(fp32);
9181 gen_store_fpr64(ctx, fp64, fd);
9182 tcg_temp_free_i64(fp64);
9184 opn = "ceil.l.s";
9185 break;
9186 case OPC_FLOOR_L_S:
9187 check_cp1_64bitmode(ctx);
9189 TCGv_i32 fp32 = tcg_temp_new_i32();
9190 TCGv_i64 fp64 = tcg_temp_new_i64();
9192 gen_load_fpr32(ctx, fp32, fs);
9193 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
9194 tcg_temp_free_i32(fp32);
9195 gen_store_fpr64(ctx, fp64, fd);
9196 tcg_temp_free_i64(fp64);
9198 opn = "floor.l.s";
9199 break;
9200 case OPC_ROUND_W_S:
9202 TCGv_i32 fp0 = tcg_temp_new_i32();
9204 gen_load_fpr32(ctx, fp0, fs);
9205 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
9206 gen_store_fpr32(ctx, fp0, fd);
9207 tcg_temp_free_i32(fp0);
9209 opn = "round.w.s";
9210 break;
9211 case OPC_TRUNC_W_S:
9213 TCGv_i32 fp0 = tcg_temp_new_i32();
9215 gen_load_fpr32(ctx, fp0, fs);
9216 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
9217 gen_store_fpr32(ctx, fp0, fd);
9218 tcg_temp_free_i32(fp0);
9220 opn = "trunc.w.s";
9221 break;
9222 case OPC_CEIL_W_S:
9224 TCGv_i32 fp0 = tcg_temp_new_i32();
9226 gen_load_fpr32(ctx, fp0, fs);
9227 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
9228 gen_store_fpr32(ctx, fp0, fd);
9229 tcg_temp_free_i32(fp0);
9231 opn = "ceil.w.s";
9232 break;
9233 case OPC_FLOOR_W_S:
9235 TCGv_i32 fp0 = tcg_temp_new_i32();
9237 gen_load_fpr32(ctx, fp0, fs);
9238 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
9239 gen_store_fpr32(ctx, fp0, fd);
9240 tcg_temp_free_i32(fp0);
9242 opn = "floor.w.s";
9243 break;
9244 case OPC_SEL_S:
9245 check_insn(ctx, ISA_MIPS32R6);
9246 gen_sel_s(ctx, op1, fd, ft, fs);
9247 opn = "sel.s";
9248 break;
9249 case OPC_SELEQZ_S:
9250 check_insn(ctx, ISA_MIPS32R6);
9251 gen_sel_s(ctx, op1, fd, ft, fs);
9252 opn = "seleqz.s";
9253 break;
9254 case OPC_SELNEZ_S:
9255 check_insn(ctx, ISA_MIPS32R6);
9256 gen_sel_s(ctx, op1, fd, ft, fs);
9257 opn = "selnez.s";
9258 break;
9259 case OPC_MOVCF_S:
9260 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9261 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9262 opn = "movcf.s";
9263 break;
9264 case OPC_MOVZ_S:
9265 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9267 TCGLabel *l1 = gen_new_label();
9268 TCGv_i32 fp0;
9270 if (ft != 0) {
9271 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9273 fp0 = tcg_temp_new_i32();
9274 gen_load_fpr32(ctx, fp0, fs);
9275 gen_store_fpr32(ctx, fp0, fd);
9276 tcg_temp_free_i32(fp0);
9277 gen_set_label(l1);
9279 opn = "movz.s";
9280 break;
9281 case OPC_MOVN_S:
9282 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9284 TCGLabel *l1 = gen_new_label();
9285 TCGv_i32 fp0;
9287 if (ft != 0) {
9288 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9289 fp0 = tcg_temp_new_i32();
9290 gen_load_fpr32(ctx, fp0, fs);
9291 gen_store_fpr32(ctx, fp0, fd);
9292 tcg_temp_free_i32(fp0);
9293 gen_set_label(l1);
9296 opn = "movn.s";
9297 break;
9298 case OPC_RECIP_S:
9299 check_cop1x(ctx);
9301 TCGv_i32 fp0 = tcg_temp_new_i32();
9303 gen_load_fpr32(ctx, fp0, fs);
9304 gen_helper_float_recip_s(fp0, cpu_env, fp0);
9305 gen_store_fpr32(ctx, fp0, fd);
9306 tcg_temp_free_i32(fp0);
9308 opn = "recip.s";
9309 break;
9310 case OPC_RSQRT_S:
9311 check_cop1x(ctx);
9313 TCGv_i32 fp0 = tcg_temp_new_i32();
9315 gen_load_fpr32(ctx, fp0, fs);
9316 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
9317 gen_store_fpr32(ctx, fp0, fd);
9318 tcg_temp_free_i32(fp0);
9320 opn = "rsqrt.s";
9321 break;
9322 case OPC_MADDF_S:
9323 check_insn(ctx, ISA_MIPS32R6);
9325 TCGv_i32 fp0 = tcg_temp_new_i32();
9326 TCGv_i32 fp1 = tcg_temp_new_i32();
9327 TCGv_i32 fp2 = tcg_temp_new_i32();
9328 gen_load_fpr32(ctx, fp0, fs);
9329 gen_load_fpr32(ctx, fp1, ft);
9330 gen_load_fpr32(ctx, fp2, fd);
9331 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
9332 gen_store_fpr32(ctx, fp2, fd);
9333 tcg_temp_free_i32(fp2);
9334 tcg_temp_free_i32(fp1);
9335 tcg_temp_free_i32(fp0);
9336 opn = "maddf.s";
9338 break;
9339 case OPC_MSUBF_S:
9340 check_insn(ctx, ISA_MIPS32R6);
9342 TCGv_i32 fp0 = tcg_temp_new_i32();
9343 TCGv_i32 fp1 = tcg_temp_new_i32();
9344 TCGv_i32 fp2 = tcg_temp_new_i32();
9345 gen_load_fpr32(ctx, fp0, fs);
9346 gen_load_fpr32(ctx, fp1, ft);
9347 gen_load_fpr32(ctx, fp2, fd);
9348 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9349 gen_store_fpr32(ctx, fp2, fd);
9350 tcg_temp_free_i32(fp2);
9351 tcg_temp_free_i32(fp1);
9352 tcg_temp_free_i32(fp0);
9353 opn = "msubf.s";
9355 break;
9356 case OPC_RINT_S:
9357 check_insn(ctx, ISA_MIPS32R6);
9359 TCGv_i32 fp0 = tcg_temp_new_i32();
9360 gen_load_fpr32(ctx, fp0, fs);
9361 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9362 gen_store_fpr32(ctx, fp0, fd);
9363 tcg_temp_free_i32(fp0);
9364 opn = "rint.s";
9366 break;
9367 case OPC_CLASS_S:
9368 check_insn(ctx, ISA_MIPS32R6);
9370 TCGv_i32 fp0 = tcg_temp_new_i32();
9371 gen_load_fpr32(ctx, fp0, fs);
9372 gen_helper_float_class_s(fp0, fp0);
9373 gen_store_fpr32(ctx, fp0, fd);
9374 tcg_temp_free_i32(fp0);
9375 opn = "class.s";
9377 break;
9378 case OPC_MIN_S: /* OPC_RECIP2_S */
9379 if (ctx->insn_flags & ISA_MIPS32R6) {
9380 /* OPC_MIN_S */
9381 TCGv_i32 fp0 = tcg_temp_new_i32();
9382 TCGv_i32 fp1 = tcg_temp_new_i32();
9383 TCGv_i32 fp2 = tcg_temp_new_i32();
9384 gen_load_fpr32(ctx, fp0, fs);
9385 gen_load_fpr32(ctx, fp1, ft);
9386 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9387 gen_store_fpr32(ctx, fp2, fd);
9388 tcg_temp_free_i32(fp2);
9389 tcg_temp_free_i32(fp1);
9390 tcg_temp_free_i32(fp0);
9391 opn = "min.s";
9392 } else {
9393 /* OPC_RECIP2_S */
9394 check_cp1_64bitmode(ctx);
9396 TCGv_i32 fp0 = tcg_temp_new_i32();
9397 TCGv_i32 fp1 = tcg_temp_new_i32();
9399 gen_load_fpr32(ctx, fp0, fs);
9400 gen_load_fpr32(ctx, fp1, ft);
9401 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9402 tcg_temp_free_i32(fp1);
9403 gen_store_fpr32(ctx, fp0, fd);
9404 tcg_temp_free_i32(fp0);
9406 opn = "recip2.s";
9408 break;
9409 case OPC_MINA_S: /* OPC_RECIP1_S */
9410 if (ctx->insn_flags & ISA_MIPS32R6) {
9411 /* OPC_MINA_S */
9412 TCGv_i32 fp0 = tcg_temp_new_i32();
9413 TCGv_i32 fp1 = tcg_temp_new_i32();
9414 TCGv_i32 fp2 = tcg_temp_new_i32();
9415 gen_load_fpr32(ctx, fp0, fs);
9416 gen_load_fpr32(ctx, fp1, ft);
9417 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9418 gen_store_fpr32(ctx, fp2, fd);
9419 tcg_temp_free_i32(fp2);
9420 tcg_temp_free_i32(fp1);
9421 tcg_temp_free_i32(fp0);
9422 opn = "mina.s";
9423 } else {
9424 /* OPC_RECIP1_S */
9425 check_cp1_64bitmode(ctx);
9427 TCGv_i32 fp0 = tcg_temp_new_i32();
9429 gen_load_fpr32(ctx, fp0, fs);
9430 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9431 gen_store_fpr32(ctx, fp0, fd);
9432 tcg_temp_free_i32(fp0);
9434 opn = "recip1.s";
9436 break;
9437 case OPC_MAX_S: /* OPC_RSQRT1_S */
9438 if (ctx->insn_flags & ISA_MIPS32R6) {
9439 /* OPC_MAX_S */
9440 TCGv_i32 fp0 = tcg_temp_new_i32();
9441 TCGv_i32 fp1 = tcg_temp_new_i32();
9442 gen_load_fpr32(ctx, fp0, fs);
9443 gen_load_fpr32(ctx, fp1, ft);
9444 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9445 gen_store_fpr32(ctx, fp1, fd);
9446 tcg_temp_free_i32(fp1);
9447 tcg_temp_free_i32(fp0);
9448 opn = "max.s";
9449 } else {
9450 /* OPC_RSQRT1_S */
9451 check_cp1_64bitmode(ctx);
9453 TCGv_i32 fp0 = tcg_temp_new_i32();
9455 gen_load_fpr32(ctx, fp0, fs);
9456 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9457 gen_store_fpr32(ctx, fp0, fd);
9458 tcg_temp_free_i32(fp0);
9460 opn = "rsqrt1.s";
9462 break;
9463 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9464 if (ctx->insn_flags & ISA_MIPS32R6) {
9465 /* OPC_MAXA_S */
9466 TCGv_i32 fp0 = tcg_temp_new_i32();
9467 TCGv_i32 fp1 = tcg_temp_new_i32();
9468 gen_load_fpr32(ctx, fp0, fs);
9469 gen_load_fpr32(ctx, fp1, ft);
9470 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9471 gen_store_fpr32(ctx, fp1, fd);
9472 tcg_temp_free_i32(fp1);
9473 tcg_temp_free_i32(fp0);
9474 opn = "maxa.s";
9475 } else {
9476 /* OPC_RSQRT2_S */
9477 check_cp1_64bitmode(ctx);
9479 TCGv_i32 fp0 = tcg_temp_new_i32();
9480 TCGv_i32 fp1 = tcg_temp_new_i32();
9482 gen_load_fpr32(ctx, fp0, fs);
9483 gen_load_fpr32(ctx, fp1, ft);
9484 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9485 tcg_temp_free_i32(fp1);
9486 gen_store_fpr32(ctx, fp0, fd);
9487 tcg_temp_free_i32(fp0);
9489 opn = "rsqrt2.s";
9491 break;
9492 case OPC_CVT_D_S:
9493 check_cp1_registers(ctx, fd);
9495 TCGv_i32 fp32 = tcg_temp_new_i32();
9496 TCGv_i64 fp64 = tcg_temp_new_i64();
9498 gen_load_fpr32(ctx, fp32, fs);
9499 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9500 tcg_temp_free_i32(fp32);
9501 gen_store_fpr64(ctx, fp64, fd);
9502 tcg_temp_free_i64(fp64);
9504 opn = "cvt.d.s";
9505 break;
9506 case OPC_CVT_W_S:
9508 TCGv_i32 fp0 = tcg_temp_new_i32();
9510 gen_load_fpr32(ctx, fp0, fs);
9511 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
9512 gen_store_fpr32(ctx, fp0, fd);
9513 tcg_temp_free_i32(fp0);
9515 opn = "cvt.w.s";
9516 break;
9517 case OPC_CVT_L_S:
9518 check_cp1_64bitmode(ctx);
9520 TCGv_i32 fp32 = tcg_temp_new_i32();
9521 TCGv_i64 fp64 = tcg_temp_new_i64();
9523 gen_load_fpr32(ctx, fp32, fs);
9524 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
9525 tcg_temp_free_i32(fp32);
9526 gen_store_fpr64(ctx, fp64, fd);
9527 tcg_temp_free_i64(fp64);
9529 opn = "cvt.l.s";
9530 break;
9531 case OPC_CVT_PS_S:
9532 check_ps(ctx);
9534 TCGv_i64 fp64 = tcg_temp_new_i64();
9535 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9536 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9538 gen_load_fpr32(ctx, fp32_0, fs);
9539 gen_load_fpr32(ctx, fp32_1, ft);
9540 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9541 tcg_temp_free_i32(fp32_1);
9542 tcg_temp_free_i32(fp32_0);
9543 gen_store_fpr64(ctx, fp64, fd);
9544 tcg_temp_free_i64(fp64);
9546 opn = "cvt.ps.s";
9547 break;
9548 case OPC_CMP_F_S:
9549 case OPC_CMP_UN_S:
9550 case OPC_CMP_EQ_S:
9551 case OPC_CMP_UEQ_S:
9552 case OPC_CMP_OLT_S:
9553 case OPC_CMP_ULT_S:
9554 case OPC_CMP_OLE_S:
9555 case OPC_CMP_ULE_S:
9556 case OPC_CMP_SF_S:
9557 case OPC_CMP_NGLE_S:
9558 case OPC_CMP_SEQ_S:
9559 case OPC_CMP_NGL_S:
9560 case OPC_CMP_LT_S:
9561 case OPC_CMP_NGE_S:
9562 case OPC_CMP_LE_S:
9563 case OPC_CMP_NGT_S:
9564 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9565 if (ctx->opcode & (1 << 6)) {
9566 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9567 opn = condnames_abs[func-48];
9568 } else {
9569 gen_cmp_s(ctx, func-48, ft, fs, cc);
9570 opn = condnames[func-48];
9572 optype = CMPOP;
9573 break;
9574 case OPC_ADD_D:
9575 check_cp1_registers(ctx, fs | ft | fd);
9577 TCGv_i64 fp0 = tcg_temp_new_i64();
9578 TCGv_i64 fp1 = tcg_temp_new_i64();
9580 gen_load_fpr64(ctx, fp0, fs);
9581 gen_load_fpr64(ctx, fp1, ft);
9582 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9583 tcg_temp_free_i64(fp1);
9584 gen_store_fpr64(ctx, fp0, fd);
9585 tcg_temp_free_i64(fp0);
9587 opn = "add.d";
9588 optype = BINOP;
9589 break;
9590 case OPC_SUB_D:
9591 check_cp1_registers(ctx, fs | ft | fd);
9593 TCGv_i64 fp0 = tcg_temp_new_i64();
9594 TCGv_i64 fp1 = tcg_temp_new_i64();
9596 gen_load_fpr64(ctx, fp0, fs);
9597 gen_load_fpr64(ctx, fp1, ft);
9598 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9599 tcg_temp_free_i64(fp1);
9600 gen_store_fpr64(ctx, fp0, fd);
9601 tcg_temp_free_i64(fp0);
9603 opn = "sub.d";
9604 optype = BINOP;
9605 break;
9606 case OPC_MUL_D:
9607 check_cp1_registers(ctx, fs | ft | fd);
9609 TCGv_i64 fp0 = tcg_temp_new_i64();
9610 TCGv_i64 fp1 = tcg_temp_new_i64();
9612 gen_load_fpr64(ctx, fp0, fs);
9613 gen_load_fpr64(ctx, fp1, ft);
9614 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9615 tcg_temp_free_i64(fp1);
9616 gen_store_fpr64(ctx, fp0, fd);
9617 tcg_temp_free_i64(fp0);
9619 opn = "mul.d";
9620 optype = BINOP;
9621 break;
9622 case OPC_DIV_D:
9623 check_cp1_registers(ctx, fs | ft | fd);
9625 TCGv_i64 fp0 = tcg_temp_new_i64();
9626 TCGv_i64 fp1 = tcg_temp_new_i64();
9628 gen_load_fpr64(ctx, fp0, fs);
9629 gen_load_fpr64(ctx, fp1, ft);
9630 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9631 tcg_temp_free_i64(fp1);
9632 gen_store_fpr64(ctx, fp0, fd);
9633 tcg_temp_free_i64(fp0);
9635 opn = "div.d";
9636 optype = BINOP;
9637 break;
9638 case OPC_SQRT_D:
9639 check_cp1_registers(ctx, fs | fd);
9641 TCGv_i64 fp0 = tcg_temp_new_i64();
9643 gen_load_fpr64(ctx, fp0, fs);
9644 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9645 gen_store_fpr64(ctx, fp0, fd);
9646 tcg_temp_free_i64(fp0);
9648 opn = "sqrt.d";
9649 break;
9650 case OPC_ABS_D:
9651 check_cp1_registers(ctx, fs | fd);
9653 TCGv_i64 fp0 = tcg_temp_new_i64();
9655 gen_load_fpr64(ctx, fp0, fs);
9656 gen_helper_float_abs_d(fp0, fp0);
9657 gen_store_fpr64(ctx, fp0, fd);
9658 tcg_temp_free_i64(fp0);
9660 opn = "abs.d";
9661 break;
9662 case OPC_MOV_D:
9663 check_cp1_registers(ctx, fs | fd);
9665 TCGv_i64 fp0 = tcg_temp_new_i64();
9667 gen_load_fpr64(ctx, fp0, fs);
9668 gen_store_fpr64(ctx, fp0, fd);
9669 tcg_temp_free_i64(fp0);
9671 opn = "mov.d";
9672 break;
9673 case OPC_NEG_D:
9674 check_cp1_registers(ctx, fs | fd);
9676 TCGv_i64 fp0 = tcg_temp_new_i64();
9678 gen_load_fpr64(ctx, fp0, fs);
9679 gen_helper_float_chs_d(fp0, fp0);
9680 gen_store_fpr64(ctx, fp0, fd);
9681 tcg_temp_free_i64(fp0);
9683 opn = "neg.d";
9684 break;
9685 case OPC_ROUND_L_D:
9686 check_cp1_64bitmode(ctx);
9688 TCGv_i64 fp0 = tcg_temp_new_i64();
9690 gen_load_fpr64(ctx, fp0, fs);
9691 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
9692 gen_store_fpr64(ctx, fp0, fd);
9693 tcg_temp_free_i64(fp0);
9695 opn = "round.l.d";
9696 break;
9697 case OPC_TRUNC_L_D:
9698 check_cp1_64bitmode(ctx);
9700 TCGv_i64 fp0 = tcg_temp_new_i64();
9702 gen_load_fpr64(ctx, fp0, fs);
9703 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
9704 gen_store_fpr64(ctx, fp0, fd);
9705 tcg_temp_free_i64(fp0);
9707 opn = "trunc.l.d";
9708 break;
9709 case OPC_CEIL_L_D:
9710 check_cp1_64bitmode(ctx);
9712 TCGv_i64 fp0 = tcg_temp_new_i64();
9714 gen_load_fpr64(ctx, fp0, fs);
9715 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
9716 gen_store_fpr64(ctx, fp0, fd);
9717 tcg_temp_free_i64(fp0);
9719 opn = "ceil.l.d";
9720 break;
9721 case OPC_FLOOR_L_D:
9722 check_cp1_64bitmode(ctx);
9724 TCGv_i64 fp0 = tcg_temp_new_i64();
9726 gen_load_fpr64(ctx, fp0, fs);
9727 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
9728 gen_store_fpr64(ctx, fp0, fd);
9729 tcg_temp_free_i64(fp0);
9731 opn = "floor.l.d";
9732 break;
9733 case OPC_ROUND_W_D:
9734 check_cp1_registers(ctx, fs);
9736 TCGv_i32 fp32 = tcg_temp_new_i32();
9737 TCGv_i64 fp64 = tcg_temp_new_i64();
9739 gen_load_fpr64(ctx, fp64, fs);
9740 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
9741 tcg_temp_free_i64(fp64);
9742 gen_store_fpr32(ctx, fp32, fd);
9743 tcg_temp_free_i32(fp32);
9745 opn = "round.w.d";
9746 break;
9747 case OPC_TRUNC_W_D:
9748 check_cp1_registers(ctx, fs);
9750 TCGv_i32 fp32 = tcg_temp_new_i32();
9751 TCGv_i64 fp64 = tcg_temp_new_i64();
9753 gen_load_fpr64(ctx, fp64, fs);
9754 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
9755 tcg_temp_free_i64(fp64);
9756 gen_store_fpr32(ctx, fp32, fd);
9757 tcg_temp_free_i32(fp32);
9759 opn = "trunc.w.d";
9760 break;
9761 case OPC_CEIL_W_D:
9762 check_cp1_registers(ctx, fs);
9764 TCGv_i32 fp32 = tcg_temp_new_i32();
9765 TCGv_i64 fp64 = tcg_temp_new_i64();
9767 gen_load_fpr64(ctx, fp64, fs);
9768 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
9769 tcg_temp_free_i64(fp64);
9770 gen_store_fpr32(ctx, fp32, fd);
9771 tcg_temp_free_i32(fp32);
9773 opn = "ceil.w.d";
9774 break;
9775 case OPC_FLOOR_W_D:
9776 check_cp1_registers(ctx, fs);
9778 TCGv_i32 fp32 = tcg_temp_new_i32();
9779 TCGv_i64 fp64 = tcg_temp_new_i64();
9781 gen_load_fpr64(ctx, fp64, fs);
9782 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
9783 tcg_temp_free_i64(fp64);
9784 gen_store_fpr32(ctx, fp32, fd);
9785 tcg_temp_free_i32(fp32);
9787 opn = "floor.w.d";
9788 break;
9789 case OPC_SEL_D:
9790 check_insn(ctx, ISA_MIPS32R6);
9791 gen_sel_d(ctx, op1, fd, ft, fs);
9792 opn = "sel.d";
9793 break;
9794 case OPC_SELEQZ_D:
9795 check_insn(ctx, ISA_MIPS32R6);
9796 gen_sel_d(ctx, op1, fd, ft, fs);
9797 opn = "seleqz.d";
9798 break;
9799 case OPC_SELNEZ_D:
9800 check_insn(ctx, ISA_MIPS32R6);
9801 gen_sel_d(ctx, op1, fd, ft, fs);
9802 opn = "selnez.d";
9803 break;
9804 case OPC_MOVCF_D:
9805 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9806 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9807 opn = "movcf.d";
9808 break;
9809 case OPC_MOVZ_D:
9810 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9812 TCGLabel *l1 = gen_new_label();
9813 TCGv_i64 fp0;
9815 if (ft != 0) {
9816 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9818 fp0 = tcg_temp_new_i64();
9819 gen_load_fpr64(ctx, fp0, fs);
9820 gen_store_fpr64(ctx, fp0, fd);
9821 tcg_temp_free_i64(fp0);
9822 gen_set_label(l1);
9824 opn = "movz.d";
9825 break;
9826 case OPC_MOVN_D:
9827 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9829 TCGLabel *l1 = gen_new_label();
9830 TCGv_i64 fp0;
9832 if (ft != 0) {
9833 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9834 fp0 = tcg_temp_new_i64();
9835 gen_load_fpr64(ctx, fp0, fs);
9836 gen_store_fpr64(ctx, fp0, fd);
9837 tcg_temp_free_i64(fp0);
9838 gen_set_label(l1);
9841 opn = "movn.d";
9842 break;
9843 case OPC_RECIP_D:
9844 check_cp1_64bitmode(ctx);
9846 TCGv_i64 fp0 = tcg_temp_new_i64();
9848 gen_load_fpr64(ctx, fp0, fs);
9849 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9850 gen_store_fpr64(ctx, fp0, fd);
9851 tcg_temp_free_i64(fp0);
9853 opn = "recip.d";
9854 break;
9855 case OPC_RSQRT_D:
9856 check_cp1_64bitmode(ctx);
9858 TCGv_i64 fp0 = tcg_temp_new_i64();
9860 gen_load_fpr64(ctx, fp0, fs);
9861 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9862 gen_store_fpr64(ctx, fp0, fd);
9863 tcg_temp_free_i64(fp0);
9865 opn = "rsqrt.d";
9866 break;
9867 case OPC_MADDF_D:
9868 check_insn(ctx, ISA_MIPS32R6);
9870 TCGv_i64 fp0 = tcg_temp_new_i64();
9871 TCGv_i64 fp1 = tcg_temp_new_i64();
9872 TCGv_i64 fp2 = tcg_temp_new_i64();
9873 gen_load_fpr64(ctx, fp0, fs);
9874 gen_load_fpr64(ctx, fp1, ft);
9875 gen_load_fpr64(ctx, fp2, fd);
9876 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9877 gen_store_fpr64(ctx, fp2, fd);
9878 tcg_temp_free_i64(fp2);
9879 tcg_temp_free_i64(fp1);
9880 tcg_temp_free_i64(fp0);
9881 opn = "maddf.d";
9883 break;
9884 case OPC_MSUBF_D:
9885 check_insn(ctx, ISA_MIPS32R6);
9887 TCGv_i64 fp0 = tcg_temp_new_i64();
9888 TCGv_i64 fp1 = tcg_temp_new_i64();
9889 TCGv_i64 fp2 = tcg_temp_new_i64();
9890 gen_load_fpr64(ctx, fp0, fs);
9891 gen_load_fpr64(ctx, fp1, ft);
9892 gen_load_fpr64(ctx, fp2, fd);
9893 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9894 gen_store_fpr64(ctx, fp2, fd);
9895 tcg_temp_free_i64(fp2);
9896 tcg_temp_free_i64(fp1);
9897 tcg_temp_free_i64(fp0);
9898 opn = "msubf.d";
9900 break;
9901 case OPC_RINT_D:
9902 check_insn(ctx, ISA_MIPS32R6);
9904 TCGv_i64 fp0 = tcg_temp_new_i64();
9905 gen_load_fpr64(ctx, fp0, fs);
9906 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9907 gen_store_fpr64(ctx, fp0, fd);
9908 tcg_temp_free_i64(fp0);
9909 opn = "rint.d";
9911 break;
9912 case OPC_CLASS_D:
9913 check_insn(ctx, ISA_MIPS32R6);
9915 TCGv_i64 fp0 = tcg_temp_new_i64();
9916 gen_load_fpr64(ctx, fp0, fs);
9917 gen_helper_float_class_d(fp0, fp0);
9918 gen_store_fpr64(ctx, fp0, fd);
9919 tcg_temp_free_i64(fp0);
9920 opn = "class.d";
9922 break;
9923 case OPC_MIN_D: /* OPC_RECIP2_D */
9924 if (ctx->insn_flags & ISA_MIPS32R6) {
9925 /* OPC_MIN_D */
9926 TCGv_i64 fp0 = tcg_temp_new_i64();
9927 TCGv_i64 fp1 = tcg_temp_new_i64();
9928 gen_load_fpr64(ctx, fp0, fs);
9929 gen_load_fpr64(ctx, fp1, ft);
9930 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9931 gen_store_fpr64(ctx, fp1, fd);
9932 tcg_temp_free_i64(fp1);
9933 tcg_temp_free_i64(fp0);
9934 opn = "min.d";
9935 } else {
9936 /* OPC_RECIP2_D */
9937 check_cp1_64bitmode(ctx);
9939 TCGv_i64 fp0 = tcg_temp_new_i64();
9940 TCGv_i64 fp1 = tcg_temp_new_i64();
9942 gen_load_fpr64(ctx, fp0, fs);
9943 gen_load_fpr64(ctx, fp1, ft);
9944 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9945 tcg_temp_free_i64(fp1);
9946 gen_store_fpr64(ctx, fp0, fd);
9947 tcg_temp_free_i64(fp0);
9949 opn = "recip2.d";
9951 break;
9952 case OPC_MINA_D: /* OPC_RECIP1_D */
9953 if (ctx->insn_flags & ISA_MIPS32R6) {
9954 /* OPC_MINA_D */
9955 TCGv_i64 fp0 = tcg_temp_new_i64();
9956 TCGv_i64 fp1 = tcg_temp_new_i64();
9957 gen_load_fpr64(ctx, fp0, fs);
9958 gen_load_fpr64(ctx, fp1, ft);
9959 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9960 gen_store_fpr64(ctx, fp1, fd);
9961 tcg_temp_free_i64(fp1);
9962 tcg_temp_free_i64(fp0);
9963 opn = "mina.d";
9964 } else {
9965 /* OPC_RECIP1_D */
9966 check_cp1_64bitmode(ctx);
9968 TCGv_i64 fp0 = tcg_temp_new_i64();
9970 gen_load_fpr64(ctx, fp0, fs);
9971 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9972 gen_store_fpr64(ctx, fp0, fd);
9973 tcg_temp_free_i64(fp0);
9975 opn = "recip1.d";
9977 break;
9978 case OPC_MAX_D: /* OPC_RSQRT1_D */
9979 if (ctx->insn_flags & ISA_MIPS32R6) {
9980 /* OPC_MAX_D */
9981 TCGv_i64 fp0 = tcg_temp_new_i64();
9982 TCGv_i64 fp1 = tcg_temp_new_i64();
9983 gen_load_fpr64(ctx, fp0, fs);
9984 gen_load_fpr64(ctx, fp1, ft);
9985 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9986 gen_store_fpr64(ctx, fp1, fd);
9987 tcg_temp_free_i64(fp1);
9988 tcg_temp_free_i64(fp0);
9989 opn = "max.d";
9990 } else {
9991 /* OPC_RSQRT1_D */
9992 check_cp1_64bitmode(ctx);
9994 TCGv_i64 fp0 = tcg_temp_new_i64();
9996 gen_load_fpr64(ctx, fp0, fs);
9997 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9998 gen_store_fpr64(ctx, fp0, fd);
9999 tcg_temp_free_i64(fp0);
10001 opn = "rsqrt1.d";
10003 break;
10004 case OPC_MAXA_D: /* OPC_RSQRT2_D */
10005 if (ctx->insn_flags & ISA_MIPS32R6) {
10006 /* OPC_MAXA_D */
10007 TCGv_i64 fp0 = tcg_temp_new_i64();
10008 TCGv_i64 fp1 = tcg_temp_new_i64();
10009 gen_load_fpr64(ctx, fp0, fs);
10010 gen_load_fpr64(ctx, fp1, ft);
10011 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
10012 gen_store_fpr64(ctx, fp1, fd);
10013 tcg_temp_free_i64(fp1);
10014 tcg_temp_free_i64(fp0);
10015 opn = "maxa.d";
10016 } else {
10017 /* OPC_RSQRT2_D */
10018 check_cp1_64bitmode(ctx);
10020 TCGv_i64 fp0 = tcg_temp_new_i64();
10021 TCGv_i64 fp1 = tcg_temp_new_i64();
10023 gen_load_fpr64(ctx, fp0, fs);
10024 gen_load_fpr64(ctx, fp1, ft);
10025 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
10026 tcg_temp_free_i64(fp1);
10027 gen_store_fpr64(ctx, fp0, fd);
10028 tcg_temp_free_i64(fp0);
10030 opn = "rsqrt2.d";
10032 break;
10033 case OPC_CMP_F_D:
10034 case OPC_CMP_UN_D:
10035 case OPC_CMP_EQ_D:
10036 case OPC_CMP_UEQ_D:
10037 case OPC_CMP_OLT_D:
10038 case OPC_CMP_ULT_D:
10039 case OPC_CMP_OLE_D:
10040 case OPC_CMP_ULE_D:
10041 case OPC_CMP_SF_D:
10042 case OPC_CMP_NGLE_D:
10043 case OPC_CMP_SEQ_D:
10044 case OPC_CMP_NGL_D:
10045 case OPC_CMP_LT_D:
10046 case OPC_CMP_NGE_D:
10047 case OPC_CMP_LE_D:
10048 case OPC_CMP_NGT_D:
10049 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10050 if (ctx->opcode & (1 << 6)) {
10051 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
10052 opn = condnames_abs[func-48];
10053 } else {
10054 gen_cmp_d(ctx, func-48, ft, fs, cc);
10055 opn = condnames[func-48];
10057 optype = CMPOP;
10058 break;
10059 case OPC_CVT_S_D:
10060 check_cp1_registers(ctx, fs);
10062 TCGv_i32 fp32 = tcg_temp_new_i32();
10063 TCGv_i64 fp64 = tcg_temp_new_i64();
10065 gen_load_fpr64(ctx, fp64, fs);
10066 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
10067 tcg_temp_free_i64(fp64);
10068 gen_store_fpr32(ctx, fp32, fd);
10069 tcg_temp_free_i32(fp32);
10071 opn = "cvt.s.d";
10072 break;
10073 case OPC_CVT_W_D:
10074 check_cp1_registers(ctx, fs);
10076 TCGv_i32 fp32 = tcg_temp_new_i32();
10077 TCGv_i64 fp64 = tcg_temp_new_i64();
10079 gen_load_fpr64(ctx, fp64, fs);
10080 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
10081 tcg_temp_free_i64(fp64);
10082 gen_store_fpr32(ctx, fp32, fd);
10083 tcg_temp_free_i32(fp32);
10085 opn = "cvt.w.d";
10086 break;
10087 case OPC_CVT_L_D:
10088 check_cp1_64bitmode(ctx);
10090 TCGv_i64 fp0 = tcg_temp_new_i64();
10092 gen_load_fpr64(ctx, fp0, fs);
10093 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
10094 gen_store_fpr64(ctx, fp0, fd);
10095 tcg_temp_free_i64(fp0);
10097 opn = "cvt.l.d";
10098 break;
10099 case OPC_CVT_S_W:
10101 TCGv_i32 fp0 = tcg_temp_new_i32();
10103 gen_load_fpr32(ctx, fp0, fs);
10104 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
10105 gen_store_fpr32(ctx, fp0, fd);
10106 tcg_temp_free_i32(fp0);
10108 opn = "cvt.s.w";
10109 break;
10110 case OPC_CVT_D_W:
10111 check_cp1_registers(ctx, fd);
10113 TCGv_i32 fp32 = tcg_temp_new_i32();
10114 TCGv_i64 fp64 = tcg_temp_new_i64();
10116 gen_load_fpr32(ctx, fp32, fs);
10117 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
10118 tcg_temp_free_i32(fp32);
10119 gen_store_fpr64(ctx, fp64, fd);
10120 tcg_temp_free_i64(fp64);
10122 opn = "cvt.d.w";
10123 break;
10124 case OPC_CVT_S_L:
10125 check_cp1_64bitmode(ctx);
10127 TCGv_i32 fp32 = tcg_temp_new_i32();
10128 TCGv_i64 fp64 = tcg_temp_new_i64();
10130 gen_load_fpr64(ctx, fp64, fs);
10131 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
10132 tcg_temp_free_i64(fp64);
10133 gen_store_fpr32(ctx, fp32, fd);
10134 tcg_temp_free_i32(fp32);
10136 opn = "cvt.s.l";
10137 break;
10138 case OPC_CVT_D_L:
10139 check_cp1_64bitmode(ctx);
10141 TCGv_i64 fp0 = tcg_temp_new_i64();
10143 gen_load_fpr64(ctx, fp0, fs);
10144 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
10145 gen_store_fpr64(ctx, fp0, fd);
10146 tcg_temp_free_i64(fp0);
10148 opn = "cvt.d.l";
10149 break;
10150 case OPC_CVT_PS_PW:
10151 check_ps(ctx);
10153 TCGv_i64 fp0 = tcg_temp_new_i64();
10155 gen_load_fpr64(ctx, fp0, fs);
10156 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
10157 gen_store_fpr64(ctx, fp0, fd);
10158 tcg_temp_free_i64(fp0);
10160 opn = "cvt.ps.pw";
10161 break;
10162 case OPC_ADD_PS:
10163 check_ps(ctx);
10165 TCGv_i64 fp0 = tcg_temp_new_i64();
10166 TCGv_i64 fp1 = tcg_temp_new_i64();
10168 gen_load_fpr64(ctx, fp0, fs);
10169 gen_load_fpr64(ctx, fp1, ft);
10170 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
10171 tcg_temp_free_i64(fp1);
10172 gen_store_fpr64(ctx, fp0, fd);
10173 tcg_temp_free_i64(fp0);
10175 opn = "add.ps";
10176 break;
10177 case OPC_SUB_PS:
10178 check_ps(ctx);
10180 TCGv_i64 fp0 = tcg_temp_new_i64();
10181 TCGv_i64 fp1 = tcg_temp_new_i64();
10183 gen_load_fpr64(ctx, fp0, fs);
10184 gen_load_fpr64(ctx, fp1, ft);
10185 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
10186 tcg_temp_free_i64(fp1);
10187 gen_store_fpr64(ctx, fp0, fd);
10188 tcg_temp_free_i64(fp0);
10190 opn = "sub.ps";
10191 break;
10192 case OPC_MUL_PS:
10193 check_ps(ctx);
10195 TCGv_i64 fp0 = tcg_temp_new_i64();
10196 TCGv_i64 fp1 = tcg_temp_new_i64();
10198 gen_load_fpr64(ctx, fp0, fs);
10199 gen_load_fpr64(ctx, fp1, ft);
10200 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
10201 tcg_temp_free_i64(fp1);
10202 gen_store_fpr64(ctx, fp0, fd);
10203 tcg_temp_free_i64(fp0);
10205 opn = "mul.ps";
10206 break;
10207 case OPC_ABS_PS:
10208 check_ps(ctx);
10210 TCGv_i64 fp0 = tcg_temp_new_i64();
10212 gen_load_fpr64(ctx, fp0, fs);
10213 gen_helper_float_abs_ps(fp0, fp0);
10214 gen_store_fpr64(ctx, fp0, fd);
10215 tcg_temp_free_i64(fp0);
10217 opn = "abs.ps";
10218 break;
10219 case OPC_MOV_PS:
10220 check_ps(ctx);
10222 TCGv_i64 fp0 = tcg_temp_new_i64();
10224 gen_load_fpr64(ctx, fp0, fs);
10225 gen_store_fpr64(ctx, fp0, fd);
10226 tcg_temp_free_i64(fp0);
10228 opn = "mov.ps";
10229 break;
10230 case OPC_NEG_PS:
10231 check_ps(ctx);
10233 TCGv_i64 fp0 = tcg_temp_new_i64();
10235 gen_load_fpr64(ctx, fp0, fs);
10236 gen_helper_float_chs_ps(fp0, fp0);
10237 gen_store_fpr64(ctx, fp0, fd);
10238 tcg_temp_free_i64(fp0);
10240 opn = "neg.ps";
10241 break;
10242 case OPC_MOVCF_PS:
10243 check_ps(ctx);
10244 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10245 opn = "movcf.ps";
10246 break;
10247 case OPC_MOVZ_PS:
10248 check_ps(ctx);
10250 TCGLabel *l1 = gen_new_label();
10251 TCGv_i64 fp0;
10253 if (ft != 0)
10254 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10255 fp0 = tcg_temp_new_i64();
10256 gen_load_fpr64(ctx, fp0, fs);
10257 gen_store_fpr64(ctx, fp0, fd);
10258 tcg_temp_free_i64(fp0);
10259 gen_set_label(l1);
10261 opn = "movz.ps";
10262 break;
10263 case OPC_MOVN_PS:
10264 check_ps(ctx);
10266 TCGLabel *l1 = gen_new_label();
10267 TCGv_i64 fp0;
10269 if (ft != 0) {
10270 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10271 fp0 = tcg_temp_new_i64();
10272 gen_load_fpr64(ctx, fp0, fs);
10273 gen_store_fpr64(ctx, fp0, fd);
10274 tcg_temp_free_i64(fp0);
10275 gen_set_label(l1);
10278 opn = "movn.ps";
10279 break;
10280 case OPC_ADDR_PS:
10281 check_ps(ctx);
10283 TCGv_i64 fp0 = tcg_temp_new_i64();
10284 TCGv_i64 fp1 = tcg_temp_new_i64();
10286 gen_load_fpr64(ctx, fp0, ft);
10287 gen_load_fpr64(ctx, fp1, fs);
10288 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
10289 tcg_temp_free_i64(fp1);
10290 gen_store_fpr64(ctx, fp0, fd);
10291 tcg_temp_free_i64(fp0);
10293 opn = "addr.ps";
10294 break;
10295 case OPC_MULR_PS:
10296 check_ps(ctx);
10298 TCGv_i64 fp0 = tcg_temp_new_i64();
10299 TCGv_i64 fp1 = tcg_temp_new_i64();
10301 gen_load_fpr64(ctx, fp0, ft);
10302 gen_load_fpr64(ctx, fp1, fs);
10303 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
10304 tcg_temp_free_i64(fp1);
10305 gen_store_fpr64(ctx, fp0, fd);
10306 tcg_temp_free_i64(fp0);
10308 opn = "mulr.ps";
10309 break;
10310 case OPC_RECIP2_PS:
10311 check_ps(ctx);
10313 TCGv_i64 fp0 = tcg_temp_new_i64();
10314 TCGv_i64 fp1 = tcg_temp_new_i64();
10316 gen_load_fpr64(ctx, fp0, fs);
10317 gen_load_fpr64(ctx, fp1, ft);
10318 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
10319 tcg_temp_free_i64(fp1);
10320 gen_store_fpr64(ctx, fp0, fd);
10321 tcg_temp_free_i64(fp0);
10323 opn = "recip2.ps";
10324 break;
10325 case OPC_RECIP1_PS:
10326 check_ps(ctx);
10328 TCGv_i64 fp0 = tcg_temp_new_i64();
10330 gen_load_fpr64(ctx, fp0, fs);
10331 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
10332 gen_store_fpr64(ctx, fp0, fd);
10333 tcg_temp_free_i64(fp0);
10335 opn = "recip1.ps";
10336 break;
10337 case OPC_RSQRT1_PS:
10338 check_ps(ctx);
10340 TCGv_i64 fp0 = tcg_temp_new_i64();
10342 gen_load_fpr64(ctx, fp0, fs);
10343 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
10344 gen_store_fpr64(ctx, fp0, fd);
10345 tcg_temp_free_i64(fp0);
10347 opn = "rsqrt1.ps";
10348 break;
10349 case OPC_RSQRT2_PS:
10350 check_ps(ctx);
10352 TCGv_i64 fp0 = tcg_temp_new_i64();
10353 TCGv_i64 fp1 = tcg_temp_new_i64();
10355 gen_load_fpr64(ctx, fp0, fs);
10356 gen_load_fpr64(ctx, fp1, ft);
10357 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
10358 tcg_temp_free_i64(fp1);
10359 gen_store_fpr64(ctx, fp0, fd);
10360 tcg_temp_free_i64(fp0);
10362 opn = "rsqrt2.ps";
10363 break;
10364 case OPC_CVT_S_PU:
10365 check_cp1_64bitmode(ctx);
10367 TCGv_i32 fp0 = tcg_temp_new_i32();
10369 gen_load_fpr32h(ctx, fp0, fs);
10370 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
10371 gen_store_fpr32(ctx, fp0, fd);
10372 tcg_temp_free_i32(fp0);
10374 opn = "cvt.s.pu";
10375 break;
10376 case OPC_CVT_PW_PS:
10377 check_ps(ctx);
10379 TCGv_i64 fp0 = tcg_temp_new_i64();
10381 gen_load_fpr64(ctx, fp0, fs);
10382 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
10383 gen_store_fpr64(ctx, fp0, fd);
10384 tcg_temp_free_i64(fp0);
10386 opn = "cvt.pw.ps";
10387 break;
10388 case OPC_CVT_S_PL:
10389 check_cp1_64bitmode(ctx);
10391 TCGv_i32 fp0 = tcg_temp_new_i32();
10393 gen_load_fpr32(ctx, fp0, fs);
10394 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10395 gen_store_fpr32(ctx, fp0, fd);
10396 tcg_temp_free_i32(fp0);
10398 opn = "cvt.s.pl";
10399 break;
10400 case OPC_PLL_PS:
10401 check_ps(ctx);
10403 TCGv_i32 fp0 = tcg_temp_new_i32();
10404 TCGv_i32 fp1 = tcg_temp_new_i32();
10406 gen_load_fpr32(ctx, fp0, fs);
10407 gen_load_fpr32(ctx, fp1, ft);
10408 gen_store_fpr32h(ctx, fp0, fd);
10409 gen_store_fpr32(ctx, fp1, fd);
10410 tcg_temp_free_i32(fp0);
10411 tcg_temp_free_i32(fp1);
10413 opn = "pll.ps";
10414 break;
10415 case OPC_PLU_PS:
10416 check_ps(ctx);
10418 TCGv_i32 fp0 = tcg_temp_new_i32();
10419 TCGv_i32 fp1 = tcg_temp_new_i32();
10421 gen_load_fpr32(ctx, fp0, fs);
10422 gen_load_fpr32h(ctx, fp1, ft);
10423 gen_store_fpr32(ctx, fp1, fd);
10424 gen_store_fpr32h(ctx, fp0, fd);
10425 tcg_temp_free_i32(fp0);
10426 tcg_temp_free_i32(fp1);
10428 opn = "plu.ps";
10429 break;
10430 case OPC_PUL_PS:
10431 check_ps(ctx);
10433 TCGv_i32 fp0 = tcg_temp_new_i32();
10434 TCGv_i32 fp1 = tcg_temp_new_i32();
10436 gen_load_fpr32h(ctx, fp0, fs);
10437 gen_load_fpr32(ctx, fp1, ft);
10438 gen_store_fpr32(ctx, fp1, fd);
10439 gen_store_fpr32h(ctx, fp0, fd);
10440 tcg_temp_free_i32(fp0);
10441 tcg_temp_free_i32(fp1);
10443 opn = "pul.ps";
10444 break;
10445 case OPC_PUU_PS:
10446 check_ps(ctx);
10448 TCGv_i32 fp0 = tcg_temp_new_i32();
10449 TCGv_i32 fp1 = tcg_temp_new_i32();
10451 gen_load_fpr32h(ctx, fp0, fs);
10452 gen_load_fpr32h(ctx, fp1, ft);
10453 gen_store_fpr32(ctx, fp1, fd);
10454 gen_store_fpr32h(ctx, fp0, fd);
10455 tcg_temp_free_i32(fp0);
10456 tcg_temp_free_i32(fp1);
10458 opn = "puu.ps";
10459 break;
10460 case OPC_CMP_F_PS:
10461 case OPC_CMP_UN_PS:
10462 case OPC_CMP_EQ_PS:
10463 case OPC_CMP_UEQ_PS:
10464 case OPC_CMP_OLT_PS:
10465 case OPC_CMP_ULT_PS:
10466 case OPC_CMP_OLE_PS:
10467 case OPC_CMP_ULE_PS:
10468 case OPC_CMP_SF_PS:
10469 case OPC_CMP_NGLE_PS:
10470 case OPC_CMP_SEQ_PS:
10471 case OPC_CMP_NGL_PS:
10472 case OPC_CMP_LT_PS:
10473 case OPC_CMP_NGE_PS:
10474 case OPC_CMP_LE_PS:
10475 case OPC_CMP_NGT_PS:
10476 if (ctx->opcode & (1 << 6)) {
10477 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10478 opn = condnames_abs[func-48];
10479 } else {
10480 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10481 opn = condnames[func-48];
10483 optype = CMPOP;
10484 break;
10485 default:
10486 MIPS_INVAL(opn);
10487 generate_exception (ctx, EXCP_RI);
10488 return;
10490 (void)opn; /* avoid a compiler warning */
10491 switch (optype) {
10492 case BINOP:
10493 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
10494 break;
10495 case CMPOP:
10496 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
10497 break;
10498 default:
10499 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
10500 break;
10504 /* Coprocessor 3 (FPU) */
10505 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10506 int fd, int fs, int base, int index)
10508 const char *opn = "extended float load/store";
10509 int store = 0;
10510 TCGv t0 = tcg_temp_new();
10512 if (base == 0) {
10513 gen_load_gpr(t0, index);
10514 } else if (index == 0) {
10515 gen_load_gpr(t0, base);
10516 } else {
10517 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10519 /* Don't do NOP if destination is zero: we must perform the actual
10520 memory access. */
10521 switch (opc) {
10522 case OPC_LWXC1:
10523 check_cop1x(ctx);
10525 TCGv_i32 fp0 = tcg_temp_new_i32();
10527 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10528 tcg_gen_trunc_tl_i32(fp0, t0);
10529 gen_store_fpr32(ctx, fp0, fd);
10530 tcg_temp_free_i32(fp0);
10532 opn = "lwxc1";
10533 break;
10534 case OPC_LDXC1:
10535 check_cop1x(ctx);
10536 check_cp1_registers(ctx, fd);
10538 TCGv_i64 fp0 = tcg_temp_new_i64();
10539 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10540 gen_store_fpr64(ctx, fp0, fd);
10541 tcg_temp_free_i64(fp0);
10543 opn = "ldxc1";
10544 break;
10545 case OPC_LUXC1:
10546 check_cp1_64bitmode(ctx);
10547 tcg_gen_andi_tl(t0, t0, ~0x7);
10549 TCGv_i64 fp0 = tcg_temp_new_i64();
10551 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10552 gen_store_fpr64(ctx, fp0, fd);
10553 tcg_temp_free_i64(fp0);
10555 opn = "luxc1";
10556 break;
10557 case OPC_SWXC1:
10558 check_cop1x(ctx);
10560 TCGv_i32 fp0 = tcg_temp_new_i32();
10561 gen_load_fpr32(ctx, fp0, fs);
10562 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10563 tcg_temp_free_i32(fp0);
10565 opn = "swxc1";
10566 store = 1;
10567 break;
10568 case OPC_SDXC1:
10569 check_cop1x(ctx);
10570 check_cp1_registers(ctx, fs);
10572 TCGv_i64 fp0 = tcg_temp_new_i64();
10573 gen_load_fpr64(ctx, fp0, fs);
10574 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10575 tcg_temp_free_i64(fp0);
10577 opn = "sdxc1";
10578 store = 1;
10579 break;
10580 case OPC_SUXC1:
10581 check_cp1_64bitmode(ctx);
10582 tcg_gen_andi_tl(t0, t0, ~0x7);
10584 TCGv_i64 fp0 = tcg_temp_new_i64();
10585 gen_load_fpr64(ctx, fp0, fs);
10586 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10587 tcg_temp_free_i64(fp0);
10589 opn = "suxc1";
10590 store = 1;
10591 break;
10593 tcg_temp_free(t0);
10594 (void)opn; (void)store; /* avoid compiler warnings */
10595 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
10596 regnames[index], regnames[base]);
10599 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10600 int fd, int fr, int fs, int ft)
10602 const char *opn = "flt3_arith";
10604 switch (opc) {
10605 case OPC_ALNV_PS:
10606 check_ps(ctx);
10608 TCGv t0 = tcg_temp_local_new();
10609 TCGv_i32 fp = tcg_temp_new_i32();
10610 TCGv_i32 fph = tcg_temp_new_i32();
10611 TCGLabel *l1 = gen_new_label();
10612 TCGLabel *l2 = gen_new_label();
10614 gen_load_gpr(t0, fr);
10615 tcg_gen_andi_tl(t0, t0, 0x7);
10617 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10618 gen_load_fpr32(ctx, fp, fs);
10619 gen_load_fpr32h(ctx, fph, fs);
10620 gen_store_fpr32(ctx, fp, fd);
10621 gen_store_fpr32h(ctx, fph, fd);
10622 tcg_gen_br(l2);
10623 gen_set_label(l1);
10624 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10625 tcg_temp_free(t0);
10626 #ifdef TARGET_WORDS_BIGENDIAN
10627 gen_load_fpr32(ctx, fp, fs);
10628 gen_load_fpr32h(ctx, fph, ft);
10629 gen_store_fpr32h(ctx, fp, fd);
10630 gen_store_fpr32(ctx, fph, fd);
10631 #else
10632 gen_load_fpr32h(ctx, fph, fs);
10633 gen_load_fpr32(ctx, fp, ft);
10634 gen_store_fpr32(ctx, fph, fd);
10635 gen_store_fpr32h(ctx, fp, fd);
10636 #endif
10637 gen_set_label(l2);
10638 tcg_temp_free_i32(fp);
10639 tcg_temp_free_i32(fph);
10641 opn = "alnv.ps";
10642 break;
10643 case OPC_MADD_S:
10644 check_cop1x(ctx);
10646 TCGv_i32 fp0 = tcg_temp_new_i32();
10647 TCGv_i32 fp1 = tcg_temp_new_i32();
10648 TCGv_i32 fp2 = tcg_temp_new_i32();
10650 gen_load_fpr32(ctx, fp0, fs);
10651 gen_load_fpr32(ctx, fp1, ft);
10652 gen_load_fpr32(ctx, fp2, fr);
10653 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10654 tcg_temp_free_i32(fp0);
10655 tcg_temp_free_i32(fp1);
10656 gen_store_fpr32(ctx, fp2, fd);
10657 tcg_temp_free_i32(fp2);
10659 opn = "madd.s";
10660 break;
10661 case OPC_MADD_D:
10662 check_cop1x(ctx);
10663 check_cp1_registers(ctx, fd | fs | ft | fr);
10665 TCGv_i64 fp0 = tcg_temp_new_i64();
10666 TCGv_i64 fp1 = tcg_temp_new_i64();
10667 TCGv_i64 fp2 = tcg_temp_new_i64();
10669 gen_load_fpr64(ctx, fp0, fs);
10670 gen_load_fpr64(ctx, fp1, ft);
10671 gen_load_fpr64(ctx, fp2, fr);
10672 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10673 tcg_temp_free_i64(fp0);
10674 tcg_temp_free_i64(fp1);
10675 gen_store_fpr64(ctx, fp2, fd);
10676 tcg_temp_free_i64(fp2);
10678 opn = "madd.d";
10679 break;
10680 case OPC_MADD_PS:
10681 check_ps(ctx);
10683 TCGv_i64 fp0 = tcg_temp_new_i64();
10684 TCGv_i64 fp1 = tcg_temp_new_i64();
10685 TCGv_i64 fp2 = tcg_temp_new_i64();
10687 gen_load_fpr64(ctx, fp0, fs);
10688 gen_load_fpr64(ctx, fp1, ft);
10689 gen_load_fpr64(ctx, fp2, fr);
10690 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10691 tcg_temp_free_i64(fp0);
10692 tcg_temp_free_i64(fp1);
10693 gen_store_fpr64(ctx, fp2, fd);
10694 tcg_temp_free_i64(fp2);
10696 opn = "madd.ps";
10697 break;
10698 case OPC_MSUB_S:
10699 check_cop1x(ctx);
10701 TCGv_i32 fp0 = tcg_temp_new_i32();
10702 TCGv_i32 fp1 = tcg_temp_new_i32();
10703 TCGv_i32 fp2 = tcg_temp_new_i32();
10705 gen_load_fpr32(ctx, fp0, fs);
10706 gen_load_fpr32(ctx, fp1, ft);
10707 gen_load_fpr32(ctx, fp2, fr);
10708 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10709 tcg_temp_free_i32(fp0);
10710 tcg_temp_free_i32(fp1);
10711 gen_store_fpr32(ctx, fp2, fd);
10712 tcg_temp_free_i32(fp2);
10714 opn = "msub.s";
10715 break;
10716 case OPC_MSUB_D:
10717 check_cop1x(ctx);
10718 check_cp1_registers(ctx, fd | fs | ft | fr);
10720 TCGv_i64 fp0 = tcg_temp_new_i64();
10721 TCGv_i64 fp1 = tcg_temp_new_i64();
10722 TCGv_i64 fp2 = tcg_temp_new_i64();
10724 gen_load_fpr64(ctx, fp0, fs);
10725 gen_load_fpr64(ctx, fp1, ft);
10726 gen_load_fpr64(ctx, fp2, fr);
10727 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10728 tcg_temp_free_i64(fp0);
10729 tcg_temp_free_i64(fp1);
10730 gen_store_fpr64(ctx, fp2, fd);
10731 tcg_temp_free_i64(fp2);
10733 opn = "msub.d";
10734 break;
10735 case OPC_MSUB_PS:
10736 check_ps(ctx);
10738 TCGv_i64 fp0 = tcg_temp_new_i64();
10739 TCGv_i64 fp1 = tcg_temp_new_i64();
10740 TCGv_i64 fp2 = tcg_temp_new_i64();
10742 gen_load_fpr64(ctx, fp0, fs);
10743 gen_load_fpr64(ctx, fp1, ft);
10744 gen_load_fpr64(ctx, fp2, fr);
10745 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10746 tcg_temp_free_i64(fp0);
10747 tcg_temp_free_i64(fp1);
10748 gen_store_fpr64(ctx, fp2, fd);
10749 tcg_temp_free_i64(fp2);
10751 opn = "msub.ps";
10752 break;
10753 case OPC_NMADD_S:
10754 check_cop1x(ctx);
10756 TCGv_i32 fp0 = tcg_temp_new_i32();
10757 TCGv_i32 fp1 = tcg_temp_new_i32();
10758 TCGv_i32 fp2 = tcg_temp_new_i32();
10760 gen_load_fpr32(ctx, fp0, fs);
10761 gen_load_fpr32(ctx, fp1, ft);
10762 gen_load_fpr32(ctx, fp2, fr);
10763 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10764 tcg_temp_free_i32(fp0);
10765 tcg_temp_free_i32(fp1);
10766 gen_store_fpr32(ctx, fp2, fd);
10767 tcg_temp_free_i32(fp2);
10769 opn = "nmadd.s";
10770 break;
10771 case OPC_NMADD_D:
10772 check_cop1x(ctx);
10773 check_cp1_registers(ctx, fd | fs | ft | fr);
10775 TCGv_i64 fp0 = tcg_temp_new_i64();
10776 TCGv_i64 fp1 = tcg_temp_new_i64();
10777 TCGv_i64 fp2 = tcg_temp_new_i64();
10779 gen_load_fpr64(ctx, fp0, fs);
10780 gen_load_fpr64(ctx, fp1, ft);
10781 gen_load_fpr64(ctx, fp2, fr);
10782 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10783 tcg_temp_free_i64(fp0);
10784 tcg_temp_free_i64(fp1);
10785 gen_store_fpr64(ctx, fp2, fd);
10786 tcg_temp_free_i64(fp2);
10788 opn = "nmadd.d";
10789 break;
10790 case OPC_NMADD_PS:
10791 check_ps(ctx);
10793 TCGv_i64 fp0 = tcg_temp_new_i64();
10794 TCGv_i64 fp1 = tcg_temp_new_i64();
10795 TCGv_i64 fp2 = tcg_temp_new_i64();
10797 gen_load_fpr64(ctx, fp0, fs);
10798 gen_load_fpr64(ctx, fp1, ft);
10799 gen_load_fpr64(ctx, fp2, fr);
10800 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10801 tcg_temp_free_i64(fp0);
10802 tcg_temp_free_i64(fp1);
10803 gen_store_fpr64(ctx, fp2, fd);
10804 tcg_temp_free_i64(fp2);
10806 opn = "nmadd.ps";
10807 break;
10808 case OPC_NMSUB_S:
10809 check_cop1x(ctx);
10811 TCGv_i32 fp0 = tcg_temp_new_i32();
10812 TCGv_i32 fp1 = tcg_temp_new_i32();
10813 TCGv_i32 fp2 = tcg_temp_new_i32();
10815 gen_load_fpr32(ctx, fp0, fs);
10816 gen_load_fpr32(ctx, fp1, ft);
10817 gen_load_fpr32(ctx, fp2, fr);
10818 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10819 tcg_temp_free_i32(fp0);
10820 tcg_temp_free_i32(fp1);
10821 gen_store_fpr32(ctx, fp2, fd);
10822 tcg_temp_free_i32(fp2);
10824 opn = "nmsub.s";
10825 break;
10826 case OPC_NMSUB_D:
10827 check_cop1x(ctx);
10828 check_cp1_registers(ctx, fd | fs | ft | fr);
10830 TCGv_i64 fp0 = tcg_temp_new_i64();
10831 TCGv_i64 fp1 = tcg_temp_new_i64();
10832 TCGv_i64 fp2 = tcg_temp_new_i64();
10834 gen_load_fpr64(ctx, fp0, fs);
10835 gen_load_fpr64(ctx, fp1, ft);
10836 gen_load_fpr64(ctx, fp2, fr);
10837 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10838 tcg_temp_free_i64(fp0);
10839 tcg_temp_free_i64(fp1);
10840 gen_store_fpr64(ctx, fp2, fd);
10841 tcg_temp_free_i64(fp2);
10843 opn = "nmsub.d";
10844 break;
10845 case OPC_NMSUB_PS:
10846 check_ps(ctx);
10848 TCGv_i64 fp0 = tcg_temp_new_i64();
10849 TCGv_i64 fp1 = tcg_temp_new_i64();
10850 TCGv_i64 fp2 = tcg_temp_new_i64();
10852 gen_load_fpr64(ctx, fp0, fs);
10853 gen_load_fpr64(ctx, fp1, ft);
10854 gen_load_fpr64(ctx, fp2, fr);
10855 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10856 tcg_temp_free_i64(fp0);
10857 tcg_temp_free_i64(fp1);
10858 gen_store_fpr64(ctx, fp2, fd);
10859 tcg_temp_free_i64(fp2);
10861 opn = "nmsub.ps";
10862 break;
10863 default:
10864 MIPS_INVAL(opn);
10865 generate_exception (ctx, EXCP_RI);
10866 return;
10868 (void)opn; /* avoid a compiler warning */
10869 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
10870 fregnames[fs], fregnames[ft]);
10873 static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
10875 TCGv t0;
10877 #if !defined(CONFIG_USER_ONLY)
10878 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10879 Therefore only check the ISA in system mode. */
10880 check_insn(ctx, ISA_MIPS32R2);
10881 #endif
10882 t0 = tcg_temp_new();
10884 switch (rd) {
10885 case 0:
10886 save_cpu_state(ctx, 1);
10887 gen_helper_rdhwr_cpunum(t0, cpu_env);
10888 gen_store_gpr(t0, rt);
10889 break;
10890 case 1:
10891 save_cpu_state(ctx, 1);
10892 gen_helper_rdhwr_synci_step(t0, cpu_env);
10893 gen_store_gpr(t0, rt);
10894 break;
10895 case 2:
10896 save_cpu_state(ctx, 1);
10897 gen_helper_rdhwr_cc(t0, cpu_env);
10898 gen_store_gpr(t0, rt);
10899 break;
10900 case 3:
10901 save_cpu_state(ctx, 1);
10902 gen_helper_rdhwr_ccres(t0, cpu_env);
10903 gen_store_gpr(t0, rt);
10904 break;
10905 case 29:
10906 #if defined(CONFIG_USER_ONLY)
10907 tcg_gen_ld_tl(t0, cpu_env,
10908 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10909 gen_store_gpr(t0, rt);
10910 break;
10911 #else
10912 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10913 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10914 tcg_gen_ld_tl(t0, cpu_env,
10915 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10916 gen_store_gpr(t0, rt);
10917 } else {
10918 generate_exception(ctx, EXCP_RI);
10920 break;
10921 #endif
10922 default: /* Invalid */
10923 MIPS_INVAL("rdhwr");
10924 generate_exception(ctx, EXCP_RI);
10925 break;
10927 tcg_temp_free(t0);
10930 static inline void clear_branch_hflags(DisasContext *ctx)
10932 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10933 if (ctx->bstate == BS_NONE) {
10934 save_cpu_state(ctx, 0);
10935 } else {
10936 /* it is not safe to save ctx->hflags as hflags may be changed
10937 in execution time by the instruction in delay / forbidden slot. */
10938 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10942 static void gen_branch(DisasContext *ctx, int insn_bytes)
10944 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10945 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10946 /* Branches completion */
10947 clear_branch_hflags(ctx);
10948 ctx->bstate = BS_BRANCH;
10949 /* FIXME: Need to clear can_do_io. */
10950 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10951 case MIPS_HFLAG_FBNSLOT:
10952 MIPS_DEBUG("forbidden slot");
10953 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10954 break;
10955 case MIPS_HFLAG_B:
10956 /* unconditional branch */
10957 MIPS_DEBUG("unconditional branch");
10958 if (proc_hflags & MIPS_HFLAG_BX) {
10959 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10961 gen_goto_tb(ctx, 0, ctx->btarget);
10962 break;
10963 case MIPS_HFLAG_BL:
10964 /* blikely taken case */
10965 MIPS_DEBUG("blikely branch taken");
10966 gen_goto_tb(ctx, 0, ctx->btarget);
10967 break;
10968 case MIPS_HFLAG_BC:
10969 /* Conditional branch */
10970 MIPS_DEBUG("conditional branch");
10972 TCGLabel *l1 = gen_new_label();
10974 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10975 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10976 gen_set_label(l1);
10977 gen_goto_tb(ctx, 0, ctx->btarget);
10979 break;
10980 case MIPS_HFLAG_BR:
10981 /* unconditional branch to register */
10982 MIPS_DEBUG("branch to register");
10983 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10984 TCGv t0 = tcg_temp_new();
10985 TCGv_i32 t1 = tcg_temp_new_i32();
10987 tcg_gen_andi_tl(t0, btarget, 0x1);
10988 tcg_gen_trunc_tl_i32(t1, t0);
10989 tcg_temp_free(t0);
10990 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10991 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10992 tcg_gen_or_i32(hflags, hflags, t1);
10993 tcg_temp_free_i32(t1);
10995 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10996 } else {
10997 tcg_gen_mov_tl(cpu_PC, btarget);
10999 if (ctx->singlestep_enabled) {
11000 save_cpu_state(ctx, 0);
11001 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
11003 tcg_gen_exit_tb(0);
11004 break;
11005 default:
11006 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
11007 abort();
11012 /* Compact Branches */
11013 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
11014 int rs, int rt, int32_t offset)
11016 int bcond_compute = 0;
11017 TCGv t0 = tcg_temp_new();
11018 TCGv t1 = tcg_temp_new();
11019 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
11021 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11022 #ifdef MIPS_DEBUG_DISAS
11023 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11024 "\n", ctx->pc);
11025 #endif
11026 generate_exception(ctx, EXCP_RI);
11027 goto out;
11030 /* Load needed operands and calculate btarget */
11031 switch (opc) {
11032 /* compact branch */
11033 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11034 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11035 gen_load_gpr(t0, rs);
11036 gen_load_gpr(t1, rt);
11037 bcond_compute = 1;
11038 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11039 if (rs <= rt && rs == 0) {
11040 /* OPC_BEQZALC, OPC_BNEZALC */
11041 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11043 break;
11044 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11045 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11046 gen_load_gpr(t0, rs);
11047 gen_load_gpr(t1, rt);
11048 bcond_compute = 1;
11049 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11050 break;
11051 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11052 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11053 if (rs == 0 || rs == rt) {
11054 /* OPC_BLEZALC, OPC_BGEZALC */
11055 /* OPC_BGTZALC, OPC_BLTZALC */
11056 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11058 gen_load_gpr(t0, rs);
11059 gen_load_gpr(t1, rt);
11060 bcond_compute = 1;
11061 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11062 break;
11063 case OPC_BC:
11064 case OPC_BALC:
11065 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11066 break;
11067 case OPC_BEQZC:
11068 case OPC_BNEZC:
11069 if (rs != 0) {
11070 /* OPC_BEQZC, OPC_BNEZC */
11071 gen_load_gpr(t0, rs);
11072 bcond_compute = 1;
11073 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11074 } else {
11075 /* OPC_JIC, OPC_JIALC */
11076 TCGv tbase = tcg_temp_new();
11077 TCGv toffset = tcg_temp_new();
11079 gen_load_gpr(tbase, rt);
11080 tcg_gen_movi_tl(toffset, offset);
11081 gen_op_addr_add(ctx, btarget, tbase, toffset);
11082 tcg_temp_free(tbase);
11083 tcg_temp_free(toffset);
11085 break;
11086 default:
11087 MIPS_INVAL("Compact branch/jump");
11088 generate_exception(ctx, EXCP_RI);
11089 goto out;
11092 if (bcond_compute == 0) {
11093 /* Uncoditional compact branch */
11094 switch (opc) {
11095 case OPC_JIALC:
11096 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11097 /* Fallthrough */
11098 case OPC_JIC:
11099 ctx->hflags |= MIPS_HFLAG_BR;
11100 break;
11101 case OPC_BALC:
11102 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11103 /* Fallthrough */
11104 case OPC_BC:
11105 ctx->hflags |= MIPS_HFLAG_B;
11106 break;
11107 default:
11108 MIPS_INVAL("Compact branch/jump");
11109 generate_exception(ctx, EXCP_RI);
11110 goto out;
11113 /* Generating branch here as compact branches don't have delay slot */
11114 gen_branch(ctx, 4);
11115 } else {
11116 /* Conditional compact branch */
11117 TCGLabel *fs = gen_new_label();
11118 save_cpu_state(ctx, 0);
11120 switch (opc) {
11121 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11122 if (rs == 0 && rt != 0) {
11123 /* OPC_BLEZALC */
11124 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11125 } else if (rs != 0 && rt != 0 && rs == rt) {
11126 /* OPC_BGEZALC */
11127 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11128 } else {
11129 /* OPC_BGEUC */
11130 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
11132 break;
11133 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11134 if (rs == 0 && rt != 0) {
11135 /* OPC_BGTZALC */
11136 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11137 } else if (rs != 0 && rt != 0 && rs == rt) {
11138 /* OPC_BLTZALC */
11139 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11140 } else {
11141 /* OPC_BLTUC */
11142 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
11144 break;
11145 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11146 if (rs == 0 && rt != 0) {
11147 /* OPC_BLEZC */
11148 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11149 } else if (rs != 0 && rt != 0 && rs == rt) {
11150 /* OPC_BGEZC */
11151 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11152 } else {
11153 /* OPC_BGEC */
11154 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
11156 break;
11157 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11158 if (rs == 0 && rt != 0) {
11159 /* OPC_BGTZC */
11160 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11161 } else if (rs != 0 && rt != 0 && rs == rt) {
11162 /* OPC_BLTZC */
11163 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11164 } else {
11165 /* OPC_BLTC */
11166 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
11168 break;
11169 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11170 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11171 if (rs >= rt) {
11172 /* OPC_BOVC, OPC_BNVC */
11173 TCGv t2 = tcg_temp_new();
11174 TCGv t3 = tcg_temp_new();
11175 TCGv t4 = tcg_temp_new();
11176 TCGv input_overflow = tcg_temp_new();
11178 gen_load_gpr(t0, rs);
11179 gen_load_gpr(t1, rt);
11180 tcg_gen_ext32s_tl(t2, t0);
11181 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
11182 tcg_gen_ext32s_tl(t3, t1);
11183 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
11184 tcg_gen_or_tl(input_overflow, input_overflow, t4);
11186 tcg_gen_add_tl(t4, t2, t3);
11187 tcg_gen_ext32s_tl(t4, t4);
11188 tcg_gen_xor_tl(t2, t2, t3);
11189 tcg_gen_xor_tl(t3, t4, t3);
11190 tcg_gen_andc_tl(t2, t3, t2);
11191 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
11192 tcg_gen_or_tl(t4, t4, input_overflow);
11193 if (opc == OPC_BOVC) {
11194 /* OPC_BOVC */
11195 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
11196 } else {
11197 /* OPC_BNVC */
11198 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
11200 tcg_temp_free(input_overflow);
11201 tcg_temp_free(t4);
11202 tcg_temp_free(t3);
11203 tcg_temp_free(t2);
11204 } else if (rs < rt && rs == 0) {
11205 /* OPC_BEQZALC, OPC_BNEZALC */
11206 if (opc == OPC_BEQZALC) {
11207 /* OPC_BEQZALC */
11208 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
11209 } else {
11210 /* OPC_BNEZALC */
11211 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
11213 } else {
11214 /* OPC_BEQC, OPC_BNEC */
11215 if (opc == OPC_BEQC) {
11216 /* OPC_BEQC */
11217 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
11218 } else {
11219 /* OPC_BNEC */
11220 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
11223 break;
11224 case OPC_BEQZC:
11225 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
11226 break;
11227 case OPC_BNEZC:
11228 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
11229 break;
11230 default:
11231 MIPS_INVAL("Compact conditional branch/jump");
11232 generate_exception(ctx, EXCP_RI);
11233 goto out;
11236 /* Generating branch here as compact branches don't have delay slot */
11237 gen_goto_tb(ctx, 1, ctx->btarget);
11238 gen_set_label(fs);
11240 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
11241 MIPS_DEBUG("Compact conditional branch");
11244 out:
11245 tcg_temp_free(t0);
11246 tcg_temp_free(t1);
11249 /* ISA extensions (ASEs) */
11250 /* MIPS16 extension to MIPS32 */
11252 /* MIPS16 major opcodes */
11253 enum {
11254 M16_OPC_ADDIUSP = 0x00,
11255 M16_OPC_ADDIUPC = 0x01,
11256 M16_OPC_B = 0x02,
11257 M16_OPC_JAL = 0x03,
11258 M16_OPC_BEQZ = 0x04,
11259 M16_OPC_BNEQZ = 0x05,
11260 M16_OPC_SHIFT = 0x06,
11261 M16_OPC_LD = 0x07,
11262 M16_OPC_RRIA = 0x08,
11263 M16_OPC_ADDIU8 = 0x09,
11264 M16_OPC_SLTI = 0x0a,
11265 M16_OPC_SLTIU = 0x0b,
11266 M16_OPC_I8 = 0x0c,
11267 M16_OPC_LI = 0x0d,
11268 M16_OPC_CMPI = 0x0e,
11269 M16_OPC_SD = 0x0f,
11270 M16_OPC_LB = 0x10,
11271 M16_OPC_LH = 0x11,
11272 M16_OPC_LWSP = 0x12,
11273 M16_OPC_LW = 0x13,
11274 M16_OPC_LBU = 0x14,
11275 M16_OPC_LHU = 0x15,
11276 M16_OPC_LWPC = 0x16,
11277 M16_OPC_LWU = 0x17,
11278 M16_OPC_SB = 0x18,
11279 M16_OPC_SH = 0x19,
11280 M16_OPC_SWSP = 0x1a,
11281 M16_OPC_SW = 0x1b,
11282 M16_OPC_RRR = 0x1c,
11283 M16_OPC_RR = 0x1d,
11284 M16_OPC_EXTEND = 0x1e,
11285 M16_OPC_I64 = 0x1f
11288 /* I8 funct field */
11289 enum {
11290 I8_BTEQZ = 0x0,
11291 I8_BTNEZ = 0x1,
11292 I8_SWRASP = 0x2,
11293 I8_ADJSP = 0x3,
11294 I8_SVRS = 0x4,
11295 I8_MOV32R = 0x5,
11296 I8_MOVR32 = 0x7
11299 /* RRR f field */
11300 enum {
11301 RRR_DADDU = 0x0,
11302 RRR_ADDU = 0x1,
11303 RRR_DSUBU = 0x2,
11304 RRR_SUBU = 0x3
11307 /* RR funct field */
11308 enum {
11309 RR_JR = 0x00,
11310 RR_SDBBP = 0x01,
11311 RR_SLT = 0x02,
11312 RR_SLTU = 0x03,
11313 RR_SLLV = 0x04,
11314 RR_BREAK = 0x05,
11315 RR_SRLV = 0x06,
11316 RR_SRAV = 0x07,
11317 RR_DSRL = 0x08,
11318 RR_CMP = 0x0a,
11319 RR_NEG = 0x0b,
11320 RR_AND = 0x0c,
11321 RR_OR = 0x0d,
11322 RR_XOR = 0x0e,
11323 RR_NOT = 0x0f,
11324 RR_MFHI = 0x10,
11325 RR_CNVT = 0x11,
11326 RR_MFLO = 0x12,
11327 RR_DSRA = 0x13,
11328 RR_DSLLV = 0x14,
11329 RR_DSRLV = 0x16,
11330 RR_DSRAV = 0x17,
11331 RR_MULT = 0x18,
11332 RR_MULTU = 0x19,
11333 RR_DIV = 0x1a,
11334 RR_DIVU = 0x1b,
11335 RR_DMULT = 0x1c,
11336 RR_DMULTU = 0x1d,
11337 RR_DDIV = 0x1e,
11338 RR_DDIVU = 0x1f
11341 /* I64 funct field */
11342 enum {
11343 I64_LDSP = 0x0,
11344 I64_SDSP = 0x1,
11345 I64_SDRASP = 0x2,
11346 I64_DADJSP = 0x3,
11347 I64_LDPC = 0x4,
11348 I64_DADDIU5 = 0x5,
11349 I64_DADDIUPC = 0x6,
11350 I64_DADDIUSP = 0x7
11353 /* RR ry field for CNVT */
11354 enum {
11355 RR_RY_CNVT_ZEB = 0x0,
11356 RR_RY_CNVT_ZEH = 0x1,
11357 RR_RY_CNVT_ZEW = 0x2,
11358 RR_RY_CNVT_SEB = 0x4,
11359 RR_RY_CNVT_SEH = 0x5,
11360 RR_RY_CNVT_SEW = 0x6,
11363 static int xlat (int r)
11365 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11367 return map[r];
11370 static void gen_mips16_save (DisasContext *ctx,
11371 int xsregs, int aregs,
11372 int do_ra, int do_s0, int do_s1,
11373 int framesize)
11375 TCGv t0 = tcg_temp_new();
11376 TCGv t1 = tcg_temp_new();
11377 TCGv t2 = tcg_temp_new();
11378 int args, astatic;
11380 switch (aregs) {
11381 case 0:
11382 case 1:
11383 case 2:
11384 case 3:
11385 case 11:
11386 args = 0;
11387 break;
11388 case 4:
11389 case 5:
11390 case 6:
11391 case 7:
11392 args = 1;
11393 break;
11394 case 8:
11395 case 9:
11396 case 10:
11397 args = 2;
11398 break;
11399 case 12:
11400 case 13:
11401 args = 3;
11402 break;
11403 case 14:
11404 args = 4;
11405 break;
11406 default:
11407 generate_exception(ctx, EXCP_RI);
11408 return;
11411 switch (args) {
11412 case 4:
11413 gen_base_offset_addr(ctx, t0, 29, 12);
11414 gen_load_gpr(t1, 7);
11415 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11416 /* Fall through */
11417 case 3:
11418 gen_base_offset_addr(ctx, t0, 29, 8);
11419 gen_load_gpr(t1, 6);
11420 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11421 /* Fall through */
11422 case 2:
11423 gen_base_offset_addr(ctx, t0, 29, 4);
11424 gen_load_gpr(t1, 5);
11425 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11426 /* Fall through */
11427 case 1:
11428 gen_base_offset_addr(ctx, t0, 29, 0);
11429 gen_load_gpr(t1, 4);
11430 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11433 gen_load_gpr(t0, 29);
11435 #define DECR_AND_STORE(reg) do { \
11436 tcg_gen_movi_tl(t2, -4); \
11437 gen_op_addr_add(ctx, t0, t0, t2); \
11438 gen_load_gpr(t1, reg); \
11439 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
11440 } while (0)
11442 if (do_ra) {
11443 DECR_AND_STORE(31);
11446 switch (xsregs) {
11447 case 7:
11448 DECR_AND_STORE(30);
11449 /* Fall through */
11450 case 6:
11451 DECR_AND_STORE(23);
11452 /* Fall through */
11453 case 5:
11454 DECR_AND_STORE(22);
11455 /* Fall through */
11456 case 4:
11457 DECR_AND_STORE(21);
11458 /* Fall through */
11459 case 3:
11460 DECR_AND_STORE(20);
11461 /* Fall through */
11462 case 2:
11463 DECR_AND_STORE(19);
11464 /* Fall through */
11465 case 1:
11466 DECR_AND_STORE(18);
11469 if (do_s1) {
11470 DECR_AND_STORE(17);
11472 if (do_s0) {
11473 DECR_AND_STORE(16);
11476 switch (aregs) {
11477 case 0:
11478 case 4:
11479 case 8:
11480 case 12:
11481 case 14:
11482 astatic = 0;
11483 break;
11484 case 1:
11485 case 5:
11486 case 9:
11487 case 13:
11488 astatic = 1;
11489 break;
11490 case 2:
11491 case 6:
11492 case 10:
11493 astatic = 2;
11494 break;
11495 case 3:
11496 case 7:
11497 astatic = 3;
11498 break;
11499 case 11:
11500 astatic = 4;
11501 break;
11502 default:
11503 generate_exception(ctx, EXCP_RI);
11504 return;
11507 if (astatic > 0) {
11508 DECR_AND_STORE(7);
11509 if (astatic > 1) {
11510 DECR_AND_STORE(6);
11511 if (astatic > 2) {
11512 DECR_AND_STORE(5);
11513 if (astatic > 3) {
11514 DECR_AND_STORE(4);
11519 #undef DECR_AND_STORE
11521 tcg_gen_movi_tl(t2, -framesize);
11522 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11523 tcg_temp_free(t0);
11524 tcg_temp_free(t1);
11525 tcg_temp_free(t2);
11528 static void gen_mips16_restore (DisasContext *ctx,
11529 int xsregs, int aregs,
11530 int do_ra, int do_s0, int do_s1,
11531 int framesize)
11533 int astatic;
11534 TCGv t0 = tcg_temp_new();
11535 TCGv t1 = tcg_temp_new();
11536 TCGv t2 = tcg_temp_new();
11538 tcg_gen_movi_tl(t2, framesize);
11539 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11541 #define DECR_AND_LOAD(reg) do { \
11542 tcg_gen_movi_tl(t2, -4); \
11543 gen_op_addr_add(ctx, t0, t0, t2); \
11544 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11545 gen_store_gpr(t1, reg); \
11546 } while (0)
11548 if (do_ra) {
11549 DECR_AND_LOAD(31);
11552 switch (xsregs) {
11553 case 7:
11554 DECR_AND_LOAD(30);
11555 /* Fall through */
11556 case 6:
11557 DECR_AND_LOAD(23);
11558 /* Fall through */
11559 case 5:
11560 DECR_AND_LOAD(22);
11561 /* Fall through */
11562 case 4:
11563 DECR_AND_LOAD(21);
11564 /* Fall through */
11565 case 3:
11566 DECR_AND_LOAD(20);
11567 /* Fall through */
11568 case 2:
11569 DECR_AND_LOAD(19);
11570 /* Fall through */
11571 case 1:
11572 DECR_AND_LOAD(18);
11575 if (do_s1) {
11576 DECR_AND_LOAD(17);
11578 if (do_s0) {
11579 DECR_AND_LOAD(16);
11582 switch (aregs) {
11583 case 0:
11584 case 4:
11585 case 8:
11586 case 12:
11587 case 14:
11588 astatic = 0;
11589 break;
11590 case 1:
11591 case 5:
11592 case 9:
11593 case 13:
11594 astatic = 1;
11595 break;
11596 case 2:
11597 case 6:
11598 case 10:
11599 astatic = 2;
11600 break;
11601 case 3:
11602 case 7:
11603 astatic = 3;
11604 break;
11605 case 11:
11606 astatic = 4;
11607 break;
11608 default:
11609 generate_exception(ctx, EXCP_RI);
11610 return;
11613 if (astatic > 0) {
11614 DECR_AND_LOAD(7);
11615 if (astatic > 1) {
11616 DECR_AND_LOAD(6);
11617 if (astatic > 2) {
11618 DECR_AND_LOAD(5);
11619 if (astatic > 3) {
11620 DECR_AND_LOAD(4);
11625 #undef DECR_AND_LOAD
11627 tcg_gen_movi_tl(t2, framesize);
11628 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11629 tcg_temp_free(t0);
11630 tcg_temp_free(t1);
11631 tcg_temp_free(t2);
11634 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11635 int is_64_bit, int extended)
11637 TCGv t0;
11639 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11640 generate_exception(ctx, EXCP_RI);
11641 return;
11644 t0 = tcg_temp_new();
11646 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11647 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11648 if (!is_64_bit) {
11649 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11652 tcg_temp_free(t0);
11655 #if defined(TARGET_MIPS64)
11656 static void decode_i64_mips16 (DisasContext *ctx,
11657 int ry, int funct, int16_t offset,
11658 int extended)
11660 switch (funct) {
11661 case I64_LDSP:
11662 check_insn(ctx, ISA_MIPS3);
11663 check_mips_64(ctx);
11664 offset = extended ? offset : offset << 3;
11665 gen_ld(ctx, OPC_LD, ry, 29, offset);
11666 break;
11667 case I64_SDSP:
11668 check_insn(ctx, ISA_MIPS3);
11669 check_mips_64(ctx);
11670 offset = extended ? offset : offset << 3;
11671 gen_st(ctx, OPC_SD, ry, 29, offset);
11672 break;
11673 case I64_SDRASP:
11674 check_insn(ctx, ISA_MIPS3);
11675 check_mips_64(ctx);
11676 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11677 gen_st(ctx, OPC_SD, 31, 29, offset);
11678 break;
11679 case I64_DADJSP:
11680 check_insn(ctx, ISA_MIPS3);
11681 check_mips_64(ctx);
11682 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11683 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11684 break;
11685 case I64_LDPC:
11686 check_insn(ctx, ISA_MIPS3);
11687 check_mips_64(ctx);
11688 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11689 generate_exception(ctx, EXCP_RI);
11690 } else {
11691 offset = extended ? offset : offset << 3;
11692 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11694 break;
11695 case I64_DADDIU5:
11696 check_insn(ctx, ISA_MIPS3);
11697 check_mips_64(ctx);
11698 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11699 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11700 break;
11701 case I64_DADDIUPC:
11702 check_insn(ctx, ISA_MIPS3);
11703 check_mips_64(ctx);
11704 offset = extended ? offset : offset << 2;
11705 gen_addiupc(ctx, ry, offset, 1, extended);
11706 break;
11707 case I64_DADDIUSP:
11708 check_insn(ctx, ISA_MIPS3);
11709 check_mips_64(ctx);
11710 offset = extended ? offset : offset << 2;
11711 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11712 break;
11715 #endif
11717 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11719 int extend = cpu_lduw_code(env, ctx->pc + 2);
11720 int op, rx, ry, funct, sa;
11721 int16_t imm, offset;
11723 ctx->opcode = (ctx->opcode << 16) | extend;
11724 op = (ctx->opcode >> 11) & 0x1f;
11725 sa = (ctx->opcode >> 22) & 0x1f;
11726 funct = (ctx->opcode >> 8) & 0x7;
11727 rx = xlat((ctx->opcode >> 8) & 0x7);
11728 ry = xlat((ctx->opcode >> 5) & 0x7);
11729 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11730 | ((ctx->opcode >> 21) & 0x3f) << 5
11731 | (ctx->opcode & 0x1f));
11733 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11734 counterparts. */
11735 switch (op) {
11736 case M16_OPC_ADDIUSP:
11737 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11738 break;
11739 case M16_OPC_ADDIUPC:
11740 gen_addiupc(ctx, rx, imm, 0, 1);
11741 break;
11742 case M16_OPC_B:
11743 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11744 /* No delay slot, so just process as a normal instruction */
11745 break;
11746 case M16_OPC_BEQZ:
11747 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11748 /* No delay slot, so just process as a normal instruction */
11749 break;
11750 case M16_OPC_BNEQZ:
11751 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11752 /* No delay slot, so just process as a normal instruction */
11753 break;
11754 case M16_OPC_SHIFT:
11755 switch (ctx->opcode & 0x3) {
11756 case 0x0:
11757 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11758 break;
11759 case 0x1:
11760 #if defined(TARGET_MIPS64)
11761 check_mips_64(ctx);
11762 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11763 #else
11764 generate_exception(ctx, EXCP_RI);
11765 #endif
11766 break;
11767 case 0x2:
11768 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11769 break;
11770 case 0x3:
11771 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11772 break;
11774 break;
11775 #if defined(TARGET_MIPS64)
11776 case M16_OPC_LD:
11777 check_insn(ctx, ISA_MIPS3);
11778 check_mips_64(ctx);
11779 gen_ld(ctx, OPC_LD, ry, rx, offset);
11780 break;
11781 #endif
11782 case M16_OPC_RRIA:
11783 imm = ctx->opcode & 0xf;
11784 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11785 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11786 imm = (int16_t) (imm << 1) >> 1;
11787 if ((ctx->opcode >> 4) & 0x1) {
11788 #if defined(TARGET_MIPS64)
11789 check_mips_64(ctx);
11790 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11791 #else
11792 generate_exception(ctx, EXCP_RI);
11793 #endif
11794 } else {
11795 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11797 break;
11798 case M16_OPC_ADDIU8:
11799 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11800 break;
11801 case M16_OPC_SLTI:
11802 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11803 break;
11804 case M16_OPC_SLTIU:
11805 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11806 break;
11807 case M16_OPC_I8:
11808 switch (funct) {
11809 case I8_BTEQZ:
11810 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11811 break;
11812 case I8_BTNEZ:
11813 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11814 break;
11815 case I8_SWRASP:
11816 gen_st(ctx, OPC_SW, 31, 29, imm);
11817 break;
11818 case I8_ADJSP:
11819 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11820 break;
11821 case I8_SVRS:
11822 check_insn(ctx, ISA_MIPS32);
11824 int xsregs = (ctx->opcode >> 24) & 0x7;
11825 int aregs = (ctx->opcode >> 16) & 0xf;
11826 int do_ra = (ctx->opcode >> 6) & 0x1;
11827 int do_s0 = (ctx->opcode >> 5) & 0x1;
11828 int do_s1 = (ctx->opcode >> 4) & 0x1;
11829 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11830 | (ctx->opcode & 0xf)) << 3;
11832 if (ctx->opcode & (1 << 7)) {
11833 gen_mips16_save(ctx, xsregs, aregs,
11834 do_ra, do_s0, do_s1,
11835 framesize);
11836 } else {
11837 gen_mips16_restore(ctx, xsregs, aregs,
11838 do_ra, do_s0, do_s1,
11839 framesize);
11842 break;
11843 default:
11844 generate_exception(ctx, EXCP_RI);
11845 break;
11847 break;
11848 case M16_OPC_LI:
11849 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11850 break;
11851 case M16_OPC_CMPI:
11852 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11853 break;
11854 #if defined(TARGET_MIPS64)
11855 case M16_OPC_SD:
11856 check_insn(ctx, ISA_MIPS3);
11857 check_mips_64(ctx);
11858 gen_st(ctx, OPC_SD, ry, rx, offset);
11859 break;
11860 #endif
11861 case M16_OPC_LB:
11862 gen_ld(ctx, OPC_LB, ry, rx, offset);
11863 break;
11864 case M16_OPC_LH:
11865 gen_ld(ctx, OPC_LH, ry, rx, offset);
11866 break;
11867 case M16_OPC_LWSP:
11868 gen_ld(ctx, OPC_LW, rx, 29, offset);
11869 break;
11870 case M16_OPC_LW:
11871 gen_ld(ctx, OPC_LW, ry, rx, offset);
11872 break;
11873 case M16_OPC_LBU:
11874 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11875 break;
11876 case M16_OPC_LHU:
11877 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11878 break;
11879 case M16_OPC_LWPC:
11880 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11881 break;
11882 #if defined(TARGET_MIPS64)
11883 case M16_OPC_LWU:
11884 check_insn(ctx, ISA_MIPS3);
11885 check_mips_64(ctx);
11886 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11887 break;
11888 #endif
11889 case M16_OPC_SB:
11890 gen_st(ctx, OPC_SB, ry, rx, offset);
11891 break;
11892 case M16_OPC_SH:
11893 gen_st(ctx, OPC_SH, ry, rx, offset);
11894 break;
11895 case M16_OPC_SWSP:
11896 gen_st(ctx, OPC_SW, rx, 29, offset);
11897 break;
11898 case M16_OPC_SW:
11899 gen_st(ctx, OPC_SW, ry, rx, offset);
11900 break;
11901 #if defined(TARGET_MIPS64)
11902 case M16_OPC_I64:
11903 decode_i64_mips16(ctx, ry, funct, offset, 1);
11904 break;
11905 #endif
11906 default:
11907 generate_exception(ctx, EXCP_RI);
11908 break;
11911 return 4;
11914 static inline bool is_uhi(int sdbbp_code)
11916 #ifdef CONFIG_USER_ONLY
11917 return false;
11918 #else
11919 return semihosting_enabled() && sdbbp_code == 1;
11920 #endif
11923 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11925 int rx, ry;
11926 int sa;
11927 int op, cnvt_op, op1, offset;
11928 int funct;
11929 int n_bytes;
11931 op = (ctx->opcode >> 11) & 0x1f;
11932 sa = (ctx->opcode >> 2) & 0x7;
11933 sa = sa == 0 ? 8 : sa;
11934 rx = xlat((ctx->opcode >> 8) & 0x7);
11935 cnvt_op = (ctx->opcode >> 5) & 0x7;
11936 ry = xlat((ctx->opcode >> 5) & 0x7);
11937 op1 = offset = ctx->opcode & 0x1f;
11939 n_bytes = 2;
11941 switch (op) {
11942 case M16_OPC_ADDIUSP:
11944 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11946 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11948 break;
11949 case M16_OPC_ADDIUPC:
11950 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11951 break;
11952 case M16_OPC_B:
11953 offset = (ctx->opcode & 0x7ff) << 1;
11954 offset = (int16_t)(offset << 4) >> 4;
11955 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11956 /* No delay slot, so just process as a normal instruction */
11957 break;
11958 case M16_OPC_JAL:
11959 offset = cpu_lduw_code(env, ctx->pc + 2);
11960 offset = (((ctx->opcode & 0x1f) << 21)
11961 | ((ctx->opcode >> 5) & 0x1f) << 16
11962 | offset) << 2;
11963 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11964 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11965 n_bytes = 4;
11966 break;
11967 case M16_OPC_BEQZ:
11968 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11969 ((int8_t)ctx->opcode) << 1, 0);
11970 /* No delay slot, so just process as a normal instruction */
11971 break;
11972 case M16_OPC_BNEQZ:
11973 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11974 ((int8_t)ctx->opcode) << 1, 0);
11975 /* No delay slot, so just process as a normal instruction */
11976 break;
11977 case M16_OPC_SHIFT:
11978 switch (ctx->opcode & 0x3) {
11979 case 0x0:
11980 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11981 break;
11982 case 0x1:
11983 #if defined(TARGET_MIPS64)
11984 check_insn(ctx, ISA_MIPS3);
11985 check_mips_64(ctx);
11986 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11987 #else
11988 generate_exception(ctx, EXCP_RI);
11989 #endif
11990 break;
11991 case 0x2:
11992 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11993 break;
11994 case 0x3:
11995 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11996 break;
11998 break;
11999 #if defined(TARGET_MIPS64)
12000 case M16_OPC_LD:
12001 check_insn(ctx, ISA_MIPS3);
12002 check_mips_64(ctx);
12003 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
12004 break;
12005 #endif
12006 case M16_OPC_RRIA:
12008 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
12010 if ((ctx->opcode >> 4) & 1) {
12011 #if defined(TARGET_MIPS64)
12012 check_insn(ctx, ISA_MIPS3);
12013 check_mips_64(ctx);
12014 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12015 #else
12016 generate_exception(ctx, EXCP_RI);
12017 #endif
12018 } else {
12019 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12022 break;
12023 case M16_OPC_ADDIU8:
12025 int16_t imm = (int8_t) ctx->opcode;
12027 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12029 break;
12030 case M16_OPC_SLTI:
12032 int16_t imm = (uint8_t) ctx->opcode;
12033 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12035 break;
12036 case M16_OPC_SLTIU:
12038 int16_t imm = (uint8_t) ctx->opcode;
12039 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12041 break;
12042 case M16_OPC_I8:
12044 int reg32;
12046 funct = (ctx->opcode >> 8) & 0x7;
12047 switch (funct) {
12048 case I8_BTEQZ:
12049 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
12050 ((int8_t)ctx->opcode) << 1, 0);
12051 break;
12052 case I8_BTNEZ:
12053 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
12054 ((int8_t)ctx->opcode) << 1, 0);
12055 break;
12056 case I8_SWRASP:
12057 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
12058 break;
12059 case I8_ADJSP:
12060 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
12061 ((int8_t)ctx->opcode) << 3);
12062 break;
12063 case I8_SVRS:
12064 check_insn(ctx, ISA_MIPS32);
12066 int do_ra = ctx->opcode & (1 << 6);
12067 int do_s0 = ctx->opcode & (1 << 5);
12068 int do_s1 = ctx->opcode & (1 << 4);
12069 int framesize = ctx->opcode & 0xf;
12071 if (framesize == 0) {
12072 framesize = 128;
12073 } else {
12074 framesize = framesize << 3;
12077 if (ctx->opcode & (1 << 7)) {
12078 gen_mips16_save(ctx, 0, 0,
12079 do_ra, do_s0, do_s1, framesize);
12080 } else {
12081 gen_mips16_restore(ctx, 0, 0,
12082 do_ra, do_s0, do_s1, framesize);
12085 break;
12086 case I8_MOV32R:
12088 int rz = xlat(ctx->opcode & 0x7);
12090 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
12091 ((ctx->opcode >> 5) & 0x7);
12092 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
12094 break;
12095 case I8_MOVR32:
12096 reg32 = ctx->opcode & 0x1f;
12097 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
12098 break;
12099 default:
12100 generate_exception(ctx, EXCP_RI);
12101 break;
12104 break;
12105 case M16_OPC_LI:
12107 int16_t imm = (uint8_t) ctx->opcode;
12109 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
12111 break;
12112 case M16_OPC_CMPI:
12114 int16_t imm = (uint8_t) ctx->opcode;
12115 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
12117 break;
12118 #if defined(TARGET_MIPS64)
12119 case M16_OPC_SD:
12120 check_insn(ctx, ISA_MIPS3);
12121 check_mips_64(ctx);
12122 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
12123 break;
12124 #endif
12125 case M16_OPC_LB:
12126 gen_ld(ctx, OPC_LB, ry, rx, offset);
12127 break;
12128 case M16_OPC_LH:
12129 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
12130 break;
12131 case M16_OPC_LWSP:
12132 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12133 break;
12134 case M16_OPC_LW:
12135 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
12136 break;
12137 case M16_OPC_LBU:
12138 gen_ld(ctx, OPC_LBU, ry, rx, offset);
12139 break;
12140 case M16_OPC_LHU:
12141 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
12142 break;
12143 case M16_OPC_LWPC:
12144 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
12145 break;
12146 #if defined (TARGET_MIPS64)
12147 case M16_OPC_LWU:
12148 check_insn(ctx, ISA_MIPS3);
12149 check_mips_64(ctx);
12150 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
12151 break;
12152 #endif
12153 case M16_OPC_SB:
12154 gen_st(ctx, OPC_SB, ry, rx, offset);
12155 break;
12156 case M16_OPC_SH:
12157 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
12158 break;
12159 case M16_OPC_SWSP:
12160 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12161 break;
12162 case M16_OPC_SW:
12163 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
12164 break;
12165 case M16_OPC_RRR:
12167 int rz = xlat((ctx->opcode >> 2) & 0x7);
12168 int mips32_op;
12170 switch (ctx->opcode & 0x3) {
12171 case RRR_ADDU:
12172 mips32_op = OPC_ADDU;
12173 break;
12174 case RRR_SUBU:
12175 mips32_op = OPC_SUBU;
12176 break;
12177 #if defined(TARGET_MIPS64)
12178 case RRR_DADDU:
12179 mips32_op = OPC_DADDU;
12180 check_insn(ctx, ISA_MIPS3);
12181 check_mips_64(ctx);
12182 break;
12183 case RRR_DSUBU:
12184 mips32_op = OPC_DSUBU;
12185 check_insn(ctx, ISA_MIPS3);
12186 check_mips_64(ctx);
12187 break;
12188 #endif
12189 default:
12190 generate_exception(ctx, EXCP_RI);
12191 goto done;
12194 gen_arith(ctx, mips32_op, rz, rx, ry);
12195 done:
12198 break;
12199 case M16_OPC_RR:
12200 switch (op1) {
12201 case RR_JR:
12203 int nd = (ctx->opcode >> 7) & 0x1;
12204 int link = (ctx->opcode >> 6) & 0x1;
12205 int ra = (ctx->opcode >> 5) & 0x1;
12207 if (nd) {
12208 check_insn(ctx, ISA_MIPS32);
12211 if (link) {
12212 op = OPC_JALR;
12213 } else {
12214 op = OPC_JR;
12217 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
12218 (nd ? 0 : 2));
12220 break;
12221 case RR_SDBBP:
12222 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
12223 gen_helper_do_semihosting(cpu_env);
12224 } else {
12225 /* XXX: not clear which exception should be raised
12226 * when in debug mode...
12228 check_insn(ctx, ISA_MIPS32);
12229 generate_exception(ctx, EXCP_DBp);
12231 break;
12232 case RR_SLT:
12233 gen_slt(ctx, OPC_SLT, 24, rx, ry);
12234 break;
12235 case RR_SLTU:
12236 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
12237 break;
12238 case RR_BREAK:
12239 generate_exception(ctx, EXCP_BREAK);
12240 break;
12241 case RR_SLLV:
12242 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
12243 break;
12244 case RR_SRLV:
12245 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
12246 break;
12247 case RR_SRAV:
12248 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
12249 break;
12250 #if defined (TARGET_MIPS64)
12251 case RR_DSRL:
12252 check_insn(ctx, ISA_MIPS3);
12253 check_mips_64(ctx);
12254 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
12255 break;
12256 #endif
12257 case RR_CMP:
12258 gen_logic(ctx, OPC_XOR, 24, rx, ry);
12259 break;
12260 case RR_NEG:
12261 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
12262 break;
12263 case RR_AND:
12264 gen_logic(ctx, OPC_AND, rx, rx, ry);
12265 break;
12266 case RR_OR:
12267 gen_logic(ctx, OPC_OR, rx, rx, ry);
12268 break;
12269 case RR_XOR:
12270 gen_logic(ctx, OPC_XOR, rx, rx, ry);
12271 break;
12272 case RR_NOT:
12273 gen_logic(ctx, OPC_NOR, rx, ry, 0);
12274 break;
12275 case RR_MFHI:
12276 gen_HILO(ctx, OPC_MFHI, 0, rx);
12277 break;
12278 case RR_CNVT:
12279 check_insn(ctx, ISA_MIPS32);
12280 switch (cnvt_op) {
12281 case RR_RY_CNVT_ZEB:
12282 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12283 break;
12284 case RR_RY_CNVT_ZEH:
12285 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12286 break;
12287 case RR_RY_CNVT_SEB:
12288 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12289 break;
12290 case RR_RY_CNVT_SEH:
12291 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12292 break;
12293 #if defined (TARGET_MIPS64)
12294 case RR_RY_CNVT_ZEW:
12295 check_insn(ctx, ISA_MIPS64);
12296 check_mips_64(ctx);
12297 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12298 break;
12299 case RR_RY_CNVT_SEW:
12300 check_insn(ctx, ISA_MIPS64);
12301 check_mips_64(ctx);
12302 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12303 break;
12304 #endif
12305 default:
12306 generate_exception(ctx, EXCP_RI);
12307 break;
12309 break;
12310 case RR_MFLO:
12311 gen_HILO(ctx, OPC_MFLO, 0, rx);
12312 break;
12313 #if defined (TARGET_MIPS64)
12314 case RR_DSRA:
12315 check_insn(ctx, ISA_MIPS3);
12316 check_mips_64(ctx);
12317 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
12318 break;
12319 case RR_DSLLV:
12320 check_insn(ctx, ISA_MIPS3);
12321 check_mips_64(ctx);
12322 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
12323 break;
12324 case RR_DSRLV:
12325 check_insn(ctx, ISA_MIPS3);
12326 check_mips_64(ctx);
12327 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
12328 break;
12329 case RR_DSRAV:
12330 check_insn(ctx, ISA_MIPS3);
12331 check_mips_64(ctx);
12332 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
12333 break;
12334 #endif
12335 case RR_MULT:
12336 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
12337 break;
12338 case RR_MULTU:
12339 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
12340 break;
12341 case RR_DIV:
12342 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
12343 break;
12344 case RR_DIVU:
12345 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
12346 break;
12347 #if defined (TARGET_MIPS64)
12348 case RR_DMULT:
12349 check_insn(ctx, ISA_MIPS3);
12350 check_mips_64(ctx);
12351 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
12352 break;
12353 case RR_DMULTU:
12354 check_insn(ctx, ISA_MIPS3);
12355 check_mips_64(ctx);
12356 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
12357 break;
12358 case RR_DDIV:
12359 check_insn(ctx, ISA_MIPS3);
12360 check_mips_64(ctx);
12361 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
12362 break;
12363 case RR_DDIVU:
12364 check_insn(ctx, ISA_MIPS3);
12365 check_mips_64(ctx);
12366 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
12367 break;
12368 #endif
12369 default:
12370 generate_exception(ctx, EXCP_RI);
12371 break;
12373 break;
12374 case M16_OPC_EXTEND:
12375 decode_extended_mips16_opc(env, ctx);
12376 n_bytes = 4;
12377 break;
12378 #if defined(TARGET_MIPS64)
12379 case M16_OPC_I64:
12380 funct = (ctx->opcode >> 8) & 0x7;
12381 decode_i64_mips16(ctx, ry, funct, offset, 0);
12382 break;
12383 #endif
12384 default:
12385 generate_exception(ctx, EXCP_RI);
12386 break;
12389 return n_bytes;
12392 /* microMIPS extension to MIPS32/MIPS64 */
12395 * microMIPS32/microMIPS64 major opcodes
12397 * 1. MIPS Architecture for Programmers Volume II-B:
12398 * The microMIPS32 Instruction Set (Revision 3.05)
12400 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12402 * 2. MIPS Architecture For Programmers Volume II-A:
12403 * The MIPS64 Instruction Set (Revision 3.51)
12406 enum {
12407 POOL32A = 0x00,
12408 POOL16A = 0x01,
12409 LBU16 = 0x02,
12410 MOVE16 = 0x03,
12411 ADDI32 = 0x04,
12412 R6_LUI = 0x04,
12413 AUI = 0x04,
12414 LBU32 = 0x05,
12415 SB32 = 0x06,
12416 LB32 = 0x07,
12418 POOL32B = 0x08,
12419 POOL16B = 0x09,
12420 LHU16 = 0x0a,
12421 ANDI16 = 0x0b,
12422 ADDIU32 = 0x0c,
12423 LHU32 = 0x0d,
12424 SH32 = 0x0e,
12425 LH32 = 0x0f,
12427 POOL32I = 0x10,
12428 POOL16C = 0x11,
12429 LWSP16 = 0x12,
12430 POOL16D = 0x13,
12431 ORI32 = 0x14,
12432 POOL32F = 0x15,
12433 POOL32S = 0x16, /* MIPS64 */
12434 DADDIU32 = 0x17, /* MIPS64 */
12436 POOL32C = 0x18,
12437 LWGP16 = 0x19,
12438 LW16 = 0x1a,
12439 POOL16E = 0x1b,
12440 XORI32 = 0x1c,
12441 JALS32 = 0x1d,
12442 BOVC = 0x1d,
12443 BEQC = 0x1d,
12444 BEQZALC = 0x1d,
12445 ADDIUPC = 0x1e,
12446 PCREL = 0x1e,
12447 BNVC = 0x1f,
12448 BNEC = 0x1f,
12449 BNEZALC = 0x1f,
12451 R6_BEQZC = 0x20,
12452 JIC = 0x20,
12453 POOL16F = 0x21,
12454 SB16 = 0x22,
12455 BEQZ16 = 0x23,
12456 BEQZC16 = 0x23,
12457 SLTI32 = 0x24,
12458 BEQ32 = 0x25,
12459 BC = 0x25,
12460 SWC132 = 0x26,
12461 LWC132 = 0x27,
12463 /* 0x29 is reserved */
12464 RES_29 = 0x29,
12465 R6_BNEZC = 0x28,
12466 JIALC = 0x28,
12467 SH16 = 0x2a,
12468 BNEZ16 = 0x2b,
12469 BNEZC16 = 0x2b,
12470 SLTIU32 = 0x2c,
12471 BNE32 = 0x2d,
12472 BALC = 0x2d,
12473 SDC132 = 0x2e,
12474 LDC132 = 0x2f,
12476 /* 0x31 is reserved */
12477 RES_31 = 0x31,
12478 BLEZALC = 0x30,
12479 BGEZALC = 0x30,
12480 BGEUC = 0x30,
12481 SWSP16 = 0x32,
12482 B16 = 0x33,
12483 BC16 = 0x33,
12484 ANDI32 = 0x34,
12485 J32 = 0x35,
12486 BGTZC = 0x35,
12487 BLTZC = 0x35,
12488 BLTC = 0x35,
12489 SD32 = 0x36, /* MIPS64 */
12490 LD32 = 0x37, /* MIPS64 */
12492 /* 0x39 is reserved */
12493 RES_39 = 0x39,
12494 BGTZALC = 0x38,
12495 BLTZALC = 0x38,
12496 BLTUC = 0x38,
12497 SW16 = 0x3a,
12498 LI16 = 0x3b,
12499 JALX32 = 0x3c,
12500 JAL32 = 0x3d,
12501 BLEZC = 0x3d,
12502 BGEZC = 0x3d,
12503 BGEC = 0x3d,
12504 SW32 = 0x3e,
12505 LW32 = 0x3f
12508 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12509 enum {
12510 ADDIUPC_00 = 0x00,
12511 ADDIUPC_07 = 0x07,
12512 AUIPC = 0x1e,
12513 ALUIPC = 0x1f,
12514 LWPC_08 = 0x08,
12515 LWPC_0F = 0x0F,
12518 /* POOL32A encoding of minor opcode field */
12520 enum {
12521 /* These opcodes are distinguished only by bits 9..6; those bits are
12522 * what are recorded below. */
12523 SLL32 = 0x0,
12524 SRL32 = 0x1,
12525 SRA = 0x2,
12526 ROTR = 0x3,
12527 SELEQZ = 0x5,
12528 SELNEZ = 0x6,
12530 SLLV = 0x0,
12531 SRLV = 0x1,
12532 SRAV = 0x2,
12533 ROTRV = 0x3,
12534 ADD = 0x4,
12535 ADDU32 = 0x5,
12536 SUB = 0x6,
12537 SUBU32 = 0x7,
12538 MUL = 0x8,
12539 AND = 0x9,
12540 OR32 = 0xa,
12541 NOR = 0xb,
12542 XOR32 = 0xc,
12543 SLT = 0xd,
12544 SLTU = 0xe,
12546 MOVN = 0x0,
12547 R6_MUL = 0x0,
12548 MOVZ = 0x1,
12549 MUH = 0x1,
12550 MULU = 0x2,
12551 MUHU = 0x3,
12552 LWXS = 0x4,
12553 R6_DIV = 0x4,
12554 MOD = 0x5,
12555 R6_DIVU = 0x6,
12556 MODU = 0x7,
12558 /* The following can be distinguished by their lower 6 bits. */
12559 INS = 0x0c,
12560 LSA = 0x0f,
12561 ALIGN = 0x1f,
12562 EXT = 0x2c,
12563 POOL32AXF = 0x3c
12566 /* POOL32AXF encoding of minor opcode field extension */
12569 * 1. MIPS Architecture for Programmers Volume II-B:
12570 * The microMIPS32 Instruction Set (Revision 3.05)
12572 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12574 * 2. MIPS Architecture for Programmers VolumeIV-e:
12575 * The MIPS DSP Application-Specific Extension
12576 * to the microMIPS32 Architecture (Revision 2.34)
12578 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12581 enum {
12582 /* bits 11..6 */
12583 TEQ = 0x00,
12584 TGE = 0x08,
12585 TGEU = 0x10,
12586 TLT = 0x20,
12587 TLTU = 0x28,
12588 TNE = 0x30,
12590 MFC0 = 0x03,
12591 MTC0 = 0x0b,
12593 /* begin of microMIPS32 DSP */
12595 /* bits 13..12 for 0x01 */
12596 MFHI_ACC = 0x0,
12597 MFLO_ACC = 0x1,
12598 MTHI_ACC = 0x2,
12599 MTLO_ACC = 0x3,
12601 /* bits 13..12 for 0x2a */
12602 MADD_ACC = 0x0,
12603 MADDU_ACC = 0x1,
12604 MSUB_ACC = 0x2,
12605 MSUBU_ACC = 0x3,
12607 /* bits 13..12 for 0x32 */
12608 MULT_ACC = 0x0,
12609 MULTU_ACC = 0x1,
12611 /* end of microMIPS32 DSP */
12613 /* bits 15..12 for 0x2c */
12614 BITSWAP = 0x0,
12615 SEB = 0x2,
12616 SEH = 0x3,
12617 CLO = 0x4,
12618 CLZ = 0x5,
12619 RDHWR = 0x6,
12620 WSBH = 0x7,
12621 MULT = 0x8,
12622 MULTU = 0x9,
12623 DIV = 0xa,
12624 DIVU = 0xb,
12625 MADD = 0xc,
12626 MADDU = 0xd,
12627 MSUB = 0xe,
12628 MSUBU = 0xf,
12630 /* bits 15..12 for 0x34 */
12631 MFC2 = 0x4,
12632 MTC2 = 0x5,
12633 MFHC2 = 0x8,
12634 MTHC2 = 0x9,
12635 CFC2 = 0xc,
12636 CTC2 = 0xd,
12638 /* bits 15..12 for 0x3c */
12639 JALR = 0x0,
12640 JR = 0x0, /* alias */
12641 JALRC = 0x0,
12642 JRC = 0x0,
12643 JALR_HB = 0x1,
12644 JALRC_HB = 0x1,
12645 JALRS = 0x4,
12646 JALRS_HB = 0x5,
12648 /* bits 15..12 for 0x05 */
12649 RDPGPR = 0xe,
12650 WRPGPR = 0xf,
12652 /* bits 15..12 for 0x0d */
12653 TLBP = 0x0,
12654 TLBR = 0x1,
12655 TLBWI = 0x2,
12656 TLBWR = 0x3,
12657 TLBINV = 0x4,
12658 TLBINVF = 0x5,
12659 WAIT = 0x9,
12660 IRET = 0xd,
12661 DERET = 0xe,
12662 ERET = 0xf,
12664 /* bits 15..12 for 0x15 */
12665 DMT = 0x0,
12666 DVPE = 0x1,
12667 EMT = 0x2,
12668 EVPE = 0x3,
12670 /* bits 15..12 for 0x1d */
12671 DI = 0x4,
12672 EI = 0x5,
12674 /* bits 15..12 for 0x2d */
12675 SYNC = 0x6,
12676 SYSCALL = 0x8,
12677 SDBBP = 0xd,
12679 /* bits 15..12 for 0x35 */
12680 MFHI32 = 0x0,
12681 MFLO32 = 0x1,
12682 MTHI32 = 0x2,
12683 MTLO32 = 0x3,
12686 /* POOL32B encoding of minor opcode field (bits 15..12) */
12688 enum {
12689 LWC2 = 0x0,
12690 LWP = 0x1,
12691 LDP = 0x4,
12692 LWM32 = 0x5,
12693 CACHE = 0x6,
12694 LDM = 0x7,
12695 SWC2 = 0x8,
12696 SWP = 0x9,
12697 SDP = 0xc,
12698 SWM32 = 0xd,
12699 SDM = 0xf
12702 /* POOL32C encoding of minor opcode field (bits 15..12) */
12704 enum {
12705 LWL = 0x0,
12706 SWL = 0x8,
12707 LWR = 0x1,
12708 SWR = 0x9,
12709 PREF = 0x2,
12710 /* 0xa is reserved */
12711 LL = 0x3,
12712 SC = 0xb,
12713 LDL = 0x4,
12714 SDL = 0xc,
12715 LDR = 0x5,
12716 SDR = 0xd,
12717 /* 0x6 is reserved */
12718 LWU = 0xe,
12719 LLD = 0x7,
12720 SCD = 0xf
12723 /* POOL32F encoding of minor opcode field (bits 5..0) */
12725 enum {
12726 /* These are the bit 7..6 values */
12727 ADD_FMT = 0x0,
12729 SUB_FMT = 0x1,
12731 MUL_FMT = 0x2,
12733 DIV_FMT = 0x3,
12735 /* These are the bit 8..6 values */
12736 MOVN_FMT = 0x0,
12737 RSQRT2_FMT = 0x0,
12738 MOVF_FMT = 0x0,
12739 RINT_FMT = 0x0,
12740 SELNEZ_FMT = 0x0,
12742 MOVZ_FMT = 0x1,
12743 LWXC1 = 0x1,
12744 MOVT_FMT = 0x1,
12745 CLASS_FMT = 0x1,
12746 SELEQZ_FMT = 0x1,
12748 PLL_PS = 0x2,
12749 SWXC1 = 0x2,
12750 SEL_FMT = 0x2,
12752 PLU_PS = 0x3,
12753 LDXC1 = 0x3,
12755 MOVN_FMT_04 = 0x4,
12756 PUL_PS = 0x4,
12757 SDXC1 = 0x4,
12758 RECIP2_FMT = 0x4,
12760 MOVZ_FMT_05 = 0x05,
12761 PUU_PS = 0x5,
12762 LUXC1 = 0x5,
12764 CVT_PS_S = 0x6,
12765 SUXC1 = 0x6,
12766 ADDR_PS = 0x6,
12767 PREFX = 0x6,
12768 MADDF_FMT = 0x6,
12770 MULR_PS = 0x7,
12771 MSUBF_FMT = 0x7,
12773 MADD_S = 0x01,
12774 MADD_D = 0x09,
12775 MADD_PS = 0x11,
12776 ALNV_PS = 0x19,
12777 MSUB_S = 0x21,
12778 MSUB_D = 0x29,
12779 MSUB_PS = 0x31,
12781 NMADD_S = 0x02,
12782 NMADD_D = 0x0a,
12783 NMADD_PS = 0x12,
12784 NMSUB_S = 0x22,
12785 NMSUB_D = 0x2a,
12786 NMSUB_PS = 0x32,
12788 MIN_FMT = 0x3,
12789 MAX_FMT = 0xb,
12790 MINA_FMT = 0x23,
12791 MAXA_FMT = 0x2b,
12792 POOL32FXF = 0x3b,
12794 CABS_COND_FMT = 0x1c, /* MIPS3D */
12795 C_COND_FMT = 0x3c,
12797 CMP_CONDN_S = 0x5,
12798 CMP_CONDN_D = 0x15
12801 /* POOL32Fxf encoding of minor opcode extension field */
12803 enum {
12804 CVT_L = 0x04,
12805 RSQRT_FMT = 0x08,
12806 FLOOR_L = 0x0c,
12807 CVT_PW_PS = 0x1c,
12808 CVT_W = 0x24,
12809 SQRT_FMT = 0x28,
12810 FLOOR_W = 0x2c,
12811 CVT_PS_PW = 0x3c,
12812 CFC1 = 0x40,
12813 RECIP_FMT = 0x48,
12814 CEIL_L = 0x4c,
12815 CTC1 = 0x60,
12816 CEIL_W = 0x6c,
12817 MFC1 = 0x80,
12818 CVT_S_PL = 0x84,
12819 TRUNC_L = 0x8c,
12820 MTC1 = 0xa0,
12821 CVT_S_PU = 0xa4,
12822 TRUNC_W = 0xac,
12823 MFHC1 = 0xc0,
12824 ROUND_L = 0xcc,
12825 MTHC1 = 0xe0,
12826 ROUND_W = 0xec,
12828 MOV_FMT = 0x01,
12829 MOVF = 0x05,
12830 ABS_FMT = 0x0d,
12831 RSQRT1_FMT = 0x1d,
12832 MOVT = 0x25,
12833 NEG_FMT = 0x2d,
12834 CVT_D = 0x4d,
12835 RECIP1_FMT = 0x5d,
12836 CVT_S = 0x6d
12839 /* POOL32I encoding of minor opcode field (bits 25..21) */
12841 enum {
12842 BLTZ = 0x00,
12843 BLTZAL = 0x01,
12844 BGEZ = 0x02,
12845 BGEZAL = 0x03,
12846 BLEZ = 0x04,
12847 BNEZC = 0x05,
12848 BGTZ = 0x06,
12849 BEQZC = 0x07,
12850 TLTI = 0x08,
12851 BC1EQZC = 0x08,
12852 TGEI = 0x09,
12853 BC1NEZC = 0x09,
12854 TLTIU = 0x0a,
12855 BC2EQZC = 0x0a,
12856 TGEIU = 0x0b,
12857 BC2NEZC = 0x0a,
12858 TNEI = 0x0c,
12859 R6_SYNCI = 0x0c,
12860 LUI = 0x0d,
12861 TEQI = 0x0e,
12862 SYNCI = 0x10,
12863 BLTZALS = 0x11,
12864 BGEZALS = 0x13,
12865 BC2F = 0x14,
12866 BC2T = 0x15,
12867 BPOSGE64 = 0x1a,
12868 BPOSGE32 = 0x1b,
12869 /* These overlap and are distinguished by bit16 of the instruction */
12870 BC1F = 0x1c,
12871 BC1T = 0x1d,
12872 BC1ANY2F = 0x1c,
12873 BC1ANY2T = 0x1d,
12874 BC1ANY4F = 0x1e,
12875 BC1ANY4T = 0x1f
12878 /* POOL16A encoding of minor opcode field */
12880 enum {
12881 ADDU16 = 0x0,
12882 SUBU16 = 0x1
12885 /* POOL16B encoding of minor opcode field */
12887 enum {
12888 SLL16 = 0x0,
12889 SRL16 = 0x1
12892 /* POOL16C encoding of minor opcode field */
12894 enum {
12895 NOT16 = 0x00,
12896 XOR16 = 0x04,
12897 AND16 = 0x08,
12898 OR16 = 0x0c,
12899 LWM16 = 0x10,
12900 SWM16 = 0x14,
12901 JR16 = 0x18,
12902 JRC16 = 0x1a,
12903 JALR16 = 0x1c,
12904 JALR16S = 0x1e,
12905 MFHI16 = 0x20,
12906 MFLO16 = 0x24,
12907 BREAK16 = 0x28,
12908 SDBBP16 = 0x2c,
12909 JRADDIUSP = 0x30
12912 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
12914 enum {
12915 R6_NOT16 = 0x00,
12916 R6_AND16 = 0x01,
12917 R6_LWM16 = 0x02,
12918 R6_JRC16 = 0x03,
12919 MOVEP = 0x04,
12920 MOVEP_07 = 0x07,
12921 R6_XOR16 = 0x08,
12922 R6_OR16 = 0x09,
12923 R6_SWM16 = 0x0a,
12924 JALRC16 = 0x0b,
12925 MOVEP_0C = 0x0c,
12926 MOVEP_0F = 0x0f,
12927 JRCADDIUSP = 0x13,
12928 R6_BREAK16 = 0x1b,
12929 R6_SDBBP16 = 0x3b
12932 /* POOL16D encoding of minor opcode field */
12934 enum {
12935 ADDIUS5 = 0x0,
12936 ADDIUSP = 0x1
12939 /* POOL16E encoding of minor opcode field */
12941 enum {
12942 ADDIUR2 = 0x0,
12943 ADDIUR1SP = 0x1
12946 static int mmreg (int r)
12948 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12950 return map[r];
12953 /* Used for 16-bit store instructions. */
12954 static int mmreg2 (int r)
12956 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12958 return map[r];
12961 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12962 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12963 #define uMIPS_RS2(op) uMIPS_RS(op)
12964 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12965 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12966 #define uMIPS_RS5(op) (op & 0x1f)
12968 /* Signed immediate */
12969 #define SIMM(op, start, width) \
12970 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12971 << (32-width)) \
12972 >> (32-width))
12973 /* Zero-extended immediate */
12974 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12976 static void gen_addiur1sp(DisasContext *ctx)
12978 int rd = mmreg(uMIPS_RD(ctx->opcode));
12980 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12983 static void gen_addiur2(DisasContext *ctx)
12985 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12986 int rd = mmreg(uMIPS_RD(ctx->opcode));
12987 int rs = mmreg(uMIPS_RS(ctx->opcode));
12989 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12992 static void gen_addiusp(DisasContext *ctx)
12994 int encoded = ZIMM(ctx->opcode, 1, 9);
12995 int decoded;
12997 if (encoded <= 1) {
12998 decoded = 256 + encoded;
12999 } else if (encoded <= 255) {
13000 decoded = encoded;
13001 } else if (encoded <= 509) {
13002 decoded = encoded - 512;
13003 } else {
13004 decoded = encoded - 768;
13007 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
13010 static void gen_addius5(DisasContext *ctx)
13012 int imm = SIMM(ctx->opcode, 1, 4);
13013 int rd = (ctx->opcode >> 5) & 0x1f;
13015 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
13018 static void gen_andi16(DisasContext *ctx)
13020 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
13021 31, 32, 63, 64, 255, 32768, 65535 };
13022 int rd = mmreg(uMIPS_RD(ctx->opcode));
13023 int rs = mmreg(uMIPS_RS(ctx->opcode));
13024 int encoded = ZIMM(ctx->opcode, 0, 4);
13026 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
13029 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
13030 int base, int16_t offset)
13032 const char *opn = "ldst_multiple";
13033 TCGv t0, t1;
13034 TCGv_i32 t2;
13036 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13037 generate_exception(ctx, EXCP_RI);
13038 return;
13041 t0 = tcg_temp_new();
13043 gen_base_offset_addr(ctx, t0, base, offset);
13045 t1 = tcg_const_tl(reglist);
13046 t2 = tcg_const_i32(ctx->mem_idx);
13048 save_cpu_state(ctx, 1);
13049 switch (opc) {
13050 case LWM32:
13051 gen_helper_lwm(cpu_env, t0, t1, t2);
13052 opn = "lwm";
13053 break;
13054 case SWM32:
13055 gen_helper_swm(cpu_env, t0, t1, t2);
13056 opn = "swm";
13057 break;
13058 #ifdef TARGET_MIPS64
13059 case LDM:
13060 gen_helper_ldm(cpu_env, t0, t1, t2);
13061 opn = "ldm";
13062 break;
13063 case SDM:
13064 gen_helper_sdm(cpu_env, t0, t1, t2);
13065 opn = "sdm";
13066 break;
13067 #endif
13069 (void)opn;
13070 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
13071 tcg_temp_free(t0);
13072 tcg_temp_free(t1);
13073 tcg_temp_free_i32(t2);
13077 static void gen_pool16c_insn(DisasContext *ctx)
13079 int rd = mmreg((ctx->opcode >> 3) & 0x7);
13080 int rs = mmreg(ctx->opcode & 0x7);
13082 switch (((ctx->opcode) >> 4) & 0x3f) {
13083 case NOT16 + 0:
13084 case NOT16 + 1:
13085 case NOT16 + 2:
13086 case NOT16 + 3:
13087 gen_logic(ctx, OPC_NOR, rd, rs, 0);
13088 break;
13089 case XOR16 + 0:
13090 case XOR16 + 1:
13091 case XOR16 + 2:
13092 case XOR16 + 3:
13093 gen_logic(ctx, OPC_XOR, rd, rd, rs);
13094 break;
13095 case AND16 + 0:
13096 case AND16 + 1:
13097 case AND16 + 2:
13098 case AND16 + 3:
13099 gen_logic(ctx, OPC_AND, rd, rd, rs);
13100 break;
13101 case OR16 + 0:
13102 case OR16 + 1:
13103 case OR16 + 2:
13104 case OR16 + 3:
13105 gen_logic(ctx, OPC_OR, rd, rd, rs);
13106 break;
13107 case LWM16 + 0:
13108 case LWM16 + 1:
13109 case LWM16 + 2:
13110 case LWM16 + 3:
13112 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13113 int offset = ZIMM(ctx->opcode, 0, 4);
13115 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
13116 29, offset << 2);
13118 break;
13119 case SWM16 + 0:
13120 case SWM16 + 1:
13121 case SWM16 + 2:
13122 case SWM16 + 3:
13124 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13125 int offset = ZIMM(ctx->opcode, 0, 4);
13127 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
13128 29, offset << 2);
13130 break;
13131 case JR16 + 0:
13132 case JR16 + 1:
13134 int reg = ctx->opcode & 0x1f;
13136 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
13138 break;
13139 case JRC16 + 0:
13140 case JRC16 + 1:
13142 int reg = ctx->opcode & 0x1f;
13143 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
13144 /* Let normal delay slot handling in our caller take us
13145 to the branch target. */
13147 break;
13148 case JALR16 + 0:
13149 case JALR16 + 1:
13150 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
13151 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13152 break;
13153 case JALR16S + 0:
13154 case JALR16S + 1:
13155 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
13156 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13157 break;
13158 case MFHI16 + 0:
13159 case MFHI16 + 1:
13160 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
13161 break;
13162 case MFLO16 + 0:
13163 case MFLO16 + 1:
13164 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
13165 break;
13166 case BREAK16:
13167 generate_exception(ctx, EXCP_BREAK);
13168 break;
13169 case SDBBP16:
13170 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
13171 gen_helper_do_semihosting(cpu_env);
13172 } else {
13173 /* XXX: not clear which exception should be raised
13174 * when in debug mode...
13176 check_insn(ctx, ISA_MIPS32);
13177 generate_exception(ctx, EXCP_DBp);
13179 break;
13180 case JRADDIUSP + 0:
13181 case JRADDIUSP + 1:
13183 int imm = ZIMM(ctx->opcode, 0, 5);
13184 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13185 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13186 /* Let normal delay slot handling in our caller take us
13187 to the branch target. */
13189 break;
13190 default:
13191 generate_exception(ctx, EXCP_RI);
13192 break;
13196 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
13197 int enc_rs)
13199 int rd, rs, re, rt;
13200 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
13201 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
13202 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
13203 rd = rd_enc[enc_dest];
13204 re = re_enc[enc_dest];
13205 rs = rs_rt_enc[enc_rs];
13206 rt = rs_rt_enc[enc_rt];
13207 if (rs) {
13208 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
13209 } else {
13210 tcg_gen_movi_tl(cpu_gpr[rd], 0);
13212 if (rt) {
13213 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
13214 } else {
13215 tcg_gen_movi_tl(cpu_gpr[re], 0);
13219 static void gen_pool16c_r6_insn(DisasContext *ctx)
13221 int rt = mmreg((ctx->opcode >> 7) & 0x7);
13222 int rs = mmreg((ctx->opcode >> 4) & 0x7);
13224 switch (ctx->opcode & 0xf) {
13225 case R6_NOT16:
13226 gen_logic(ctx, OPC_NOR, rt, rs, 0);
13227 break;
13228 case R6_AND16:
13229 gen_logic(ctx, OPC_AND, rt, rt, rs);
13230 break;
13231 case R6_LWM16:
13233 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13234 int offset = extract32(ctx->opcode, 4, 4);
13235 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
13237 break;
13238 case R6_JRC16: /* JRCADDIUSP */
13239 if ((ctx->opcode >> 4) & 1) {
13240 /* JRCADDIUSP */
13241 int imm = extract32(ctx->opcode, 5, 5);
13242 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13243 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13244 } else {
13245 /* JRC16 */
13246 int rs = extract32(ctx->opcode, 5, 5);
13247 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
13249 break;
13250 case MOVEP ... MOVEP_07:
13251 case MOVEP_0C ... MOVEP_0F:
13253 int enc_dest = uMIPS_RD(ctx->opcode);
13254 int enc_rt = uMIPS_RS2(ctx->opcode);
13255 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
13256 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
13258 break;
13259 case R6_XOR16:
13260 gen_logic(ctx, OPC_XOR, rt, rt, rs);
13261 break;
13262 case R6_OR16:
13263 gen_logic(ctx, OPC_OR, rt, rt, rs);
13264 break;
13265 case R6_SWM16:
13267 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13268 int offset = extract32(ctx->opcode, 4, 4);
13269 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
13271 break;
13272 case JALRC16: /* BREAK16, SDBBP16 */
13273 switch (ctx->opcode & 0x3f) {
13274 case JALRC16:
13275 case JALRC16 + 0x20:
13276 /* JALRC16 */
13277 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
13278 31, 0, 0);
13279 break;
13280 case R6_BREAK16:
13281 /* BREAK16 */
13282 generate_exception(ctx, EXCP_BREAK);
13283 break;
13284 case R6_SDBBP16:
13285 /* SDBBP16 */
13286 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
13287 gen_helper_do_semihosting(cpu_env);
13288 } else {
13289 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13290 generate_exception(ctx, EXCP_RI);
13291 } else {
13292 generate_exception(ctx, EXCP_DBp);
13295 break;
13297 break;
13298 default:
13299 generate_exception(ctx, EXCP_RI);
13300 break;
13304 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
13306 TCGv t0 = tcg_temp_new();
13307 TCGv t1 = tcg_temp_new();
13309 gen_load_gpr(t0, base);
13311 if (index != 0) {
13312 gen_load_gpr(t1, index);
13313 tcg_gen_shli_tl(t1, t1, 2);
13314 gen_op_addr_add(ctx, t0, t1, t0);
13317 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13318 gen_store_gpr(t1, rd);
13320 tcg_temp_free(t0);
13321 tcg_temp_free(t1);
13324 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
13325 int base, int16_t offset)
13327 const char *opn = "ldst_pair";
13328 TCGv t0, t1;
13330 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
13331 generate_exception(ctx, EXCP_RI);
13332 return;
13335 t0 = tcg_temp_new();
13336 t1 = tcg_temp_new();
13338 gen_base_offset_addr(ctx, t0, base, offset);
13340 switch (opc) {
13341 case LWP:
13342 if (rd == base) {
13343 generate_exception(ctx, EXCP_RI);
13344 return;
13346 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13347 gen_store_gpr(t1, rd);
13348 tcg_gen_movi_tl(t1, 4);
13349 gen_op_addr_add(ctx, t0, t0, t1);
13350 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13351 gen_store_gpr(t1, rd+1);
13352 opn = "lwp";
13353 break;
13354 case SWP:
13355 gen_load_gpr(t1, rd);
13356 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13357 tcg_gen_movi_tl(t1, 4);
13358 gen_op_addr_add(ctx, t0, t0, t1);
13359 gen_load_gpr(t1, rd+1);
13360 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13361 opn = "swp";
13362 break;
13363 #ifdef TARGET_MIPS64
13364 case LDP:
13365 if (rd == base) {
13366 generate_exception(ctx, EXCP_RI);
13367 return;
13369 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13370 gen_store_gpr(t1, rd);
13371 tcg_gen_movi_tl(t1, 8);
13372 gen_op_addr_add(ctx, t0, t0, t1);
13373 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13374 gen_store_gpr(t1, rd+1);
13375 opn = "ldp";
13376 break;
13377 case SDP:
13378 gen_load_gpr(t1, rd);
13379 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13380 tcg_gen_movi_tl(t1, 8);
13381 gen_op_addr_add(ctx, t0, t0, t1);
13382 gen_load_gpr(t1, rd+1);
13383 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13384 opn = "sdp";
13385 break;
13386 #endif
13388 (void)opn; /* avoid a compiler warning */
13389 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
13390 tcg_temp_free(t0);
13391 tcg_temp_free(t1);
13394 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
13396 int extension = (ctx->opcode >> 6) & 0x3f;
13397 int minor = (ctx->opcode >> 12) & 0xf;
13398 uint32_t mips32_op;
13400 switch (extension) {
13401 case TEQ:
13402 mips32_op = OPC_TEQ;
13403 goto do_trap;
13404 case TGE:
13405 mips32_op = OPC_TGE;
13406 goto do_trap;
13407 case TGEU:
13408 mips32_op = OPC_TGEU;
13409 goto do_trap;
13410 case TLT:
13411 mips32_op = OPC_TLT;
13412 goto do_trap;
13413 case TLTU:
13414 mips32_op = OPC_TLTU;
13415 goto do_trap;
13416 case TNE:
13417 mips32_op = OPC_TNE;
13418 do_trap:
13419 gen_trap(ctx, mips32_op, rs, rt, -1);
13420 break;
13421 #ifndef CONFIG_USER_ONLY
13422 case MFC0:
13423 case MFC0 + 32:
13424 check_cp0_enabled(ctx);
13425 if (rt == 0) {
13426 /* Treat as NOP. */
13427 break;
13429 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
13430 break;
13431 case MTC0:
13432 case MTC0 + 32:
13433 check_cp0_enabled(ctx);
13435 TCGv t0 = tcg_temp_new();
13437 gen_load_gpr(t0, rt);
13438 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
13439 tcg_temp_free(t0);
13441 break;
13442 #endif
13443 case 0x2a:
13444 switch (minor & 3) {
13445 case MADD_ACC:
13446 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
13447 break;
13448 case MADDU_ACC:
13449 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
13450 break;
13451 case MSUB_ACC:
13452 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
13453 break;
13454 case MSUBU_ACC:
13455 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
13456 break;
13457 default:
13458 goto pool32axf_invalid;
13460 break;
13461 case 0x32:
13462 switch (minor & 3) {
13463 case MULT_ACC:
13464 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
13465 break;
13466 case MULTU_ACC:
13467 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
13468 break;
13469 default:
13470 goto pool32axf_invalid;
13472 break;
13473 case 0x2c:
13474 switch (minor) {
13475 case BITSWAP:
13476 check_insn(ctx, ISA_MIPS32R6);
13477 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
13478 break;
13479 case SEB:
13480 gen_bshfl(ctx, OPC_SEB, rs, rt);
13481 break;
13482 case SEH:
13483 gen_bshfl(ctx, OPC_SEH, rs, rt);
13484 break;
13485 case CLO:
13486 mips32_op = OPC_CLO;
13487 goto do_cl;
13488 case CLZ:
13489 mips32_op = OPC_CLZ;
13490 do_cl:
13491 check_insn(ctx, ISA_MIPS32);
13492 gen_cl(ctx, mips32_op, rt, rs);
13493 break;
13494 case RDHWR:
13495 gen_rdhwr(ctx, rt, rs);
13496 break;
13497 case WSBH:
13498 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13499 break;
13500 case MULT:
13501 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13502 mips32_op = OPC_MULT;
13503 goto do_mul;
13504 case MULTU:
13505 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13506 mips32_op = OPC_MULTU;
13507 goto do_mul;
13508 case DIV:
13509 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13510 mips32_op = OPC_DIV;
13511 goto do_div;
13512 case DIVU:
13513 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13514 mips32_op = OPC_DIVU;
13515 goto do_div;
13516 do_div:
13517 check_insn(ctx, ISA_MIPS32);
13518 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13519 break;
13520 case MADD:
13521 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13522 mips32_op = OPC_MADD;
13523 goto do_mul;
13524 case MADDU:
13525 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13526 mips32_op = OPC_MADDU;
13527 goto do_mul;
13528 case MSUB:
13529 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13530 mips32_op = OPC_MSUB;
13531 goto do_mul;
13532 case MSUBU:
13533 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13534 mips32_op = OPC_MSUBU;
13535 do_mul:
13536 check_insn(ctx, ISA_MIPS32);
13537 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13538 break;
13539 default:
13540 goto pool32axf_invalid;
13542 break;
13543 case 0x34:
13544 switch (minor) {
13545 case MFC2:
13546 case MTC2:
13547 case MFHC2:
13548 case MTHC2:
13549 case CFC2:
13550 case CTC2:
13551 generate_exception_err(ctx, EXCP_CpU, 2);
13552 break;
13553 default:
13554 goto pool32axf_invalid;
13556 break;
13557 case 0x3c:
13558 switch (minor) {
13559 case JALR: /* JALRC */
13560 case JALR_HB: /* JALRC_HB */
13561 if (ctx->insn_flags & ISA_MIPS32R6) {
13562 /* JALRC, JALRC_HB */
13563 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13564 } else {
13565 /* JALR, JALR_HB */
13566 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13567 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13569 break;
13570 case JALRS:
13571 case JALRS_HB:
13572 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13573 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13574 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13575 break;
13576 default:
13577 goto pool32axf_invalid;
13579 break;
13580 case 0x05:
13581 switch (minor) {
13582 case RDPGPR:
13583 check_cp0_enabled(ctx);
13584 check_insn(ctx, ISA_MIPS32R2);
13585 gen_load_srsgpr(rs, rt);
13586 break;
13587 case WRPGPR:
13588 check_cp0_enabled(ctx);
13589 check_insn(ctx, ISA_MIPS32R2);
13590 gen_store_srsgpr(rs, rt);
13591 break;
13592 default:
13593 goto pool32axf_invalid;
13595 break;
13596 #ifndef CONFIG_USER_ONLY
13597 case 0x0d:
13598 switch (minor) {
13599 case TLBP:
13600 mips32_op = OPC_TLBP;
13601 goto do_cp0;
13602 case TLBR:
13603 mips32_op = OPC_TLBR;
13604 goto do_cp0;
13605 case TLBWI:
13606 mips32_op = OPC_TLBWI;
13607 goto do_cp0;
13608 case TLBWR:
13609 mips32_op = OPC_TLBWR;
13610 goto do_cp0;
13611 case TLBINV:
13612 mips32_op = OPC_TLBINV;
13613 goto do_cp0;
13614 case TLBINVF:
13615 mips32_op = OPC_TLBINVF;
13616 goto do_cp0;
13617 case WAIT:
13618 mips32_op = OPC_WAIT;
13619 goto do_cp0;
13620 case DERET:
13621 mips32_op = OPC_DERET;
13622 goto do_cp0;
13623 case ERET:
13624 mips32_op = OPC_ERET;
13625 do_cp0:
13626 gen_cp0(env, ctx, mips32_op, rt, rs);
13627 break;
13628 default:
13629 goto pool32axf_invalid;
13631 break;
13632 case 0x1d:
13633 switch (minor) {
13634 case DI:
13635 check_cp0_enabled(ctx);
13637 TCGv t0 = tcg_temp_new();
13639 save_cpu_state(ctx, 1);
13640 gen_helper_di(t0, cpu_env);
13641 gen_store_gpr(t0, rs);
13642 /* Stop translation as we may have switched the execution mode */
13643 ctx->bstate = BS_STOP;
13644 tcg_temp_free(t0);
13646 break;
13647 case EI:
13648 check_cp0_enabled(ctx);
13650 TCGv t0 = tcg_temp_new();
13652 save_cpu_state(ctx, 1);
13653 gen_helper_ei(t0, cpu_env);
13654 gen_store_gpr(t0, rs);
13655 /* Stop translation as we may have switched the execution mode */
13656 ctx->bstate = BS_STOP;
13657 tcg_temp_free(t0);
13659 break;
13660 default:
13661 goto pool32axf_invalid;
13663 break;
13664 #endif
13665 case 0x2d:
13666 switch (minor) {
13667 case SYNC:
13668 /* NOP */
13669 break;
13670 case SYSCALL:
13671 generate_exception(ctx, EXCP_SYSCALL);
13672 ctx->bstate = BS_STOP;
13673 break;
13674 case SDBBP:
13675 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
13676 gen_helper_do_semihosting(cpu_env);
13677 } else {
13678 check_insn(ctx, ISA_MIPS32);
13679 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13680 generate_exception(ctx, EXCP_RI);
13681 } else {
13682 generate_exception(ctx, EXCP_DBp);
13685 break;
13686 default:
13687 goto pool32axf_invalid;
13689 break;
13690 case 0x01:
13691 switch (minor & 3) {
13692 case MFHI_ACC:
13693 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
13694 break;
13695 case MFLO_ACC:
13696 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
13697 break;
13698 case MTHI_ACC:
13699 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
13700 break;
13701 case MTLO_ACC:
13702 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
13703 break;
13704 default:
13705 goto pool32axf_invalid;
13707 break;
13708 case 0x35:
13709 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13710 switch (minor) {
13711 case MFHI32:
13712 gen_HILO(ctx, OPC_MFHI, 0, rs);
13713 break;
13714 case MFLO32:
13715 gen_HILO(ctx, OPC_MFLO, 0, rs);
13716 break;
13717 case MTHI32:
13718 gen_HILO(ctx, OPC_MTHI, 0, rs);
13719 break;
13720 case MTLO32:
13721 gen_HILO(ctx, OPC_MTLO, 0, rs);
13722 break;
13723 default:
13724 goto pool32axf_invalid;
13726 break;
13727 default:
13728 pool32axf_invalid:
13729 MIPS_INVAL("pool32axf");
13730 generate_exception(ctx, EXCP_RI);
13731 break;
13735 /* Values for microMIPS fmt field. Variable-width, depending on which
13736 formats the instruction supports. */
13738 enum {
13739 FMT_SD_S = 0,
13740 FMT_SD_D = 1,
13742 FMT_SDPS_S = 0,
13743 FMT_SDPS_D = 1,
13744 FMT_SDPS_PS = 2,
13746 FMT_SWL_S = 0,
13747 FMT_SWL_W = 1,
13748 FMT_SWL_L = 2,
13750 FMT_DWL_D = 0,
13751 FMT_DWL_W = 1,
13752 FMT_DWL_L = 2
13755 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
13757 int extension = (ctx->opcode >> 6) & 0x3ff;
13758 uint32_t mips32_op;
13760 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
13761 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
13762 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
13764 switch (extension) {
13765 case FLOAT_1BIT_FMT(CFC1, 0):
13766 mips32_op = OPC_CFC1;
13767 goto do_cp1;
13768 case FLOAT_1BIT_FMT(CTC1, 0):
13769 mips32_op = OPC_CTC1;
13770 goto do_cp1;
13771 case FLOAT_1BIT_FMT(MFC1, 0):
13772 mips32_op = OPC_MFC1;
13773 goto do_cp1;
13774 case FLOAT_1BIT_FMT(MTC1, 0):
13775 mips32_op = OPC_MTC1;
13776 goto do_cp1;
13777 case FLOAT_1BIT_FMT(MFHC1, 0):
13778 mips32_op = OPC_MFHC1;
13779 goto do_cp1;
13780 case FLOAT_1BIT_FMT(MTHC1, 0):
13781 mips32_op = OPC_MTHC1;
13782 do_cp1:
13783 gen_cp1(ctx, mips32_op, rt, rs);
13784 break;
13786 /* Reciprocal square root */
13787 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
13788 mips32_op = OPC_RSQRT_S;
13789 goto do_unaryfp;
13790 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
13791 mips32_op = OPC_RSQRT_D;
13792 goto do_unaryfp;
13794 /* Square root */
13795 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
13796 mips32_op = OPC_SQRT_S;
13797 goto do_unaryfp;
13798 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
13799 mips32_op = OPC_SQRT_D;
13800 goto do_unaryfp;
13802 /* Reciprocal */
13803 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
13804 mips32_op = OPC_RECIP_S;
13805 goto do_unaryfp;
13806 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
13807 mips32_op = OPC_RECIP_D;
13808 goto do_unaryfp;
13810 /* Floor */
13811 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
13812 mips32_op = OPC_FLOOR_L_S;
13813 goto do_unaryfp;
13814 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
13815 mips32_op = OPC_FLOOR_L_D;
13816 goto do_unaryfp;
13817 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
13818 mips32_op = OPC_FLOOR_W_S;
13819 goto do_unaryfp;
13820 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
13821 mips32_op = OPC_FLOOR_W_D;
13822 goto do_unaryfp;
13824 /* Ceiling */
13825 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
13826 mips32_op = OPC_CEIL_L_S;
13827 goto do_unaryfp;
13828 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
13829 mips32_op = OPC_CEIL_L_D;
13830 goto do_unaryfp;
13831 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
13832 mips32_op = OPC_CEIL_W_S;
13833 goto do_unaryfp;
13834 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
13835 mips32_op = OPC_CEIL_W_D;
13836 goto do_unaryfp;
13838 /* Truncation */
13839 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
13840 mips32_op = OPC_TRUNC_L_S;
13841 goto do_unaryfp;
13842 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
13843 mips32_op = OPC_TRUNC_L_D;
13844 goto do_unaryfp;
13845 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
13846 mips32_op = OPC_TRUNC_W_S;
13847 goto do_unaryfp;
13848 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
13849 mips32_op = OPC_TRUNC_W_D;
13850 goto do_unaryfp;
13852 /* Round */
13853 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
13854 mips32_op = OPC_ROUND_L_S;
13855 goto do_unaryfp;
13856 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
13857 mips32_op = OPC_ROUND_L_D;
13858 goto do_unaryfp;
13859 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
13860 mips32_op = OPC_ROUND_W_S;
13861 goto do_unaryfp;
13862 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
13863 mips32_op = OPC_ROUND_W_D;
13864 goto do_unaryfp;
13866 /* Integer to floating-point conversion */
13867 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
13868 mips32_op = OPC_CVT_L_S;
13869 goto do_unaryfp;
13870 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
13871 mips32_op = OPC_CVT_L_D;
13872 goto do_unaryfp;
13873 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
13874 mips32_op = OPC_CVT_W_S;
13875 goto do_unaryfp;
13876 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
13877 mips32_op = OPC_CVT_W_D;
13878 goto do_unaryfp;
13880 /* Paired-foo conversions */
13881 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
13882 mips32_op = OPC_CVT_S_PL;
13883 goto do_unaryfp;
13884 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13885 mips32_op = OPC_CVT_S_PU;
13886 goto do_unaryfp;
13887 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13888 mips32_op = OPC_CVT_PW_PS;
13889 goto do_unaryfp;
13890 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13891 mips32_op = OPC_CVT_PS_PW;
13892 goto do_unaryfp;
13894 /* Floating-point moves */
13895 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13896 mips32_op = OPC_MOV_S;
13897 goto do_unaryfp;
13898 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13899 mips32_op = OPC_MOV_D;
13900 goto do_unaryfp;
13901 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13902 mips32_op = OPC_MOV_PS;
13903 goto do_unaryfp;
13905 /* Absolute value */
13906 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13907 mips32_op = OPC_ABS_S;
13908 goto do_unaryfp;
13909 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13910 mips32_op = OPC_ABS_D;
13911 goto do_unaryfp;
13912 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13913 mips32_op = OPC_ABS_PS;
13914 goto do_unaryfp;
13916 /* Negation */
13917 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13918 mips32_op = OPC_NEG_S;
13919 goto do_unaryfp;
13920 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13921 mips32_op = OPC_NEG_D;
13922 goto do_unaryfp;
13923 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13924 mips32_op = OPC_NEG_PS;
13925 goto do_unaryfp;
13927 /* Reciprocal square root step */
13928 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13929 mips32_op = OPC_RSQRT1_S;
13930 goto do_unaryfp;
13931 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13932 mips32_op = OPC_RSQRT1_D;
13933 goto do_unaryfp;
13934 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13935 mips32_op = OPC_RSQRT1_PS;
13936 goto do_unaryfp;
13938 /* Reciprocal step */
13939 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13940 mips32_op = OPC_RECIP1_S;
13941 goto do_unaryfp;
13942 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13943 mips32_op = OPC_RECIP1_S;
13944 goto do_unaryfp;
13945 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13946 mips32_op = OPC_RECIP1_PS;
13947 goto do_unaryfp;
13949 /* Conversions from double */
13950 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13951 mips32_op = OPC_CVT_D_S;
13952 goto do_unaryfp;
13953 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13954 mips32_op = OPC_CVT_D_W;
13955 goto do_unaryfp;
13956 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13957 mips32_op = OPC_CVT_D_L;
13958 goto do_unaryfp;
13960 /* Conversions from single */
13961 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13962 mips32_op = OPC_CVT_S_D;
13963 goto do_unaryfp;
13964 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13965 mips32_op = OPC_CVT_S_W;
13966 goto do_unaryfp;
13967 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13968 mips32_op = OPC_CVT_S_L;
13969 do_unaryfp:
13970 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13971 break;
13973 /* Conditional moves on floating-point codes */
13974 case COND_FLOAT_MOV(MOVT, 0):
13975 case COND_FLOAT_MOV(MOVT, 1):
13976 case COND_FLOAT_MOV(MOVT, 2):
13977 case COND_FLOAT_MOV(MOVT, 3):
13978 case COND_FLOAT_MOV(MOVT, 4):
13979 case COND_FLOAT_MOV(MOVT, 5):
13980 case COND_FLOAT_MOV(MOVT, 6):
13981 case COND_FLOAT_MOV(MOVT, 7):
13982 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13983 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13984 break;
13985 case COND_FLOAT_MOV(MOVF, 0):
13986 case COND_FLOAT_MOV(MOVF, 1):
13987 case COND_FLOAT_MOV(MOVF, 2):
13988 case COND_FLOAT_MOV(MOVF, 3):
13989 case COND_FLOAT_MOV(MOVF, 4):
13990 case COND_FLOAT_MOV(MOVF, 5):
13991 case COND_FLOAT_MOV(MOVF, 6):
13992 case COND_FLOAT_MOV(MOVF, 7):
13993 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13994 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13995 break;
13996 default:
13997 MIPS_INVAL("pool32fxf");
13998 generate_exception(ctx, EXCP_RI);
13999 break;
14003 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
14005 int32_t offset;
14006 uint16_t insn;
14007 int rt, rs, rd, rr;
14008 int16_t imm;
14009 uint32_t op, minor, mips32_op;
14010 uint32_t cond, fmt, cc;
14012 insn = cpu_lduw_code(env, ctx->pc + 2);
14013 ctx->opcode = (ctx->opcode << 16) | insn;
14015 rt = (ctx->opcode >> 21) & 0x1f;
14016 rs = (ctx->opcode >> 16) & 0x1f;
14017 rd = (ctx->opcode >> 11) & 0x1f;
14018 rr = (ctx->opcode >> 6) & 0x1f;
14019 imm = (int16_t) ctx->opcode;
14021 op = (ctx->opcode >> 26) & 0x3f;
14022 switch (op) {
14023 case POOL32A:
14024 minor = ctx->opcode & 0x3f;
14025 switch (minor) {
14026 case 0x00:
14027 minor = (ctx->opcode >> 6) & 0xf;
14028 switch (minor) {
14029 case SLL32:
14030 mips32_op = OPC_SLL;
14031 goto do_shifti;
14032 case SRA:
14033 mips32_op = OPC_SRA;
14034 goto do_shifti;
14035 case SRL32:
14036 mips32_op = OPC_SRL;
14037 goto do_shifti;
14038 case ROTR:
14039 mips32_op = OPC_ROTR;
14040 do_shifti:
14041 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
14042 break;
14043 case SELEQZ:
14044 check_insn(ctx, ISA_MIPS32R6);
14045 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
14046 break;
14047 case SELNEZ:
14048 check_insn(ctx, ISA_MIPS32R6);
14049 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
14050 break;
14051 default:
14052 goto pool32a_invalid;
14054 break;
14055 case 0x10:
14056 minor = (ctx->opcode >> 6) & 0xf;
14057 switch (minor) {
14058 /* Arithmetic */
14059 case ADD:
14060 mips32_op = OPC_ADD;
14061 goto do_arith;
14062 case ADDU32:
14063 mips32_op = OPC_ADDU;
14064 goto do_arith;
14065 case SUB:
14066 mips32_op = OPC_SUB;
14067 goto do_arith;
14068 case SUBU32:
14069 mips32_op = OPC_SUBU;
14070 goto do_arith;
14071 case MUL:
14072 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14073 mips32_op = OPC_MUL;
14074 do_arith:
14075 gen_arith(ctx, mips32_op, rd, rs, rt);
14076 break;
14077 /* Shifts */
14078 case SLLV:
14079 mips32_op = OPC_SLLV;
14080 goto do_shift;
14081 case SRLV:
14082 mips32_op = OPC_SRLV;
14083 goto do_shift;
14084 case SRAV:
14085 mips32_op = OPC_SRAV;
14086 goto do_shift;
14087 case ROTRV:
14088 mips32_op = OPC_ROTRV;
14089 do_shift:
14090 gen_shift(ctx, mips32_op, rd, rs, rt);
14091 break;
14092 /* Logical operations */
14093 case AND:
14094 mips32_op = OPC_AND;
14095 goto do_logic;
14096 case OR32:
14097 mips32_op = OPC_OR;
14098 goto do_logic;
14099 case NOR:
14100 mips32_op = OPC_NOR;
14101 goto do_logic;
14102 case XOR32:
14103 mips32_op = OPC_XOR;
14104 do_logic:
14105 gen_logic(ctx, mips32_op, rd, rs, rt);
14106 break;
14107 /* Set less than */
14108 case SLT:
14109 mips32_op = OPC_SLT;
14110 goto do_slt;
14111 case SLTU:
14112 mips32_op = OPC_SLTU;
14113 do_slt:
14114 gen_slt(ctx, mips32_op, rd, rs, rt);
14115 break;
14116 default:
14117 goto pool32a_invalid;
14119 break;
14120 case 0x18:
14121 minor = (ctx->opcode >> 6) & 0xf;
14122 switch (minor) {
14123 /* Conditional moves */
14124 case MOVN: /* MUL */
14125 if (ctx->insn_flags & ISA_MIPS32R6) {
14126 /* MUL */
14127 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
14128 } else {
14129 /* MOVN */
14130 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
14132 break;
14133 case MOVZ: /* MUH */
14134 if (ctx->insn_flags & ISA_MIPS32R6) {
14135 /* MUH */
14136 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
14137 } else {
14138 /* MOVZ */
14139 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
14141 break;
14142 case MULU:
14143 check_insn(ctx, ISA_MIPS32R6);
14144 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
14145 break;
14146 case MUHU:
14147 check_insn(ctx, ISA_MIPS32R6);
14148 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
14149 break;
14150 case LWXS: /* DIV */
14151 if (ctx->insn_flags & ISA_MIPS32R6) {
14152 /* DIV */
14153 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
14154 } else {
14155 /* LWXS */
14156 gen_ldxs(ctx, rs, rt, rd);
14158 break;
14159 case MOD:
14160 check_insn(ctx, ISA_MIPS32R6);
14161 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
14162 break;
14163 case R6_DIVU:
14164 check_insn(ctx, ISA_MIPS32R6);
14165 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
14166 break;
14167 case MODU:
14168 check_insn(ctx, ISA_MIPS32R6);
14169 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
14170 break;
14171 default:
14172 goto pool32a_invalid;
14174 break;
14175 case INS:
14176 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
14177 return;
14178 case LSA:
14179 check_insn(ctx, ISA_MIPS32R6);
14180 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
14181 extract32(ctx->opcode, 9, 2));
14182 break;
14183 case ALIGN:
14184 check_insn(ctx, ISA_MIPS32R6);
14185 gen_align(ctx, OPC_ALIGN, rd, rs, rt,
14186 extract32(ctx->opcode, 9, 2));
14187 break;
14188 case EXT:
14189 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
14190 return;
14191 case POOL32AXF:
14192 gen_pool32axf(env, ctx, rt, rs);
14193 break;
14194 case 0x07:
14195 generate_exception(ctx, EXCP_BREAK);
14196 break;
14197 default:
14198 pool32a_invalid:
14199 MIPS_INVAL("pool32a");
14200 generate_exception(ctx, EXCP_RI);
14201 break;
14203 break;
14204 case POOL32B:
14205 minor = (ctx->opcode >> 12) & 0xf;
14206 switch (minor) {
14207 case CACHE:
14208 check_cp0_enabled(ctx);
14209 /* Treat as no-op. */
14210 break;
14211 case LWC2:
14212 case SWC2:
14213 /* COP2: Not implemented. */
14214 generate_exception_err(ctx, EXCP_CpU, 2);
14215 break;
14216 #ifdef TARGET_MIPS64
14217 case LDP:
14218 case SDP:
14219 check_insn(ctx, ISA_MIPS3);
14220 check_mips_64(ctx);
14221 /* Fallthrough */
14222 #endif
14223 case LWP:
14224 case SWP:
14225 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14226 break;
14227 #ifdef TARGET_MIPS64
14228 case LDM:
14229 case SDM:
14230 check_insn(ctx, ISA_MIPS3);
14231 check_mips_64(ctx);
14232 /* Fallthrough */
14233 #endif
14234 case LWM32:
14235 case SWM32:
14236 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14237 break;
14238 default:
14239 MIPS_INVAL("pool32b");
14240 generate_exception(ctx, EXCP_RI);
14241 break;
14243 break;
14244 case POOL32F:
14245 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14246 minor = ctx->opcode & 0x3f;
14247 check_cp1_enabled(ctx);
14248 switch (minor) {
14249 case ALNV_PS:
14250 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14251 mips32_op = OPC_ALNV_PS;
14252 goto do_madd;
14253 case MADD_S:
14254 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14255 mips32_op = OPC_MADD_S;
14256 goto do_madd;
14257 case MADD_D:
14258 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14259 mips32_op = OPC_MADD_D;
14260 goto do_madd;
14261 case MADD_PS:
14262 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14263 mips32_op = OPC_MADD_PS;
14264 goto do_madd;
14265 case MSUB_S:
14266 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14267 mips32_op = OPC_MSUB_S;
14268 goto do_madd;
14269 case MSUB_D:
14270 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14271 mips32_op = OPC_MSUB_D;
14272 goto do_madd;
14273 case MSUB_PS:
14274 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14275 mips32_op = OPC_MSUB_PS;
14276 goto do_madd;
14277 case NMADD_S:
14278 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14279 mips32_op = OPC_NMADD_S;
14280 goto do_madd;
14281 case NMADD_D:
14282 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14283 mips32_op = OPC_NMADD_D;
14284 goto do_madd;
14285 case NMADD_PS:
14286 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14287 mips32_op = OPC_NMADD_PS;
14288 goto do_madd;
14289 case NMSUB_S:
14290 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14291 mips32_op = OPC_NMSUB_S;
14292 goto do_madd;
14293 case NMSUB_D:
14294 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14295 mips32_op = OPC_NMSUB_D;
14296 goto do_madd;
14297 case NMSUB_PS:
14298 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14299 mips32_op = OPC_NMSUB_PS;
14300 do_madd:
14301 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
14302 break;
14303 case CABS_COND_FMT:
14304 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14305 cond = (ctx->opcode >> 6) & 0xf;
14306 cc = (ctx->opcode >> 13) & 0x7;
14307 fmt = (ctx->opcode >> 10) & 0x3;
14308 switch (fmt) {
14309 case 0x0:
14310 gen_cmpabs_s(ctx, cond, rt, rs, cc);
14311 break;
14312 case 0x1:
14313 gen_cmpabs_d(ctx, cond, rt, rs, cc);
14314 break;
14315 case 0x2:
14316 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
14317 break;
14318 default:
14319 goto pool32f_invalid;
14321 break;
14322 case C_COND_FMT:
14323 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14324 cond = (ctx->opcode >> 6) & 0xf;
14325 cc = (ctx->opcode >> 13) & 0x7;
14326 fmt = (ctx->opcode >> 10) & 0x3;
14327 switch (fmt) {
14328 case 0x0:
14329 gen_cmp_s(ctx, cond, rt, rs, cc);
14330 break;
14331 case 0x1:
14332 gen_cmp_d(ctx, cond, rt, rs, cc);
14333 break;
14334 case 0x2:
14335 gen_cmp_ps(ctx, cond, rt, rs, cc);
14336 break;
14337 default:
14338 goto pool32f_invalid;
14340 break;
14341 case CMP_CONDN_S:
14342 check_insn(ctx, ISA_MIPS32R6);
14343 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14344 break;
14345 case CMP_CONDN_D:
14346 check_insn(ctx, ISA_MIPS32R6);
14347 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14348 break;
14349 case POOL32FXF:
14350 gen_pool32fxf(ctx, rt, rs);
14351 break;
14352 case 0x00:
14353 /* PLL foo */
14354 switch ((ctx->opcode >> 6) & 0x7) {
14355 case PLL_PS:
14356 mips32_op = OPC_PLL_PS;
14357 goto do_ps;
14358 case PLU_PS:
14359 mips32_op = OPC_PLU_PS;
14360 goto do_ps;
14361 case PUL_PS:
14362 mips32_op = OPC_PUL_PS;
14363 goto do_ps;
14364 case PUU_PS:
14365 mips32_op = OPC_PUU_PS;
14366 goto do_ps;
14367 case CVT_PS_S:
14368 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14369 mips32_op = OPC_CVT_PS_S;
14370 do_ps:
14371 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14372 break;
14373 default:
14374 goto pool32f_invalid;
14376 break;
14377 case MIN_FMT:
14378 check_insn(ctx, ISA_MIPS32R6);
14379 switch ((ctx->opcode >> 9) & 0x3) {
14380 case FMT_SDPS_S:
14381 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
14382 break;
14383 case FMT_SDPS_D:
14384 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
14385 break;
14386 default:
14387 goto pool32f_invalid;
14389 break;
14390 case 0x08:
14391 /* [LS][WDU]XC1 */
14392 switch ((ctx->opcode >> 6) & 0x7) {
14393 case LWXC1:
14394 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14395 mips32_op = OPC_LWXC1;
14396 goto do_ldst_cp1;
14397 case SWXC1:
14398 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14399 mips32_op = OPC_SWXC1;
14400 goto do_ldst_cp1;
14401 case LDXC1:
14402 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14403 mips32_op = OPC_LDXC1;
14404 goto do_ldst_cp1;
14405 case SDXC1:
14406 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14407 mips32_op = OPC_SDXC1;
14408 goto do_ldst_cp1;
14409 case LUXC1:
14410 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14411 mips32_op = OPC_LUXC1;
14412 goto do_ldst_cp1;
14413 case SUXC1:
14414 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14415 mips32_op = OPC_SUXC1;
14416 do_ldst_cp1:
14417 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
14418 break;
14419 default:
14420 goto pool32f_invalid;
14422 break;
14423 case MAX_FMT:
14424 check_insn(ctx, ISA_MIPS32R6);
14425 switch ((ctx->opcode >> 9) & 0x3) {
14426 case FMT_SDPS_S:
14427 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
14428 break;
14429 case FMT_SDPS_D:
14430 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
14431 break;
14432 default:
14433 goto pool32f_invalid;
14435 break;
14436 case 0x18:
14437 /* 3D insns */
14438 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14439 fmt = (ctx->opcode >> 9) & 0x3;
14440 switch ((ctx->opcode >> 6) & 0x7) {
14441 case RSQRT2_FMT:
14442 switch (fmt) {
14443 case FMT_SDPS_S:
14444 mips32_op = OPC_RSQRT2_S;
14445 goto do_3d;
14446 case FMT_SDPS_D:
14447 mips32_op = OPC_RSQRT2_D;
14448 goto do_3d;
14449 case FMT_SDPS_PS:
14450 mips32_op = OPC_RSQRT2_PS;
14451 goto do_3d;
14452 default:
14453 goto pool32f_invalid;
14455 break;
14456 case RECIP2_FMT:
14457 switch (fmt) {
14458 case FMT_SDPS_S:
14459 mips32_op = OPC_RECIP2_S;
14460 goto do_3d;
14461 case FMT_SDPS_D:
14462 mips32_op = OPC_RECIP2_D;
14463 goto do_3d;
14464 case FMT_SDPS_PS:
14465 mips32_op = OPC_RECIP2_PS;
14466 goto do_3d;
14467 default:
14468 goto pool32f_invalid;
14470 break;
14471 case ADDR_PS:
14472 mips32_op = OPC_ADDR_PS;
14473 goto do_3d;
14474 case MULR_PS:
14475 mips32_op = OPC_MULR_PS;
14476 do_3d:
14477 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14478 break;
14479 default:
14480 goto pool32f_invalid;
14482 break;
14483 case 0x20:
14484 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
14485 cc = (ctx->opcode >> 13) & 0x7;
14486 fmt = (ctx->opcode >> 9) & 0x3;
14487 switch ((ctx->opcode >> 6) & 0x7) {
14488 case MOVF_FMT: /* RINT_FMT */
14489 if (ctx->insn_flags & ISA_MIPS32R6) {
14490 /* RINT_FMT */
14491 switch (fmt) {
14492 case FMT_SDPS_S:
14493 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14494 break;
14495 case FMT_SDPS_D:
14496 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14497 break;
14498 default:
14499 goto pool32f_invalid;
14501 } else {
14502 /* MOVF_FMT */
14503 switch (fmt) {
14504 case FMT_SDPS_S:
14505 gen_movcf_s(ctx, rs, rt, cc, 0);
14506 break;
14507 case FMT_SDPS_D:
14508 gen_movcf_d(ctx, rs, rt, cc, 0);
14509 break;
14510 case FMT_SDPS_PS:
14511 check_ps(ctx);
14512 gen_movcf_ps(ctx, rs, rt, cc, 0);
14513 break;
14514 default:
14515 goto pool32f_invalid;
14518 break;
14519 case MOVT_FMT: /* CLASS_FMT */
14520 if (ctx->insn_flags & ISA_MIPS32R6) {
14521 /* CLASS_FMT */
14522 switch (fmt) {
14523 case FMT_SDPS_S:
14524 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14525 break;
14526 case FMT_SDPS_D:
14527 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14528 break;
14529 default:
14530 goto pool32f_invalid;
14532 } else {
14533 /* MOVT_FMT */
14534 switch (fmt) {
14535 case FMT_SDPS_S:
14536 gen_movcf_s(ctx, rs, rt, cc, 1);
14537 break;
14538 case FMT_SDPS_D:
14539 gen_movcf_d(ctx, rs, rt, cc, 1);
14540 break;
14541 case FMT_SDPS_PS:
14542 check_ps(ctx);
14543 gen_movcf_ps(ctx, rs, rt, cc, 1);
14544 break;
14545 default:
14546 goto pool32f_invalid;
14549 break;
14550 case PREFX:
14551 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14552 break;
14553 default:
14554 goto pool32f_invalid;
14556 break;
14557 #define FINSN_3ARG_SDPS(prfx) \
14558 switch ((ctx->opcode >> 8) & 0x3) { \
14559 case FMT_SDPS_S: \
14560 mips32_op = OPC_##prfx##_S; \
14561 goto do_fpop; \
14562 case FMT_SDPS_D: \
14563 mips32_op = OPC_##prfx##_D; \
14564 goto do_fpop; \
14565 case FMT_SDPS_PS: \
14566 check_ps(ctx); \
14567 mips32_op = OPC_##prfx##_PS; \
14568 goto do_fpop; \
14569 default: \
14570 goto pool32f_invalid; \
14572 case MINA_FMT:
14573 check_insn(ctx, ISA_MIPS32R6);
14574 switch ((ctx->opcode >> 9) & 0x3) {
14575 case FMT_SDPS_S:
14576 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14577 break;
14578 case FMT_SDPS_D:
14579 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14580 break;
14581 default:
14582 goto pool32f_invalid;
14584 break;
14585 case MAXA_FMT:
14586 check_insn(ctx, ISA_MIPS32R6);
14587 switch ((ctx->opcode >> 9) & 0x3) {
14588 case FMT_SDPS_S:
14589 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14590 break;
14591 case FMT_SDPS_D:
14592 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14593 break;
14594 default:
14595 goto pool32f_invalid;
14597 break;
14598 case 0x30:
14599 /* regular FP ops */
14600 switch ((ctx->opcode >> 6) & 0x3) {
14601 case ADD_FMT:
14602 FINSN_3ARG_SDPS(ADD);
14603 break;
14604 case SUB_FMT:
14605 FINSN_3ARG_SDPS(SUB);
14606 break;
14607 case MUL_FMT:
14608 FINSN_3ARG_SDPS(MUL);
14609 break;
14610 case DIV_FMT:
14611 fmt = (ctx->opcode >> 8) & 0x3;
14612 if (fmt == 1) {
14613 mips32_op = OPC_DIV_D;
14614 } else if (fmt == 0) {
14615 mips32_op = OPC_DIV_S;
14616 } else {
14617 goto pool32f_invalid;
14619 goto do_fpop;
14620 default:
14621 goto pool32f_invalid;
14623 break;
14624 case 0x38:
14625 /* cmovs */
14626 switch ((ctx->opcode >> 6) & 0x7) {
14627 case MOVN_FMT: /* SELNEZ_FMT */
14628 if (ctx->insn_flags & ISA_MIPS32R6) {
14629 /* SELNEZ_FMT */
14630 switch ((ctx->opcode >> 9) & 0x3) {
14631 case FMT_SDPS_S:
14632 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14633 break;
14634 case FMT_SDPS_D:
14635 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
14636 break;
14637 default:
14638 goto pool32f_invalid;
14640 } else {
14641 /* MOVN_FMT */
14642 FINSN_3ARG_SDPS(MOVN);
14644 break;
14645 case MOVN_FMT_04:
14646 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14647 FINSN_3ARG_SDPS(MOVN);
14648 break;
14649 case MOVZ_FMT: /* SELEQZ_FMT */
14650 if (ctx->insn_flags & ISA_MIPS32R6) {
14651 /* SELEQZ_FMT */
14652 switch ((ctx->opcode >> 9) & 0x3) {
14653 case FMT_SDPS_S:
14654 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
14655 break;
14656 case FMT_SDPS_D:
14657 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
14658 break;
14659 default:
14660 goto pool32f_invalid;
14662 } else {
14663 /* MOVZ_FMT */
14664 FINSN_3ARG_SDPS(MOVZ);
14666 break;
14667 case MOVZ_FMT_05:
14668 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14669 FINSN_3ARG_SDPS(MOVZ);
14670 break;
14671 case SEL_FMT:
14672 check_insn(ctx, ISA_MIPS32R6);
14673 switch ((ctx->opcode >> 9) & 0x3) {
14674 case FMT_SDPS_S:
14675 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
14676 break;
14677 case FMT_SDPS_D:
14678 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
14679 break;
14680 default:
14681 goto pool32f_invalid;
14683 break;
14684 case MADDF_FMT:
14685 check_insn(ctx, ISA_MIPS32R6);
14686 switch ((ctx->opcode >> 9) & 0x3) {
14687 case FMT_SDPS_S:
14688 mips32_op = OPC_MADDF_S;
14689 goto do_fpop;
14690 case FMT_SDPS_D:
14691 mips32_op = OPC_MADDF_D;
14692 goto do_fpop;
14693 default:
14694 goto pool32f_invalid;
14696 break;
14697 case MSUBF_FMT:
14698 check_insn(ctx, ISA_MIPS32R6);
14699 switch ((ctx->opcode >> 9) & 0x3) {
14700 case FMT_SDPS_S:
14701 mips32_op = OPC_MSUBF_S;
14702 goto do_fpop;
14703 case FMT_SDPS_D:
14704 mips32_op = OPC_MSUBF_D;
14705 goto do_fpop;
14706 default:
14707 goto pool32f_invalid;
14709 break;
14710 default:
14711 goto pool32f_invalid;
14713 break;
14714 do_fpop:
14715 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14716 break;
14717 default:
14718 pool32f_invalid:
14719 MIPS_INVAL("pool32f");
14720 generate_exception(ctx, EXCP_RI);
14721 break;
14723 } else {
14724 generate_exception_err(ctx, EXCP_CpU, 1);
14726 break;
14727 case POOL32I:
14728 minor = (ctx->opcode >> 21) & 0x1f;
14729 switch (minor) {
14730 case BLTZ:
14731 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14732 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
14733 break;
14734 case BLTZAL:
14735 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14736 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
14737 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14738 break;
14739 case BLTZALS:
14740 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14741 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
14742 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14743 break;
14744 case BGEZ:
14745 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14746 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
14747 break;
14748 case BGEZAL:
14749 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14750 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
14751 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14752 break;
14753 case BGEZALS:
14754 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14755 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
14756 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14757 break;
14758 case BLEZ:
14759 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14760 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
14761 break;
14762 case BGTZ:
14763 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14764 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
14765 break;
14767 /* Traps */
14768 case TLTI: /* BC1EQZC */
14769 if (ctx->insn_flags & ISA_MIPS32R6) {
14770 /* BC1EQZC */
14771 check_cp1_enabled(ctx);
14772 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
14773 } else {
14774 /* TLTI */
14775 mips32_op = OPC_TLTI;
14776 goto do_trapi;
14778 break;
14779 case TGEI: /* BC1NEZC */
14780 if (ctx->insn_flags & ISA_MIPS32R6) {
14781 /* BC1NEZC */
14782 check_cp1_enabled(ctx);
14783 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
14784 } else {
14785 /* TGEI */
14786 mips32_op = OPC_TGEI;
14787 goto do_trapi;
14789 break;
14790 case TLTIU:
14791 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14792 mips32_op = OPC_TLTIU;
14793 goto do_trapi;
14794 case TGEIU:
14795 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14796 mips32_op = OPC_TGEIU;
14797 goto do_trapi;
14798 case TNEI: /* SYNCI */
14799 if (ctx->insn_flags & ISA_MIPS32R6) {
14800 /* SYNCI */
14801 /* Break the TB to be able to sync copied instructions
14802 immediately */
14803 ctx->bstate = BS_STOP;
14804 } else {
14805 /* TNEI */
14806 mips32_op = OPC_TNEI;
14807 goto do_trapi;
14809 break;
14810 case TEQI:
14811 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14812 mips32_op = OPC_TEQI;
14813 do_trapi:
14814 gen_trap(ctx, mips32_op, rs, -1, imm);
14815 break;
14817 case BNEZC:
14818 case BEQZC:
14819 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14820 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
14821 4, rs, 0, imm << 1, 0);
14822 /* Compact branches don't have a delay slot, so just let
14823 the normal delay slot handling take us to the branch
14824 target. */
14825 break;
14826 case LUI:
14827 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14828 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
14829 break;
14830 case SYNCI:
14831 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14832 /* Break the TB to be able to sync copied instructions
14833 immediately */
14834 ctx->bstate = BS_STOP;
14835 break;
14836 case BC2F:
14837 case BC2T:
14838 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14839 /* COP2: Not implemented. */
14840 generate_exception_err(ctx, EXCP_CpU, 2);
14841 break;
14842 case BC1F:
14843 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14844 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
14845 goto do_cp1branch;
14846 case BC1T:
14847 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14848 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
14849 goto do_cp1branch;
14850 case BC1ANY4F:
14851 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14852 mips32_op = OPC_BC1FANY4;
14853 goto do_cp1mips3d;
14854 case BC1ANY4T:
14855 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14856 mips32_op = OPC_BC1TANY4;
14857 do_cp1mips3d:
14858 check_cop1x(ctx);
14859 check_insn(ctx, ASE_MIPS3D);
14860 /* Fall through */
14861 do_cp1branch:
14862 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14863 check_cp1_enabled(ctx);
14864 gen_compute_branch1(ctx, mips32_op,
14865 (ctx->opcode >> 18) & 0x7, imm << 1);
14866 } else {
14867 generate_exception_err(ctx, EXCP_CpU, 1);
14869 break;
14870 case BPOSGE64:
14871 case BPOSGE32:
14872 /* MIPS DSP: not implemented */
14873 /* Fall through */
14874 default:
14875 MIPS_INVAL("pool32i");
14876 generate_exception(ctx, EXCP_RI);
14877 break;
14879 break;
14880 case POOL32C:
14881 minor = (ctx->opcode >> 12) & 0xf;
14882 offset = sextract32(ctx->opcode, 0,
14883 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
14884 switch (minor) {
14885 case LWL:
14886 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14887 mips32_op = OPC_LWL;
14888 goto do_ld_lr;
14889 case SWL:
14890 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14891 mips32_op = OPC_SWL;
14892 goto do_st_lr;
14893 case LWR:
14894 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14895 mips32_op = OPC_LWR;
14896 goto do_ld_lr;
14897 case SWR:
14898 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14899 mips32_op = OPC_SWR;
14900 goto do_st_lr;
14901 #if defined(TARGET_MIPS64)
14902 case LDL:
14903 check_insn(ctx, ISA_MIPS3);
14904 check_mips_64(ctx);
14905 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14906 mips32_op = OPC_LDL;
14907 goto do_ld_lr;
14908 case SDL:
14909 check_insn(ctx, ISA_MIPS3);
14910 check_mips_64(ctx);
14911 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14912 mips32_op = OPC_SDL;
14913 goto do_st_lr;
14914 case LDR:
14915 check_insn(ctx, ISA_MIPS3);
14916 check_mips_64(ctx);
14917 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14918 mips32_op = OPC_LDR;
14919 goto do_ld_lr;
14920 case SDR:
14921 check_insn(ctx, ISA_MIPS3);
14922 check_mips_64(ctx);
14923 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14924 mips32_op = OPC_SDR;
14925 goto do_st_lr;
14926 case LWU:
14927 check_insn(ctx, ISA_MIPS3);
14928 check_mips_64(ctx);
14929 mips32_op = OPC_LWU;
14930 goto do_ld_lr;
14931 case LLD:
14932 check_insn(ctx, ISA_MIPS3);
14933 check_mips_64(ctx);
14934 mips32_op = OPC_LLD;
14935 goto do_ld_lr;
14936 #endif
14937 case LL:
14938 mips32_op = OPC_LL;
14939 goto do_ld_lr;
14940 do_ld_lr:
14941 gen_ld(ctx, mips32_op, rt, rs, offset);
14942 break;
14943 do_st_lr:
14944 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
14945 break;
14946 case SC:
14947 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
14948 break;
14949 #if defined(TARGET_MIPS64)
14950 case SCD:
14951 check_insn(ctx, ISA_MIPS3);
14952 check_mips_64(ctx);
14953 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
14954 break;
14955 #endif
14956 case PREF:
14957 /* Treat as no-op */
14958 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
14959 /* hint codes 24-31 are reserved and signal RI */
14960 generate_exception(ctx, EXCP_RI);
14962 break;
14963 default:
14964 MIPS_INVAL("pool32c");
14965 generate_exception(ctx, EXCP_RI);
14966 break;
14968 break;
14969 case ADDI32: /* AUI, LUI */
14970 if (ctx->insn_flags & ISA_MIPS32R6) {
14971 /* AUI, LUI */
14972 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
14973 } else {
14974 /* ADDI32 */
14975 mips32_op = OPC_ADDI;
14976 goto do_addi;
14978 break;
14979 case ADDIU32:
14980 mips32_op = OPC_ADDIU;
14981 do_addi:
14982 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
14983 break;
14985 /* Logical operations */
14986 case ORI32:
14987 mips32_op = OPC_ORI;
14988 goto do_logici;
14989 case XORI32:
14990 mips32_op = OPC_XORI;
14991 goto do_logici;
14992 case ANDI32:
14993 mips32_op = OPC_ANDI;
14994 do_logici:
14995 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
14996 break;
14998 /* Set less than immediate */
14999 case SLTI32:
15000 mips32_op = OPC_SLTI;
15001 goto do_slti;
15002 case SLTIU32:
15003 mips32_op = OPC_SLTIU;
15004 do_slti:
15005 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
15006 break;
15007 case JALX32:
15008 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15009 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15010 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
15011 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15012 break;
15013 case JALS32: /* BOVC, BEQC, BEQZALC */
15014 if (ctx->insn_flags & ISA_MIPS32R6) {
15015 if (rs >= rt) {
15016 /* BOVC */
15017 mips32_op = OPC_BOVC;
15018 } else if (rs < rt && rs == 0) {
15019 /* BEQZALC */
15020 mips32_op = OPC_BEQZALC;
15021 } else {
15022 /* BEQC */
15023 mips32_op = OPC_BEQC;
15025 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15026 } else {
15027 /* JALS32 */
15028 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
15029 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
15030 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15032 break;
15033 case BEQ32: /* BC */
15034 if (ctx->insn_flags & ISA_MIPS32R6) {
15035 /* BC */
15036 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
15037 sextract32(ctx->opcode << 1, 0, 27));
15038 } else {
15039 /* BEQ32 */
15040 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
15042 break;
15043 case BNE32: /* BALC */
15044 if (ctx->insn_flags & ISA_MIPS32R6) {
15045 /* BALC */
15046 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
15047 sextract32(ctx->opcode << 1, 0, 27));
15048 } else {
15049 /* BNE32 */
15050 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
15052 break;
15053 case J32: /* BGTZC, BLTZC, BLTC */
15054 if (ctx->insn_flags & ISA_MIPS32R6) {
15055 if (rs == 0 && rt != 0) {
15056 /* BGTZC */
15057 mips32_op = OPC_BGTZC;
15058 } else if (rs != 0 && rt != 0 && rs == rt) {
15059 /* BLTZC */
15060 mips32_op = OPC_BLTZC;
15061 } else {
15062 /* BLTC */
15063 mips32_op = OPC_BLTC;
15065 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15066 } else {
15067 /* J32 */
15068 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
15069 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15071 break;
15072 case JAL32: /* BLEZC, BGEZC, BGEC */
15073 if (ctx->insn_flags & ISA_MIPS32R6) {
15074 if (rs == 0 && rt != 0) {
15075 /* BLEZC */
15076 mips32_op = OPC_BLEZC;
15077 } else if (rs != 0 && rt != 0 && rs == rt) {
15078 /* BGEZC */
15079 mips32_op = OPC_BGEZC;
15080 } else {
15081 /* BGEC */
15082 mips32_op = OPC_BGEC;
15084 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15085 } else {
15086 /* JAL32 */
15087 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
15088 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15089 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15091 break;
15092 /* Floating point (COP1) */
15093 case LWC132:
15094 mips32_op = OPC_LWC1;
15095 goto do_cop1;
15096 case LDC132:
15097 mips32_op = OPC_LDC1;
15098 goto do_cop1;
15099 case SWC132:
15100 mips32_op = OPC_SWC1;
15101 goto do_cop1;
15102 case SDC132:
15103 mips32_op = OPC_SDC1;
15104 do_cop1:
15105 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
15106 break;
15107 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15108 if (ctx->insn_flags & ISA_MIPS32R6) {
15109 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15110 switch ((ctx->opcode >> 16) & 0x1f) {
15111 case ADDIUPC_00 ... ADDIUPC_07:
15112 gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
15113 break;
15114 case AUIPC:
15115 gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
15116 break;
15117 case ALUIPC:
15118 gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
15119 break;
15120 case LWPC_08 ... LWPC_0F:
15121 gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
15122 break;
15123 default:
15124 generate_exception(ctx, EXCP_RI);
15125 break;
15127 } else {
15128 /* ADDIUPC */
15129 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
15130 int offset = SIMM(ctx->opcode, 0, 23) << 2;
15132 gen_addiupc(ctx, reg, offset, 0, 0);
15134 break;
15135 case BNVC: /* BNEC, BNEZALC */
15136 check_insn(ctx, ISA_MIPS32R6);
15137 if (rs >= rt) {
15138 /* BNVC */
15139 mips32_op = OPC_BNVC;
15140 } else if (rs < rt && rs == 0) {
15141 /* BNEZALC */
15142 mips32_op = OPC_BNEZALC;
15143 } else {
15144 /* BNEC */
15145 mips32_op = OPC_BNEC;
15147 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15148 break;
15149 case R6_BNEZC: /* JIALC */
15150 check_insn(ctx, ISA_MIPS32R6);
15151 if (rt != 0) {
15152 /* BNEZC */
15153 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
15154 sextract32(ctx->opcode << 1, 0, 22));
15155 } else {
15156 /* JIALC */
15157 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
15159 break;
15160 case R6_BEQZC: /* JIC */
15161 check_insn(ctx, ISA_MIPS32R6);
15162 if (rt != 0) {
15163 /* BEQZC */
15164 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
15165 sextract32(ctx->opcode << 1, 0, 22));
15166 } else {
15167 /* JIC */
15168 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
15170 break;
15171 case BLEZALC: /* BGEZALC, BGEUC */
15172 check_insn(ctx, ISA_MIPS32R6);
15173 if (rs == 0 && rt != 0) {
15174 /* BLEZALC */
15175 mips32_op = OPC_BLEZALC;
15176 } else if (rs != 0 && rt != 0 && rs == rt) {
15177 /* BGEZALC */
15178 mips32_op = OPC_BGEZALC;
15179 } else {
15180 /* BGEUC */
15181 mips32_op = OPC_BGEUC;
15183 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15184 break;
15185 case BGTZALC: /* BLTZALC, BLTUC */
15186 check_insn(ctx, ISA_MIPS32R6);
15187 if (rs == 0 && rt != 0) {
15188 /* BGTZALC */
15189 mips32_op = OPC_BGTZALC;
15190 } else if (rs != 0 && rt != 0 && rs == rt) {
15191 /* BLTZALC */
15192 mips32_op = OPC_BLTZALC;
15193 } else {
15194 /* BLTUC */
15195 mips32_op = OPC_BLTUC;
15197 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15198 break;
15199 /* Loads and stores */
15200 case LB32:
15201 mips32_op = OPC_LB;
15202 goto do_ld;
15203 case LBU32:
15204 mips32_op = OPC_LBU;
15205 goto do_ld;
15206 case LH32:
15207 mips32_op = OPC_LH;
15208 goto do_ld;
15209 case LHU32:
15210 mips32_op = OPC_LHU;
15211 goto do_ld;
15212 case LW32:
15213 mips32_op = OPC_LW;
15214 goto do_ld;
15215 #ifdef TARGET_MIPS64
15216 case LD32:
15217 check_insn(ctx, ISA_MIPS3);
15218 check_mips_64(ctx);
15219 mips32_op = OPC_LD;
15220 goto do_ld;
15221 case SD32:
15222 check_insn(ctx, ISA_MIPS3);
15223 check_mips_64(ctx);
15224 mips32_op = OPC_SD;
15225 goto do_st;
15226 #endif
15227 case SB32:
15228 mips32_op = OPC_SB;
15229 goto do_st;
15230 case SH32:
15231 mips32_op = OPC_SH;
15232 goto do_st;
15233 case SW32:
15234 mips32_op = OPC_SW;
15235 goto do_st;
15236 do_ld:
15237 gen_ld(ctx, mips32_op, rt, rs, imm);
15238 break;
15239 do_st:
15240 gen_st(ctx, mips32_op, rt, rs, imm);
15241 break;
15242 default:
15243 generate_exception(ctx, EXCP_RI);
15244 break;
15248 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
15250 uint32_t op;
15252 /* make sure instructions are on a halfword boundary */
15253 if (ctx->pc & 0x1) {
15254 env->CP0_BadVAddr = ctx->pc;
15255 generate_exception(ctx, EXCP_AdEL);
15256 ctx->bstate = BS_STOP;
15257 return 2;
15260 op = (ctx->opcode >> 10) & 0x3f;
15261 /* Enforce properly-sized instructions in a delay slot */
15262 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
15263 switch (op & 0x7) { /* MSB-3..MSB-5 */
15264 case 0:
15265 /* POOL32A, POOL32B, POOL32I, POOL32C */
15266 case 4:
15267 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
15268 case 5:
15269 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
15270 case 6:
15271 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
15272 case 7:
15273 /* LB32, LH32, LWC132, LDC132, LW32 */
15274 if (ctx->hflags & MIPS_HFLAG_BDS16) {
15275 generate_exception(ctx, EXCP_RI);
15276 /* Just stop translation; the user is confused. */
15277 ctx->bstate = BS_STOP;
15278 return 2;
15280 break;
15281 case 1:
15282 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
15283 case 2:
15284 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
15285 case 3:
15286 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
15287 if (ctx->hflags & MIPS_HFLAG_BDS32) {
15288 generate_exception(ctx, EXCP_RI);
15289 /* Just stop translation; the user is confused. */
15290 ctx->bstate = BS_STOP;
15291 return 2;
15293 break;
15297 switch (op) {
15298 case POOL16A:
15300 int rd = mmreg(uMIPS_RD(ctx->opcode));
15301 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
15302 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
15303 uint32_t opc = 0;
15305 switch (ctx->opcode & 0x1) {
15306 case ADDU16:
15307 opc = OPC_ADDU;
15308 break;
15309 case SUBU16:
15310 opc = OPC_SUBU;
15311 break;
15313 if (ctx->insn_flags & ISA_MIPS32R6) {
15314 /* In the Release 6 the register number location in
15315 * the instruction encoding has changed.
15317 gen_arith(ctx, opc, rs1, rd, rs2);
15318 } else {
15319 gen_arith(ctx, opc, rd, rs1, rs2);
15322 break;
15323 case POOL16B:
15325 int rd = mmreg(uMIPS_RD(ctx->opcode));
15326 int rs = mmreg(uMIPS_RS(ctx->opcode));
15327 int amount = (ctx->opcode >> 1) & 0x7;
15328 uint32_t opc = 0;
15329 amount = amount == 0 ? 8 : amount;
15331 switch (ctx->opcode & 0x1) {
15332 case SLL16:
15333 opc = OPC_SLL;
15334 break;
15335 case SRL16:
15336 opc = OPC_SRL;
15337 break;
15340 gen_shift_imm(ctx, opc, rd, rs, amount);
15342 break;
15343 case POOL16C:
15344 if (ctx->insn_flags & ISA_MIPS32R6) {
15345 gen_pool16c_r6_insn(ctx);
15346 } else {
15347 gen_pool16c_insn(ctx);
15349 break;
15350 case LWGP16:
15352 int rd = mmreg(uMIPS_RD(ctx->opcode));
15353 int rb = 28; /* GP */
15354 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
15356 gen_ld(ctx, OPC_LW, rd, rb, offset);
15358 break;
15359 case POOL16F:
15360 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15361 if (ctx->opcode & 1) {
15362 generate_exception(ctx, EXCP_RI);
15363 } else {
15364 /* MOVEP */
15365 int enc_dest = uMIPS_RD(ctx->opcode);
15366 int enc_rt = uMIPS_RS2(ctx->opcode);
15367 int enc_rs = uMIPS_RS1(ctx->opcode);
15368 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15370 break;
15371 case LBU16:
15373 int rd = mmreg(uMIPS_RD(ctx->opcode));
15374 int rb = mmreg(uMIPS_RS(ctx->opcode));
15375 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15376 offset = (offset == 0xf ? -1 : offset);
15378 gen_ld(ctx, OPC_LBU, rd, rb, offset);
15380 break;
15381 case LHU16:
15383 int rd = mmreg(uMIPS_RD(ctx->opcode));
15384 int rb = mmreg(uMIPS_RS(ctx->opcode));
15385 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15387 gen_ld(ctx, OPC_LHU, rd, rb, offset);
15389 break;
15390 case LWSP16:
15392 int rd = (ctx->opcode >> 5) & 0x1f;
15393 int rb = 29; /* SP */
15394 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15396 gen_ld(ctx, OPC_LW, rd, rb, offset);
15398 break;
15399 case LW16:
15401 int rd = mmreg(uMIPS_RD(ctx->opcode));
15402 int rb = mmreg(uMIPS_RS(ctx->opcode));
15403 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15405 gen_ld(ctx, OPC_LW, rd, rb, offset);
15407 break;
15408 case SB16:
15410 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15411 int rb = mmreg(uMIPS_RS(ctx->opcode));
15412 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15414 gen_st(ctx, OPC_SB, rd, rb, offset);
15416 break;
15417 case SH16:
15419 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15420 int rb = mmreg(uMIPS_RS(ctx->opcode));
15421 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15423 gen_st(ctx, OPC_SH, rd, rb, offset);
15425 break;
15426 case SWSP16:
15428 int rd = (ctx->opcode >> 5) & 0x1f;
15429 int rb = 29; /* SP */
15430 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15432 gen_st(ctx, OPC_SW, rd, rb, offset);
15434 break;
15435 case SW16:
15437 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15438 int rb = mmreg(uMIPS_RS(ctx->opcode));
15439 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15441 gen_st(ctx, OPC_SW, rd, rb, offset);
15443 break;
15444 case MOVE16:
15446 int rd = uMIPS_RD5(ctx->opcode);
15447 int rs = uMIPS_RS5(ctx->opcode);
15449 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
15451 break;
15452 case ANDI16:
15453 gen_andi16(ctx);
15454 break;
15455 case POOL16D:
15456 switch (ctx->opcode & 0x1) {
15457 case ADDIUS5:
15458 gen_addius5(ctx);
15459 break;
15460 case ADDIUSP:
15461 gen_addiusp(ctx);
15462 break;
15464 break;
15465 case POOL16E:
15466 switch (ctx->opcode & 0x1) {
15467 case ADDIUR2:
15468 gen_addiur2(ctx);
15469 break;
15470 case ADDIUR1SP:
15471 gen_addiur1sp(ctx);
15472 break;
15474 break;
15475 case B16: /* BC16 */
15476 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
15477 sextract32(ctx->opcode, 0, 10) << 1,
15478 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15479 break;
15480 case BNEZ16: /* BNEZC16 */
15481 case BEQZ16: /* BEQZC16 */
15482 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
15483 mmreg(uMIPS_RD(ctx->opcode)),
15484 0, sextract32(ctx->opcode, 0, 7) << 1,
15485 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15487 break;
15488 case LI16:
15490 int reg = mmreg(uMIPS_RD(ctx->opcode));
15491 int imm = ZIMM(ctx->opcode, 0, 7);
15493 imm = (imm == 0x7f ? -1 : imm);
15494 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15496 break;
15497 case RES_29:
15498 case RES_31:
15499 case RES_39:
15500 generate_exception(ctx, EXCP_RI);
15501 break;
15502 default:
15503 decode_micromips32_opc(env, ctx);
15504 return 4;
15507 return 2;
15510 /* SmartMIPS extension to MIPS32 */
15512 #if defined(TARGET_MIPS64)
15514 /* MDMX extension to MIPS64 */
15516 #endif
15518 /* MIPSDSP functions. */
15519 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
15520 int rd, int base, int offset)
15522 const char *opn = "ldx";
15523 TCGv t0;
15525 check_dsp(ctx);
15526 t0 = tcg_temp_new();
15528 if (base == 0) {
15529 gen_load_gpr(t0, offset);
15530 } else if (offset == 0) {
15531 gen_load_gpr(t0, base);
15532 } else {
15533 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
15536 switch (opc) {
15537 case OPC_LBUX:
15538 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
15539 gen_store_gpr(t0, rd);
15540 opn = "lbux";
15541 break;
15542 case OPC_LHX:
15543 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
15544 gen_store_gpr(t0, rd);
15545 opn = "lhx";
15546 break;
15547 case OPC_LWX:
15548 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
15549 gen_store_gpr(t0, rd);
15550 opn = "lwx";
15551 break;
15552 #if defined(TARGET_MIPS64)
15553 case OPC_LDX:
15554 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
15555 gen_store_gpr(t0, rd);
15556 opn = "ldx";
15557 break;
15558 #endif
15560 (void)opn; /* avoid a compiler warning */
15561 MIPS_DEBUG("%s %s, %s(%s)", opn,
15562 regnames[rd], regnames[offset], regnames[base]);
15563 tcg_temp_free(t0);
15566 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
15567 int ret, int v1, int v2)
15569 const char *opn = "mipsdsp arith";
15570 TCGv v1_t;
15571 TCGv v2_t;
15573 if (ret == 0) {
15574 /* Treat as NOP. */
15575 MIPS_DEBUG("NOP");
15576 return;
15579 v1_t = tcg_temp_new();
15580 v2_t = tcg_temp_new();
15582 gen_load_gpr(v1_t, v1);
15583 gen_load_gpr(v2_t, v2);
15585 switch (op1) {
15586 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
15587 case OPC_MULT_G_2E:
15588 check_dspr2(ctx);
15589 switch (op2) {
15590 case OPC_ADDUH_QB:
15591 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
15592 break;
15593 case OPC_ADDUH_R_QB:
15594 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15595 break;
15596 case OPC_ADDQH_PH:
15597 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
15598 break;
15599 case OPC_ADDQH_R_PH:
15600 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15601 break;
15602 case OPC_ADDQH_W:
15603 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
15604 break;
15605 case OPC_ADDQH_R_W:
15606 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15607 break;
15608 case OPC_SUBUH_QB:
15609 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
15610 break;
15611 case OPC_SUBUH_R_QB:
15612 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15613 break;
15614 case OPC_SUBQH_PH:
15615 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
15616 break;
15617 case OPC_SUBQH_R_PH:
15618 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15619 break;
15620 case OPC_SUBQH_W:
15621 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
15622 break;
15623 case OPC_SUBQH_R_W:
15624 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15625 break;
15627 break;
15628 case OPC_ABSQ_S_PH_DSP:
15629 switch (op2) {
15630 case OPC_ABSQ_S_QB:
15631 check_dspr2(ctx);
15632 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
15633 break;
15634 case OPC_ABSQ_S_PH:
15635 check_dsp(ctx);
15636 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
15637 break;
15638 case OPC_ABSQ_S_W:
15639 check_dsp(ctx);
15640 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
15641 break;
15642 case OPC_PRECEQ_W_PHL:
15643 check_dsp(ctx);
15644 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
15645 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15646 break;
15647 case OPC_PRECEQ_W_PHR:
15648 check_dsp(ctx);
15649 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
15650 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
15651 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15652 break;
15653 case OPC_PRECEQU_PH_QBL:
15654 check_dsp(ctx);
15655 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
15656 break;
15657 case OPC_PRECEQU_PH_QBR:
15658 check_dsp(ctx);
15659 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
15660 break;
15661 case OPC_PRECEQU_PH_QBLA:
15662 check_dsp(ctx);
15663 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
15664 break;
15665 case OPC_PRECEQU_PH_QBRA:
15666 check_dsp(ctx);
15667 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
15668 break;
15669 case OPC_PRECEU_PH_QBL:
15670 check_dsp(ctx);
15671 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
15672 break;
15673 case OPC_PRECEU_PH_QBR:
15674 check_dsp(ctx);
15675 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
15676 break;
15677 case OPC_PRECEU_PH_QBLA:
15678 check_dsp(ctx);
15679 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
15680 break;
15681 case OPC_PRECEU_PH_QBRA:
15682 check_dsp(ctx);
15683 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
15684 break;
15686 break;
15687 case OPC_ADDU_QB_DSP:
15688 switch (op2) {
15689 case OPC_ADDQ_PH:
15690 check_dsp(ctx);
15691 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15692 break;
15693 case OPC_ADDQ_S_PH:
15694 check_dsp(ctx);
15695 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15696 break;
15697 case OPC_ADDQ_S_W:
15698 check_dsp(ctx);
15699 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15700 break;
15701 case OPC_ADDU_QB:
15702 check_dsp(ctx);
15703 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15704 break;
15705 case OPC_ADDU_S_QB:
15706 check_dsp(ctx);
15707 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15708 break;
15709 case OPC_ADDU_PH:
15710 check_dspr2(ctx);
15711 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15712 break;
15713 case OPC_ADDU_S_PH:
15714 check_dspr2(ctx);
15715 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15716 break;
15717 case OPC_SUBQ_PH:
15718 check_dsp(ctx);
15719 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15720 break;
15721 case OPC_SUBQ_S_PH:
15722 check_dsp(ctx);
15723 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15724 break;
15725 case OPC_SUBQ_S_W:
15726 check_dsp(ctx);
15727 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15728 break;
15729 case OPC_SUBU_QB:
15730 check_dsp(ctx);
15731 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15732 break;
15733 case OPC_SUBU_S_QB:
15734 check_dsp(ctx);
15735 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15736 break;
15737 case OPC_SUBU_PH:
15738 check_dspr2(ctx);
15739 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15740 break;
15741 case OPC_SUBU_S_PH:
15742 check_dspr2(ctx);
15743 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15744 break;
15745 case OPC_ADDSC:
15746 check_dsp(ctx);
15747 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15748 break;
15749 case OPC_ADDWC:
15750 check_dsp(ctx);
15751 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15752 break;
15753 case OPC_MODSUB:
15754 check_dsp(ctx);
15755 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
15756 break;
15757 case OPC_RADDU_W_QB:
15758 check_dsp(ctx);
15759 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
15760 break;
15762 break;
15763 case OPC_CMPU_EQ_QB_DSP:
15764 switch (op2) {
15765 case OPC_PRECR_QB_PH:
15766 check_dspr2(ctx);
15767 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15768 break;
15769 case OPC_PRECRQ_QB_PH:
15770 check_dsp(ctx);
15771 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15772 break;
15773 case OPC_PRECR_SRA_PH_W:
15774 check_dspr2(ctx);
15776 TCGv_i32 sa_t = tcg_const_i32(v2);
15777 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
15778 cpu_gpr[ret]);
15779 tcg_temp_free_i32(sa_t);
15780 break;
15782 case OPC_PRECR_SRA_R_PH_W:
15783 check_dspr2(ctx);
15785 TCGv_i32 sa_t = tcg_const_i32(v2);
15786 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
15787 cpu_gpr[ret]);
15788 tcg_temp_free_i32(sa_t);
15789 break;
15791 case OPC_PRECRQ_PH_W:
15792 check_dsp(ctx);
15793 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
15794 break;
15795 case OPC_PRECRQ_RS_PH_W:
15796 check_dsp(ctx);
15797 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15798 break;
15799 case OPC_PRECRQU_S_QB_PH:
15800 check_dsp(ctx);
15801 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15802 break;
15804 break;
15805 #ifdef TARGET_MIPS64
15806 case OPC_ABSQ_S_QH_DSP:
15807 switch (op2) {
15808 case OPC_PRECEQ_L_PWL:
15809 check_dsp(ctx);
15810 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
15811 break;
15812 case OPC_PRECEQ_L_PWR:
15813 check_dsp(ctx);
15814 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
15815 break;
15816 case OPC_PRECEQ_PW_QHL:
15817 check_dsp(ctx);
15818 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
15819 break;
15820 case OPC_PRECEQ_PW_QHR:
15821 check_dsp(ctx);
15822 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
15823 break;
15824 case OPC_PRECEQ_PW_QHLA:
15825 check_dsp(ctx);
15826 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
15827 break;
15828 case OPC_PRECEQ_PW_QHRA:
15829 check_dsp(ctx);
15830 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
15831 break;
15832 case OPC_PRECEQU_QH_OBL:
15833 check_dsp(ctx);
15834 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
15835 break;
15836 case OPC_PRECEQU_QH_OBR:
15837 check_dsp(ctx);
15838 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
15839 break;
15840 case OPC_PRECEQU_QH_OBLA:
15841 check_dsp(ctx);
15842 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
15843 break;
15844 case OPC_PRECEQU_QH_OBRA:
15845 check_dsp(ctx);
15846 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
15847 break;
15848 case OPC_PRECEU_QH_OBL:
15849 check_dsp(ctx);
15850 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
15851 break;
15852 case OPC_PRECEU_QH_OBR:
15853 check_dsp(ctx);
15854 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
15855 break;
15856 case OPC_PRECEU_QH_OBLA:
15857 check_dsp(ctx);
15858 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
15859 break;
15860 case OPC_PRECEU_QH_OBRA:
15861 check_dsp(ctx);
15862 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
15863 break;
15864 case OPC_ABSQ_S_OB:
15865 check_dspr2(ctx);
15866 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
15867 break;
15868 case OPC_ABSQ_S_PW:
15869 check_dsp(ctx);
15870 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
15871 break;
15872 case OPC_ABSQ_S_QH:
15873 check_dsp(ctx);
15874 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
15875 break;
15877 break;
15878 case OPC_ADDU_OB_DSP:
15879 switch (op2) {
15880 case OPC_RADDU_L_OB:
15881 check_dsp(ctx);
15882 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
15883 break;
15884 case OPC_SUBQ_PW:
15885 check_dsp(ctx);
15886 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15887 break;
15888 case OPC_SUBQ_S_PW:
15889 check_dsp(ctx);
15890 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15891 break;
15892 case OPC_SUBQ_QH:
15893 check_dsp(ctx);
15894 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15895 break;
15896 case OPC_SUBQ_S_QH:
15897 check_dsp(ctx);
15898 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15899 break;
15900 case OPC_SUBU_OB:
15901 check_dsp(ctx);
15902 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15903 break;
15904 case OPC_SUBU_S_OB:
15905 check_dsp(ctx);
15906 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15907 break;
15908 case OPC_SUBU_QH:
15909 check_dspr2(ctx);
15910 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15911 break;
15912 case OPC_SUBU_S_QH:
15913 check_dspr2(ctx);
15914 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15915 break;
15916 case OPC_SUBUH_OB:
15917 check_dspr2(ctx);
15918 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
15919 break;
15920 case OPC_SUBUH_R_OB:
15921 check_dspr2(ctx);
15922 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15923 break;
15924 case OPC_ADDQ_PW:
15925 check_dsp(ctx);
15926 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15927 break;
15928 case OPC_ADDQ_S_PW:
15929 check_dsp(ctx);
15930 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15931 break;
15932 case OPC_ADDQ_QH:
15933 check_dsp(ctx);
15934 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15935 break;
15936 case OPC_ADDQ_S_QH:
15937 check_dsp(ctx);
15938 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15939 break;
15940 case OPC_ADDU_OB:
15941 check_dsp(ctx);
15942 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15943 break;
15944 case OPC_ADDU_S_OB:
15945 check_dsp(ctx);
15946 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15947 break;
15948 case OPC_ADDU_QH:
15949 check_dspr2(ctx);
15950 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15951 break;
15952 case OPC_ADDU_S_QH:
15953 check_dspr2(ctx);
15954 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15955 break;
15956 case OPC_ADDUH_OB:
15957 check_dspr2(ctx);
15958 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
15959 break;
15960 case OPC_ADDUH_R_OB:
15961 check_dspr2(ctx);
15962 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15963 break;
15965 break;
15966 case OPC_CMPU_EQ_OB_DSP:
15967 switch (op2) {
15968 case OPC_PRECR_OB_QH:
15969 check_dspr2(ctx);
15970 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15971 break;
15972 case OPC_PRECR_SRA_QH_PW:
15973 check_dspr2(ctx);
15975 TCGv_i32 ret_t = tcg_const_i32(ret);
15976 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
15977 tcg_temp_free_i32(ret_t);
15978 break;
15980 case OPC_PRECR_SRA_R_QH_PW:
15981 check_dspr2(ctx);
15983 TCGv_i32 sa_v = tcg_const_i32(ret);
15984 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
15985 tcg_temp_free_i32(sa_v);
15986 break;
15988 case OPC_PRECRQ_OB_QH:
15989 check_dsp(ctx);
15990 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15991 break;
15992 case OPC_PRECRQ_PW_L:
15993 check_dsp(ctx);
15994 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
15995 break;
15996 case OPC_PRECRQ_QH_PW:
15997 check_dsp(ctx);
15998 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
15999 break;
16000 case OPC_PRECRQ_RS_QH_PW:
16001 check_dsp(ctx);
16002 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16003 break;
16004 case OPC_PRECRQU_S_OB_QH:
16005 check_dsp(ctx);
16006 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16007 break;
16009 break;
16010 #endif
16013 tcg_temp_free(v1_t);
16014 tcg_temp_free(v2_t);
16016 (void)opn; /* avoid a compiler warning */
16017 MIPS_DEBUG("%s", opn);
16020 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
16021 int ret, int v1, int v2)
16023 uint32_t op2;
16024 const char *opn = "mipsdsp shift";
16025 TCGv t0;
16026 TCGv v1_t;
16027 TCGv v2_t;
16029 if (ret == 0) {
16030 /* Treat as NOP. */
16031 MIPS_DEBUG("NOP");
16032 return;
16035 t0 = tcg_temp_new();
16036 v1_t = tcg_temp_new();
16037 v2_t = tcg_temp_new();
16039 tcg_gen_movi_tl(t0, v1);
16040 gen_load_gpr(v1_t, v1);
16041 gen_load_gpr(v2_t, v2);
16043 switch (opc) {
16044 case OPC_SHLL_QB_DSP:
16046 op2 = MASK_SHLL_QB(ctx->opcode);
16047 switch (op2) {
16048 case OPC_SHLL_QB:
16049 check_dsp(ctx);
16050 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
16051 break;
16052 case OPC_SHLLV_QB:
16053 check_dsp(ctx);
16054 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16055 break;
16056 case OPC_SHLL_PH:
16057 check_dsp(ctx);
16058 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
16059 break;
16060 case OPC_SHLLV_PH:
16061 check_dsp(ctx);
16062 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16063 break;
16064 case OPC_SHLL_S_PH:
16065 check_dsp(ctx);
16066 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
16067 break;
16068 case OPC_SHLLV_S_PH:
16069 check_dsp(ctx);
16070 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16071 break;
16072 case OPC_SHLL_S_W:
16073 check_dsp(ctx);
16074 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
16075 break;
16076 case OPC_SHLLV_S_W:
16077 check_dsp(ctx);
16078 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16079 break;
16080 case OPC_SHRL_QB:
16081 check_dsp(ctx);
16082 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
16083 break;
16084 case OPC_SHRLV_QB:
16085 check_dsp(ctx);
16086 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
16087 break;
16088 case OPC_SHRL_PH:
16089 check_dspr2(ctx);
16090 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
16091 break;
16092 case OPC_SHRLV_PH:
16093 check_dspr2(ctx);
16094 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
16095 break;
16096 case OPC_SHRA_QB:
16097 check_dspr2(ctx);
16098 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
16099 break;
16100 case OPC_SHRA_R_QB:
16101 check_dspr2(ctx);
16102 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
16103 break;
16104 case OPC_SHRAV_QB:
16105 check_dspr2(ctx);
16106 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
16107 break;
16108 case OPC_SHRAV_R_QB:
16109 check_dspr2(ctx);
16110 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
16111 break;
16112 case OPC_SHRA_PH:
16113 check_dsp(ctx);
16114 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
16115 break;
16116 case OPC_SHRA_R_PH:
16117 check_dsp(ctx);
16118 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
16119 break;
16120 case OPC_SHRAV_PH:
16121 check_dsp(ctx);
16122 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
16123 break;
16124 case OPC_SHRAV_R_PH:
16125 check_dsp(ctx);
16126 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
16127 break;
16128 case OPC_SHRA_R_W:
16129 check_dsp(ctx);
16130 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
16131 break;
16132 case OPC_SHRAV_R_W:
16133 check_dsp(ctx);
16134 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
16135 break;
16136 default: /* Invalid */
16137 MIPS_INVAL("MASK SHLL.QB");
16138 generate_exception(ctx, EXCP_RI);
16139 break;
16141 break;
16143 #ifdef TARGET_MIPS64
16144 case OPC_SHLL_OB_DSP:
16145 op2 = MASK_SHLL_OB(ctx->opcode);
16146 switch (op2) {
16147 case OPC_SHLL_PW:
16148 check_dsp(ctx);
16149 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
16150 break;
16151 case OPC_SHLLV_PW:
16152 check_dsp(ctx);
16153 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16154 break;
16155 case OPC_SHLL_S_PW:
16156 check_dsp(ctx);
16157 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
16158 break;
16159 case OPC_SHLLV_S_PW:
16160 check_dsp(ctx);
16161 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16162 break;
16163 case OPC_SHLL_OB:
16164 check_dsp(ctx);
16165 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
16166 break;
16167 case OPC_SHLLV_OB:
16168 check_dsp(ctx);
16169 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16170 break;
16171 case OPC_SHLL_QH:
16172 check_dsp(ctx);
16173 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
16174 break;
16175 case OPC_SHLLV_QH:
16176 check_dsp(ctx);
16177 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16178 break;
16179 case OPC_SHLL_S_QH:
16180 check_dsp(ctx);
16181 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
16182 break;
16183 case OPC_SHLLV_S_QH:
16184 check_dsp(ctx);
16185 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16186 break;
16187 case OPC_SHRA_OB:
16188 check_dspr2(ctx);
16189 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
16190 break;
16191 case OPC_SHRAV_OB:
16192 check_dspr2(ctx);
16193 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
16194 break;
16195 case OPC_SHRA_R_OB:
16196 check_dspr2(ctx);
16197 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
16198 break;
16199 case OPC_SHRAV_R_OB:
16200 check_dspr2(ctx);
16201 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
16202 break;
16203 case OPC_SHRA_PW:
16204 check_dsp(ctx);
16205 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
16206 break;
16207 case OPC_SHRAV_PW:
16208 check_dsp(ctx);
16209 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
16210 break;
16211 case OPC_SHRA_R_PW:
16212 check_dsp(ctx);
16213 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
16214 break;
16215 case OPC_SHRAV_R_PW:
16216 check_dsp(ctx);
16217 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
16218 break;
16219 case OPC_SHRA_QH:
16220 check_dsp(ctx);
16221 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
16222 break;
16223 case OPC_SHRAV_QH:
16224 check_dsp(ctx);
16225 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
16226 break;
16227 case OPC_SHRA_R_QH:
16228 check_dsp(ctx);
16229 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
16230 break;
16231 case OPC_SHRAV_R_QH:
16232 check_dsp(ctx);
16233 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
16234 break;
16235 case OPC_SHRL_OB:
16236 check_dsp(ctx);
16237 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
16238 break;
16239 case OPC_SHRLV_OB:
16240 check_dsp(ctx);
16241 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
16242 break;
16243 case OPC_SHRL_QH:
16244 check_dspr2(ctx);
16245 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
16246 break;
16247 case OPC_SHRLV_QH:
16248 check_dspr2(ctx);
16249 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
16250 break;
16251 default: /* Invalid */
16252 MIPS_INVAL("MASK SHLL.OB");
16253 generate_exception(ctx, EXCP_RI);
16254 break;
16256 break;
16257 #endif
16260 tcg_temp_free(t0);
16261 tcg_temp_free(v1_t);
16262 tcg_temp_free(v2_t);
16263 (void)opn; /* avoid a compiler warning */
16264 MIPS_DEBUG("%s", opn);
16267 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
16268 int ret, int v1, int v2, int check_ret)
16270 const char *opn = "mipsdsp multiply";
16271 TCGv_i32 t0;
16272 TCGv v1_t;
16273 TCGv v2_t;
16275 if ((ret == 0) && (check_ret == 1)) {
16276 /* Treat as NOP. */
16277 MIPS_DEBUG("NOP");
16278 return;
16281 t0 = tcg_temp_new_i32();
16282 v1_t = tcg_temp_new();
16283 v2_t = tcg_temp_new();
16285 tcg_gen_movi_i32(t0, ret);
16286 gen_load_gpr(v1_t, v1);
16287 gen_load_gpr(v2_t, v2);
16289 switch (op1) {
16290 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
16291 * the same mask and op1. */
16292 case OPC_MULT_G_2E:
16293 check_dspr2(ctx);
16294 switch (op2) {
16295 case OPC_MUL_PH:
16296 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16297 break;
16298 case OPC_MUL_S_PH:
16299 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16300 break;
16301 case OPC_MULQ_S_W:
16302 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16303 break;
16304 case OPC_MULQ_RS_W:
16305 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16306 break;
16308 break;
16309 case OPC_DPA_W_PH_DSP:
16310 switch (op2) {
16311 case OPC_DPAU_H_QBL:
16312 check_dsp(ctx);
16313 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
16314 break;
16315 case OPC_DPAU_H_QBR:
16316 check_dsp(ctx);
16317 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
16318 break;
16319 case OPC_DPSU_H_QBL:
16320 check_dsp(ctx);
16321 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
16322 break;
16323 case OPC_DPSU_H_QBR:
16324 check_dsp(ctx);
16325 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
16326 break;
16327 case OPC_DPA_W_PH:
16328 check_dspr2(ctx);
16329 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
16330 break;
16331 case OPC_DPAX_W_PH:
16332 check_dspr2(ctx);
16333 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
16334 break;
16335 case OPC_DPAQ_S_W_PH:
16336 check_dsp(ctx);
16337 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16338 break;
16339 case OPC_DPAQX_S_W_PH:
16340 check_dspr2(ctx);
16341 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16342 break;
16343 case OPC_DPAQX_SA_W_PH:
16344 check_dspr2(ctx);
16345 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16346 break;
16347 case OPC_DPS_W_PH:
16348 check_dspr2(ctx);
16349 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
16350 break;
16351 case OPC_DPSX_W_PH:
16352 check_dspr2(ctx);
16353 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
16354 break;
16355 case OPC_DPSQ_S_W_PH:
16356 check_dsp(ctx);
16357 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16358 break;
16359 case OPC_DPSQX_S_W_PH:
16360 check_dspr2(ctx);
16361 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16362 break;
16363 case OPC_DPSQX_SA_W_PH:
16364 check_dspr2(ctx);
16365 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16366 break;
16367 case OPC_MULSAQ_S_W_PH:
16368 check_dsp(ctx);
16369 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16370 break;
16371 case OPC_DPAQ_SA_L_W:
16372 check_dsp(ctx);
16373 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16374 break;
16375 case OPC_DPSQ_SA_L_W:
16376 check_dsp(ctx);
16377 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16378 break;
16379 case OPC_MAQ_S_W_PHL:
16380 check_dsp(ctx);
16381 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
16382 break;
16383 case OPC_MAQ_S_W_PHR:
16384 check_dsp(ctx);
16385 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
16386 break;
16387 case OPC_MAQ_SA_W_PHL:
16388 check_dsp(ctx);
16389 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
16390 break;
16391 case OPC_MAQ_SA_W_PHR:
16392 check_dsp(ctx);
16393 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
16394 break;
16395 case OPC_MULSA_W_PH:
16396 check_dspr2(ctx);
16397 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
16398 break;
16400 break;
16401 #ifdef TARGET_MIPS64
16402 case OPC_DPAQ_W_QH_DSP:
16404 int ac = ret & 0x03;
16405 tcg_gen_movi_i32(t0, ac);
16407 switch (op2) {
16408 case OPC_DMADD:
16409 check_dsp(ctx);
16410 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
16411 break;
16412 case OPC_DMADDU:
16413 check_dsp(ctx);
16414 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
16415 break;
16416 case OPC_DMSUB:
16417 check_dsp(ctx);
16418 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
16419 break;
16420 case OPC_DMSUBU:
16421 check_dsp(ctx);
16422 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
16423 break;
16424 case OPC_DPA_W_QH:
16425 check_dspr2(ctx);
16426 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
16427 break;
16428 case OPC_DPAQ_S_W_QH:
16429 check_dsp(ctx);
16430 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16431 break;
16432 case OPC_DPAQ_SA_L_PW:
16433 check_dsp(ctx);
16434 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16435 break;
16436 case OPC_DPAU_H_OBL:
16437 check_dsp(ctx);
16438 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
16439 break;
16440 case OPC_DPAU_H_OBR:
16441 check_dsp(ctx);
16442 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
16443 break;
16444 case OPC_DPS_W_QH:
16445 check_dspr2(ctx);
16446 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
16447 break;
16448 case OPC_DPSQ_S_W_QH:
16449 check_dsp(ctx);
16450 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16451 break;
16452 case OPC_DPSQ_SA_L_PW:
16453 check_dsp(ctx);
16454 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16455 break;
16456 case OPC_DPSU_H_OBL:
16457 check_dsp(ctx);
16458 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
16459 break;
16460 case OPC_DPSU_H_OBR:
16461 check_dsp(ctx);
16462 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
16463 break;
16464 case OPC_MAQ_S_L_PWL:
16465 check_dsp(ctx);
16466 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
16467 break;
16468 case OPC_MAQ_S_L_PWR:
16469 check_dsp(ctx);
16470 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
16471 break;
16472 case OPC_MAQ_S_W_QHLL:
16473 check_dsp(ctx);
16474 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
16475 break;
16476 case OPC_MAQ_SA_W_QHLL:
16477 check_dsp(ctx);
16478 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
16479 break;
16480 case OPC_MAQ_S_W_QHLR:
16481 check_dsp(ctx);
16482 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
16483 break;
16484 case OPC_MAQ_SA_W_QHLR:
16485 check_dsp(ctx);
16486 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
16487 break;
16488 case OPC_MAQ_S_W_QHRL:
16489 check_dsp(ctx);
16490 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
16491 break;
16492 case OPC_MAQ_SA_W_QHRL:
16493 check_dsp(ctx);
16494 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
16495 break;
16496 case OPC_MAQ_S_W_QHRR:
16497 check_dsp(ctx);
16498 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
16499 break;
16500 case OPC_MAQ_SA_W_QHRR:
16501 check_dsp(ctx);
16502 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
16503 break;
16504 case OPC_MULSAQ_S_L_PW:
16505 check_dsp(ctx);
16506 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
16507 break;
16508 case OPC_MULSAQ_S_W_QH:
16509 check_dsp(ctx);
16510 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16511 break;
16514 break;
16515 #endif
16516 case OPC_ADDU_QB_DSP:
16517 switch (op2) {
16518 case OPC_MULEU_S_PH_QBL:
16519 check_dsp(ctx);
16520 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16521 break;
16522 case OPC_MULEU_S_PH_QBR:
16523 check_dsp(ctx);
16524 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16525 break;
16526 case OPC_MULQ_RS_PH:
16527 check_dsp(ctx);
16528 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16529 break;
16530 case OPC_MULEQ_S_W_PHL:
16531 check_dsp(ctx);
16532 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16533 break;
16534 case OPC_MULEQ_S_W_PHR:
16535 check_dsp(ctx);
16536 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16537 break;
16538 case OPC_MULQ_S_PH:
16539 check_dspr2(ctx);
16540 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16541 break;
16543 break;
16544 #ifdef TARGET_MIPS64
16545 case OPC_ADDU_OB_DSP:
16546 switch (op2) {
16547 case OPC_MULEQ_S_PW_QHL:
16548 check_dsp(ctx);
16549 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16550 break;
16551 case OPC_MULEQ_S_PW_QHR:
16552 check_dsp(ctx);
16553 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16554 break;
16555 case OPC_MULEU_S_QH_OBL:
16556 check_dsp(ctx);
16557 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16558 break;
16559 case OPC_MULEU_S_QH_OBR:
16560 check_dsp(ctx);
16561 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16562 break;
16563 case OPC_MULQ_RS_QH:
16564 check_dsp(ctx);
16565 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16566 break;
16568 break;
16569 #endif
16572 tcg_temp_free_i32(t0);
16573 tcg_temp_free(v1_t);
16574 tcg_temp_free(v2_t);
16576 (void)opn; /* avoid a compiler warning */
16577 MIPS_DEBUG("%s", opn);
16581 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16582 int ret, int val)
16584 const char *opn = "mipsdsp Bit/ Manipulation";
16585 int16_t imm;
16586 TCGv t0;
16587 TCGv val_t;
16589 if (ret == 0) {
16590 /* Treat as NOP. */
16591 MIPS_DEBUG("NOP");
16592 return;
16595 t0 = tcg_temp_new();
16596 val_t = tcg_temp_new();
16597 gen_load_gpr(val_t, val);
16599 switch (op1) {
16600 case OPC_ABSQ_S_PH_DSP:
16601 switch (op2) {
16602 case OPC_BITREV:
16603 check_dsp(ctx);
16604 gen_helper_bitrev(cpu_gpr[ret], val_t);
16605 break;
16606 case OPC_REPL_QB:
16607 check_dsp(ctx);
16609 target_long result;
16610 imm = (ctx->opcode >> 16) & 0xFF;
16611 result = (uint32_t)imm << 24 |
16612 (uint32_t)imm << 16 |
16613 (uint32_t)imm << 8 |
16614 (uint32_t)imm;
16615 result = (int32_t)result;
16616 tcg_gen_movi_tl(cpu_gpr[ret], result);
16618 break;
16619 case OPC_REPLV_QB:
16620 check_dsp(ctx);
16621 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16622 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16623 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16624 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16625 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16626 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16627 break;
16628 case OPC_REPL_PH:
16629 check_dsp(ctx);
16631 imm = (ctx->opcode >> 16) & 0x03FF;
16632 imm = (int16_t)(imm << 6) >> 6;
16633 tcg_gen_movi_tl(cpu_gpr[ret], \
16634 (target_long)((int32_t)imm << 16 | \
16635 (uint16_t)imm));
16637 break;
16638 case OPC_REPLV_PH:
16639 check_dsp(ctx);
16640 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16641 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16642 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16643 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16644 break;
16646 break;
16647 #ifdef TARGET_MIPS64
16648 case OPC_ABSQ_S_QH_DSP:
16649 switch (op2) {
16650 case OPC_REPL_OB:
16651 check_dsp(ctx);
16653 target_long temp;
16655 imm = (ctx->opcode >> 16) & 0xFF;
16656 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
16657 temp = (temp << 16) | temp;
16658 temp = (temp << 32) | temp;
16659 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16660 break;
16662 case OPC_REPL_PW:
16663 check_dsp(ctx);
16665 target_long temp;
16667 imm = (ctx->opcode >> 16) & 0x03FF;
16668 imm = (int16_t)(imm << 6) >> 6;
16669 temp = ((target_long)imm << 32) \
16670 | ((target_long)imm & 0xFFFFFFFF);
16671 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16672 break;
16674 case OPC_REPL_QH:
16675 check_dsp(ctx);
16677 target_long temp;
16679 imm = (ctx->opcode >> 16) & 0x03FF;
16680 imm = (int16_t)(imm << 6) >> 6;
16682 temp = ((uint64_t)(uint16_t)imm << 48) |
16683 ((uint64_t)(uint16_t)imm << 32) |
16684 ((uint64_t)(uint16_t)imm << 16) |
16685 (uint64_t)(uint16_t)imm;
16686 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16687 break;
16689 case OPC_REPLV_OB:
16690 check_dsp(ctx);
16691 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16692 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16693 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16694 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16695 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16696 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16697 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16698 break;
16699 case OPC_REPLV_PW:
16700 check_dsp(ctx);
16701 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
16702 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16703 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16704 break;
16705 case OPC_REPLV_QH:
16706 check_dsp(ctx);
16707 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16708 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16709 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16710 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16711 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16712 break;
16714 break;
16715 #endif
16717 tcg_temp_free(t0);
16718 tcg_temp_free(val_t);
16720 (void)opn; /* avoid a compiler warning */
16721 MIPS_DEBUG("%s", opn);
16724 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
16725 uint32_t op1, uint32_t op2,
16726 int ret, int v1, int v2, int check_ret)
16728 const char *opn = "mipsdsp add compare pick";
16729 TCGv t1;
16730 TCGv v1_t;
16731 TCGv v2_t;
16733 if ((ret == 0) && (check_ret == 1)) {
16734 /* Treat as NOP. */
16735 MIPS_DEBUG("NOP");
16736 return;
16739 t1 = tcg_temp_new();
16740 v1_t = tcg_temp_new();
16741 v2_t = tcg_temp_new();
16743 gen_load_gpr(v1_t, v1);
16744 gen_load_gpr(v2_t, v2);
16746 switch (op1) {
16747 case OPC_CMPU_EQ_QB_DSP:
16748 switch (op2) {
16749 case OPC_CMPU_EQ_QB:
16750 check_dsp(ctx);
16751 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
16752 break;
16753 case OPC_CMPU_LT_QB:
16754 check_dsp(ctx);
16755 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
16756 break;
16757 case OPC_CMPU_LE_QB:
16758 check_dsp(ctx);
16759 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
16760 break;
16761 case OPC_CMPGU_EQ_QB:
16762 check_dsp(ctx);
16763 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
16764 break;
16765 case OPC_CMPGU_LT_QB:
16766 check_dsp(ctx);
16767 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
16768 break;
16769 case OPC_CMPGU_LE_QB:
16770 check_dsp(ctx);
16771 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
16772 break;
16773 case OPC_CMPGDU_EQ_QB:
16774 check_dspr2(ctx);
16775 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
16776 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16777 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16778 tcg_gen_shli_tl(t1, t1, 24);
16779 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16780 break;
16781 case OPC_CMPGDU_LT_QB:
16782 check_dspr2(ctx);
16783 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
16784 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16785 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16786 tcg_gen_shli_tl(t1, t1, 24);
16787 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16788 break;
16789 case OPC_CMPGDU_LE_QB:
16790 check_dspr2(ctx);
16791 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
16792 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16793 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16794 tcg_gen_shli_tl(t1, t1, 24);
16795 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16796 break;
16797 case OPC_CMP_EQ_PH:
16798 check_dsp(ctx);
16799 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
16800 break;
16801 case OPC_CMP_LT_PH:
16802 check_dsp(ctx);
16803 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
16804 break;
16805 case OPC_CMP_LE_PH:
16806 check_dsp(ctx);
16807 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
16808 break;
16809 case OPC_PICK_QB:
16810 check_dsp(ctx);
16811 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16812 break;
16813 case OPC_PICK_PH:
16814 check_dsp(ctx);
16815 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16816 break;
16817 case OPC_PACKRL_PH:
16818 check_dsp(ctx);
16819 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
16820 break;
16822 break;
16823 #ifdef TARGET_MIPS64
16824 case OPC_CMPU_EQ_OB_DSP:
16825 switch (op2) {
16826 case OPC_CMP_EQ_PW:
16827 check_dsp(ctx);
16828 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
16829 break;
16830 case OPC_CMP_LT_PW:
16831 check_dsp(ctx);
16832 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
16833 break;
16834 case OPC_CMP_LE_PW:
16835 check_dsp(ctx);
16836 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
16837 break;
16838 case OPC_CMP_EQ_QH:
16839 check_dsp(ctx);
16840 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
16841 break;
16842 case OPC_CMP_LT_QH:
16843 check_dsp(ctx);
16844 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
16845 break;
16846 case OPC_CMP_LE_QH:
16847 check_dsp(ctx);
16848 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
16849 break;
16850 case OPC_CMPGDU_EQ_OB:
16851 check_dspr2(ctx);
16852 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16853 break;
16854 case OPC_CMPGDU_LT_OB:
16855 check_dspr2(ctx);
16856 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16857 break;
16858 case OPC_CMPGDU_LE_OB:
16859 check_dspr2(ctx);
16860 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16861 break;
16862 case OPC_CMPGU_EQ_OB:
16863 check_dsp(ctx);
16864 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
16865 break;
16866 case OPC_CMPGU_LT_OB:
16867 check_dsp(ctx);
16868 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
16869 break;
16870 case OPC_CMPGU_LE_OB:
16871 check_dsp(ctx);
16872 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
16873 break;
16874 case OPC_CMPU_EQ_OB:
16875 check_dsp(ctx);
16876 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
16877 break;
16878 case OPC_CMPU_LT_OB:
16879 check_dsp(ctx);
16880 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
16881 break;
16882 case OPC_CMPU_LE_OB:
16883 check_dsp(ctx);
16884 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
16885 break;
16886 case OPC_PACKRL_PW:
16887 check_dsp(ctx);
16888 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
16889 break;
16890 case OPC_PICK_OB:
16891 check_dsp(ctx);
16892 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16893 break;
16894 case OPC_PICK_PW:
16895 check_dsp(ctx);
16896 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16897 break;
16898 case OPC_PICK_QH:
16899 check_dsp(ctx);
16900 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16901 break;
16903 break;
16904 #endif
16907 tcg_temp_free(t1);
16908 tcg_temp_free(v1_t);
16909 tcg_temp_free(v2_t);
16911 (void)opn; /* avoid a compiler warning */
16912 MIPS_DEBUG("%s", opn);
16915 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
16916 uint32_t op1, int rt, int rs, int sa)
16918 const char *opn = "mipsdsp append/dappend";
16919 TCGv t0;
16921 check_dspr2(ctx);
16923 if (rt == 0) {
16924 /* Treat as NOP. */
16925 MIPS_DEBUG("NOP");
16926 return;
16929 t0 = tcg_temp_new();
16930 gen_load_gpr(t0, rs);
16932 switch (op1) {
16933 case OPC_APPEND_DSP:
16934 switch (MASK_APPEND(ctx->opcode)) {
16935 case OPC_APPEND:
16936 if (sa != 0) {
16937 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
16939 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16940 break;
16941 case OPC_PREPEND:
16942 if (sa != 0) {
16943 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
16944 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16945 tcg_gen_shli_tl(t0, t0, 32 - sa);
16946 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16948 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16949 break;
16950 case OPC_BALIGN:
16951 sa &= 3;
16952 if (sa != 0 && sa != 2) {
16953 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16954 tcg_gen_ext32u_tl(t0, t0);
16955 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
16956 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16958 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16959 break;
16960 default: /* Invalid */
16961 MIPS_INVAL("MASK APPEND");
16962 generate_exception(ctx, EXCP_RI);
16963 break;
16965 break;
16966 #ifdef TARGET_MIPS64
16967 case OPC_DAPPEND_DSP:
16968 switch (MASK_DAPPEND(ctx->opcode)) {
16969 case OPC_DAPPEND:
16970 if (sa != 0) {
16971 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
16973 break;
16974 case OPC_PREPENDD:
16975 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
16976 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
16977 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
16978 break;
16979 case OPC_PREPENDW:
16980 if (sa != 0) {
16981 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16982 tcg_gen_shli_tl(t0, t0, 64 - sa);
16983 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16985 break;
16986 case OPC_DBALIGN:
16987 sa &= 7;
16988 if (sa != 0 && sa != 2 && sa != 4) {
16989 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16990 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
16991 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16993 break;
16994 default: /* Invalid */
16995 MIPS_INVAL("MASK DAPPEND");
16996 generate_exception(ctx, EXCP_RI);
16997 break;
16999 break;
17000 #endif
17002 tcg_temp_free(t0);
17003 (void)opn; /* avoid a compiler warning */
17004 MIPS_DEBUG("%s", opn);
17007 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
17008 int ret, int v1, int v2, int check_ret)
17011 const char *opn = "mipsdsp accumulator";
17012 TCGv t0;
17013 TCGv t1;
17014 TCGv v1_t;
17015 TCGv v2_t;
17016 int16_t imm;
17018 if ((ret == 0) && (check_ret == 1)) {
17019 /* Treat as NOP. */
17020 MIPS_DEBUG("NOP");
17021 return;
17024 t0 = tcg_temp_new();
17025 t1 = tcg_temp_new();
17026 v1_t = tcg_temp_new();
17027 v2_t = tcg_temp_new();
17029 gen_load_gpr(v1_t, v1);
17030 gen_load_gpr(v2_t, v2);
17032 switch (op1) {
17033 case OPC_EXTR_W_DSP:
17034 check_dsp(ctx);
17035 switch (op2) {
17036 case OPC_EXTR_W:
17037 tcg_gen_movi_tl(t0, v2);
17038 tcg_gen_movi_tl(t1, v1);
17039 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
17040 break;
17041 case OPC_EXTR_R_W:
17042 tcg_gen_movi_tl(t0, v2);
17043 tcg_gen_movi_tl(t1, v1);
17044 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
17045 break;
17046 case OPC_EXTR_RS_W:
17047 tcg_gen_movi_tl(t0, v2);
17048 tcg_gen_movi_tl(t1, v1);
17049 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
17050 break;
17051 case OPC_EXTR_S_H:
17052 tcg_gen_movi_tl(t0, v2);
17053 tcg_gen_movi_tl(t1, v1);
17054 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17055 break;
17056 case OPC_EXTRV_S_H:
17057 tcg_gen_movi_tl(t0, v2);
17058 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
17059 break;
17060 case OPC_EXTRV_W:
17061 tcg_gen_movi_tl(t0, v2);
17062 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17063 break;
17064 case OPC_EXTRV_R_W:
17065 tcg_gen_movi_tl(t0, v2);
17066 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17067 break;
17068 case OPC_EXTRV_RS_W:
17069 tcg_gen_movi_tl(t0, v2);
17070 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17071 break;
17072 case OPC_EXTP:
17073 tcg_gen_movi_tl(t0, v2);
17074 tcg_gen_movi_tl(t1, v1);
17075 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
17076 break;
17077 case OPC_EXTPV:
17078 tcg_gen_movi_tl(t0, v2);
17079 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
17080 break;
17081 case OPC_EXTPDP:
17082 tcg_gen_movi_tl(t0, v2);
17083 tcg_gen_movi_tl(t1, v1);
17084 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
17085 break;
17086 case OPC_EXTPDPV:
17087 tcg_gen_movi_tl(t0, v2);
17088 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
17089 break;
17090 case OPC_SHILO:
17091 imm = (ctx->opcode >> 20) & 0x3F;
17092 tcg_gen_movi_tl(t0, ret);
17093 tcg_gen_movi_tl(t1, imm);
17094 gen_helper_shilo(t0, t1, cpu_env);
17095 break;
17096 case OPC_SHILOV:
17097 tcg_gen_movi_tl(t0, ret);
17098 gen_helper_shilo(t0, v1_t, cpu_env);
17099 break;
17100 case OPC_MTHLIP:
17101 tcg_gen_movi_tl(t0, ret);
17102 gen_helper_mthlip(t0, v1_t, cpu_env);
17103 break;
17104 case OPC_WRDSP:
17105 imm = (ctx->opcode >> 11) & 0x3FF;
17106 tcg_gen_movi_tl(t0, imm);
17107 gen_helper_wrdsp(v1_t, t0, cpu_env);
17108 break;
17109 case OPC_RDDSP:
17110 imm = (ctx->opcode >> 16) & 0x03FF;
17111 tcg_gen_movi_tl(t0, imm);
17112 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
17113 break;
17115 break;
17116 #ifdef TARGET_MIPS64
17117 case OPC_DEXTR_W_DSP:
17118 check_dsp(ctx);
17119 switch (op2) {
17120 case OPC_DMTHLIP:
17121 tcg_gen_movi_tl(t0, ret);
17122 gen_helper_dmthlip(v1_t, t0, cpu_env);
17123 break;
17124 case OPC_DSHILO:
17126 int shift = (ctx->opcode >> 19) & 0x7F;
17127 int ac = (ctx->opcode >> 11) & 0x03;
17128 tcg_gen_movi_tl(t0, shift);
17129 tcg_gen_movi_tl(t1, ac);
17130 gen_helper_dshilo(t0, t1, cpu_env);
17131 break;
17133 case OPC_DSHILOV:
17135 int ac = (ctx->opcode >> 11) & 0x03;
17136 tcg_gen_movi_tl(t0, ac);
17137 gen_helper_dshilo(v1_t, t0, cpu_env);
17138 break;
17140 case OPC_DEXTP:
17141 tcg_gen_movi_tl(t0, v2);
17142 tcg_gen_movi_tl(t1, v1);
17144 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
17145 break;
17146 case OPC_DEXTPV:
17147 tcg_gen_movi_tl(t0, v2);
17148 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
17149 break;
17150 case OPC_DEXTPDP:
17151 tcg_gen_movi_tl(t0, v2);
17152 tcg_gen_movi_tl(t1, v1);
17153 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
17154 break;
17155 case OPC_DEXTPDPV:
17156 tcg_gen_movi_tl(t0, v2);
17157 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
17158 break;
17159 case OPC_DEXTR_L:
17160 tcg_gen_movi_tl(t0, v2);
17161 tcg_gen_movi_tl(t1, v1);
17162 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
17163 break;
17164 case OPC_DEXTR_R_L:
17165 tcg_gen_movi_tl(t0, v2);
17166 tcg_gen_movi_tl(t1, v1);
17167 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
17168 break;
17169 case OPC_DEXTR_RS_L:
17170 tcg_gen_movi_tl(t0, v2);
17171 tcg_gen_movi_tl(t1, v1);
17172 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
17173 break;
17174 case OPC_DEXTR_W:
17175 tcg_gen_movi_tl(t0, v2);
17176 tcg_gen_movi_tl(t1, v1);
17177 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
17178 break;
17179 case OPC_DEXTR_R_W:
17180 tcg_gen_movi_tl(t0, v2);
17181 tcg_gen_movi_tl(t1, v1);
17182 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
17183 break;
17184 case OPC_DEXTR_RS_W:
17185 tcg_gen_movi_tl(t0, v2);
17186 tcg_gen_movi_tl(t1, v1);
17187 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
17188 break;
17189 case OPC_DEXTR_S_H:
17190 tcg_gen_movi_tl(t0, v2);
17191 tcg_gen_movi_tl(t1, v1);
17192 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17193 break;
17194 case OPC_DEXTRV_S_H:
17195 tcg_gen_movi_tl(t0, v2);
17196 tcg_gen_movi_tl(t1, v1);
17197 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17198 break;
17199 case OPC_DEXTRV_L:
17200 tcg_gen_movi_tl(t0, v2);
17201 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17202 break;
17203 case OPC_DEXTRV_R_L:
17204 tcg_gen_movi_tl(t0, v2);
17205 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17206 break;
17207 case OPC_DEXTRV_RS_L:
17208 tcg_gen_movi_tl(t0, v2);
17209 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17210 break;
17211 case OPC_DEXTRV_W:
17212 tcg_gen_movi_tl(t0, v2);
17213 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17214 break;
17215 case OPC_DEXTRV_R_W:
17216 tcg_gen_movi_tl(t0, v2);
17217 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17218 break;
17219 case OPC_DEXTRV_RS_W:
17220 tcg_gen_movi_tl(t0, v2);
17221 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17222 break;
17224 break;
17225 #endif
17228 tcg_temp_free(t0);
17229 tcg_temp_free(t1);
17230 tcg_temp_free(v1_t);
17231 tcg_temp_free(v2_t);
17233 (void)opn; /* avoid a compiler warning */
17234 MIPS_DEBUG("%s", opn);
17237 /* End MIPSDSP functions. */
17239 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
17241 int rs, rt, rd, sa;
17242 uint32_t op1, op2;
17244 rs = (ctx->opcode >> 21) & 0x1f;
17245 rt = (ctx->opcode >> 16) & 0x1f;
17246 rd = (ctx->opcode >> 11) & 0x1f;
17247 sa = (ctx->opcode >> 6) & 0x1f;
17249 op1 = MASK_SPECIAL(ctx->opcode);
17250 switch (op1) {
17251 case OPC_LSA:
17252 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
17253 break;
17254 case OPC_MULT ... OPC_DIVU:
17255 op2 = MASK_R6_MULDIV(ctx->opcode);
17256 switch (op2) {
17257 case R6_OPC_MUL:
17258 case R6_OPC_MUH:
17259 case R6_OPC_MULU:
17260 case R6_OPC_MUHU:
17261 case R6_OPC_DIV:
17262 case R6_OPC_MOD:
17263 case R6_OPC_DIVU:
17264 case R6_OPC_MODU:
17265 gen_r6_muldiv(ctx, op2, rd, rs, rt);
17266 break;
17267 default:
17268 MIPS_INVAL("special_r6 muldiv");
17269 generate_exception(ctx, EXCP_RI);
17270 break;
17272 break;
17273 case OPC_SELEQZ:
17274 case OPC_SELNEZ:
17275 gen_cond_move(ctx, op1, rd, rs, rt);
17276 break;
17277 case R6_OPC_CLO:
17278 case R6_OPC_CLZ:
17279 if (rt == 0 && sa == 1) {
17280 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17281 We need additionally to check other fields */
17282 gen_cl(ctx, op1, rd, rs);
17283 } else {
17284 generate_exception(ctx, EXCP_RI);
17286 break;
17287 case R6_OPC_SDBBP:
17288 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17289 gen_helper_do_semihosting(cpu_env);
17290 } else {
17291 if (ctx->hflags & MIPS_HFLAG_SBRI) {
17292 generate_exception(ctx, EXCP_RI);
17293 } else {
17294 generate_exception(ctx, EXCP_DBp);
17297 break;
17298 #if defined(TARGET_MIPS64)
17299 case OPC_DLSA:
17300 check_mips_64(ctx);
17301 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
17302 break;
17303 case R6_OPC_DCLO:
17304 case R6_OPC_DCLZ:
17305 if (rt == 0 && sa == 1) {
17306 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17307 We need additionally to check other fields */
17308 check_mips_64(ctx);
17309 gen_cl(ctx, op1, rd, rs);
17310 } else {
17311 generate_exception(ctx, EXCP_RI);
17313 break;
17314 case OPC_DMULT ... OPC_DDIVU:
17315 op2 = MASK_R6_MULDIV(ctx->opcode);
17316 switch (op2) {
17317 case R6_OPC_DMUL:
17318 case R6_OPC_DMUH:
17319 case R6_OPC_DMULU:
17320 case R6_OPC_DMUHU:
17321 case R6_OPC_DDIV:
17322 case R6_OPC_DMOD:
17323 case R6_OPC_DDIVU:
17324 case R6_OPC_DMODU:
17325 check_mips_64(ctx);
17326 gen_r6_muldiv(ctx, op2, rd, rs, rt);
17327 break;
17328 default:
17329 MIPS_INVAL("special_r6 muldiv");
17330 generate_exception(ctx, EXCP_RI);
17331 break;
17333 break;
17334 #endif
17335 default: /* Invalid */
17336 MIPS_INVAL("special_r6");
17337 generate_exception(ctx, EXCP_RI);
17338 break;
17342 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
17344 int rs, rt, rd, sa;
17345 uint32_t op1;
17347 rs = (ctx->opcode >> 21) & 0x1f;
17348 rt = (ctx->opcode >> 16) & 0x1f;
17349 rd = (ctx->opcode >> 11) & 0x1f;
17350 sa = (ctx->opcode >> 6) & 0x1f;
17352 op1 = MASK_SPECIAL(ctx->opcode);
17353 switch (op1) {
17354 case OPC_MOVN: /* Conditional move */
17355 case OPC_MOVZ:
17356 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
17357 INSN_LOONGSON2E | INSN_LOONGSON2F);
17358 gen_cond_move(ctx, op1, rd, rs, rt);
17359 break;
17360 case OPC_MFHI: /* Move from HI/LO */
17361 case OPC_MFLO:
17362 gen_HILO(ctx, op1, rs & 3, rd);
17363 break;
17364 case OPC_MTHI:
17365 case OPC_MTLO: /* Move to HI/LO */
17366 gen_HILO(ctx, op1, rd & 3, rs);
17367 break;
17368 case OPC_MOVCI:
17369 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
17370 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17371 check_cp1_enabled(ctx);
17372 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
17373 (ctx->opcode >> 16) & 1);
17374 } else {
17375 generate_exception_err(ctx, EXCP_CpU, 1);
17377 break;
17378 case OPC_MULT:
17379 case OPC_MULTU:
17380 if (sa) {
17381 check_insn(ctx, INSN_VR54XX);
17382 op1 = MASK_MUL_VR54XX(ctx->opcode);
17383 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
17384 } else {
17385 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17387 break;
17388 case OPC_DIV:
17389 case OPC_DIVU:
17390 gen_muldiv(ctx, op1, 0, rs, rt);
17391 break;
17392 #if defined(TARGET_MIPS64)
17393 case OPC_DMULT ... OPC_DDIVU:
17394 check_insn(ctx, ISA_MIPS3);
17395 check_mips_64(ctx);
17396 gen_muldiv(ctx, op1, 0, rs, rt);
17397 break;
17398 #endif
17399 case OPC_JR:
17400 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17401 break;
17402 case OPC_SPIM:
17403 #ifdef MIPS_STRICT_STANDARD
17404 MIPS_INVAL("SPIM");
17405 generate_exception(ctx, EXCP_RI);
17406 #else
17407 /* Implemented as RI exception for now. */
17408 MIPS_INVAL("spim (unofficial)");
17409 generate_exception(ctx, EXCP_RI);
17410 #endif
17411 break;
17412 default: /* Invalid */
17413 MIPS_INVAL("special_legacy");
17414 generate_exception(ctx, EXCP_RI);
17415 break;
17419 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
17421 int rs, rt, rd, sa;
17422 uint32_t op1;
17424 rs = (ctx->opcode >> 21) & 0x1f;
17425 rt = (ctx->opcode >> 16) & 0x1f;
17426 rd = (ctx->opcode >> 11) & 0x1f;
17427 sa = (ctx->opcode >> 6) & 0x1f;
17429 op1 = MASK_SPECIAL(ctx->opcode);
17430 switch (op1) {
17431 case OPC_SLL: /* Shift with immediate */
17432 if (sa == 5 && rd == 0 &&
17433 rs == 0 && rt == 0) { /* PAUSE */
17434 if ((ctx->insn_flags & ISA_MIPS32R6) &&
17435 (ctx->hflags & MIPS_HFLAG_BMASK)) {
17436 MIPS_DEBUG("CTI in delay / forbidden slot");
17437 generate_exception(ctx, EXCP_RI);
17438 break;
17441 /* Fallthrough */
17442 case OPC_SRA:
17443 gen_shift_imm(ctx, op1, rd, rt, sa);
17444 break;
17445 case OPC_SRL:
17446 switch ((ctx->opcode >> 21) & 0x1f) {
17447 case 1:
17448 /* rotr is decoded as srl on non-R2 CPUs */
17449 if (ctx->insn_flags & ISA_MIPS32R2) {
17450 op1 = OPC_ROTR;
17452 /* Fallthrough */
17453 case 0:
17454 gen_shift_imm(ctx, op1, rd, rt, sa);
17455 break;
17456 default:
17457 generate_exception(ctx, EXCP_RI);
17458 break;
17460 break;
17461 case OPC_ADD ... OPC_SUBU:
17462 gen_arith(ctx, op1, rd, rs, rt);
17463 break;
17464 case OPC_SLLV: /* Shifts */
17465 case OPC_SRAV:
17466 gen_shift(ctx, op1, rd, rs, rt);
17467 break;
17468 case OPC_SRLV:
17469 switch ((ctx->opcode >> 6) & 0x1f) {
17470 case 1:
17471 /* rotrv is decoded as srlv on non-R2 CPUs */
17472 if (ctx->insn_flags & ISA_MIPS32R2) {
17473 op1 = OPC_ROTRV;
17475 /* Fallthrough */
17476 case 0:
17477 gen_shift(ctx, op1, rd, rs, rt);
17478 break;
17479 default:
17480 generate_exception(ctx, EXCP_RI);
17481 break;
17483 break;
17484 case OPC_SLT: /* Set on less than */
17485 case OPC_SLTU:
17486 gen_slt(ctx, op1, rd, rs, rt);
17487 break;
17488 case OPC_AND: /* Logic*/
17489 case OPC_OR:
17490 case OPC_NOR:
17491 case OPC_XOR:
17492 gen_logic(ctx, op1, rd, rs, rt);
17493 break;
17494 case OPC_JALR:
17495 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17496 break;
17497 case OPC_TGE ... OPC_TEQ: /* Traps */
17498 case OPC_TNE:
17499 check_insn(ctx, ISA_MIPS2);
17500 gen_trap(ctx, op1, rs, rt, -1);
17501 break;
17502 case OPC_LSA: /* OPC_PMON */
17503 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17504 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17505 decode_opc_special_r6(env, ctx);
17506 } else {
17507 /* Pmon entry point, also R4010 selsl */
17508 #ifdef MIPS_STRICT_STANDARD
17509 MIPS_INVAL("PMON / selsl");
17510 generate_exception(ctx, EXCP_RI);
17511 #else
17512 gen_helper_0e0i(pmon, sa);
17513 #endif
17515 break;
17516 case OPC_SYSCALL:
17517 generate_exception(ctx, EXCP_SYSCALL);
17518 ctx->bstate = BS_STOP;
17519 break;
17520 case OPC_BREAK:
17521 generate_exception(ctx, EXCP_BREAK);
17522 break;
17523 case OPC_SYNC:
17524 check_insn(ctx, ISA_MIPS2);
17525 /* Treat as NOP. */
17526 break;
17528 #if defined(TARGET_MIPS64)
17529 /* MIPS64 specific opcodes */
17530 case OPC_DSLL:
17531 case OPC_DSRA:
17532 case OPC_DSLL32:
17533 case OPC_DSRA32:
17534 check_insn(ctx, ISA_MIPS3);
17535 check_mips_64(ctx);
17536 gen_shift_imm(ctx, op1, rd, rt, sa);
17537 break;
17538 case OPC_DSRL:
17539 switch ((ctx->opcode >> 21) & 0x1f) {
17540 case 1:
17541 /* drotr is decoded as dsrl on non-R2 CPUs */
17542 if (ctx->insn_flags & ISA_MIPS32R2) {
17543 op1 = OPC_DROTR;
17545 /* Fallthrough */
17546 case 0:
17547 check_insn(ctx, ISA_MIPS3);
17548 check_mips_64(ctx);
17549 gen_shift_imm(ctx, op1, rd, rt, sa);
17550 break;
17551 default:
17552 generate_exception(ctx, EXCP_RI);
17553 break;
17555 break;
17556 case OPC_DSRL32:
17557 switch ((ctx->opcode >> 21) & 0x1f) {
17558 case 1:
17559 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
17560 if (ctx->insn_flags & ISA_MIPS32R2) {
17561 op1 = OPC_DROTR32;
17563 /* Fallthrough */
17564 case 0:
17565 check_insn(ctx, ISA_MIPS3);
17566 check_mips_64(ctx);
17567 gen_shift_imm(ctx, op1, rd, rt, sa);
17568 break;
17569 default:
17570 generate_exception(ctx, EXCP_RI);
17571 break;
17573 break;
17574 case OPC_DADD ... OPC_DSUBU:
17575 check_insn(ctx, ISA_MIPS3);
17576 check_mips_64(ctx);
17577 gen_arith(ctx, op1, rd, rs, rt);
17578 break;
17579 case OPC_DSLLV:
17580 case OPC_DSRAV:
17581 check_insn(ctx, ISA_MIPS3);
17582 check_mips_64(ctx);
17583 gen_shift(ctx, op1, rd, rs, rt);
17584 break;
17585 case OPC_DSRLV:
17586 switch ((ctx->opcode >> 6) & 0x1f) {
17587 case 1:
17588 /* drotrv is decoded as dsrlv on non-R2 CPUs */
17589 if (ctx->insn_flags & ISA_MIPS32R2) {
17590 op1 = OPC_DROTRV;
17592 /* Fallthrough */
17593 case 0:
17594 check_insn(ctx, ISA_MIPS3);
17595 check_mips_64(ctx);
17596 gen_shift(ctx, op1, rd, rs, rt);
17597 break;
17598 default:
17599 generate_exception(ctx, EXCP_RI);
17600 break;
17602 break;
17603 case OPC_DLSA:
17604 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17605 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17606 decode_opc_special_r6(env, ctx);
17608 break;
17609 #endif
17610 default:
17611 if (ctx->insn_flags & ISA_MIPS32R6) {
17612 decode_opc_special_r6(env, ctx);
17613 } else {
17614 decode_opc_special_legacy(env, ctx);
17619 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
17621 int rs, rt, rd;
17622 uint32_t op1;
17624 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17626 rs = (ctx->opcode >> 21) & 0x1f;
17627 rt = (ctx->opcode >> 16) & 0x1f;
17628 rd = (ctx->opcode >> 11) & 0x1f;
17630 op1 = MASK_SPECIAL2(ctx->opcode);
17631 switch (op1) {
17632 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
17633 case OPC_MSUB ... OPC_MSUBU:
17634 check_insn(ctx, ISA_MIPS32);
17635 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17636 break;
17637 case OPC_MUL:
17638 gen_arith(ctx, op1, rd, rs, rt);
17639 break;
17640 case OPC_DIV_G_2F:
17641 case OPC_DIVU_G_2F:
17642 case OPC_MULT_G_2F:
17643 case OPC_MULTU_G_2F:
17644 case OPC_MOD_G_2F:
17645 case OPC_MODU_G_2F:
17646 check_insn(ctx, INSN_LOONGSON2F);
17647 gen_loongson_integer(ctx, op1, rd, rs, rt);
17648 break;
17649 case OPC_CLO:
17650 case OPC_CLZ:
17651 check_insn(ctx, ISA_MIPS32);
17652 gen_cl(ctx, op1, rd, rs);
17653 break;
17654 case OPC_SDBBP:
17655 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17656 gen_helper_do_semihosting(cpu_env);
17657 } else {
17658 /* XXX: not clear which exception should be raised
17659 * when in debug mode...
17661 check_insn(ctx, ISA_MIPS32);
17662 generate_exception(ctx, EXCP_DBp);
17664 break;
17665 #if defined(TARGET_MIPS64)
17666 case OPC_DCLO:
17667 case OPC_DCLZ:
17668 check_insn(ctx, ISA_MIPS64);
17669 check_mips_64(ctx);
17670 gen_cl(ctx, op1, rd, rs);
17671 break;
17672 case OPC_DMULT_G_2F:
17673 case OPC_DMULTU_G_2F:
17674 case OPC_DDIV_G_2F:
17675 case OPC_DDIVU_G_2F:
17676 case OPC_DMOD_G_2F:
17677 case OPC_DMODU_G_2F:
17678 check_insn(ctx, INSN_LOONGSON2F);
17679 gen_loongson_integer(ctx, op1, rd, rs, rt);
17680 break;
17681 #endif
17682 default: /* Invalid */
17683 MIPS_INVAL("special2_legacy");
17684 generate_exception(ctx, EXCP_RI);
17685 break;
17689 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
17691 int rs, rt, rd, sa;
17692 uint32_t op1, op2;
17693 int16_t imm;
17695 rs = (ctx->opcode >> 21) & 0x1f;
17696 rt = (ctx->opcode >> 16) & 0x1f;
17697 rd = (ctx->opcode >> 11) & 0x1f;
17698 sa = (ctx->opcode >> 6) & 0x1f;
17699 imm = (int16_t)ctx->opcode >> 7;
17701 op1 = MASK_SPECIAL3(ctx->opcode);
17702 switch (op1) {
17703 case R6_OPC_PREF:
17704 if (rt >= 24) {
17705 /* hint codes 24-31 are reserved and signal RI */
17706 generate_exception(ctx, EXCP_RI);
17708 /* Treat as NOP. */
17709 break;
17710 case R6_OPC_CACHE:
17711 /* Treat as NOP. */
17712 break;
17713 case R6_OPC_SC:
17714 gen_st_cond(ctx, op1, rt, rs, imm);
17715 break;
17716 case R6_OPC_LL:
17717 gen_ld(ctx, op1, rt, rs, imm);
17718 break;
17719 case OPC_BSHFL:
17721 if (rd == 0) {
17722 /* Treat as NOP. */
17723 break;
17725 op2 = MASK_BSHFL(ctx->opcode);
17726 switch (op2) {
17727 case OPC_ALIGN ... OPC_ALIGN_END:
17728 gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3);
17729 break;
17730 case OPC_BITSWAP:
17731 gen_bitswap(ctx, op2, rd, rt);
17732 break;
17735 break;
17736 #if defined(TARGET_MIPS64)
17737 case R6_OPC_SCD:
17738 gen_st_cond(ctx, op1, rt, rs, imm);
17739 break;
17740 case R6_OPC_LLD:
17741 gen_ld(ctx, op1, rt, rs, imm);
17742 break;
17743 case OPC_DBSHFL:
17744 check_mips_64(ctx);
17746 if (rd == 0) {
17747 /* Treat as NOP. */
17748 break;
17750 op2 = MASK_DBSHFL(ctx->opcode);
17751 switch (op2) {
17752 case OPC_DALIGN ... OPC_DALIGN_END:
17753 gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7);
17754 break;
17755 case OPC_DBITSWAP:
17756 gen_bitswap(ctx, op2, rd, rt);
17757 break;
17761 break;
17762 #endif
17763 default: /* Invalid */
17764 MIPS_INVAL("special3_r6");
17765 generate_exception(ctx, EXCP_RI);
17766 break;
17770 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
17772 int rs, rt, rd;
17773 uint32_t op1, op2;
17775 rs = (ctx->opcode >> 21) & 0x1f;
17776 rt = (ctx->opcode >> 16) & 0x1f;
17777 rd = (ctx->opcode >> 11) & 0x1f;
17779 op1 = MASK_SPECIAL3(ctx->opcode);
17780 switch (op1) {
17781 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
17782 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
17783 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
17784 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
17785 * the same mask and op1. */
17786 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
17787 op2 = MASK_ADDUH_QB(ctx->opcode);
17788 switch (op2) {
17789 case OPC_ADDUH_QB:
17790 case OPC_ADDUH_R_QB:
17791 case OPC_ADDQH_PH:
17792 case OPC_ADDQH_R_PH:
17793 case OPC_ADDQH_W:
17794 case OPC_ADDQH_R_W:
17795 case OPC_SUBUH_QB:
17796 case OPC_SUBUH_R_QB:
17797 case OPC_SUBQH_PH:
17798 case OPC_SUBQH_R_PH:
17799 case OPC_SUBQH_W:
17800 case OPC_SUBQH_R_W:
17801 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17802 break;
17803 case OPC_MUL_PH:
17804 case OPC_MUL_S_PH:
17805 case OPC_MULQ_S_W:
17806 case OPC_MULQ_RS_W:
17807 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17808 break;
17809 default:
17810 MIPS_INVAL("MASK ADDUH.QB");
17811 generate_exception(ctx, EXCP_RI);
17812 break;
17814 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
17815 gen_loongson_integer(ctx, op1, rd, rs, rt);
17816 } else {
17817 generate_exception(ctx, EXCP_RI);
17819 break;
17820 case OPC_LX_DSP:
17821 op2 = MASK_LX(ctx->opcode);
17822 switch (op2) {
17823 #if defined(TARGET_MIPS64)
17824 case OPC_LDX:
17825 #endif
17826 case OPC_LBUX:
17827 case OPC_LHX:
17828 case OPC_LWX:
17829 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
17830 break;
17831 default: /* Invalid */
17832 MIPS_INVAL("MASK LX");
17833 generate_exception(ctx, EXCP_RI);
17834 break;
17836 break;
17837 case OPC_ABSQ_S_PH_DSP:
17838 op2 = MASK_ABSQ_S_PH(ctx->opcode);
17839 switch (op2) {
17840 case OPC_ABSQ_S_QB:
17841 case OPC_ABSQ_S_PH:
17842 case OPC_ABSQ_S_W:
17843 case OPC_PRECEQ_W_PHL:
17844 case OPC_PRECEQ_W_PHR:
17845 case OPC_PRECEQU_PH_QBL:
17846 case OPC_PRECEQU_PH_QBR:
17847 case OPC_PRECEQU_PH_QBLA:
17848 case OPC_PRECEQU_PH_QBRA:
17849 case OPC_PRECEU_PH_QBL:
17850 case OPC_PRECEU_PH_QBR:
17851 case OPC_PRECEU_PH_QBLA:
17852 case OPC_PRECEU_PH_QBRA:
17853 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17854 break;
17855 case OPC_BITREV:
17856 case OPC_REPL_QB:
17857 case OPC_REPLV_QB:
17858 case OPC_REPL_PH:
17859 case OPC_REPLV_PH:
17860 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17861 break;
17862 default:
17863 MIPS_INVAL("MASK ABSQ_S.PH");
17864 generate_exception(ctx, EXCP_RI);
17865 break;
17867 break;
17868 case OPC_ADDU_QB_DSP:
17869 op2 = MASK_ADDU_QB(ctx->opcode);
17870 switch (op2) {
17871 case OPC_ADDQ_PH:
17872 case OPC_ADDQ_S_PH:
17873 case OPC_ADDQ_S_W:
17874 case OPC_ADDU_QB:
17875 case OPC_ADDU_S_QB:
17876 case OPC_ADDU_PH:
17877 case OPC_ADDU_S_PH:
17878 case OPC_SUBQ_PH:
17879 case OPC_SUBQ_S_PH:
17880 case OPC_SUBQ_S_W:
17881 case OPC_SUBU_QB:
17882 case OPC_SUBU_S_QB:
17883 case OPC_SUBU_PH:
17884 case OPC_SUBU_S_PH:
17885 case OPC_ADDSC:
17886 case OPC_ADDWC:
17887 case OPC_MODSUB:
17888 case OPC_RADDU_W_QB:
17889 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17890 break;
17891 case OPC_MULEU_S_PH_QBL:
17892 case OPC_MULEU_S_PH_QBR:
17893 case OPC_MULQ_RS_PH:
17894 case OPC_MULEQ_S_W_PHL:
17895 case OPC_MULEQ_S_W_PHR:
17896 case OPC_MULQ_S_PH:
17897 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17898 break;
17899 default: /* Invalid */
17900 MIPS_INVAL("MASK ADDU.QB");
17901 generate_exception(ctx, EXCP_RI);
17902 break;
17905 break;
17906 case OPC_CMPU_EQ_QB_DSP:
17907 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
17908 switch (op2) {
17909 case OPC_PRECR_SRA_PH_W:
17910 case OPC_PRECR_SRA_R_PH_W:
17911 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17912 break;
17913 case OPC_PRECR_QB_PH:
17914 case OPC_PRECRQ_QB_PH:
17915 case OPC_PRECRQ_PH_W:
17916 case OPC_PRECRQ_RS_PH_W:
17917 case OPC_PRECRQU_S_QB_PH:
17918 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17919 break;
17920 case OPC_CMPU_EQ_QB:
17921 case OPC_CMPU_LT_QB:
17922 case OPC_CMPU_LE_QB:
17923 case OPC_CMP_EQ_PH:
17924 case OPC_CMP_LT_PH:
17925 case OPC_CMP_LE_PH:
17926 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17927 break;
17928 case OPC_CMPGU_EQ_QB:
17929 case OPC_CMPGU_LT_QB:
17930 case OPC_CMPGU_LE_QB:
17931 case OPC_CMPGDU_EQ_QB:
17932 case OPC_CMPGDU_LT_QB:
17933 case OPC_CMPGDU_LE_QB:
17934 case OPC_PICK_QB:
17935 case OPC_PICK_PH:
17936 case OPC_PACKRL_PH:
17937 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17938 break;
17939 default: /* Invalid */
17940 MIPS_INVAL("MASK CMPU.EQ.QB");
17941 generate_exception(ctx, EXCP_RI);
17942 break;
17944 break;
17945 case OPC_SHLL_QB_DSP:
17946 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17947 break;
17948 case OPC_DPA_W_PH_DSP:
17949 op2 = MASK_DPA_W_PH(ctx->opcode);
17950 switch (op2) {
17951 case OPC_DPAU_H_QBL:
17952 case OPC_DPAU_H_QBR:
17953 case OPC_DPSU_H_QBL:
17954 case OPC_DPSU_H_QBR:
17955 case OPC_DPA_W_PH:
17956 case OPC_DPAX_W_PH:
17957 case OPC_DPAQ_S_W_PH:
17958 case OPC_DPAQX_S_W_PH:
17959 case OPC_DPAQX_SA_W_PH:
17960 case OPC_DPS_W_PH:
17961 case OPC_DPSX_W_PH:
17962 case OPC_DPSQ_S_W_PH:
17963 case OPC_DPSQX_S_W_PH:
17964 case OPC_DPSQX_SA_W_PH:
17965 case OPC_MULSAQ_S_W_PH:
17966 case OPC_DPAQ_SA_L_W:
17967 case OPC_DPSQ_SA_L_W:
17968 case OPC_MAQ_S_W_PHL:
17969 case OPC_MAQ_S_W_PHR:
17970 case OPC_MAQ_SA_W_PHL:
17971 case OPC_MAQ_SA_W_PHR:
17972 case OPC_MULSA_W_PH:
17973 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17974 break;
17975 default: /* Invalid */
17976 MIPS_INVAL("MASK DPAW.PH");
17977 generate_exception(ctx, EXCP_RI);
17978 break;
17980 break;
17981 case OPC_INSV_DSP:
17982 op2 = MASK_INSV(ctx->opcode);
17983 switch (op2) {
17984 case OPC_INSV:
17985 check_dsp(ctx);
17987 TCGv t0, t1;
17989 if (rt == 0) {
17990 MIPS_DEBUG("NOP");
17991 break;
17994 t0 = tcg_temp_new();
17995 t1 = tcg_temp_new();
17997 gen_load_gpr(t0, rt);
17998 gen_load_gpr(t1, rs);
18000 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
18002 tcg_temp_free(t0);
18003 tcg_temp_free(t1);
18004 break;
18006 default: /* Invalid */
18007 MIPS_INVAL("MASK INSV");
18008 generate_exception(ctx, EXCP_RI);
18009 break;
18011 break;
18012 case OPC_APPEND_DSP:
18013 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
18014 break;
18015 case OPC_EXTR_W_DSP:
18016 op2 = MASK_EXTR_W(ctx->opcode);
18017 switch (op2) {
18018 case OPC_EXTR_W:
18019 case OPC_EXTR_R_W:
18020 case OPC_EXTR_RS_W:
18021 case OPC_EXTR_S_H:
18022 case OPC_EXTRV_S_H:
18023 case OPC_EXTRV_W:
18024 case OPC_EXTRV_R_W:
18025 case OPC_EXTRV_RS_W:
18026 case OPC_EXTP:
18027 case OPC_EXTPV:
18028 case OPC_EXTPDP:
18029 case OPC_EXTPDPV:
18030 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
18031 break;
18032 case OPC_RDDSP:
18033 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
18034 break;
18035 case OPC_SHILO:
18036 case OPC_SHILOV:
18037 case OPC_MTHLIP:
18038 case OPC_WRDSP:
18039 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
18040 break;
18041 default: /* Invalid */
18042 MIPS_INVAL("MASK EXTR.W");
18043 generate_exception(ctx, EXCP_RI);
18044 break;
18046 break;
18047 #if defined(TARGET_MIPS64)
18048 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
18049 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
18050 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
18051 check_insn(ctx, INSN_LOONGSON2E);
18052 gen_loongson_integer(ctx, op1, rd, rs, rt);
18053 break;
18054 case OPC_ABSQ_S_QH_DSP:
18055 op2 = MASK_ABSQ_S_QH(ctx->opcode);
18056 switch (op2) {
18057 case OPC_PRECEQ_L_PWL:
18058 case OPC_PRECEQ_L_PWR:
18059 case OPC_PRECEQ_PW_QHL:
18060 case OPC_PRECEQ_PW_QHR:
18061 case OPC_PRECEQ_PW_QHLA:
18062 case OPC_PRECEQ_PW_QHRA:
18063 case OPC_PRECEQU_QH_OBL:
18064 case OPC_PRECEQU_QH_OBR:
18065 case OPC_PRECEQU_QH_OBLA:
18066 case OPC_PRECEQU_QH_OBRA:
18067 case OPC_PRECEU_QH_OBL:
18068 case OPC_PRECEU_QH_OBR:
18069 case OPC_PRECEU_QH_OBLA:
18070 case OPC_PRECEU_QH_OBRA:
18071 case OPC_ABSQ_S_OB:
18072 case OPC_ABSQ_S_PW:
18073 case OPC_ABSQ_S_QH:
18074 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18075 break;
18076 case OPC_REPL_OB:
18077 case OPC_REPL_PW:
18078 case OPC_REPL_QH:
18079 case OPC_REPLV_OB:
18080 case OPC_REPLV_PW:
18081 case OPC_REPLV_QH:
18082 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
18083 break;
18084 default: /* Invalid */
18085 MIPS_INVAL("MASK ABSQ_S.QH");
18086 generate_exception(ctx, EXCP_RI);
18087 break;
18089 break;
18090 case OPC_ADDU_OB_DSP:
18091 op2 = MASK_ADDU_OB(ctx->opcode);
18092 switch (op2) {
18093 case OPC_RADDU_L_OB:
18094 case OPC_SUBQ_PW:
18095 case OPC_SUBQ_S_PW:
18096 case OPC_SUBQ_QH:
18097 case OPC_SUBQ_S_QH:
18098 case OPC_SUBU_OB:
18099 case OPC_SUBU_S_OB:
18100 case OPC_SUBU_QH:
18101 case OPC_SUBU_S_QH:
18102 case OPC_SUBUH_OB:
18103 case OPC_SUBUH_R_OB:
18104 case OPC_ADDQ_PW:
18105 case OPC_ADDQ_S_PW:
18106 case OPC_ADDQ_QH:
18107 case OPC_ADDQ_S_QH:
18108 case OPC_ADDU_OB:
18109 case OPC_ADDU_S_OB:
18110 case OPC_ADDU_QH:
18111 case OPC_ADDU_S_QH:
18112 case OPC_ADDUH_OB:
18113 case OPC_ADDUH_R_OB:
18114 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18115 break;
18116 case OPC_MULEQ_S_PW_QHL:
18117 case OPC_MULEQ_S_PW_QHR:
18118 case OPC_MULEU_S_QH_OBL:
18119 case OPC_MULEU_S_QH_OBR:
18120 case OPC_MULQ_RS_QH:
18121 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
18122 break;
18123 default: /* Invalid */
18124 MIPS_INVAL("MASK ADDU.OB");
18125 generate_exception(ctx, EXCP_RI);
18126 break;
18128 break;
18129 case OPC_CMPU_EQ_OB_DSP:
18130 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
18131 switch (op2) {
18132 case OPC_PRECR_SRA_QH_PW:
18133 case OPC_PRECR_SRA_R_QH_PW:
18134 /* Return value is rt. */
18135 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
18136 break;
18137 case OPC_PRECR_OB_QH:
18138 case OPC_PRECRQ_OB_QH:
18139 case OPC_PRECRQ_PW_L:
18140 case OPC_PRECRQ_QH_PW:
18141 case OPC_PRECRQ_RS_QH_PW:
18142 case OPC_PRECRQU_S_OB_QH:
18143 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18144 break;
18145 case OPC_CMPU_EQ_OB:
18146 case OPC_CMPU_LT_OB:
18147 case OPC_CMPU_LE_OB:
18148 case OPC_CMP_EQ_QH:
18149 case OPC_CMP_LT_QH:
18150 case OPC_CMP_LE_QH:
18151 case OPC_CMP_EQ_PW:
18152 case OPC_CMP_LT_PW:
18153 case OPC_CMP_LE_PW:
18154 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
18155 break;
18156 case OPC_CMPGDU_EQ_OB:
18157 case OPC_CMPGDU_LT_OB:
18158 case OPC_CMPGDU_LE_OB:
18159 case OPC_CMPGU_EQ_OB:
18160 case OPC_CMPGU_LT_OB:
18161 case OPC_CMPGU_LE_OB:
18162 case OPC_PACKRL_PW:
18163 case OPC_PICK_OB:
18164 case OPC_PICK_PW:
18165 case OPC_PICK_QH:
18166 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
18167 break;
18168 default: /* Invalid */
18169 MIPS_INVAL("MASK CMPU_EQ.OB");
18170 generate_exception(ctx, EXCP_RI);
18171 break;
18173 break;
18174 case OPC_DAPPEND_DSP:
18175 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
18176 break;
18177 case OPC_DEXTR_W_DSP:
18178 op2 = MASK_DEXTR_W(ctx->opcode);
18179 switch (op2) {
18180 case OPC_DEXTP:
18181 case OPC_DEXTPDP:
18182 case OPC_DEXTPDPV:
18183 case OPC_DEXTPV:
18184 case OPC_DEXTR_L:
18185 case OPC_DEXTR_R_L:
18186 case OPC_DEXTR_RS_L:
18187 case OPC_DEXTR_W:
18188 case OPC_DEXTR_R_W:
18189 case OPC_DEXTR_RS_W:
18190 case OPC_DEXTR_S_H:
18191 case OPC_DEXTRV_L:
18192 case OPC_DEXTRV_R_L:
18193 case OPC_DEXTRV_RS_L:
18194 case OPC_DEXTRV_S_H:
18195 case OPC_DEXTRV_W:
18196 case OPC_DEXTRV_R_W:
18197 case OPC_DEXTRV_RS_W:
18198 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
18199 break;
18200 case OPC_DMTHLIP:
18201 case OPC_DSHILO:
18202 case OPC_DSHILOV:
18203 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
18204 break;
18205 default: /* Invalid */
18206 MIPS_INVAL("MASK EXTR.W");
18207 generate_exception(ctx, EXCP_RI);
18208 break;
18210 break;
18211 case OPC_DPAQ_W_QH_DSP:
18212 op2 = MASK_DPAQ_W_QH(ctx->opcode);
18213 switch (op2) {
18214 case OPC_DPAU_H_OBL:
18215 case OPC_DPAU_H_OBR:
18216 case OPC_DPSU_H_OBL:
18217 case OPC_DPSU_H_OBR:
18218 case OPC_DPA_W_QH:
18219 case OPC_DPAQ_S_W_QH:
18220 case OPC_DPS_W_QH:
18221 case OPC_DPSQ_S_W_QH:
18222 case OPC_MULSAQ_S_W_QH:
18223 case OPC_DPAQ_SA_L_PW:
18224 case OPC_DPSQ_SA_L_PW:
18225 case OPC_MULSAQ_S_L_PW:
18226 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
18227 break;
18228 case OPC_MAQ_S_W_QHLL:
18229 case OPC_MAQ_S_W_QHLR:
18230 case OPC_MAQ_S_W_QHRL:
18231 case OPC_MAQ_S_W_QHRR:
18232 case OPC_MAQ_SA_W_QHLL:
18233 case OPC_MAQ_SA_W_QHLR:
18234 case OPC_MAQ_SA_W_QHRL:
18235 case OPC_MAQ_SA_W_QHRR:
18236 case OPC_MAQ_S_L_PWL:
18237 case OPC_MAQ_S_L_PWR:
18238 case OPC_DMADD:
18239 case OPC_DMADDU:
18240 case OPC_DMSUB:
18241 case OPC_DMSUBU:
18242 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
18243 break;
18244 default: /* Invalid */
18245 MIPS_INVAL("MASK DPAQ.W.QH");
18246 generate_exception(ctx, EXCP_RI);
18247 break;
18249 break;
18250 case OPC_DINSV_DSP:
18251 op2 = MASK_INSV(ctx->opcode);
18252 switch (op2) {
18253 case OPC_DINSV:
18255 TCGv t0, t1;
18257 if (rt == 0) {
18258 MIPS_DEBUG("NOP");
18259 break;
18261 check_dsp(ctx);
18263 t0 = tcg_temp_new();
18264 t1 = tcg_temp_new();
18266 gen_load_gpr(t0, rt);
18267 gen_load_gpr(t1, rs);
18269 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
18271 tcg_temp_free(t0);
18272 tcg_temp_free(t1);
18273 break;
18275 default: /* Invalid */
18276 MIPS_INVAL("MASK DINSV");
18277 generate_exception(ctx, EXCP_RI);
18278 break;
18280 break;
18281 case OPC_SHLL_OB_DSP:
18282 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
18283 break;
18284 #endif
18285 default: /* Invalid */
18286 MIPS_INVAL("special3_legacy");
18287 generate_exception(ctx, EXCP_RI);
18288 break;
18292 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
18294 int rs, rt, rd, sa;
18295 uint32_t op1, op2;
18297 rs = (ctx->opcode >> 21) & 0x1f;
18298 rt = (ctx->opcode >> 16) & 0x1f;
18299 rd = (ctx->opcode >> 11) & 0x1f;
18300 sa = (ctx->opcode >> 6) & 0x1f;
18302 op1 = MASK_SPECIAL3(ctx->opcode);
18303 switch (op1) {
18304 case OPC_EXT:
18305 case OPC_INS:
18306 check_insn(ctx, ISA_MIPS32R2);
18307 gen_bitops(ctx, op1, rt, rs, sa, rd);
18308 break;
18309 case OPC_BSHFL:
18310 op2 = MASK_BSHFL(ctx->opcode);
18311 switch (op2) {
18312 case OPC_ALIGN ... OPC_ALIGN_END:
18313 case OPC_BITSWAP:
18314 check_insn(ctx, ISA_MIPS32R6);
18315 decode_opc_special3_r6(env, ctx);
18316 break;
18317 default:
18318 check_insn(ctx, ISA_MIPS32R2);
18319 gen_bshfl(ctx, op2, rt, rd);
18320 break;
18322 break;
18323 #if defined(TARGET_MIPS64)
18324 case OPC_DEXTM ... OPC_DEXT:
18325 case OPC_DINSM ... OPC_DINS:
18326 check_insn(ctx, ISA_MIPS64R2);
18327 check_mips_64(ctx);
18328 gen_bitops(ctx, op1, rt, rs, sa, rd);
18329 break;
18330 case OPC_DBSHFL:
18331 op2 = MASK_DBSHFL(ctx->opcode);
18332 switch (op2) {
18333 case OPC_DALIGN ... OPC_DALIGN_END:
18334 case OPC_DBITSWAP:
18335 check_insn(ctx, ISA_MIPS32R6);
18336 decode_opc_special3_r6(env, ctx);
18337 break;
18338 default:
18339 check_insn(ctx, ISA_MIPS64R2);
18340 check_mips_64(ctx);
18341 op2 = MASK_DBSHFL(ctx->opcode);
18342 gen_bshfl(ctx, op2, rt, rd);
18343 break;
18345 break;
18346 #endif
18347 case OPC_RDHWR:
18348 gen_rdhwr(ctx, rt, rd);
18349 break;
18350 case OPC_FORK:
18351 check_insn(ctx, ASE_MT);
18353 TCGv t0 = tcg_temp_new();
18354 TCGv t1 = tcg_temp_new();
18356 gen_load_gpr(t0, rt);
18357 gen_load_gpr(t1, rs);
18358 gen_helper_fork(t0, t1);
18359 tcg_temp_free(t0);
18360 tcg_temp_free(t1);
18362 break;
18363 case OPC_YIELD:
18364 check_insn(ctx, ASE_MT);
18366 TCGv t0 = tcg_temp_new();
18368 save_cpu_state(ctx, 1);
18369 gen_load_gpr(t0, rs);
18370 gen_helper_yield(t0, cpu_env, t0);
18371 gen_store_gpr(t0, rd);
18372 tcg_temp_free(t0);
18374 break;
18375 default:
18376 if (ctx->insn_flags & ISA_MIPS32R6) {
18377 decode_opc_special3_r6(env, ctx);
18378 } else {
18379 decode_opc_special3_legacy(env, ctx);
18384 /* MIPS SIMD Architecture (MSA) */
18385 static inline int check_msa_access(DisasContext *ctx)
18387 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
18388 !(ctx->hflags & MIPS_HFLAG_F64))) {
18389 generate_exception(ctx, EXCP_RI);
18390 return 0;
18393 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
18394 if (ctx->insn_flags & ASE_MSA) {
18395 generate_exception(ctx, EXCP_MSADIS);
18396 return 0;
18397 } else {
18398 generate_exception(ctx, EXCP_RI);
18399 return 0;
18402 return 1;
18405 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
18407 /* generates tcg ops to check if any element is 0 */
18408 /* Note this function only works with MSA_WRLEN = 128 */
18409 uint64_t eval_zero_or_big = 0;
18410 uint64_t eval_big = 0;
18411 TCGv_i64 t0 = tcg_temp_new_i64();
18412 TCGv_i64 t1 = tcg_temp_new_i64();
18413 switch (df) {
18414 case DF_BYTE:
18415 eval_zero_or_big = 0x0101010101010101ULL;
18416 eval_big = 0x8080808080808080ULL;
18417 break;
18418 case DF_HALF:
18419 eval_zero_or_big = 0x0001000100010001ULL;
18420 eval_big = 0x8000800080008000ULL;
18421 break;
18422 case DF_WORD:
18423 eval_zero_or_big = 0x0000000100000001ULL;
18424 eval_big = 0x8000000080000000ULL;
18425 break;
18426 case DF_DOUBLE:
18427 eval_zero_or_big = 0x0000000000000001ULL;
18428 eval_big = 0x8000000000000000ULL;
18429 break;
18431 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
18432 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
18433 tcg_gen_andi_i64(t0, t0, eval_big);
18434 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
18435 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
18436 tcg_gen_andi_i64(t1, t1, eval_big);
18437 tcg_gen_or_i64(t0, t0, t1);
18438 /* if all bits are zero then all elements are not zero */
18439 /* if some bit is non-zero then some element is zero */
18440 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
18441 tcg_gen_trunc_i64_tl(tresult, t0);
18442 tcg_temp_free_i64(t0);
18443 tcg_temp_free_i64(t1);
18446 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
18448 uint8_t df = (ctx->opcode >> 21) & 0x3;
18449 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18450 int64_t s16 = (int16_t)ctx->opcode;
18452 check_msa_access(ctx);
18454 if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
18455 MIPS_DEBUG("CTI in delay / forbidden slot");
18456 generate_exception(ctx, EXCP_RI);
18457 return;
18459 switch (op1) {
18460 case OPC_BZ_V:
18461 case OPC_BNZ_V:
18463 TCGv_i64 t0 = tcg_temp_new_i64();
18464 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
18465 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
18466 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
18467 tcg_gen_trunc_i64_tl(bcond, t0);
18468 tcg_temp_free_i64(t0);
18470 break;
18471 case OPC_BZ_B:
18472 case OPC_BZ_H:
18473 case OPC_BZ_W:
18474 case OPC_BZ_D:
18475 gen_check_zero_element(bcond, df, wt);
18476 break;
18477 case OPC_BNZ_B:
18478 case OPC_BNZ_H:
18479 case OPC_BNZ_W:
18480 case OPC_BNZ_D:
18481 gen_check_zero_element(bcond, df, wt);
18482 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
18483 break;
18486 ctx->btarget = ctx->pc + (s16 << 2) + 4;
18488 ctx->hflags |= MIPS_HFLAG_BC;
18489 ctx->hflags |= MIPS_HFLAG_BDS32;
18492 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
18494 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
18495 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
18496 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18497 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18499 TCGv_i32 twd = tcg_const_i32(wd);
18500 TCGv_i32 tws = tcg_const_i32(ws);
18501 TCGv_i32 ti8 = tcg_const_i32(i8);
18503 switch (MASK_MSA_I8(ctx->opcode)) {
18504 case OPC_ANDI_B:
18505 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
18506 break;
18507 case OPC_ORI_B:
18508 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
18509 break;
18510 case OPC_NORI_B:
18511 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
18512 break;
18513 case OPC_XORI_B:
18514 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
18515 break;
18516 case OPC_BMNZI_B:
18517 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
18518 break;
18519 case OPC_BMZI_B:
18520 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
18521 break;
18522 case OPC_BSELI_B:
18523 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
18524 break;
18525 case OPC_SHF_B:
18526 case OPC_SHF_H:
18527 case OPC_SHF_W:
18529 uint8_t df = (ctx->opcode >> 24) & 0x3;
18530 if (df == DF_DOUBLE) {
18531 generate_exception(ctx, EXCP_RI);
18532 } else {
18533 TCGv_i32 tdf = tcg_const_i32(df);
18534 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
18535 tcg_temp_free_i32(tdf);
18538 break;
18539 default:
18540 MIPS_INVAL("MSA instruction");
18541 generate_exception(ctx, EXCP_RI);
18542 break;
18545 tcg_temp_free_i32(twd);
18546 tcg_temp_free_i32(tws);
18547 tcg_temp_free_i32(ti8);
18550 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
18552 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18553 uint8_t df = (ctx->opcode >> 21) & 0x3;
18554 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
18555 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
18556 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18557 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18559 TCGv_i32 tdf = tcg_const_i32(df);
18560 TCGv_i32 twd = tcg_const_i32(wd);
18561 TCGv_i32 tws = tcg_const_i32(ws);
18562 TCGv_i32 timm = tcg_temp_new_i32();
18563 tcg_gen_movi_i32(timm, u5);
18565 switch (MASK_MSA_I5(ctx->opcode)) {
18566 case OPC_ADDVI_df:
18567 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
18568 break;
18569 case OPC_SUBVI_df:
18570 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
18571 break;
18572 case OPC_MAXI_S_df:
18573 tcg_gen_movi_i32(timm, s5);
18574 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
18575 break;
18576 case OPC_MAXI_U_df:
18577 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
18578 break;
18579 case OPC_MINI_S_df:
18580 tcg_gen_movi_i32(timm, s5);
18581 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
18582 break;
18583 case OPC_MINI_U_df:
18584 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
18585 break;
18586 case OPC_CEQI_df:
18587 tcg_gen_movi_i32(timm, s5);
18588 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
18589 break;
18590 case OPC_CLTI_S_df:
18591 tcg_gen_movi_i32(timm, s5);
18592 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
18593 break;
18594 case OPC_CLTI_U_df:
18595 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
18596 break;
18597 case OPC_CLEI_S_df:
18598 tcg_gen_movi_i32(timm, s5);
18599 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
18600 break;
18601 case OPC_CLEI_U_df:
18602 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
18603 break;
18604 case OPC_LDI_df:
18606 int32_t s10 = sextract32(ctx->opcode, 11, 10);
18607 tcg_gen_movi_i32(timm, s10);
18608 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
18610 break;
18611 default:
18612 MIPS_INVAL("MSA instruction");
18613 generate_exception(ctx, EXCP_RI);
18614 break;
18617 tcg_temp_free_i32(tdf);
18618 tcg_temp_free_i32(twd);
18619 tcg_temp_free_i32(tws);
18620 tcg_temp_free_i32(timm);
18623 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
18625 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18626 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
18627 uint32_t df = 0, m = 0;
18628 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18629 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18631 TCGv_i32 tdf;
18632 TCGv_i32 tm;
18633 TCGv_i32 twd;
18634 TCGv_i32 tws;
18636 if ((dfm & 0x40) == 0x00) {
18637 m = dfm & 0x3f;
18638 df = DF_DOUBLE;
18639 } else if ((dfm & 0x60) == 0x40) {
18640 m = dfm & 0x1f;
18641 df = DF_WORD;
18642 } else if ((dfm & 0x70) == 0x60) {
18643 m = dfm & 0x0f;
18644 df = DF_HALF;
18645 } else if ((dfm & 0x78) == 0x70) {
18646 m = dfm & 0x7;
18647 df = DF_BYTE;
18648 } else {
18649 generate_exception(ctx, EXCP_RI);
18650 return;
18653 tdf = tcg_const_i32(df);
18654 tm = tcg_const_i32(m);
18655 twd = tcg_const_i32(wd);
18656 tws = tcg_const_i32(ws);
18658 switch (MASK_MSA_BIT(ctx->opcode)) {
18659 case OPC_SLLI_df:
18660 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
18661 break;
18662 case OPC_SRAI_df:
18663 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
18664 break;
18665 case OPC_SRLI_df:
18666 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
18667 break;
18668 case OPC_BCLRI_df:
18669 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
18670 break;
18671 case OPC_BSETI_df:
18672 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
18673 break;
18674 case OPC_BNEGI_df:
18675 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
18676 break;
18677 case OPC_BINSLI_df:
18678 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
18679 break;
18680 case OPC_BINSRI_df:
18681 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
18682 break;
18683 case OPC_SAT_S_df:
18684 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
18685 break;
18686 case OPC_SAT_U_df:
18687 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
18688 break;
18689 case OPC_SRARI_df:
18690 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
18691 break;
18692 case OPC_SRLRI_df:
18693 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
18694 break;
18695 default:
18696 MIPS_INVAL("MSA instruction");
18697 generate_exception(ctx, EXCP_RI);
18698 break;
18701 tcg_temp_free_i32(tdf);
18702 tcg_temp_free_i32(tm);
18703 tcg_temp_free_i32(twd);
18704 tcg_temp_free_i32(tws);
18707 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
18709 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18710 uint8_t df = (ctx->opcode >> 21) & 0x3;
18711 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18712 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18713 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18715 TCGv_i32 tdf = tcg_const_i32(df);
18716 TCGv_i32 twd = tcg_const_i32(wd);
18717 TCGv_i32 tws = tcg_const_i32(ws);
18718 TCGv_i32 twt = tcg_const_i32(wt);
18720 switch (MASK_MSA_3R(ctx->opcode)) {
18721 case OPC_SLL_df:
18722 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
18723 break;
18724 case OPC_ADDV_df:
18725 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
18726 break;
18727 case OPC_CEQ_df:
18728 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
18729 break;
18730 case OPC_ADD_A_df:
18731 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
18732 break;
18733 case OPC_SUBS_S_df:
18734 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
18735 break;
18736 case OPC_MULV_df:
18737 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
18738 break;
18739 case OPC_SLD_df:
18740 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
18741 break;
18742 case OPC_VSHF_df:
18743 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
18744 break;
18745 case OPC_SRA_df:
18746 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
18747 break;
18748 case OPC_SUBV_df:
18749 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
18750 break;
18751 case OPC_ADDS_A_df:
18752 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
18753 break;
18754 case OPC_SUBS_U_df:
18755 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
18756 break;
18757 case OPC_MADDV_df:
18758 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
18759 break;
18760 case OPC_SPLAT_df:
18761 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
18762 break;
18763 case OPC_SRAR_df:
18764 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
18765 break;
18766 case OPC_SRL_df:
18767 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
18768 break;
18769 case OPC_MAX_S_df:
18770 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
18771 break;
18772 case OPC_CLT_S_df:
18773 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
18774 break;
18775 case OPC_ADDS_S_df:
18776 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
18777 break;
18778 case OPC_SUBSUS_U_df:
18779 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
18780 break;
18781 case OPC_MSUBV_df:
18782 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
18783 break;
18784 case OPC_PCKEV_df:
18785 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
18786 break;
18787 case OPC_SRLR_df:
18788 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
18789 break;
18790 case OPC_BCLR_df:
18791 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
18792 break;
18793 case OPC_MAX_U_df:
18794 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
18795 break;
18796 case OPC_CLT_U_df:
18797 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
18798 break;
18799 case OPC_ADDS_U_df:
18800 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
18801 break;
18802 case OPC_SUBSUU_S_df:
18803 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
18804 break;
18805 case OPC_PCKOD_df:
18806 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
18807 break;
18808 case OPC_BSET_df:
18809 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
18810 break;
18811 case OPC_MIN_S_df:
18812 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
18813 break;
18814 case OPC_CLE_S_df:
18815 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
18816 break;
18817 case OPC_AVE_S_df:
18818 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
18819 break;
18820 case OPC_ASUB_S_df:
18821 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
18822 break;
18823 case OPC_DIV_S_df:
18824 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
18825 break;
18826 case OPC_ILVL_df:
18827 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
18828 break;
18829 case OPC_BNEG_df:
18830 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
18831 break;
18832 case OPC_MIN_U_df:
18833 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
18834 break;
18835 case OPC_CLE_U_df:
18836 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
18837 break;
18838 case OPC_AVE_U_df:
18839 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
18840 break;
18841 case OPC_ASUB_U_df:
18842 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
18843 break;
18844 case OPC_DIV_U_df:
18845 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
18846 break;
18847 case OPC_ILVR_df:
18848 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
18849 break;
18850 case OPC_BINSL_df:
18851 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
18852 break;
18853 case OPC_MAX_A_df:
18854 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
18855 break;
18856 case OPC_AVER_S_df:
18857 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
18858 break;
18859 case OPC_MOD_S_df:
18860 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
18861 break;
18862 case OPC_ILVEV_df:
18863 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
18864 break;
18865 case OPC_BINSR_df:
18866 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
18867 break;
18868 case OPC_MIN_A_df:
18869 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
18870 break;
18871 case OPC_AVER_U_df:
18872 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
18873 break;
18874 case OPC_MOD_U_df:
18875 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
18876 break;
18877 case OPC_ILVOD_df:
18878 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
18879 break;
18881 case OPC_DOTP_S_df:
18882 case OPC_DOTP_U_df:
18883 case OPC_DPADD_S_df:
18884 case OPC_DPADD_U_df:
18885 case OPC_DPSUB_S_df:
18886 case OPC_HADD_S_df:
18887 case OPC_DPSUB_U_df:
18888 case OPC_HADD_U_df:
18889 case OPC_HSUB_S_df:
18890 case OPC_HSUB_U_df:
18891 if (df == DF_BYTE) {
18892 generate_exception(ctx, EXCP_RI);
18894 switch (MASK_MSA_3R(ctx->opcode)) {
18895 case OPC_DOTP_S_df:
18896 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
18897 break;
18898 case OPC_DOTP_U_df:
18899 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
18900 break;
18901 case OPC_DPADD_S_df:
18902 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
18903 break;
18904 case OPC_DPADD_U_df:
18905 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
18906 break;
18907 case OPC_DPSUB_S_df:
18908 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
18909 break;
18910 case OPC_HADD_S_df:
18911 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
18912 break;
18913 case OPC_DPSUB_U_df:
18914 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
18915 break;
18916 case OPC_HADD_U_df:
18917 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
18918 break;
18919 case OPC_HSUB_S_df:
18920 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
18921 break;
18922 case OPC_HSUB_U_df:
18923 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
18924 break;
18926 break;
18927 default:
18928 MIPS_INVAL("MSA instruction");
18929 generate_exception(ctx, EXCP_RI);
18930 break;
18932 tcg_temp_free_i32(twd);
18933 tcg_temp_free_i32(tws);
18934 tcg_temp_free_i32(twt);
18935 tcg_temp_free_i32(tdf);
18938 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
18940 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
18941 uint8_t source = (ctx->opcode >> 11) & 0x1f;
18942 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
18943 TCGv telm = tcg_temp_new();
18944 TCGv_i32 tsr = tcg_const_i32(source);
18945 TCGv_i32 tdt = tcg_const_i32(dest);
18947 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
18948 case OPC_CTCMSA:
18949 gen_load_gpr(telm, source);
18950 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
18951 break;
18952 case OPC_CFCMSA:
18953 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
18954 gen_store_gpr(telm, dest);
18955 break;
18956 case OPC_MOVE_V:
18957 gen_helper_msa_move_v(cpu_env, tdt, tsr);
18958 break;
18959 default:
18960 MIPS_INVAL("MSA instruction");
18961 generate_exception(ctx, EXCP_RI);
18962 break;
18965 tcg_temp_free(telm);
18966 tcg_temp_free_i32(tdt);
18967 tcg_temp_free_i32(tsr);
18970 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
18971 uint32_t n)
18973 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18974 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18975 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18977 TCGv_i32 tws = tcg_const_i32(ws);
18978 TCGv_i32 twd = tcg_const_i32(wd);
18979 TCGv_i32 tn = tcg_const_i32(n);
18980 TCGv_i32 tdf = tcg_const_i32(df);
18982 switch (MASK_MSA_ELM(ctx->opcode)) {
18983 case OPC_SLDI_df:
18984 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
18985 break;
18986 case OPC_SPLATI_df:
18987 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
18988 break;
18989 case OPC_INSVE_df:
18990 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
18991 break;
18992 case OPC_COPY_S_df:
18993 case OPC_COPY_U_df:
18994 case OPC_INSERT_df:
18995 #if !defined(TARGET_MIPS64)
18996 /* Double format valid only for MIPS64 */
18997 if (df == DF_DOUBLE) {
18998 generate_exception(ctx, EXCP_RI);
18999 break;
19001 #endif
19002 switch (MASK_MSA_ELM(ctx->opcode)) {
19003 case OPC_COPY_S_df:
19004 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
19005 break;
19006 case OPC_COPY_U_df:
19007 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
19008 break;
19009 case OPC_INSERT_df:
19010 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
19011 break;
19013 break;
19014 default:
19015 MIPS_INVAL("MSA instruction");
19016 generate_exception(ctx, EXCP_RI);
19018 tcg_temp_free_i32(twd);
19019 tcg_temp_free_i32(tws);
19020 tcg_temp_free_i32(tn);
19021 tcg_temp_free_i32(tdf);
19024 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
19026 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
19027 uint32_t df = 0, n = 0;
19029 if ((dfn & 0x30) == 0x00) {
19030 n = dfn & 0x0f;
19031 df = DF_BYTE;
19032 } else if ((dfn & 0x38) == 0x20) {
19033 n = dfn & 0x07;
19034 df = DF_HALF;
19035 } else if ((dfn & 0x3c) == 0x30) {
19036 n = dfn & 0x03;
19037 df = DF_WORD;
19038 } else if ((dfn & 0x3e) == 0x38) {
19039 n = dfn & 0x01;
19040 df = DF_DOUBLE;
19041 } else if (dfn == 0x3E) {
19042 /* CTCMSA, CFCMSA, MOVE.V */
19043 gen_msa_elm_3e(env, ctx);
19044 return;
19045 } else {
19046 generate_exception(ctx, EXCP_RI);
19047 return;
19050 gen_msa_elm_df(env, ctx, df, n);
19053 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
19055 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
19056 uint8_t df = (ctx->opcode >> 21) & 0x1;
19057 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19058 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19059 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19061 TCGv_i32 twd = tcg_const_i32(wd);
19062 TCGv_i32 tws = tcg_const_i32(ws);
19063 TCGv_i32 twt = tcg_const_i32(wt);
19064 TCGv_i32 tdf = tcg_temp_new_i32();
19066 /* adjust df value for floating-point instruction */
19067 tcg_gen_movi_i32(tdf, df + 2);
19069 switch (MASK_MSA_3RF(ctx->opcode)) {
19070 case OPC_FCAF_df:
19071 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
19072 break;
19073 case OPC_FADD_df:
19074 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
19075 break;
19076 case OPC_FCUN_df:
19077 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
19078 break;
19079 case OPC_FSUB_df:
19080 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
19081 break;
19082 case OPC_FCOR_df:
19083 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
19084 break;
19085 case OPC_FCEQ_df:
19086 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
19087 break;
19088 case OPC_FMUL_df:
19089 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
19090 break;
19091 case OPC_FCUNE_df:
19092 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
19093 break;
19094 case OPC_FCUEQ_df:
19095 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
19096 break;
19097 case OPC_FDIV_df:
19098 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
19099 break;
19100 case OPC_FCNE_df:
19101 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
19102 break;
19103 case OPC_FCLT_df:
19104 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
19105 break;
19106 case OPC_FMADD_df:
19107 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
19108 break;
19109 case OPC_MUL_Q_df:
19110 tcg_gen_movi_i32(tdf, df + 1);
19111 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
19112 break;
19113 case OPC_FCULT_df:
19114 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
19115 break;
19116 case OPC_FMSUB_df:
19117 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
19118 break;
19119 case OPC_MADD_Q_df:
19120 tcg_gen_movi_i32(tdf, df + 1);
19121 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
19122 break;
19123 case OPC_FCLE_df:
19124 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
19125 break;
19126 case OPC_MSUB_Q_df:
19127 tcg_gen_movi_i32(tdf, df + 1);
19128 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
19129 break;
19130 case OPC_FCULE_df:
19131 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
19132 break;
19133 case OPC_FEXP2_df:
19134 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
19135 break;
19136 case OPC_FSAF_df:
19137 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
19138 break;
19139 case OPC_FEXDO_df:
19140 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
19141 break;
19142 case OPC_FSUN_df:
19143 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
19144 break;
19145 case OPC_FSOR_df:
19146 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
19147 break;
19148 case OPC_FSEQ_df:
19149 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
19150 break;
19151 case OPC_FTQ_df:
19152 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
19153 break;
19154 case OPC_FSUNE_df:
19155 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
19156 break;
19157 case OPC_FSUEQ_df:
19158 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
19159 break;
19160 case OPC_FSNE_df:
19161 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
19162 break;
19163 case OPC_FSLT_df:
19164 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
19165 break;
19166 case OPC_FMIN_df:
19167 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
19168 break;
19169 case OPC_MULR_Q_df:
19170 tcg_gen_movi_i32(tdf, df + 1);
19171 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
19172 break;
19173 case OPC_FSULT_df:
19174 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
19175 break;
19176 case OPC_FMIN_A_df:
19177 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
19178 break;
19179 case OPC_MADDR_Q_df:
19180 tcg_gen_movi_i32(tdf, df + 1);
19181 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
19182 break;
19183 case OPC_FSLE_df:
19184 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
19185 break;
19186 case OPC_FMAX_df:
19187 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
19188 break;
19189 case OPC_MSUBR_Q_df:
19190 tcg_gen_movi_i32(tdf, df + 1);
19191 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
19192 break;
19193 case OPC_FSULE_df:
19194 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
19195 break;
19196 case OPC_FMAX_A_df:
19197 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
19198 break;
19199 default:
19200 MIPS_INVAL("MSA instruction");
19201 generate_exception(ctx, EXCP_RI);
19202 break;
19205 tcg_temp_free_i32(twd);
19206 tcg_temp_free_i32(tws);
19207 tcg_temp_free_i32(twt);
19208 tcg_temp_free_i32(tdf);
19211 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
19213 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
19214 (op & (0x7 << 18)))
19215 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19216 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19217 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19218 uint8_t df = (ctx->opcode >> 16) & 0x3;
19219 TCGv_i32 twd = tcg_const_i32(wd);
19220 TCGv_i32 tws = tcg_const_i32(ws);
19221 TCGv_i32 twt = tcg_const_i32(wt);
19222 TCGv_i32 tdf = tcg_const_i32(df);
19224 switch (MASK_MSA_2R(ctx->opcode)) {
19225 case OPC_FILL_df:
19226 #if !defined(TARGET_MIPS64)
19227 /* Double format valid only for MIPS64 */
19228 if (df == DF_DOUBLE) {
19229 generate_exception(ctx, EXCP_RI);
19230 break;
19232 #endif
19233 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
19234 break;
19235 case OPC_PCNT_df:
19236 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
19237 break;
19238 case OPC_NLOC_df:
19239 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
19240 break;
19241 case OPC_NLZC_df:
19242 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
19243 break;
19244 default:
19245 MIPS_INVAL("MSA instruction");
19246 generate_exception(ctx, EXCP_RI);
19247 break;
19250 tcg_temp_free_i32(twd);
19251 tcg_temp_free_i32(tws);
19252 tcg_temp_free_i32(twt);
19253 tcg_temp_free_i32(tdf);
19256 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
19258 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
19259 (op & (0xf << 17)))
19260 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19261 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19262 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19263 uint8_t df = (ctx->opcode >> 16) & 0x1;
19264 TCGv_i32 twd = tcg_const_i32(wd);
19265 TCGv_i32 tws = tcg_const_i32(ws);
19266 TCGv_i32 twt = tcg_const_i32(wt);
19267 /* adjust df value for floating-point instruction */
19268 TCGv_i32 tdf = tcg_const_i32(df + 2);
19270 switch (MASK_MSA_2RF(ctx->opcode)) {
19271 case OPC_FCLASS_df:
19272 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
19273 break;
19274 case OPC_FTRUNC_S_df:
19275 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
19276 break;
19277 case OPC_FTRUNC_U_df:
19278 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
19279 break;
19280 case OPC_FSQRT_df:
19281 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
19282 break;
19283 case OPC_FRSQRT_df:
19284 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
19285 break;
19286 case OPC_FRCP_df:
19287 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
19288 break;
19289 case OPC_FRINT_df:
19290 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
19291 break;
19292 case OPC_FLOG2_df:
19293 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
19294 break;
19295 case OPC_FEXUPL_df:
19296 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
19297 break;
19298 case OPC_FEXUPR_df:
19299 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
19300 break;
19301 case OPC_FFQL_df:
19302 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
19303 break;
19304 case OPC_FFQR_df:
19305 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
19306 break;
19307 case OPC_FTINT_S_df:
19308 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
19309 break;
19310 case OPC_FTINT_U_df:
19311 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
19312 break;
19313 case OPC_FFINT_S_df:
19314 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
19315 break;
19316 case OPC_FFINT_U_df:
19317 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
19318 break;
19321 tcg_temp_free_i32(twd);
19322 tcg_temp_free_i32(tws);
19323 tcg_temp_free_i32(twt);
19324 tcg_temp_free_i32(tdf);
19327 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
19329 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
19330 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19331 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19332 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19333 TCGv_i32 twd = tcg_const_i32(wd);
19334 TCGv_i32 tws = tcg_const_i32(ws);
19335 TCGv_i32 twt = tcg_const_i32(wt);
19337 switch (MASK_MSA_VEC(ctx->opcode)) {
19338 case OPC_AND_V:
19339 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
19340 break;
19341 case OPC_OR_V:
19342 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
19343 break;
19344 case OPC_NOR_V:
19345 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
19346 break;
19347 case OPC_XOR_V:
19348 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
19349 break;
19350 case OPC_BMNZ_V:
19351 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
19352 break;
19353 case OPC_BMZ_V:
19354 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
19355 break;
19356 case OPC_BSEL_V:
19357 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
19358 break;
19359 default:
19360 MIPS_INVAL("MSA instruction");
19361 generate_exception(ctx, EXCP_RI);
19362 break;
19365 tcg_temp_free_i32(twd);
19366 tcg_temp_free_i32(tws);
19367 tcg_temp_free_i32(twt);
19370 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
19372 switch (MASK_MSA_VEC(ctx->opcode)) {
19373 case OPC_AND_V:
19374 case OPC_OR_V:
19375 case OPC_NOR_V:
19376 case OPC_XOR_V:
19377 case OPC_BMNZ_V:
19378 case OPC_BMZ_V:
19379 case OPC_BSEL_V:
19380 gen_msa_vec_v(env, ctx);
19381 break;
19382 case OPC_MSA_2R:
19383 gen_msa_2r(env, ctx);
19384 break;
19385 case OPC_MSA_2RF:
19386 gen_msa_2rf(env, ctx);
19387 break;
19388 default:
19389 MIPS_INVAL("MSA instruction");
19390 generate_exception(ctx, EXCP_RI);
19391 break;
19395 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
19397 uint32_t opcode = ctx->opcode;
19398 check_insn(ctx, ASE_MSA);
19399 check_msa_access(ctx);
19401 switch (MASK_MSA_MINOR(opcode)) {
19402 case OPC_MSA_I8_00:
19403 case OPC_MSA_I8_01:
19404 case OPC_MSA_I8_02:
19405 gen_msa_i8(env, ctx);
19406 break;
19407 case OPC_MSA_I5_06:
19408 case OPC_MSA_I5_07:
19409 gen_msa_i5(env, ctx);
19410 break;
19411 case OPC_MSA_BIT_09:
19412 case OPC_MSA_BIT_0A:
19413 gen_msa_bit(env, ctx);
19414 break;
19415 case OPC_MSA_3R_0D:
19416 case OPC_MSA_3R_0E:
19417 case OPC_MSA_3R_0F:
19418 case OPC_MSA_3R_10:
19419 case OPC_MSA_3R_11:
19420 case OPC_MSA_3R_12:
19421 case OPC_MSA_3R_13:
19422 case OPC_MSA_3R_14:
19423 case OPC_MSA_3R_15:
19424 gen_msa_3r(env, ctx);
19425 break;
19426 case OPC_MSA_ELM:
19427 gen_msa_elm(env, ctx);
19428 break;
19429 case OPC_MSA_3RF_1A:
19430 case OPC_MSA_3RF_1B:
19431 case OPC_MSA_3RF_1C:
19432 gen_msa_3rf(env, ctx);
19433 break;
19434 case OPC_MSA_VEC:
19435 gen_msa_vec(env, ctx);
19436 break;
19437 case OPC_LD_B:
19438 case OPC_LD_H:
19439 case OPC_LD_W:
19440 case OPC_LD_D:
19441 case OPC_ST_B:
19442 case OPC_ST_H:
19443 case OPC_ST_W:
19444 case OPC_ST_D:
19446 int32_t s10 = sextract32(ctx->opcode, 16, 10);
19447 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
19448 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19449 uint8_t df = (ctx->opcode >> 0) & 0x3;
19451 TCGv_i32 twd = tcg_const_i32(wd);
19452 TCGv taddr = tcg_temp_new();
19453 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
19455 switch (MASK_MSA_MINOR(opcode)) {
19456 case OPC_LD_B:
19457 gen_helper_msa_ld_b(cpu_env, twd, taddr);
19458 break;
19459 case OPC_LD_H:
19460 gen_helper_msa_ld_h(cpu_env, twd, taddr);
19461 break;
19462 case OPC_LD_W:
19463 gen_helper_msa_ld_w(cpu_env, twd, taddr);
19464 break;
19465 case OPC_LD_D:
19466 gen_helper_msa_ld_d(cpu_env, twd, taddr);
19467 break;
19468 case OPC_ST_B:
19469 gen_helper_msa_st_b(cpu_env, twd, taddr);
19470 break;
19471 case OPC_ST_H:
19472 gen_helper_msa_st_h(cpu_env, twd, taddr);
19473 break;
19474 case OPC_ST_W:
19475 gen_helper_msa_st_w(cpu_env, twd, taddr);
19476 break;
19477 case OPC_ST_D:
19478 gen_helper_msa_st_d(cpu_env, twd, taddr);
19479 break;
19482 tcg_temp_free_i32(twd);
19483 tcg_temp_free(taddr);
19485 break;
19486 default:
19487 MIPS_INVAL("MSA instruction");
19488 generate_exception(ctx, EXCP_RI);
19489 break;
19494 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
19496 int32_t offset;
19497 int rs, rt, rd, sa;
19498 uint32_t op, op1;
19499 int16_t imm;
19501 /* make sure instructions are on a word boundary */
19502 if (ctx->pc & 0x3) {
19503 env->CP0_BadVAddr = ctx->pc;
19504 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
19505 ctx->bstate = BS_STOP;
19506 return;
19509 /* Handle blikely not taken case */
19510 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
19511 TCGLabel *l1 = gen_new_label();
19513 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
19514 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
19515 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
19516 gen_goto_tb(ctx, 1, ctx->pc + 4);
19517 gen_set_label(l1);
19520 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
19521 tcg_gen_debug_insn_start(ctx->pc);
19524 op = MASK_OP_MAJOR(ctx->opcode);
19525 rs = (ctx->opcode >> 21) & 0x1f;
19526 rt = (ctx->opcode >> 16) & 0x1f;
19527 rd = (ctx->opcode >> 11) & 0x1f;
19528 sa = (ctx->opcode >> 6) & 0x1f;
19529 imm = (int16_t)ctx->opcode;
19530 switch (op) {
19531 case OPC_SPECIAL:
19532 decode_opc_special(env, ctx);
19533 break;
19534 case OPC_SPECIAL2:
19535 decode_opc_special2_legacy(env, ctx);
19536 break;
19537 case OPC_SPECIAL3:
19538 decode_opc_special3(env, ctx);
19539 break;
19540 case OPC_REGIMM:
19541 op1 = MASK_REGIMM(ctx->opcode);
19542 switch (op1) {
19543 case OPC_BLTZL: /* REGIMM branches */
19544 case OPC_BGEZL:
19545 case OPC_BLTZALL:
19546 case OPC_BGEZALL:
19547 check_insn(ctx, ISA_MIPS2);
19548 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19549 /* Fallthrough */
19550 case OPC_BLTZ:
19551 case OPC_BGEZ:
19552 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19553 break;
19554 case OPC_BLTZAL:
19555 case OPC_BGEZAL:
19556 if (ctx->insn_flags & ISA_MIPS32R6) {
19557 if (rs == 0) {
19558 /* OPC_NAL, OPC_BAL */
19559 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
19560 } else {
19561 generate_exception(ctx, EXCP_RI);
19563 } else {
19564 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19566 break;
19567 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
19568 case OPC_TNEI:
19569 check_insn(ctx, ISA_MIPS2);
19570 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19571 gen_trap(ctx, op1, rs, -1, imm);
19572 break;
19573 case OPC_SYNCI:
19574 check_insn(ctx, ISA_MIPS32R2);
19575 /* Break the TB to be able to sync copied instructions
19576 immediately */
19577 ctx->bstate = BS_STOP;
19578 break;
19579 case OPC_BPOSGE32: /* MIPS DSP branch */
19580 #if defined(TARGET_MIPS64)
19581 case OPC_BPOSGE64:
19582 #endif
19583 check_dsp(ctx);
19584 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
19585 break;
19586 #if defined(TARGET_MIPS64)
19587 case OPC_DAHI:
19588 check_insn(ctx, ISA_MIPS32R6);
19589 check_mips_64(ctx);
19590 if (rs != 0) {
19591 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
19593 MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm);
19594 break;
19595 case OPC_DATI:
19596 check_insn(ctx, ISA_MIPS32R6);
19597 check_mips_64(ctx);
19598 if (rs != 0) {
19599 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
19601 MIPS_DEBUG("dati %s, %04x", regnames[rs], imm);
19602 break;
19603 #endif
19604 default: /* Invalid */
19605 MIPS_INVAL("regimm");
19606 generate_exception(ctx, EXCP_RI);
19607 break;
19609 break;
19610 case OPC_CP0:
19611 check_cp0_enabled(ctx);
19612 op1 = MASK_CP0(ctx->opcode);
19613 switch (op1) {
19614 case OPC_MFC0:
19615 case OPC_MTC0:
19616 case OPC_MFTR:
19617 case OPC_MTTR:
19618 case OPC_MFHC0:
19619 case OPC_MTHC0:
19620 #if defined(TARGET_MIPS64)
19621 case OPC_DMFC0:
19622 case OPC_DMTC0:
19623 #endif
19624 #ifndef CONFIG_USER_ONLY
19625 gen_cp0(env, ctx, op1, rt, rd);
19626 #endif /* !CONFIG_USER_ONLY */
19627 break;
19628 case OPC_C0_FIRST ... OPC_C0_LAST:
19629 #ifndef CONFIG_USER_ONLY
19630 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
19631 #endif /* !CONFIG_USER_ONLY */
19632 break;
19633 case OPC_MFMC0:
19634 #ifndef CONFIG_USER_ONLY
19636 uint32_t op2;
19637 TCGv t0 = tcg_temp_new();
19639 op2 = MASK_MFMC0(ctx->opcode);
19640 switch (op2) {
19641 case OPC_DMT:
19642 check_insn(ctx, ASE_MT);
19643 gen_helper_dmt(t0);
19644 gen_store_gpr(t0, rt);
19645 break;
19646 case OPC_EMT:
19647 check_insn(ctx, ASE_MT);
19648 gen_helper_emt(t0);
19649 gen_store_gpr(t0, rt);
19650 break;
19651 case OPC_DVPE:
19652 check_insn(ctx, ASE_MT);
19653 gen_helper_dvpe(t0, cpu_env);
19654 gen_store_gpr(t0, rt);
19655 break;
19656 case OPC_EVPE:
19657 check_insn(ctx, ASE_MT);
19658 gen_helper_evpe(t0, cpu_env);
19659 gen_store_gpr(t0, rt);
19660 break;
19661 case OPC_DI:
19662 check_insn(ctx, ISA_MIPS32R2);
19663 save_cpu_state(ctx, 1);
19664 gen_helper_di(t0, cpu_env);
19665 gen_store_gpr(t0, rt);
19666 /* Stop translation as we may have switched
19667 the execution mode. */
19668 ctx->bstate = BS_STOP;
19669 break;
19670 case OPC_EI:
19671 check_insn(ctx, ISA_MIPS32R2);
19672 save_cpu_state(ctx, 1);
19673 gen_helper_ei(t0, cpu_env);
19674 gen_store_gpr(t0, rt);
19675 /* Stop translation as we may have switched
19676 the execution mode. */
19677 ctx->bstate = BS_STOP;
19678 break;
19679 default: /* Invalid */
19680 MIPS_INVAL("mfmc0");
19681 generate_exception(ctx, EXCP_RI);
19682 break;
19684 tcg_temp_free(t0);
19686 #endif /* !CONFIG_USER_ONLY */
19687 break;
19688 case OPC_RDPGPR:
19689 check_insn(ctx, ISA_MIPS32R2);
19690 gen_load_srsgpr(rt, rd);
19691 break;
19692 case OPC_WRPGPR:
19693 check_insn(ctx, ISA_MIPS32R2);
19694 gen_store_srsgpr(rt, rd);
19695 break;
19696 default:
19697 MIPS_INVAL("cp0");
19698 generate_exception(ctx, EXCP_RI);
19699 break;
19701 break;
19702 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
19703 if (ctx->insn_flags & ISA_MIPS32R6) {
19704 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
19705 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19706 } else {
19707 /* OPC_ADDI */
19708 /* Arithmetic with immediate opcode */
19709 gen_arith_imm(ctx, op, rt, rs, imm);
19711 break;
19712 case OPC_ADDIU:
19713 gen_arith_imm(ctx, op, rt, rs, imm);
19714 break;
19715 case OPC_SLTI: /* Set on less than with immediate opcode */
19716 case OPC_SLTIU:
19717 gen_slt_imm(ctx, op, rt, rs, imm);
19718 break;
19719 case OPC_ANDI: /* Arithmetic with immediate opcode */
19720 case OPC_LUI: /* OPC_AUI */
19721 case OPC_ORI:
19722 case OPC_XORI:
19723 gen_logic_imm(ctx, op, rt, rs, imm);
19724 break;
19725 case OPC_J ... OPC_JAL: /* Jump */
19726 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19727 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19728 break;
19729 /* Branch */
19730 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
19731 if (ctx->insn_flags & ISA_MIPS32R6) {
19732 if (rt == 0) {
19733 generate_exception(ctx, EXCP_RI);
19734 break;
19736 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
19737 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19738 } else {
19739 /* OPC_BLEZL */
19740 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19742 break;
19743 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
19744 if (ctx->insn_flags & ISA_MIPS32R6) {
19745 if (rt == 0) {
19746 generate_exception(ctx, EXCP_RI);
19747 break;
19749 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
19750 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19751 } else {
19752 /* OPC_BGTZL */
19753 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19755 break;
19756 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
19757 if (rt == 0) {
19758 /* OPC_BLEZ */
19759 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19760 } else {
19761 check_insn(ctx, ISA_MIPS32R6);
19762 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
19763 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19765 break;
19766 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
19767 if (rt == 0) {
19768 /* OPC_BGTZ */
19769 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19770 } else {
19771 check_insn(ctx, ISA_MIPS32R6);
19772 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
19773 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19775 break;
19776 case OPC_BEQL:
19777 case OPC_BNEL:
19778 check_insn(ctx, ISA_MIPS2);
19779 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19780 /* Fallthrough */
19781 case OPC_BEQ:
19782 case OPC_BNE:
19783 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19784 break;
19785 case OPC_LL: /* Load and stores */
19786 check_insn(ctx, ISA_MIPS2);
19787 /* Fallthrough */
19788 case OPC_LWL:
19789 case OPC_LWR:
19790 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19791 /* Fallthrough */
19792 case OPC_LB ... OPC_LH:
19793 case OPC_LW ... OPC_LHU:
19794 gen_ld(ctx, op, rt, rs, imm);
19795 break;
19796 case OPC_SWL:
19797 case OPC_SWR:
19798 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19799 /* fall through */
19800 case OPC_SB ... OPC_SH:
19801 case OPC_SW:
19802 gen_st(ctx, op, rt, rs, imm);
19803 break;
19804 case OPC_SC:
19805 check_insn(ctx, ISA_MIPS2);
19806 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19807 gen_st_cond(ctx, op, rt, rs, imm);
19808 break;
19809 case OPC_CACHE:
19810 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19811 check_cp0_enabled(ctx);
19812 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
19813 /* Treat as NOP. */
19814 break;
19815 case OPC_PREF:
19816 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19817 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
19818 /* Treat as NOP. */
19819 break;
19821 /* Floating point (COP1). */
19822 case OPC_LWC1:
19823 case OPC_LDC1:
19824 case OPC_SWC1:
19825 case OPC_SDC1:
19826 gen_cop1_ldst(ctx, op, rt, rs, imm);
19827 break;
19829 case OPC_CP1:
19830 op1 = MASK_CP1(ctx->opcode);
19832 switch (op1) {
19833 case OPC_MFHC1:
19834 case OPC_MTHC1:
19835 check_cp1_enabled(ctx);
19836 check_insn(ctx, ISA_MIPS32R2);
19837 case OPC_MFC1:
19838 case OPC_CFC1:
19839 case OPC_MTC1:
19840 case OPC_CTC1:
19841 check_cp1_enabled(ctx);
19842 gen_cp1(ctx, op1, rt, rd);
19843 break;
19844 #if defined(TARGET_MIPS64)
19845 case OPC_DMFC1:
19846 case OPC_DMTC1:
19847 check_cp1_enabled(ctx);
19848 check_insn(ctx, ISA_MIPS3);
19849 check_mips_64(ctx);
19850 gen_cp1(ctx, op1, rt, rd);
19851 break;
19852 #endif
19853 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
19854 check_cp1_enabled(ctx);
19855 if (ctx->insn_flags & ISA_MIPS32R6) {
19856 /* OPC_BC1EQZ */
19857 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19858 rt, imm << 2, 4);
19859 } else {
19860 /* OPC_BC1ANY2 */
19861 check_cop1x(ctx);
19862 check_insn(ctx, ASE_MIPS3D);
19863 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19864 (rt >> 2) & 0x7, imm << 2);
19866 break;
19867 case OPC_BC1NEZ:
19868 check_cp1_enabled(ctx);
19869 check_insn(ctx, ISA_MIPS32R6);
19870 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19871 rt, imm << 2, 4);
19872 break;
19873 case OPC_BC1ANY4:
19874 check_cp1_enabled(ctx);
19875 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19876 check_cop1x(ctx);
19877 check_insn(ctx, ASE_MIPS3D);
19878 /* fall through */
19879 case OPC_BC1:
19880 check_cp1_enabled(ctx);
19881 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19882 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19883 (rt >> 2) & 0x7, imm << 2);
19884 break;
19885 case OPC_PS_FMT:
19886 check_ps(ctx);
19887 /* fall through */
19888 case OPC_S_FMT:
19889 case OPC_D_FMT:
19890 check_cp1_enabled(ctx);
19891 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19892 (imm >> 8) & 0x7);
19893 break;
19894 case OPC_W_FMT:
19895 case OPC_L_FMT:
19897 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
19898 check_cp1_enabled(ctx);
19899 if (ctx->insn_flags & ISA_MIPS32R6) {
19900 switch (r6_op) {
19901 case R6_OPC_CMP_AF_S:
19902 case R6_OPC_CMP_UN_S:
19903 case R6_OPC_CMP_EQ_S:
19904 case R6_OPC_CMP_UEQ_S:
19905 case R6_OPC_CMP_LT_S:
19906 case R6_OPC_CMP_ULT_S:
19907 case R6_OPC_CMP_LE_S:
19908 case R6_OPC_CMP_ULE_S:
19909 case R6_OPC_CMP_SAF_S:
19910 case R6_OPC_CMP_SUN_S:
19911 case R6_OPC_CMP_SEQ_S:
19912 case R6_OPC_CMP_SEUQ_S:
19913 case R6_OPC_CMP_SLT_S:
19914 case R6_OPC_CMP_SULT_S:
19915 case R6_OPC_CMP_SLE_S:
19916 case R6_OPC_CMP_SULE_S:
19917 case R6_OPC_CMP_OR_S:
19918 case R6_OPC_CMP_UNE_S:
19919 case R6_OPC_CMP_NE_S:
19920 case R6_OPC_CMP_SOR_S:
19921 case R6_OPC_CMP_SUNE_S:
19922 case R6_OPC_CMP_SNE_S:
19923 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19924 break;
19925 case R6_OPC_CMP_AF_D:
19926 case R6_OPC_CMP_UN_D:
19927 case R6_OPC_CMP_EQ_D:
19928 case R6_OPC_CMP_UEQ_D:
19929 case R6_OPC_CMP_LT_D:
19930 case R6_OPC_CMP_ULT_D:
19931 case R6_OPC_CMP_LE_D:
19932 case R6_OPC_CMP_ULE_D:
19933 case R6_OPC_CMP_SAF_D:
19934 case R6_OPC_CMP_SUN_D:
19935 case R6_OPC_CMP_SEQ_D:
19936 case R6_OPC_CMP_SEUQ_D:
19937 case R6_OPC_CMP_SLT_D:
19938 case R6_OPC_CMP_SULT_D:
19939 case R6_OPC_CMP_SLE_D:
19940 case R6_OPC_CMP_SULE_D:
19941 case R6_OPC_CMP_OR_D:
19942 case R6_OPC_CMP_UNE_D:
19943 case R6_OPC_CMP_NE_D:
19944 case R6_OPC_CMP_SOR_D:
19945 case R6_OPC_CMP_SUNE_D:
19946 case R6_OPC_CMP_SNE_D:
19947 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19948 break;
19949 default:
19950 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
19951 rt, rd, sa, (imm >> 8) & 0x7);
19953 break;
19955 } else {
19956 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19957 (imm >> 8) & 0x7);
19959 break;
19961 case OPC_BZ_V:
19962 case OPC_BNZ_V:
19963 case OPC_BZ_B:
19964 case OPC_BZ_H:
19965 case OPC_BZ_W:
19966 case OPC_BZ_D:
19967 case OPC_BNZ_B:
19968 case OPC_BNZ_H:
19969 case OPC_BNZ_W:
19970 case OPC_BNZ_D:
19971 check_insn(ctx, ASE_MSA);
19972 gen_msa_branch(env, ctx, op1);
19973 break;
19974 default:
19975 MIPS_INVAL("cp1");
19976 generate_exception(ctx, EXCP_RI);
19977 break;
19979 break;
19981 /* Compact branches [R6] and COP2 [non-R6] */
19982 case OPC_BC: /* OPC_LWC2 */
19983 case OPC_BALC: /* OPC_SWC2 */
19984 if (ctx->insn_flags & ISA_MIPS32R6) {
19985 /* OPC_BC, OPC_BALC */
19986 gen_compute_compact_branch(ctx, op, 0, 0,
19987 sextract32(ctx->opcode << 2, 0, 28));
19988 } else {
19989 /* OPC_LWC2, OPC_SWC2 */
19990 /* COP2: Not implemented. */
19991 generate_exception_err(ctx, EXCP_CpU, 2);
19993 break;
19994 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
19995 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
19996 if (ctx->insn_flags & ISA_MIPS32R6) {
19997 if (rs != 0) {
19998 /* OPC_BEQZC, OPC_BNEZC */
19999 gen_compute_compact_branch(ctx, op, rs, 0,
20000 sextract32(ctx->opcode << 2, 0, 23));
20001 } else {
20002 /* OPC_JIC, OPC_JIALC */
20003 gen_compute_compact_branch(ctx, op, 0, rt, imm);
20005 } else {
20006 /* OPC_LWC2, OPC_SWC2 */
20007 /* COP2: Not implemented. */
20008 generate_exception_err(ctx, EXCP_CpU, 2);
20010 break;
20011 case OPC_CP2:
20012 check_insn(ctx, INSN_LOONGSON2F);
20013 /* Note that these instructions use different fields. */
20014 gen_loongson_multimedia(ctx, sa, rd, rt);
20015 break;
20017 case OPC_CP3:
20018 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20019 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20020 check_cp1_enabled(ctx);
20021 op1 = MASK_CP3(ctx->opcode);
20022 switch (op1) {
20023 case OPC_LUXC1:
20024 case OPC_SUXC1:
20025 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
20026 /* Fallthrough */
20027 case OPC_LWXC1:
20028 case OPC_LDXC1:
20029 case OPC_SWXC1:
20030 case OPC_SDXC1:
20031 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20032 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
20033 break;
20034 case OPC_PREFX:
20035 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20036 /* Treat as NOP. */
20037 break;
20038 case OPC_ALNV_PS:
20039 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
20040 /* Fallthrough */
20041 case OPC_MADD_S:
20042 case OPC_MADD_D:
20043 case OPC_MADD_PS:
20044 case OPC_MSUB_S:
20045 case OPC_MSUB_D:
20046 case OPC_MSUB_PS:
20047 case OPC_NMADD_S:
20048 case OPC_NMADD_D:
20049 case OPC_NMADD_PS:
20050 case OPC_NMSUB_S:
20051 case OPC_NMSUB_D:
20052 case OPC_NMSUB_PS:
20053 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20054 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
20055 break;
20056 default:
20057 MIPS_INVAL("cp3");
20058 generate_exception (ctx, EXCP_RI);
20059 break;
20061 } else {
20062 generate_exception_err(ctx, EXCP_CpU, 1);
20064 break;
20066 #if defined(TARGET_MIPS64)
20067 /* MIPS64 opcodes */
20068 case OPC_LDL ... OPC_LDR:
20069 case OPC_LLD:
20070 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20071 /* fall through */
20072 case OPC_LWU:
20073 case OPC_LD:
20074 check_insn(ctx, ISA_MIPS3);
20075 check_mips_64(ctx);
20076 gen_ld(ctx, op, rt, rs, imm);
20077 break;
20078 case OPC_SDL ... OPC_SDR:
20079 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20080 /* fall through */
20081 case OPC_SD:
20082 check_insn(ctx, ISA_MIPS3);
20083 check_mips_64(ctx);
20084 gen_st(ctx, op, rt, rs, imm);
20085 break;
20086 case OPC_SCD:
20087 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20088 check_insn(ctx, ISA_MIPS3);
20089 check_mips_64(ctx);
20090 gen_st_cond(ctx, op, rt, rs, imm);
20091 break;
20092 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
20093 if (ctx->insn_flags & ISA_MIPS32R6) {
20094 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
20095 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
20096 } else {
20097 /* OPC_DADDI */
20098 check_insn(ctx, ISA_MIPS3);
20099 check_mips_64(ctx);
20100 gen_arith_imm(ctx, op, rt, rs, imm);
20102 break;
20103 case OPC_DADDIU:
20104 check_insn(ctx, ISA_MIPS3);
20105 check_mips_64(ctx);
20106 gen_arith_imm(ctx, op, rt, rs, imm);
20107 break;
20108 #else
20109 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
20110 if (ctx->insn_flags & ISA_MIPS32R6) {
20111 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
20112 } else {
20113 MIPS_INVAL("major opcode");
20114 generate_exception(ctx, EXCP_RI);
20116 break;
20117 #endif
20118 case OPC_DAUI: /* OPC_JALX */
20119 if (ctx->insn_flags & ISA_MIPS32R6) {
20120 #if defined(TARGET_MIPS64)
20121 /* OPC_DAUI */
20122 check_mips_64(ctx);
20123 if (rt != 0) {
20124 TCGv t0 = tcg_temp_new();
20125 gen_load_gpr(t0, rs);
20126 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
20127 tcg_temp_free(t0);
20129 MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm);
20130 #else
20131 generate_exception(ctx, EXCP_RI);
20132 MIPS_INVAL("major opcode");
20133 #endif
20134 } else {
20135 /* OPC_JALX */
20136 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
20137 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
20138 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
20140 break;
20141 case OPC_MSA: /* OPC_MDMX */
20142 /* MDMX: Not implemented. */
20143 gen_msa(env, ctx);
20144 break;
20145 case OPC_PCREL:
20146 check_insn(ctx, ISA_MIPS32R6);
20147 gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
20148 break;
20149 default: /* Invalid */
20150 MIPS_INVAL("major opcode");
20151 generate_exception(ctx, EXCP_RI);
20152 break;
20156 static inline void
20157 gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
20158 bool search_pc)
20160 CPUState *cs = CPU(cpu);
20161 CPUMIPSState *env = &cpu->env;
20162 DisasContext ctx;
20163 target_ulong pc_start;
20164 target_ulong next_page_start;
20165 CPUBreakpoint *bp;
20166 int j, lj = -1;
20167 int num_insns;
20168 int max_insns;
20169 int insn_bytes;
20170 int is_slot;
20172 if (search_pc)
20173 qemu_log("search pc %d\n", search_pc);
20175 pc_start = tb->pc;
20176 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
20177 ctx.pc = pc_start;
20178 ctx.saved_pc = -1;
20179 ctx.singlestep_enabled = cs->singlestep_enabled;
20180 ctx.insn_flags = env->insn_flags;
20181 ctx.CP0_Config1 = env->CP0_Config1;
20182 ctx.tb = tb;
20183 ctx.bstate = BS_NONE;
20184 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
20185 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
20186 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
20187 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
20188 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
20189 ctx.PAMask = env->PAMask;
20190 ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
20191 ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
20192 /* Restore delay slot state from the tb context. */
20193 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
20194 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
20195 ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
20196 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
20197 restore_cpu_state(env, &ctx);
20198 #ifdef CONFIG_USER_ONLY
20199 ctx.mem_idx = MIPS_HFLAG_UM;
20200 #else
20201 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
20202 #endif
20203 ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
20204 MO_UNALN : MO_ALIGN;
20205 num_insns = 0;
20206 max_insns = tb->cflags & CF_COUNT_MASK;
20207 if (max_insns == 0)
20208 max_insns = CF_COUNT_MASK;
20209 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
20210 gen_tb_start(tb);
20211 while (ctx.bstate == BS_NONE) {
20212 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
20213 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
20214 if (bp->pc == ctx.pc) {
20215 save_cpu_state(&ctx, 1);
20216 ctx.bstate = BS_BRANCH;
20217 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
20218 /* Include the breakpoint location or the tb won't
20219 * be flushed when it must be. */
20220 ctx.pc += 4;
20221 goto done_generating;
20226 if (search_pc) {
20227 j = tcg_op_buf_count();
20228 if (lj < j) {
20229 lj++;
20230 while (lj < j)
20231 tcg_ctx.gen_opc_instr_start[lj++] = 0;
20233 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
20234 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
20235 gen_opc_btarget[lj] = ctx.btarget;
20236 tcg_ctx.gen_opc_instr_start[lj] = 1;
20237 tcg_ctx.gen_opc_icount[lj] = num_insns;
20239 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
20240 gen_io_start();
20242 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
20243 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
20244 ctx.opcode = cpu_ldl_code(env, ctx.pc);
20245 insn_bytes = 4;
20246 decode_opc(env, &ctx);
20247 } else if (ctx.insn_flags & ASE_MICROMIPS) {
20248 ctx.opcode = cpu_lduw_code(env, ctx.pc);
20249 insn_bytes = decode_micromips_opc(env, &ctx);
20250 } else if (ctx.insn_flags & ASE_MIPS16) {
20251 ctx.opcode = cpu_lduw_code(env, ctx.pc);
20252 insn_bytes = decode_mips16_opc(env, &ctx);
20253 } else {
20254 generate_exception(&ctx, EXCP_RI);
20255 ctx.bstate = BS_STOP;
20256 break;
20259 if (ctx.hflags & MIPS_HFLAG_BMASK) {
20260 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
20261 MIPS_HFLAG_FBNSLOT))) {
20262 /* force to generate branch as there is neither delay nor
20263 forbidden slot */
20264 is_slot = 1;
20266 if ((ctx.hflags & MIPS_HFLAG_M16) &&
20267 (ctx.hflags & MIPS_HFLAG_FBNSLOT)) {
20268 /* Force to generate branch as microMIPS R6 doesn't restrict
20269 branches in the forbidden slot. */
20270 is_slot = 1;
20273 if (is_slot) {
20274 gen_branch(&ctx, insn_bytes);
20276 ctx.pc += insn_bytes;
20278 num_insns++;
20280 /* Execute a branch and its delay slot as a single instruction.
20281 This is what GDB expects and is consistent with what the
20282 hardware does (e.g. if a delay slot instruction faults, the
20283 reported PC is the PC of the branch). */
20284 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
20285 break;
20288 if (ctx.pc >= next_page_start) {
20289 break;
20292 if (tcg_op_buf_full()) {
20293 break;
20296 if (num_insns >= max_insns)
20297 break;
20299 if (singlestep)
20300 break;
20302 if (tb->cflags & CF_LAST_IO) {
20303 gen_io_end();
20305 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
20306 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
20307 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
20308 } else {
20309 switch (ctx.bstate) {
20310 case BS_STOP:
20311 gen_goto_tb(&ctx, 0, ctx.pc);
20312 break;
20313 case BS_NONE:
20314 save_cpu_state(&ctx, 0);
20315 gen_goto_tb(&ctx, 0, ctx.pc);
20316 break;
20317 case BS_EXCP:
20318 tcg_gen_exit_tb(0);
20319 break;
20320 case BS_BRANCH:
20321 default:
20322 break;
20325 done_generating:
20326 gen_tb_end(tb, num_insns);
20328 if (search_pc) {
20329 j = tcg_op_buf_count();
20330 lj++;
20331 while (lj <= j)
20332 tcg_ctx.gen_opc_instr_start[lj++] = 0;
20333 } else {
20334 tb->size = ctx.pc - pc_start;
20335 tb->icount = num_insns;
20337 #ifdef DEBUG_DISAS
20338 LOG_DISAS("\n");
20339 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
20340 qemu_log("IN: %s\n", lookup_symbol(pc_start));
20341 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
20342 qemu_log("\n");
20344 #endif
20347 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
20349 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
20352 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
20354 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
20357 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
20358 int flags)
20360 int i;
20361 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
20363 #define printfpr(fp) \
20364 do { \
20365 if (is_fpu64) \
20366 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20367 " fd:%13g fs:%13g psu: %13g\n", \
20368 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
20369 (double)(fp)->fd, \
20370 (double)(fp)->fs[FP_ENDIAN_IDX], \
20371 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
20372 else { \
20373 fpr_t tmp; \
20374 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
20375 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
20376 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20377 " fd:%13g fs:%13g psu:%13g\n", \
20378 tmp.w[FP_ENDIAN_IDX], tmp.d, \
20379 (double)tmp.fd, \
20380 (double)tmp.fs[FP_ENDIAN_IDX], \
20381 (double)tmp.fs[!FP_ENDIAN_IDX]); \
20383 } while(0)
20386 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
20387 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
20388 get_float_exception_flags(&env->active_fpu.fp_status));
20389 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
20390 fpu_fprintf(f, "%3s: ", fregnames[i]);
20391 printfpr(&env->active_fpu.fpr[i]);
20394 #undef printfpr
20397 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
20398 /* Debug help: The architecture requires 32bit code to maintain proper
20399 sign-extended values on 64bit machines. */
20401 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
20403 static void
20404 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
20405 fprintf_function cpu_fprintf,
20406 int flags)
20408 int i;
20410 if (!SIGN_EXT_P(env->active_tc.PC))
20411 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
20412 if (!SIGN_EXT_P(env->active_tc.HI[0]))
20413 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
20414 if (!SIGN_EXT_P(env->active_tc.LO[0]))
20415 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
20416 if (!SIGN_EXT_P(env->btarget))
20417 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
20419 for (i = 0; i < 32; i++) {
20420 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
20421 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
20424 if (!SIGN_EXT_P(env->CP0_EPC))
20425 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
20426 if (!SIGN_EXT_P(env->lladdr))
20427 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
20429 #endif
20431 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
20432 int flags)
20434 MIPSCPU *cpu = MIPS_CPU(cs);
20435 CPUMIPSState *env = &cpu->env;
20436 int i;
20438 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
20439 " LO=0x" TARGET_FMT_lx " ds %04x "
20440 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
20441 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
20442 env->hflags, env->btarget, env->bcond);
20443 for (i = 0; i < 32; i++) {
20444 if ((i & 3) == 0)
20445 cpu_fprintf(f, "GPR%02d:", i);
20446 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
20447 if ((i & 3) == 3)
20448 cpu_fprintf(f, "\n");
20451 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
20452 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
20453 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
20454 PRIx64 "\n",
20455 env->CP0_Config0, env->CP0_Config1, env->lladdr);
20456 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
20457 env->CP0_Config2, env->CP0_Config3);
20458 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
20459 env->CP0_Config4, env->CP0_Config5);
20460 if (env->hflags & MIPS_HFLAG_FPU)
20461 fpu_dump_state(env, f, cpu_fprintf, flags);
20462 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
20463 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
20464 #endif
20467 void mips_tcg_init(void)
20469 int i;
20470 static int inited;
20472 /* Initialize various static tables. */
20473 if (inited)
20474 return;
20476 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
20477 TCGV_UNUSED(cpu_gpr[0]);
20478 for (i = 1; i < 32; i++)
20479 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
20480 offsetof(CPUMIPSState, active_tc.gpr[i]),
20481 regnames[i]);
20483 for (i = 0; i < 32; i++) {
20484 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
20485 msa_wr_d[i * 2] =
20486 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]);
20487 /* The scalar floating-point unit (FPU) registers are mapped on
20488 * the MSA vector registers. */
20489 fpu_f64[i] = msa_wr_d[i * 2];
20490 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
20491 msa_wr_d[i * 2 + 1] =
20492 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + 1]);
20495 cpu_PC = tcg_global_mem_new(TCG_AREG0,
20496 offsetof(CPUMIPSState, active_tc.PC), "PC");
20497 for (i = 0; i < MIPS_DSP_ACC; i++) {
20498 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
20499 offsetof(CPUMIPSState, active_tc.HI[i]),
20500 regnames_HI[i]);
20501 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
20502 offsetof(CPUMIPSState, active_tc.LO[i]),
20503 regnames_LO[i]);
20505 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
20506 offsetof(CPUMIPSState, active_tc.DSPControl),
20507 "DSPControl");
20508 bcond = tcg_global_mem_new(TCG_AREG0,
20509 offsetof(CPUMIPSState, bcond), "bcond");
20510 btarget = tcg_global_mem_new(TCG_AREG0,
20511 offsetof(CPUMIPSState, btarget), "btarget");
20512 hflags = tcg_global_mem_new_i32(TCG_AREG0,
20513 offsetof(CPUMIPSState, hflags), "hflags");
20515 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
20516 offsetof(CPUMIPSState, active_fpu.fcr0),
20517 "fcr0");
20518 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
20519 offsetof(CPUMIPSState, active_fpu.fcr31),
20520 "fcr31");
20522 inited = 1;
20525 #include "translate_init.c"
20527 MIPSCPU *cpu_mips_init(const char *cpu_model)
20529 MIPSCPU *cpu;
20530 CPUMIPSState *env;
20531 const mips_def_t *def;
20533 def = cpu_mips_find_by_name(cpu_model);
20534 if (!def)
20535 return NULL;
20536 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
20537 env = &cpu->env;
20538 env->cpu_model = def;
20540 #ifndef CONFIG_USER_ONLY
20541 mmu_init(env, def);
20542 #endif
20543 fpu_init(env, def);
20544 mvp_init(env, def);
20546 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
20548 return cpu;
20551 void cpu_state_reset(CPUMIPSState *env)
20553 MIPSCPU *cpu = mips_env_get_cpu(env);
20554 CPUState *cs = CPU(cpu);
20556 /* Reset registers to their default values */
20557 env->CP0_PRid = env->cpu_model->CP0_PRid;
20558 env->CP0_Config0 = env->cpu_model->CP0_Config0;
20559 #ifdef TARGET_WORDS_BIGENDIAN
20560 env->CP0_Config0 |= (1 << CP0C0_BE);
20561 #endif
20562 env->CP0_Config1 = env->cpu_model->CP0_Config1;
20563 env->CP0_Config2 = env->cpu_model->CP0_Config2;
20564 env->CP0_Config3 = env->cpu_model->CP0_Config3;
20565 env->CP0_Config4 = env->cpu_model->CP0_Config4;
20566 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
20567 env->CP0_Config5 = env->cpu_model->CP0_Config5;
20568 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
20569 env->CP0_Config6 = env->cpu_model->CP0_Config6;
20570 env->CP0_Config7 = env->cpu_model->CP0_Config7;
20571 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
20572 << env->cpu_model->CP0_LLAddr_shift;
20573 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
20574 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
20575 env->CCRes = env->cpu_model->CCRes;
20576 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
20577 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
20578 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
20579 env->current_tc = 0;
20580 env->SEGBITS = env->cpu_model->SEGBITS;
20581 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
20582 #if defined(TARGET_MIPS64)
20583 if (env->cpu_model->insn_flags & ISA_MIPS3) {
20584 env->SEGMask |= 3ULL << 62;
20586 #endif
20587 env->PABITS = env->cpu_model->PABITS;
20588 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
20589 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
20590 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
20591 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
20592 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
20593 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
20594 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
20595 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
20596 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
20597 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
20598 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
20599 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
20600 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
20601 env->msair = env->cpu_model->MSAIR;
20602 env->insn_flags = env->cpu_model->insn_flags;
20604 #if defined(CONFIG_USER_ONLY)
20605 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
20606 # ifdef TARGET_MIPS64
20607 /* Enable 64-bit register mode. */
20608 env->CP0_Status |= (1 << CP0St_PX);
20609 # endif
20610 # ifdef TARGET_ABI_MIPSN64
20611 /* Enable 64-bit address mode. */
20612 env->CP0_Status |= (1 << CP0St_UX);
20613 # endif
20614 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
20615 hardware registers. */
20616 env->CP0_HWREna |= 0x0000000F;
20617 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
20618 env->CP0_Status |= (1 << CP0St_CU1);
20620 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
20621 env->CP0_Status |= (1 << CP0St_MX);
20623 # if defined(TARGET_MIPS64)
20624 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
20625 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
20626 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
20627 env->CP0_Status |= (1 << CP0St_FR);
20629 # endif
20630 #else
20631 if (env->hflags & MIPS_HFLAG_BMASK) {
20632 /* If the exception was raised from a delay slot,
20633 come back to the jump. */
20634 env->CP0_ErrorEPC = (env->active_tc.PC
20635 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
20636 } else {
20637 env->CP0_ErrorEPC = env->active_tc.PC;
20639 env->active_tc.PC = (int32_t)0xBFC00000;
20640 env->CP0_Random = env->tlb->nb_tlb - 1;
20641 env->tlb->tlb_in_use = env->tlb->nb_tlb;
20642 env->CP0_Wired = 0;
20643 env->CP0_EBase = (cs->cpu_index & 0x3FF);
20644 if (kvm_enabled()) {
20645 env->CP0_EBase |= 0x40000000;
20646 } else {
20647 env->CP0_EBase |= 0x80000000;
20649 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
20650 /* vectored interrupts not implemented, timer on int 7,
20651 no performance counters. */
20652 env->CP0_IntCtl = 0xe0000000;
20654 int i;
20656 for (i = 0; i < 7; i++) {
20657 env->CP0_WatchLo[i] = 0;
20658 env->CP0_WatchHi[i] = 0x80000000;
20660 env->CP0_WatchLo[7] = 0;
20661 env->CP0_WatchHi[7] = 0;
20663 /* Count register increments in debug mode, EJTAG version 1 */
20664 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
20666 cpu_mips_store_count(env, 1);
20668 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
20669 int i;
20671 /* Only TC0 on VPE 0 starts as active. */
20672 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
20673 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
20674 env->tcs[i].CP0_TCHalt = 1;
20676 env->active_tc.CP0_TCHalt = 1;
20677 cs->halted = 1;
20679 if (cs->cpu_index == 0) {
20680 /* VPE0 starts up enabled. */
20681 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
20682 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
20684 /* TC0 starts up unhalted. */
20685 cs->halted = 0;
20686 env->active_tc.CP0_TCHalt = 0;
20687 env->tcs[0].CP0_TCHalt = 0;
20688 /* With thread 0 active. */
20689 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
20690 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
20693 #endif
20694 if ((env->insn_flags & ISA_MIPS32R6) &&
20695 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
20696 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
20697 env->CP0_Status |= (1 << CP0St_FR);
20700 /* MSA */
20701 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
20702 msa_reset(env);
20705 compute_hflags(env);
20706 restore_rounding_mode(env);
20707 restore_flush_mode(env);
20708 restore_pamask(env);
20709 cs->exception_index = EXCP_NONE;
20711 if (semihosting_get_argc()) {
20712 /* UHI interface can be used to obtain argc and argv */
20713 env->active_tc.gpr[4] = -1;
20717 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
20719 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
20720 env->hflags &= ~MIPS_HFLAG_BMASK;
20721 env->hflags |= gen_opc_hflags[pc_pos];
20722 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
20723 case MIPS_HFLAG_BR:
20724 break;
20725 case MIPS_HFLAG_BC:
20726 case MIPS_HFLAG_BL:
20727 case MIPS_HFLAG_B:
20728 env->btarget = gen_opc_btarget[pc_pos];
20729 break;